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 5531201 : BreakableControlFlowBuilder::~BreakableControlFlowBuilder() {
14 : BindBreakTarget();
15 : DCHECK(break_labels_.empty() || break_labels_.is_bound());
16 5531296 : if (block_coverage_builder_ != nullptr) {
17 : block_coverage_builder_->IncrementBlockCounter(
18 1875 : node_, SourceRangeKind::kContinuation);
19 : }
20 5531447 : }
21 :
22 0 : void BreakableControlFlowBuilder::BindBreakTarget() {
23 5531201 : break_labels_.Bind(builder());
24 0 : }
25 :
26 54089 : void BreakableControlFlowBuilder::EmitJump(BytecodeLabels* sites) {
27 54089 : builder()->Jump(sites->New());
28 54093 : }
29 :
30 40486 : void BreakableControlFlowBuilder::EmitJumpIfTrue(
31 : BytecodeArrayBuilder::ToBooleanMode mode, BytecodeLabels* sites) {
32 40486 : builder()->JumpIfTrue(mode, sites->New());
33 40499 : }
34 :
35 4749 : void BreakableControlFlowBuilder::EmitJumpIfFalse(
36 : BytecodeArrayBuilder::ToBooleanMode mode, BytecodeLabels* sites) {
37 4749 : builder()->JumpIfFalse(mode, sites->New());
38 4751 : }
39 :
40 4749 : void BreakableControlFlowBuilder::EmitJumpIfUndefined(BytecodeLabels* sites) {
41 4749 : builder()->JumpIfUndefined(sites->New());
42 4751 : }
43 :
44 0 : void BreakableControlFlowBuilder::EmitJumpIfNull(BytecodeLabels* sites) {
45 0 : builder()->JumpIfNull(sites->New());
46 0 : }
47 :
48 561330 : LoopBuilder::~LoopBuilder() {
49 : DCHECK(continue_labels_.empty() || continue_labels_.is_bound());
50 280721 : }
51 :
52 264740 : 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 264740 : builder()->Bind(&loop_header_);
59 264755 : }
60 :
61 264897 : void LoopBuilder::LoopBody() {
62 264897 : if (block_coverage_builder_ != nullptr) {
63 285 : block_coverage_builder_->IncrementBlockCounter(block_coverage_body_slot_);
64 : }
65 264897 : }
66 :
67 264769 : 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 : DCHECK(loop_header_.is_bound());
74 264769 : builder()->JumpLoop(&loop_header_, level);
75 264780 : }
76 :
77 265089 : void LoopBuilder::BindContinueTarget() { continue_labels_.Bind(builder()); }
78 :
79 10440 : SwitchBuilder::~SwitchBuilder() {
80 : #ifdef DEBUG
81 : for (auto site : case_sites_) {
82 : DCHECK(site.is_bound());
83 : }
84 : #endif
85 10440 : }
86 :
87 79105 : void SwitchBuilder::SetCaseTarget(int index, CaseClause* clause) {
88 79105 : BytecodeLabel& site = case_sites_.at(index);
89 79105 : builder()->Bind(&site);
90 79105 : if (block_coverage_builder_) {
91 : block_coverage_builder_->IncrementBlockCounter(clause,
92 30 : SourceRangeKind::kBody);
93 : }
94 79105 : }
95 :
96 110388 : TryCatchBuilder::~TryCatchBuilder() {
97 110388 : if (block_coverage_builder_ != nullptr) {
98 : block_coverage_builder_->IncrementBlockCounter(
99 75 : statement_, SourceRangeKind::kContinuation);
100 : }
101 110388 : }
102 :
103 110410 : void TryCatchBuilder::BeginTry(Register context) {
104 110410 : builder()->MarkTryBegin(handler_id_, context);
105 110420 : }
106 :
107 :
108 110409 : void TryCatchBuilder::EndTry() {
109 441689 : builder()->MarkTryEnd(handler_id_);
110 220850 : builder()->Jump(&exit_);
111 220854 : builder()->Bind(&handler_);
112 220856 : builder()->MarkHandler(handler_id_, catch_prediction_);
113 :
114 110399 : if (block_coverage_builder_ != nullptr) {
115 : block_coverage_builder_->IncrementBlockCounter(statement_,
116 75 : SourceRangeKind::kCatch);
117 : }
118 110399 : }
119 :
120 110416 : void TryCatchBuilder::EndCatch() { builder()->Bind(&exit_); }
121 :
122 44102 : TryFinallyBuilder::~TryFinallyBuilder() {
123 44102 : if (block_coverage_builder_ != nullptr) {
124 : block_coverage_builder_->IncrementBlockCounter(
125 35 : statement_, SourceRangeKind::kContinuation);
126 : }
127 44105 : }
128 :
129 44100 : void TryFinallyBuilder::BeginTry(Register context) {
130 44100 : builder()->MarkTryBegin(handler_id_, context);
131 44107 : }
132 :
133 :
134 55612 : void TryFinallyBuilder::LeaveTry() {
135 55612 : builder()->Jump(finalization_sites_.New());
136 55613 : }
137 :
138 :
139 44110 : void TryFinallyBuilder::EndTry() {
140 44110 : builder()->MarkTryEnd(handler_id_);
141 44109 : }
142 :
143 :
144 44108 : void TryFinallyBuilder::BeginHandler() {
145 88219 : builder()->Bind(&handler_);
146 88222 : builder()->MarkHandler(handler_id_, catch_prediction_);
147 44111 : }
148 :
149 44107 : void TryFinallyBuilder::BeginFinally() {
150 44107 : finalization_sites_.Bind(builder());
151 :
152 44112 : if (block_coverage_builder_ != nullptr) {
153 : block_coverage_builder_->IncrementBlockCounter(statement_,
154 35 : SourceRangeKind::kFinally);
155 : }
156 44112 : }
157 :
158 44103 : void TryFinallyBuilder::EndFinally() {
159 : // Nothing to be done here.
160 44103 : }
161 :
162 580906 : ConditionalControlFlowBuilder::~ConditionalControlFlowBuilder() {
163 580906 : if (!else_labels_.is_bound()) else_labels_.Bind(builder());
164 580902 : end_labels_.Bind(builder());
165 :
166 : DCHECK(end_labels_.empty() || end_labels_.is_bound());
167 : DCHECK(then_labels_.empty() || then_labels_.is_bound());
168 : DCHECK(else_labels_.empty() || else_labels_.is_bound());
169 :
170 : // IfStatement requires a continuation counter, Conditional does not (as it
171 : // can only contain expressions).
172 581577 : if (block_coverage_builder_ != nullptr && node_->IsIfStatement()) {
173 : block_coverage_builder_->IncrementBlockCounter(
174 550 : node_, SourceRangeKind::kContinuation);
175 : }
176 580925 : }
177 :
178 81146 : void ConditionalControlFlowBuilder::JumpToEnd() {
179 : DCHECK(end_labels_.empty()); // May only be called once.
180 81146 : builder()->Jump(end_labels_.New());
181 81158 : }
182 :
183 572484 : void ConditionalControlFlowBuilder::Then() {
184 572484 : then_labels()->Bind(builder());
185 572489 : if (block_coverage_builder_ != nullptr) {
186 625 : block_coverage_builder_->IncrementBlockCounter(block_coverage_then_slot_);
187 : }
188 572489 : }
189 :
190 88311 : void ConditionalControlFlowBuilder::Else() {
191 88311 : else_labels()->Bind(builder());
192 88309 : if (block_coverage_builder_ != nullptr) {
193 155 : block_coverage_builder_->IncrementBlockCounter(block_coverage_else_slot_);
194 : }
195 88309 : }
196 :
197 : } // namespace interpreter
198 : } // namespace internal
199 183867 : } // namespace v8
|