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