Line data Source code
1 : // Copyright 2015 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include "src/interpreter/control-flow-builders.h"
6 : #include "src/objects-inl.h"
7 :
8 : namespace v8 {
9 : namespace internal {
10 : namespace interpreter {
11 :
12 :
13 11077584 : BreakableControlFlowBuilder::~BreakableControlFlowBuilder() {
14 : BindBreakTarget();
15 : DCHECK(break_labels_.empty() || break_labels_.is_bound());
16 5538790 : if (block_coverage_builder_ != nullptr) {
17 : block_coverage_builder_->IncrementBlockCounter(
18 1532 : node_, SourceRangeKind::kContinuation);
19 : }
20 5538818 : }
21 :
22 0 : void BreakableControlFlowBuilder::BindBreakTarget() {
23 5538766 : break_labels_.Bind(builder());
24 0 : }
25 :
26 52910 : void BreakableControlFlowBuilder::EmitJump(BytecodeLabels* sites) {
27 52910 : builder()->Jump(sites->New());
28 52911 : }
29 :
30 37700 : void BreakableControlFlowBuilder::EmitJumpIfTrue(
31 : BytecodeArrayBuilder::ToBooleanMode mode, BytecodeLabels* sites) {
32 37700 : builder()->JumpIfTrue(mode, sites->New());
33 37703 : }
34 :
35 4752 : void BreakableControlFlowBuilder::EmitJumpIfFalse(
36 : BytecodeArrayBuilder::ToBooleanMode mode, BytecodeLabels* sites) {
37 4752 : builder()->JumpIfFalse(mode, sites->New());
38 4753 : }
39 :
40 4753 : void BreakableControlFlowBuilder::EmitJumpIfUndefined(BytecodeLabels* sites) {
41 4753 : builder()->JumpIfUndefined(sites->New());
42 4753 : }
43 :
44 0 : void BreakableControlFlowBuilder::EmitJumpIfNull(BytecodeLabels* sites) {
45 0 : builder()->JumpIfNull(sites->New());
46 0 : }
47 :
48 556418 : LoopBuilder::~LoopBuilder() {
49 : DCHECK(continue_labels_.empty() || continue_labels_.is_bound());
50 278216 : }
51 :
52 262283 : void LoopBuilder::LoopHeader() {
53 : // Jumps from before the loop header into the loop violate ordering
54 : // requirements of bytecode basic blocks. The only entry into a loop
55 : // must be the loop header. Surely breaks is okay? Not if nested
56 : // and misplaced between the headers.
57 : DCHECK(break_labels_.empty() && continue_labels_.empty());
58 262283 : builder()->Bind(&loop_header_);
59 262287 : }
60 :
61 262431 : void LoopBuilder::LoopBody() {
62 262431 : if (block_coverage_builder_ != nullptr) {
63 228 : block_coverage_builder_->IncrementBlockCounter(block_coverage_body_slot_);
64 : }
65 262431 : }
66 :
67 262285 : void LoopBuilder::JumpToHeader(int loop_depth) {
68 : // Pass the proper loop nesting level to the backwards branch, to trigger
69 : // on-stack replacement when armed for the given loop nesting depth.
70 : int level = Min(loop_depth, AbstractCode::kMaxLoopNestingMarker - 1);
71 : // Loop must have closed form, i.e. all loop elements are within the loop,
72 : // the loop header precedes the body and next elements in the loop.
73 262285 : builder()->JumpLoop(&loop_header_, level);
74 262290 : }
75 :
76 262629 : void LoopBuilder::BindContinueTarget() { continue_labels_.Bind(builder()); }
77 :
78 21308 : SwitchBuilder::~SwitchBuilder() {
79 : #ifdef DEBUG
80 : for (auto site : case_sites_) {
81 : DCHECK(!site.has_referrer_jump() || site.is_bound());
82 : }
83 : #endif
84 10654 : }
85 :
86 80517 : void SwitchBuilder::SetCaseTarget(int index, CaseClause* clause) {
87 80517 : BytecodeLabel& site = case_sites_.at(index);
88 80517 : builder()->Bind(&site);
89 80517 : if (block_coverage_builder_) {
90 : block_coverage_builder_->IncrementBlockCounter(clause,
91 24 : SourceRangeKind::kBody);
92 : }
93 80517 : }
94 :
95 225958 : TryCatchBuilder::~TryCatchBuilder() {
96 112979 : if (block_coverage_builder_ != nullptr) {
97 : block_coverage_builder_->IncrementBlockCounter(
98 68 : statement_, SourceRangeKind::kContinuation);
99 : }
100 112979 : }
101 :
102 112979 : void TryCatchBuilder::BeginTry(Register context) {
103 112979 : builder()->MarkTryBegin(handler_id_, context);
104 112986 : }
105 :
106 :
107 112984 : void TryCatchBuilder::EndTry() {
108 112984 : builder()->MarkTryEnd(handler_id_);
109 112986 : builder()->Jump(&exit_);
110 112986 : builder()->MarkHandler(handler_id_, catch_prediction_);
111 :
112 112985 : if (block_coverage_builder_ != nullptr) {
113 68 : block_coverage_builder_->IncrementBlockCounter(statement_,
114 68 : SourceRangeKind::kCatch);
115 : }
116 112985 : }
117 :
118 112983 : void TryCatchBuilder::EndCatch() { builder()->Bind(&exit_); }
119 :
120 83106 : TryFinallyBuilder::~TryFinallyBuilder() {
121 41552 : if (block_coverage_builder_ != nullptr) {
122 : block_coverage_builder_->IncrementBlockCounter(
123 28 : statement_, SourceRangeKind::kContinuation);
124 : }
125 41554 : }
126 :
127 41552 : void TryFinallyBuilder::BeginTry(Register context) {
128 41552 : builder()->MarkTryBegin(handler_id_, context);
129 41554 : }
130 :
131 :
132 52494 : void TryFinallyBuilder::LeaveTry() {
133 52494 : builder()->Jump(finalization_sites_.New());
134 52495 : }
135 :
136 :
137 41550 : void TryFinallyBuilder::EndTry() {
138 41550 : builder()->MarkTryEnd(handler_id_);
139 41551 : }
140 :
141 :
142 41554 : void TryFinallyBuilder::BeginHandler() {
143 41554 : builder()->Bind(&handler_);
144 41554 : builder()->MarkHandler(handler_id_, catch_prediction_);
145 41553 : }
146 :
147 41553 : void TryFinallyBuilder::BeginFinally() {
148 41553 : finalization_sites_.Bind(builder());
149 :
150 41554 : if (block_coverage_builder_ != nullptr) {
151 28 : block_coverage_builder_->IncrementBlockCounter(statement_,
152 28 : SourceRangeKind::kFinally);
153 : }
154 41554 : }
155 :
156 41553 : void TryFinallyBuilder::EndFinally() {
157 : // Nothing to be done here.
158 41553 : }
159 :
160 1222291 : ConditionalControlFlowBuilder::~ConditionalControlFlowBuilder() {
161 611143 : if (!else_labels_.is_bound()) else_labels_.Bind(builder());
162 611147 : end_labels_.Bind(builder());
163 :
164 : DCHECK(end_labels_.empty() || end_labels_.is_bound());
165 : DCHECK(then_labels_.empty() || then_labels_.is_bound());
166 : DCHECK(else_labels_.empty() || else_labels_.is_bound());
167 :
168 : // IfStatement requires a continuation counter, Conditional does not (as it
169 : // can only contain expressions).
170 611673 : if (block_coverage_builder_ != nullptr && node_->IsIfStatement()) {
171 : block_coverage_builder_->IncrementBlockCounter(
172 444 : node_, SourceRangeKind::kContinuation);
173 : }
174 611148 : }
175 :
176 72165 : void ConditionalControlFlowBuilder::JumpToEnd() {
177 : DCHECK(end_labels_.empty()); // May only be called once.
178 72165 : builder()->Jump(end_labels_.New());
179 72165 : }
180 :
181 602732 : void ConditionalControlFlowBuilder::Then() {
182 602732 : then_labels()->Bind(builder());
183 602736 : if (block_coverage_builder_ != nullptr) {
184 504 : block_coverage_builder_->IncrementBlockCounter(block_coverage_then_slot_);
185 : }
186 602736 : }
187 :
188 79320 : void ConditionalControlFlowBuilder::Else() {
189 79320 : else_labels()->Bind(builder());
190 79320 : if (block_coverage_builder_ != nullptr) {
191 124 : block_coverage_builder_->IncrementBlockCounter(block_coverage_else_slot_);
192 : }
193 79320 : }
194 :
195 : } // namespace interpreter
196 : } // namespace internal
197 121996 : } // namespace v8
|