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 5404332 : BreakableControlFlowBuilder::~BreakableControlFlowBuilder() {
14 : BindBreakTarget();
15 : DCHECK(break_labels_.empty() || break_labels_.is_bound());
16 5404332 : if (block_coverage_builder_ != nullptr && needs_continuation_counter()) {
17 : block_coverage_builder_->IncrementBlockCounter(
18 846 : node_, SourceRangeKind::kContinuation);
19 : }
20 5402251 : }
21 :
22 0 : void BreakableControlFlowBuilder::BindBreakTarget() {
23 5402251 : break_labels_.Bind(builder());
24 0 : }
25 :
26 86049 : void BreakableControlFlowBuilder::EmitJump(BytecodeLabels* sites) {
27 86049 : builder()->Jump(sites->New());
28 86049 : }
29 :
30 24663 : void BreakableControlFlowBuilder::EmitJumpIfTrue(
31 : BytecodeArrayBuilder::ToBooleanMode mode, BytecodeLabels* sites) {
32 24663 : builder()->JumpIfTrue(mode, sites->New());
33 24663 : }
34 :
35 6072 : void BreakableControlFlowBuilder::EmitJumpIfFalse(
36 : BytecodeArrayBuilder::ToBooleanMode mode, BytecodeLabels* sites) {
37 6072 : builder()->JumpIfFalse(mode, sites->New());
38 6072 : }
39 :
40 6072 : void BreakableControlFlowBuilder::EmitJumpIfUndefined(BytecodeLabels* sites) {
41 6072 : builder()->JumpIfUndefined(sites->New());
42 6072 : }
43 :
44 0 : void BreakableControlFlowBuilder::EmitJumpIfNull(BytecodeLabels* sites) {
45 0 : builder()->JumpIfNull(sites->New());
46 0 : }
47 :
48 477626 : LoopBuilder::~LoopBuilder() {
49 : DCHECK(continue_labels_.empty() || continue_labels_.is_bound());
50 : // Restore the parent jump table.
51 238813 : if (generator_jump_table_location_ != nullptr) {
52 1086 : *generator_jump_table_location_ = parent_generator_jump_table_;
53 : }
54 238813 : }
55 :
56 221790 : void LoopBuilder::LoopHeader() {
57 : // Jumps from before the loop header into the loop violate ordering
58 : // requirements of bytecode basic blocks. The only entry into a loop
59 : // must be the loop header. Surely breaks is okay? Not if nested
60 : // and misplaced between the headers.
61 : DCHECK(break_labels_.empty() && continue_labels_.empty());
62 222876 : builder()->Bind(&loop_header_);
63 221790 : }
64 :
65 1086 : void LoopBuilder::LoopHeaderInGenerator(
66 : BytecodeJumpTable** generator_jump_table, int first_resume_id,
67 : int resume_count) {
68 : // Bind all the resume points that are inside the loop to be at the loop
69 : // header.
70 2345 : for (int id = first_resume_id; id < first_resume_id + resume_count; ++id) {
71 2345 : builder()->Bind(*generator_jump_table, id);
72 : }
73 :
74 : // Create the loop header.
75 : LoopHeader();
76 :
77 : // Create a new jump table for after the loop header for only these
78 : // resume points.
79 1086 : generator_jump_table_location_ = generator_jump_table;
80 1086 : parent_generator_jump_table_ = *generator_jump_table;
81 : *generator_jump_table =
82 1086 : builder()->AllocateJumpTable(resume_count, first_resume_id);
83 1086 : }
84 :
85 222999 : void LoopBuilder::LoopBody() {
86 222999 : if (block_coverage_builder_ != nullptr) {
87 318 : block_coverage_builder_->IncrementBlockCounter(block_coverage_body_slot_);
88 : }
89 222999 : }
90 :
91 222876 : void LoopBuilder::JumpToHeader(int loop_depth) {
92 : // Pass the proper loop nesting level to the backwards branch, to trigger
93 : // on-stack replacement when armed for the given loop nesting depth.
94 : int level = Min(loop_depth, AbstractCode::kMaxLoopNestingMarker - 1);
95 : // Loop must have closed form, i.e. all loop elements are within the loop,
96 : // the loop header precedes the body and next elements in the loop.
97 : DCHECK(loop_header_.is_bound());
98 222876 : builder()->JumpLoop(&loop_header_, level);
99 222876 : }
100 :
101 223246 : void LoopBuilder::BindContinueTarget() { continue_labels_.Bind(builder()); }
102 :
103 16671 : SwitchBuilder::~SwitchBuilder() {
104 : #ifdef DEBUG
105 : for (auto site : case_sites_) {
106 : DCHECK(site.is_bound());
107 : }
108 : #endif
109 16671 : }
110 :
111 100608 : void SwitchBuilder::SetCaseTarget(int index, CaseClause* clause) {
112 100608 : BytecodeLabel& site = case_sites_.at(index);
113 100608 : builder()->Bind(&site);
114 100608 : if (block_coverage_builder_) {
115 : block_coverage_builder_->IncrementBlockCounter(clause,
116 36 : SourceRangeKind::kBody);
117 : }
118 100608 : }
119 :
120 :
121 102123 : void TryCatchBuilder::BeginTry(Register context) {
122 102123 : builder()->MarkTryBegin(handler_id_, context);
123 102123 : }
124 :
125 :
126 102123 : void TryCatchBuilder::EndTry() {
127 408492 : builder()->MarkTryEnd(handler_id_);
128 204246 : builder()->Jump(&exit_);
129 204246 : builder()->Bind(&handler_);
130 204246 : builder()->MarkHandler(handler_id_, catch_prediction_);
131 102123 : }
132 :
133 :
134 102123 : void TryCatchBuilder::EndCatch() { builder()->Bind(&exit_); }
135 :
136 :
137 36312 : void TryFinallyBuilder::BeginTry(Register context) {
138 36312 : builder()->MarkTryBegin(handler_id_, context);
139 36312 : }
140 :
141 :
142 53844 : void TryFinallyBuilder::LeaveTry() {
143 53844 : builder()->Jump(finalization_sites_.New());
144 53844 : }
145 :
146 :
147 36312 : void TryFinallyBuilder::EndTry() {
148 36312 : builder()->MarkTryEnd(handler_id_);
149 36312 : }
150 :
151 :
152 36312 : void TryFinallyBuilder::BeginHandler() {
153 72624 : builder()->Bind(&handler_);
154 72624 : builder()->MarkHandler(handler_id_, catch_prediction_);
155 36312 : }
156 :
157 36312 : void TryFinallyBuilder::BeginFinally() { finalization_sites_.Bind(builder()); }
158 :
159 36312 : void TryFinallyBuilder::EndFinally() {
160 : // Nothing to be done here.
161 36312 : }
162 :
163 1015593 : ConditionalControlFlowBuilder::~ConditionalControlFlowBuilder() {
164 1015593 : if (!else_labels_.is_bound()) else_labels_.Bind(builder());
165 1015593 : end_labels_.Bind(builder());
166 :
167 : DCHECK(end_labels_.empty() || end_labels_.is_bound());
168 : DCHECK(then_labels_.empty() || then_labels_.is_bound());
169 : DCHECK(else_labels_.empty() || else_labels_.is_bound());
170 :
171 : // IfStatement requires a continuation counter, Conditional does not (as it
172 : // can only contain expressions).
173 1016367 : if (block_coverage_builder_ != nullptr && node_->IsIfStatement()) {
174 : block_coverage_builder_->IncrementBlockCounter(
175 685 : node_, SourceRangeKind::kContinuation);
176 : }
177 1015594 : }
178 :
179 288846 : void ConditionalControlFlowBuilder::JumpToEnd() {
180 : DCHECK(end_labels_.empty()); // May only be called once.
181 288846 : builder()->Jump(end_labels_.New());
182 288846 : }
183 :
184 1007125 : void ConditionalControlFlowBuilder::Then() {
185 1007125 : then_labels()->Bind(builder());
186 1007125 : if (block_coverage_builder_ != nullptr) {
187 755 : block_coverage_builder_->IncrementBlockCounter(block_coverage_then_slot_);
188 : }
189 1007125 : }
190 :
191 296017 : void ConditionalControlFlowBuilder::Else() {
192 296017 : else_labels()->Bind(builder());
193 296017 : if (block_coverage_builder_ != nullptr) {
194 292 : block_coverage_builder_->IncrementBlockCounter(block_coverage_else_slot_);
195 : }
196 296017 : }
197 :
198 : } // namespace interpreter
199 : } // namespace internal
200 : } // namespace v8
|