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
~BreakableControlFlowBuilder()13 BreakableControlFlowBuilder::~BreakableControlFlowBuilder() {
14 DCHECK(break_labels_.empty() || break_labels_.is_bound());
15 }
16
BindBreakTarget()17 void BreakableControlFlowBuilder::BindBreakTarget() {
18 break_labels_.Bind(builder());
19 }
20
EmitJump(BytecodeLabels * sites)21 void BreakableControlFlowBuilder::EmitJump(BytecodeLabels* sites) {
22 builder()->Jump(sites->New());
23 }
24
EmitJumpIfTrue(BytecodeLabels * sites)25 void BreakableControlFlowBuilder::EmitJumpIfTrue(BytecodeLabels* sites) {
26 builder()->JumpIfTrue(sites->New());
27 }
28
EmitJumpIfFalse(BytecodeLabels * sites)29 void BreakableControlFlowBuilder::EmitJumpIfFalse(BytecodeLabels* sites) {
30 builder()->JumpIfFalse(sites->New());
31 }
32
EmitJumpIfUndefined(BytecodeLabels * sites)33 void BreakableControlFlowBuilder::EmitJumpIfUndefined(BytecodeLabels* sites) {
34 builder()->JumpIfUndefined(sites->New());
35 }
36
EmitJumpIfNull(BytecodeLabels * sites)37 void BreakableControlFlowBuilder::EmitJumpIfNull(BytecodeLabels* sites) {
38 builder()->JumpIfNull(sites->New());
39 }
40
41
EndBlock()42 void BlockBuilder::EndBlock() {
43 builder()->Bind(&block_end_);
44 BindBreakTarget();
45 }
46
~LoopBuilder()47 LoopBuilder::~LoopBuilder() {
48 DCHECK(continue_labels_.empty() || continue_labels_.is_bound());
49 DCHECK(header_labels_.empty() || header_labels_.is_bound());
50 }
51
LoopHeader(ZoneVector<BytecodeLabel> * additional_labels)52 void LoopBuilder::LoopHeader(ZoneVector<BytecodeLabel>* additional_labels) {
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 if (additional_labels != nullptr) {
60 for (auto& label : *additional_labels) {
61 builder()->Bind(&label);
62 }
63 }
64 }
65
JumpToHeader(int loop_depth)66 void LoopBuilder::JumpToHeader(int loop_depth) {
67 // Pass the proper loop nesting level to the backwards branch, to trigger
68 // on-stack replacement when armed for the given loop nesting depth.
69 int level = Min(loop_depth, AbstractCode::kMaxLoopNestingMarker - 1);
70 // Loop must have closed form, i.e. all loop elements are within the loop,
71 // the loop header precedes the body and next elements in the loop.
72 DCHECK(loop_header_.is_bound());
73 builder()->JumpLoop(&loop_header_, level);
74 }
75
EndLoop()76 void LoopBuilder::EndLoop() {
77 BindBreakTarget();
78 header_labels_.BindToLabel(builder(), loop_header_);
79 }
80
BindContinueTarget()81 void LoopBuilder::BindContinueTarget() { continue_labels_.Bind(builder()); }
82
~SwitchBuilder()83 SwitchBuilder::~SwitchBuilder() {
84 #ifdef DEBUG
85 for (auto site : case_sites_) {
86 DCHECK(site.is_bound());
87 }
88 #endif
89 }
90
91
SetCaseTarget(int index)92 void SwitchBuilder::SetCaseTarget(int index) {
93 BytecodeLabel& site = case_sites_.at(index);
94 builder()->Bind(&site);
95 }
96
97
BeginTry(Register context)98 void TryCatchBuilder::BeginTry(Register context) {
99 builder()->MarkTryBegin(handler_id_, context);
100 }
101
102
EndTry()103 void TryCatchBuilder::EndTry() {
104 builder()->MarkTryEnd(handler_id_);
105 builder()->Jump(&exit_);
106 builder()->Bind(&handler_);
107 builder()->MarkHandler(handler_id_, catch_prediction_);
108 }
109
110
EndCatch()111 void TryCatchBuilder::EndCatch() { builder()->Bind(&exit_); }
112
113
BeginTry(Register context)114 void TryFinallyBuilder::BeginTry(Register context) {
115 builder()->MarkTryBegin(handler_id_, context);
116 }
117
118
LeaveTry()119 void TryFinallyBuilder::LeaveTry() {
120 builder()->Jump(finalization_sites_.New());
121 }
122
123
EndTry()124 void TryFinallyBuilder::EndTry() {
125 builder()->MarkTryEnd(handler_id_);
126 }
127
128
BeginHandler()129 void TryFinallyBuilder::BeginHandler() {
130 builder()->Bind(&handler_);
131 builder()->MarkHandler(handler_id_, catch_prediction_);
132 }
133
BeginFinally()134 void TryFinallyBuilder::BeginFinally() { finalization_sites_.Bind(builder()); }
135
EndFinally()136 void TryFinallyBuilder::EndFinally() {
137 // Nothing to be done here.
138 }
139
140 } // namespace interpreter
141 } // namespace internal
142 } // namespace v8
143