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 11089285 : BreakableControlFlowBuilder::~BreakableControlFlowBuilder() {
14 : BindBreakTarget();
15 : DCHECK(break_labels_.empty() || break_labels_.is_bound());
16 5544633 : if (block_coverage_builder_ != nullptr) {
17 : block_coverage_builder_->IncrementBlockCounter(
18 1532 : node_, SourceRangeKind::kContinuation);
19 : }
20 5544663 : }
21 :
22 0 : void BreakableControlFlowBuilder::BindBreakTarget() {
23 5544622 : break_labels_.Bind(builder());
24 0 : }
25 :
26 52910 : void BreakableControlFlowBuilder::EmitJump(BytecodeLabels* sites) {
27 52910 : builder()->Jump(sites->New());
28 52910 : }
29 :
30 37798 : void BreakableControlFlowBuilder::EmitJumpIfTrue(
31 : BytecodeArrayBuilder::ToBooleanMode mode, BytecodeLabels* sites) {
32 37798 : builder()->JumpIfTrue(mode, sites->New());
33 37804 : }
34 :
35 4752 : void BreakableControlFlowBuilder::EmitJumpIfFalse(
36 : BytecodeArrayBuilder::ToBooleanMode mode, BytecodeLabels* sites) {
37 4752 : builder()->JumpIfFalse(mode, sites->New());
38 4752 : }
39 :
40 4752 : void BreakableControlFlowBuilder::EmitJumpIfUndefined(BytecodeLabels* sites) {
41 4752 : builder()->JumpIfUndefined(sites->New());
42 4752 : }
43 :
44 0 : void BreakableControlFlowBuilder::EmitJumpIfNull(BytecodeLabels* sites) {
45 0 : builder()->JumpIfNull(sites->New());
46 0 : }
47 :
48 556780 : LoopBuilder::~LoopBuilder() {
49 : DCHECK(continue_labels_.empty() || continue_labels_.is_bound());
50 278392 : }
51 :
52 262458 : 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 262458 : builder()->Bind(&loop_header_);
59 262459 : }
60 :
61 262608 : void LoopBuilder::LoopBody() {
62 262608 : if (block_coverage_builder_ != nullptr) {
63 228 : block_coverage_builder_->IncrementBlockCounter(block_coverage_body_slot_);
64 : }
65 262608 : }
66 :
67 262462 : 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 262462 : builder()->JumpLoop(&loop_header_, level);
74 262462 : }
75 :
76 262809 : void LoopBuilder::BindContinueTarget() { continue_labels_.Bind(builder()); }
77 :
78 21310 : SwitchBuilder::~SwitchBuilder() {
79 : #ifdef DEBUG
80 : for (auto site : case_sites_) {
81 : DCHECK(!site.has_referrer_jump() || site.is_bound());
82 : }
83 : #endif
84 10655 : }
85 :
86 80537 : void SwitchBuilder::SetCaseTarget(int index, CaseClause* clause) {
87 80537 : BytecodeLabel& site = case_sites_.at(index);
88 80537 : builder()->Bind(&site);
89 80537 : if (block_coverage_builder_) {
90 : block_coverage_builder_->IncrementBlockCounter(clause,
91 24 : SourceRangeKind::kBody);
92 : }
93 80537 : }
94 :
95 226244 : TryCatchBuilder::~TryCatchBuilder() {
96 113122 : if (block_coverage_builder_ != nullptr) {
97 : block_coverage_builder_->IncrementBlockCounter(
98 68 : statement_, SourceRangeKind::kContinuation);
99 : }
100 113122 : }
101 :
102 113130 : void TryCatchBuilder::BeginTry(Register context) {
103 113130 : builder()->MarkTryBegin(handler_id_, context);
104 113135 : }
105 :
106 :
107 113128 : void TryCatchBuilder::EndTry() {
108 113128 : builder()->MarkTryEnd(handler_id_);
109 113135 : builder()->Jump(&exit_);
110 113133 : builder()->MarkHandler(handler_id_, catch_prediction_);
111 :
112 113133 : if (block_coverage_builder_ != nullptr) {
113 68 : block_coverage_builder_->IncrementBlockCounter(statement_,
114 68 : SourceRangeKind::kCatch);
115 : }
116 113133 : }
117 :
118 113134 : void TryCatchBuilder::EndCatch() { builder()->Bind(&exit_); }
119 :
120 83273 : TryFinallyBuilder::~TryFinallyBuilder() {
121 41636 : if (block_coverage_builder_ != nullptr) {
122 : block_coverage_builder_->IncrementBlockCounter(
123 28 : statement_, SourceRangeKind::kContinuation);
124 : }
125 41637 : }
126 :
127 41635 : void TryFinallyBuilder::BeginTry(Register context) {
128 41635 : builder()->MarkTryBegin(handler_id_, context);
129 41641 : }
130 :
131 :
132 52589 : void TryFinallyBuilder::LeaveTry() {
133 52589 : builder()->Jump(finalization_sites_.New());
134 52591 : }
135 :
136 :
137 41640 : void TryFinallyBuilder::EndTry() {
138 41640 : builder()->MarkTryEnd(handler_id_);
139 41641 : }
140 :
141 :
142 41642 : void TryFinallyBuilder::BeginHandler() {
143 41642 : builder()->Bind(&handler_);
144 41643 : builder()->MarkHandler(handler_id_, catch_prediction_);
145 41641 : }
146 :
147 41643 : void TryFinallyBuilder::BeginFinally() {
148 41643 : finalization_sites_.Bind(builder());
149 :
150 41644 : if (block_coverage_builder_ != nullptr) {
151 28 : block_coverage_builder_->IncrementBlockCounter(statement_,
152 28 : SourceRangeKind::kFinally);
153 : }
154 41644 : }
155 :
156 41641 : void TryFinallyBuilder::EndFinally() {
157 : // Nothing to be done here.
158 41641 : }
159 :
160 1223849 : ConditionalControlFlowBuilder::~ConditionalControlFlowBuilder() {
161 611921 : if (!else_labels_.is_bound()) else_labels_.Bind(builder());
162 611922 : 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 612452 : if (block_coverage_builder_ != nullptr && node_->IsIfStatement()) {
171 : block_coverage_builder_->IncrementBlockCounter(
172 444 : node_, SourceRangeKind::kContinuation);
173 : }
174 611928 : }
175 :
176 72248 : void ConditionalControlFlowBuilder::JumpToEnd() {
177 : DCHECK(end_labels_.empty()); // May only be called once.
178 72248 : builder()->Jump(end_labels_.New());
179 72250 : }
180 :
181 603501 : void ConditionalControlFlowBuilder::Then() {
182 603501 : then_labels()->Bind(builder());
183 603505 : if (block_coverage_builder_ != nullptr) {
184 504 : block_coverage_builder_->IncrementBlockCounter(block_coverage_then_slot_);
185 : }
186 603505 : }
187 :
188 79408 : void ConditionalControlFlowBuilder::Else() {
189 79408 : else_labels()->Bind(builder());
190 79407 : if (block_coverage_builder_ != nullptr) {
191 124 : block_coverage_builder_->IncrementBlockCounter(block_coverage_else_slot_);
192 : }
193 79407 : }
194 :
195 : } // namespace interpreter
196 : } // namespace internal
197 122036 : } // namespace v8
|