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 5381499 : BreakableControlFlowBuilder::~BreakableControlFlowBuilder() {
14 : BindBreakTarget();
15 : DCHECK(break_labels_.empty() || break_labels_.is_bound());
16 5381519 : if (block_coverage_builder_ != nullptr) {
17 : block_coverage_builder_->IncrementBlockCounter(
18 1500 : node_, SourceRangeKind::kContinuation);
19 : }
20 5381569 : }
21 :
22 0 : void BreakableControlFlowBuilder::BindBreakTarget() {
23 5381499 : break_labels_.Bind(builder());
24 0 : }
25 :
26 53867 : void BreakableControlFlowBuilder::EmitJump(BytecodeLabels* sites) {
27 53867 : builder()->Jump(sites->New());
28 53870 : }
29 :
30 37724 : void BreakableControlFlowBuilder::EmitJumpIfTrue(
31 : BytecodeArrayBuilder::ToBooleanMode mode, BytecodeLabels* sites) {
32 37724 : builder()->JumpIfTrue(mode, sites->New());
33 37729 : }
34 :
35 4736 : void BreakableControlFlowBuilder::EmitJumpIfFalse(
36 : BytecodeArrayBuilder::ToBooleanMode mode, BytecodeLabels* sites) {
37 4736 : builder()->JumpIfFalse(mode, sites->New());
38 4742 : }
39 :
40 4738 : void BreakableControlFlowBuilder::EmitJumpIfUndefined(BytecodeLabels* sites) {
41 4738 : builder()->JumpIfUndefined(sites->New());
42 4742 : }
43 :
44 0 : void BreakableControlFlowBuilder::EmitJumpIfNull(BytecodeLabels* sites) {
45 0 : builder()->JumpIfNull(sites->New());
46 0 : }
47 :
48 554610 : LoopBuilder::~LoopBuilder() {
49 : DCHECK(continue_labels_.empty() || continue_labels_.is_bound());
50 277325 : }
51 :
52 261381 : 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 261381 : builder()->Bind(&loop_header_);
59 261402 : }
60 :
61 261536 : void LoopBuilder::LoopBody() {
62 261536 : if (block_coverage_builder_ != nullptr) {
63 228 : block_coverage_builder_->IncrementBlockCounter(block_coverage_body_slot_);
64 : }
65 261536 : }
66 :
67 261403 : 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 261403 : builder()->JumpLoop(&loop_header_, level);
75 261417 : }
76 :
77 261728 : void LoopBuilder::BindContinueTarget() { continue_labels_.Bind(builder()); }
78 :
79 10612 : SwitchBuilder::~SwitchBuilder() {
80 : #ifdef DEBUG
81 : for (auto site : case_sites_) {
82 : DCHECK(site.is_bound());
83 : }
84 : #endif
85 10612 : }
86 :
87 80093 : void SwitchBuilder::SetCaseTarget(int index, CaseClause* clause) {
88 80093 : BytecodeLabel& site = case_sites_.at(index);
89 80093 : builder()->Bind(&site);
90 80093 : if (block_coverage_builder_) {
91 : block_coverage_builder_->IncrementBlockCounter(clause,
92 24 : SourceRangeKind::kBody);
93 : }
94 80093 : }
95 :
96 107064 : TryCatchBuilder::~TryCatchBuilder() {
97 107064 : if (block_coverage_builder_ != nullptr) {
98 : block_coverage_builder_->IncrementBlockCounter(
99 60 : statement_, SourceRangeKind::kContinuation);
100 : }
101 107064 : }
102 :
103 107073 : void TryCatchBuilder::BeginTry(Register context) {
104 107073 : builder()->MarkTryBegin(handler_id_, context);
105 107087 : }
106 :
107 :
108 107073 : void TryCatchBuilder::EndTry() {
109 428337 : builder()->MarkTryEnd(handler_id_);
110 214176 : builder()->Jump(&exit_);
111 214174 : builder()->Bind(&handler_);
112 214178 : builder()->MarkHandler(handler_id_, catch_prediction_);
113 :
114 107069 : if (block_coverage_builder_ != nullptr) {
115 : block_coverage_builder_->IncrementBlockCounter(statement_,
116 60 : SourceRangeKind::kCatch);
117 : }
118 107069 : }
119 :
120 107082 : void TryCatchBuilder::EndCatch() { builder()->Bind(&exit_); }
121 :
122 41601 : TryFinallyBuilder::~TryFinallyBuilder() {
123 41601 : if (block_coverage_builder_ != nullptr) {
124 : block_coverage_builder_->IncrementBlockCounter(
125 28 : statement_, SourceRangeKind::kContinuation);
126 : }
127 41600 : }
128 :
129 41596 : void TryFinallyBuilder::BeginTry(Register context) {
130 41596 : builder()->MarkTryBegin(handler_id_, context);
131 41601 : }
132 :
133 :
134 52419 : void TryFinallyBuilder::LeaveTry() {
135 52419 : builder()->Jump(finalization_sites_.New());
136 52422 : }
137 :
138 :
139 41601 : void TryFinallyBuilder::EndTry() {
140 41601 : builder()->MarkTryEnd(handler_id_);
141 41605 : }
142 :
143 :
144 41597 : void TryFinallyBuilder::BeginHandler() {
145 83196 : builder()->Bind(&handler_);
146 83198 : builder()->MarkHandler(handler_id_, catch_prediction_);
147 41604 : }
148 :
149 41600 : void TryFinallyBuilder::BeginFinally() {
150 41600 : finalization_sites_.Bind(builder());
151 :
152 41605 : if (block_coverage_builder_ != nullptr) {
153 : block_coverage_builder_->IncrementBlockCounter(statement_,
154 28 : SourceRangeKind::kFinally);
155 : }
156 41605 : }
157 :
158 41599 : void TryFinallyBuilder::EndFinally() {
159 : // Nothing to be done here.
160 41599 : }
161 :
162 596340 : ConditionalControlFlowBuilder::~ConditionalControlFlowBuilder() {
163 596340 : if (!else_labels_.is_bound()) else_labels_.Bind(builder());
164 596340 : 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 596870 : if (block_coverage_builder_ != nullptr && node_->IsIfStatement()) {
173 : block_coverage_builder_->IncrementBlockCounter(
174 440 : node_, SourceRangeKind::kContinuation);
175 : }
176 596347 : }
177 :
178 69986 : void ConditionalControlFlowBuilder::JumpToEnd() {
179 : DCHECK(end_labels_.empty()); // May only be called once.
180 69986 : builder()->Jump(end_labels_.New());
181 69991 : }
182 :
183 587926 : void ConditionalControlFlowBuilder::Then() {
184 587926 : then_labels()->Bind(builder());
185 587933 : if (block_coverage_builder_ != nullptr) {
186 500 : block_coverage_builder_->IncrementBlockCounter(block_coverage_then_slot_);
187 : }
188 587933 : }
189 :
190 77144 : void ConditionalControlFlowBuilder::Else() {
191 77144 : else_labels()->Bind(builder());
192 77145 : if (block_coverage_builder_ != nullptr) {
193 124 : block_coverage_builder_->IncrementBlockCounter(block_coverage_else_slot_);
194 : }
195 77145 : }
196 :
197 : } // namespace interpreter
198 : } // namespace internal
199 178779 : } // namespace v8
|