blob: 6510aa443aaa2a605989865596cc8227406d3a48 [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// 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
7namespace v8 {
8namespace internal {
9namespace interpreter {
10
11
12BreakableControlFlowBuilder::~BreakableControlFlowBuilder() {
13 DCHECK(break_sites_.empty());
14}
15
16
17void BreakableControlFlowBuilder::SetBreakTarget(const BytecodeLabel& target) {
18 BindLabels(target, &break_sites_);
19}
20
21
22void BreakableControlFlowBuilder::EmitJump(ZoneVector<BytecodeLabel>* sites) {
23 sites->push_back(BytecodeLabel());
24 builder()->Jump(&sites->back());
25}
26
27
28void BreakableControlFlowBuilder::EmitJumpIfTrue(
29 ZoneVector<BytecodeLabel>* sites) {
30 sites->push_back(BytecodeLabel());
31 builder()->JumpIfTrue(&sites->back());
32}
33
34
35void BreakableControlFlowBuilder::EmitJumpIfFalse(
36 ZoneVector<BytecodeLabel>* sites) {
37 sites->push_back(BytecodeLabel());
38 builder()->JumpIfFalse(&sites->back());
39}
40
41
42void BreakableControlFlowBuilder::EmitJumpIfUndefined(
43 ZoneVector<BytecodeLabel>* sites) {
44 sites->push_back(BytecodeLabel());
45 builder()->JumpIfUndefined(&sites->back());
46}
47
48
49void BreakableControlFlowBuilder::EmitJumpIfNull(
50 ZoneVector<BytecodeLabel>* sites) {
51 sites->push_back(BytecodeLabel());
52 builder()->JumpIfNull(&sites->back());
53}
54
55
56void BreakableControlFlowBuilder::EmitJump(ZoneVector<BytecodeLabel>* sites,
57 int index) {
58 builder()->Jump(&sites->at(index));
59}
60
61
62void BreakableControlFlowBuilder::EmitJumpIfTrue(
63 ZoneVector<BytecodeLabel>* sites, int index) {
64 builder()->JumpIfTrue(&sites->at(index));
65}
66
67
68void BreakableControlFlowBuilder::EmitJumpIfFalse(
69 ZoneVector<BytecodeLabel>* sites, int index) {
70 builder()->JumpIfFalse(&sites->at(index));
71}
72
73
74void BreakableControlFlowBuilder::BindLabels(const BytecodeLabel& target,
75 ZoneVector<BytecodeLabel>* sites) {
76 for (size_t i = 0; i < sites->size(); i++) {
77 BytecodeLabel& site = sites->at(i);
78 builder()->Bind(target, &site);
79 }
80 sites->clear();
81}
82
83
84void BlockBuilder::EndBlock() {
85 builder()->Bind(&block_end_);
86 SetBreakTarget(block_end_);
87}
88
89
90LoopBuilder::~LoopBuilder() { DCHECK(continue_sites_.empty()); }
91
92
93void LoopBuilder::LoopHeader() {
94 // Jumps from before the loop header into the loop violate ordering
95 // requirements of bytecode basic blocks. The only entry into a loop
96 // must be the loop header. Surely breaks is okay? Not if nested
97 // and misplaced between the headers.
98 DCHECK(break_sites_.empty() && continue_sites_.empty());
99 builder()->Bind(&loop_header_);
100}
101
102
103void LoopBuilder::EndLoop() {
104 // Loop must have closed form, i.e. all loop elements are within the loop,
105 // the loop header precedes the body and next elements in the loop.
106 DCHECK(loop_header_.is_bound());
107 builder()->Bind(&loop_end_);
108 SetBreakTarget(loop_end_);
109 if (next_.is_bound()) {
110 DCHECK(!condition_.is_bound() || next_.offset() >= condition_.offset());
111 SetContinueTarget(next_);
112 } else {
113 DCHECK(condition_.is_bound());
114 DCHECK_GE(condition_.offset(), loop_header_.offset());
115 DCHECK_LE(condition_.offset(), loop_end_.offset());
116 SetContinueTarget(condition_);
117 }
118}
119
120
121void LoopBuilder::SetContinueTarget(const BytecodeLabel& target) {
122 BindLabels(target, &continue_sites_);
123}
124
125
126SwitchBuilder::~SwitchBuilder() {
127#ifdef DEBUG
128 for (auto site : case_sites_) {
129 DCHECK(site.is_bound());
130 }
131#endif
132}
133
134
135void SwitchBuilder::SetCaseTarget(int index) {
136 BytecodeLabel& site = case_sites_.at(index);
137 builder()->Bind(&site);
138}
139
Ben Murdoch097c5b22016-05-18 11:27:45 +0100140
141void TryCatchBuilder::BeginTry(Register context) {
142 builder()->MarkTryBegin(handler_id_, context);
143}
144
145
146void TryCatchBuilder::EndTry() {
147 builder()->MarkTryEnd(handler_id_);
148 builder()->Jump(&exit_);
149 builder()->Bind(&handler_);
150 builder()->MarkHandler(handler_id_, true);
151}
152
153
154void TryCatchBuilder::EndCatch() { builder()->Bind(&exit_); }
155
156
157void TryFinallyBuilder::BeginTry(Register context) {
158 builder()->MarkTryBegin(handler_id_, context);
159}
160
161
162void TryFinallyBuilder::LeaveTry() {
163 finalization_sites_.push_back(BytecodeLabel());
164 builder()->Jump(&finalization_sites_.back());
165}
166
167
168void TryFinallyBuilder::EndTry() {
169 builder()->MarkTryEnd(handler_id_);
170}
171
172
173void TryFinallyBuilder::BeginHandler() {
174 builder()->Bind(&handler_);
175 builder()->MarkHandler(handler_id_, will_catch_);
176}
177
178
179void TryFinallyBuilder::BeginFinally() {
180 for (size_t i = 0; i < finalization_sites_.size(); i++) {
181 BytecodeLabel& site = finalization_sites_.at(i);
182 builder()->Bind(&site);
183 }
184}
185
186
187void TryFinallyBuilder::EndFinally() {
188 // Nothing to be done here.
189}
190
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000191} // namespace interpreter
192} // namespace internal
193} // namespace v8