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 11089082 : BreakableControlFlowBuilder::~BreakableControlFlowBuilder() {
14 : BindBreakTarget();
15 : DCHECK(break_labels_.empty() || break_labels_.is_bound());
16 5544535 : if (block_coverage_builder_ != nullptr) {
17 : block_coverage_builder_->IncrementBlockCounter(
18 1532 : node_, SourceRangeKind::kContinuation);
19 : }
20 5544558 : }
21 :
22 0 : void BreakableControlFlowBuilder::BindBreakTarget() {
23 5544524 : break_labels_.Bind(builder());
24 0 : }
25 :
26 52916 : void BreakableControlFlowBuilder::EmitJump(BytecodeLabels* sites) {
27 52916 : builder()->Jump(sites->New());
28 52917 : }
29 :
30 37808 : void BreakableControlFlowBuilder::EmitJumpIfTrue(
31 : BytecodeArrayBuilder::ToBooleanMode mode, BytecodeLabels* sites) {
32 37808 : builder()->JumpIfTrue(mode, sites->New());
33 37812 : }
34 :
35 4753 : void BreakableControlFlowBuilder::EmitJumpIfFalse(
36 : BytecodeArrayBuilder::ToBooleanMode mode, BytecodeLabels* sites) {
37 4753 : 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 556806 : LoopBuilder::~LoopBuilder() {
49 : DCHECK(continue_labels_.empty() || continue_labels_.is_bound());
50 278407 : }
51 :
52 262465 : 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 262465 : builder()->Bind(&loop_header_);
59 262474 : }
60 :
61 262614 : void LoopBuilder::LoopBody() {
62 262614 : if (block_coverage_builder_ != nullptr) {
63 228 : block_coverage_builder_->IncrementBlockCounter(block_coverage_body_slot_);
64 : }
65 262614 : }
66 :
67 262479 : 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 262479 : builder()->JumpLoop(&loop_header_, level);
74 262476 : }
75 :
76 262816 : void LoopBuilder::BindContinueTarget() { continue_labels_.Bind(builder()); }
77 :
78 21330 : SwitchBuilder::~SwitchBuilder() {
79 : #ifdef DEBUG
80 : for (auto site : case_sites_) {
81 : DCHECK(!site.has_referrer_jump() || site.is_bound());
82 : }
83 : #endif
84 10665 : }
85 :
86 80583 : void SwitchBuilder::SetCaseTarget(int index, CaseClause* clause) {
87 80583 : BytecodeLabel& site = case_sites_.at(index);
88 80583 : builder()->Bind(&site);
89 80583 : if (block_coverage_builder_) {
90 : block_coverage_builder_->IncrementBlockCounter(clause,
91 24 : SourceRangeKind::kBody);
92 : }
93 80583 : }
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 113129 : void TryCatchBuilder::BeginTry(Register context) {
103 113129 : builder()->MarkTryBegin(handler_id_, context);
104 113132 : }
105 :
106 :
107 113126 : void TryCatchBuilder::EndTry() {
108 113126 : builder()->MarkTryEnd(handler_id_);
109 113130 : 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 113130 : void TryCatchBuilder::EndCatch() { builder()->Bind(&exit_); }
119 :
120 83294 : TryFinallyBuilder::~TryFinallyBuilder() {
121 41646 : if (block_coverage_builder_ != nullptr) {
122 : block_coverage_builder_->IncrementBlockCounter(
123 28 : statement_, SourceRangeKind::kContinuation);
124 : }
125 41648 : }
126 :
127 41645 : void TryFinallyBuilder::BeginTry(Register context) {
128 41645 : builder()->MarkTryBegin(handler_id_, context);
129 41651 : }
130 :
131 :
132 52607 : void TryFinallyBuilder::LeaveTry() {
133 52607 : builder()->Jump(finalization_sites_.New());
134 52606 : }
135 :
136 :
137 41652 : void TryFinallyBuilder::EndTry() {
138 41652 : builder()->MarkTryEnd(handler_id_);
139 41646 : }
140 :
141 :
142 41651 : void TryFinallyBuilder::BeginHandler() {
143 41651 : builder()->Bind(&handler_);
144 41649 : builder()->MarkHandler(handler_id_, catch_prediction_);
145 41653 : }
146 :
147 41648 : void TryFinallyBuilder::BeginFinally() {
148 41648 : finalization_sites_.Bind(builder());
149 :
150 41651 : if (block_coverage_builder_ != nullptr) {
151 28 : block_coverage_builder_->IncrementBlockCounter(statement_,
152 28 : SourceRangeKind::kFinally);
153 : }
154 41651 : }
155 :
156 41651 : void TryFinallyBuilder::EndFinally() {
157 : // Nothing to be done here.
158 41651 : }
159 :
160 1223872 : ConditionalControlFlowBuilder::~ConditionalControlFlowBuilder() {
161 611931 : if (!else_labels_.is_bound()) else_labels_.Bind(builder());
162 611938 : 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 612465 : if (block_coverage_builder_ != nullptr && node_->IsIfStatement()) {
171 : block_coverage_builder_->IncrementBlockCounter(
172 444 : node_, SourceRangeKind::kContinuation);
173 : }
174 611941 : }
175 :
176 72239 : void ConditionalControlFlowBuilder::JumpToEnd() {
177 : DCHECK(end_labels_.empty()); // May only be called once.
178 72239 : builder()->Jump(end_labels_.New());
179 72240 : }
180 :
181 603511 : void ConditionalControlFlowBuilder::Then() {
182 603511 : then_labels()->Bind(builder());
183 603517 : if (block_coverage_builder_ != nullptr) {
184 504 : block_coverage_builder_->IncrementBlockCounter(block_coverage_then_slot_);
185 : }
186 603517 : }
187 :
188 79396 : void ConditionalControlFlowBuilder::Else() {
189 79396 : else_labels()->Bind(builder());
190 79396 : if (block_coverage_builder_ != nullptr) {
191 124 : block_coverage_builder_->IncrementBlockCounter(block_coverage_else_slot_);
192 : }
193 79396 : }
194 :
195 : } // namespace interpreter
196 : } // namespace internal
197 122036 : } // namespace v8
|