1// Copyright 2013 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/compiler/control-builders.h"
6
7namespace v8 {
8namespace internal {
9namespace compiler {
10
11
12void IfBuilder::If(Node* condition, BranchHint hint) {
13  builder_->NewBranch(condition, hint);
14  else_environment_ = environment()->CopyForConditional();
15}
16
17
18void IfBuilder::Then() { builder_->NewIfTrue(); }
19
20
21void IfBuilder::Else() {
22  builder_->NewMerge();
23  then_environment_ = environment();
24  set_environment(else_environment_);
25  builder_->NewIfFalse();
26}
27
28
29void IfBuilder::End() {
30  then_environment_->Merge(environment());
31  set_environment(then_environment_);
32}
33
34
35void LoopBuilder::BeginLoop(BitVector* assigned, bool is_osr) {
36  loop_environment_ = environment()->CopyForLoop(assigned, is_osr);
37  continue_environment_ = environment()->CopyAsUnreachable();
38  break_environment_ = environment()->CopyAsUnreachable();
39  assigned_ = assigned;
40}
41
42
43void LoopBuilder::Continue() {
44  continue_environment_->Merge(environment());
45  environment()->MarkAsUnreachable();
46}
47
48
49void LoopBuilder::Break() {
50  break_environment_->Merge(environment());
51  environment()->MarkAsUnreachable();
52}
53
54
55void LoopBuilder::EndBody() {
56  continue_environment_->Merge(environment());
57  set_environment(continue_environment_);
58}
59
60
61void LoopBuilder::EndLoop() {
62  loop_environment_->Merge(environment());
63  set_environment(break_environment_);
64  ExitLoop();
65}
66
67
68void LoopBuilder::BreakUnless(Node* condition) {
69  IfBuilder control_if(builder_);
70  control_if.If(condition);
71  control_if.Then();
72  control_if.Else();
73  Break();
74  control_if.End();
75}
76
77
78void LoopBuilder::BreakWhen(Node* condition) {
79  IfBuilder control_if(builder_);
80  control_if.If(condition);
81  control_if.Then();
82  Break();
83  control_if.Else();
84  control_if.End();
85}
86
87void LoopBuilder::ExitLoop(Node** extra_value_to_rename) {
88  if (extra_value_to_rename) {
89    environment()->Push(*extra_value_to_rename);
90  }
91  environment()->PrepareForLoopExit(loop_environment_->GetControlDependency(),
92                                    assigned_);
93  if (extra_value_to_rename) {
94    *extra_value_to_rename = environment()->Pop();
95  }
96}
97
98void SwitchBuilder::BeginSwitch() {
99  body_environment_ = environment()->CopyAsUnreachable();
100  label_environment_ = environment()->CopyAsUnreachable();
101  break_environment_ = environment()->CopyAsUnreachable();
102}
103
104
105void SwitchBuilder::BeginLabel(int index, Node* condition) {
106  builder_->NewBranch(condition);
107  label_environment_ = environment()->CopyForConditional();
108  builder_->NewIfTrue();
109  body_environments_[index] = environment();
110}
111
112
113void SwitchBuilder::EndLabel() {
114  set_environment(label_environment_);
115  builder_->NewIfFalse();
116}
117
118
119void SwitchBuilder::DefaultAt(int index) {
120  label_environment_ = environment()->CopyAsUnreachable();
121  body_environments_[index] = environment();
122}
123
124
125void SwitchBuilder::BeginCase(int index) {
126  set_environment(body_environments_[index]);
127  environment()->Merge(body_environment_);
128}
129
130
131void SwitchBuilder::Break() {
132  break_environment_->Merge(environment());
133  environment()->MarkAsUnreachable();
134}
135
136
137void SwitchBuilder::EndCase() { body_environment_ = environment(); }
138
139
140void SwitchBuilder::EndSwitch() {
141  break_environment_->Merge(label_environment_);
142  break_environment_->Merge(environment());
143  set_environment(break_environment_);
144}
145
146
147void BlockBuilder::BeginBlock() {
148  break_environment_ = environment()->CopyAsUnreachable();
149}
150
151
152void BlockBuilder::Break() {
153  break_environment_->Merge(environment());
154  environment()->MarkAsUnreachable();
155}
156
157
158void BlockBuilder::BreakWhen(Node* condition, BranchHint hint) {
159  IfBuilder control_if(builder_);
160  control_if.If(condition, hint);
161  control_if.Then();
162  Break();
163  control_if.Else();
164  control_if.End();
165}
166
167
168void BlockBuilder::BreakUnless(Node* condition, BranchHint hint) {
169  IfBuilder control_if(builder_);
170  control_if.If(condition, hint);
171  control_if.Then();
172  control_if.Else();
173  Break();
174  control_if.End();
175}
176
177
178void BlockBuilder::EndBlock() {
179  break_environment_->Merge(environment());
180  set_environment(break_environment_);
181}
182
183
184void TryCatchBuilder::BeginTry() {
185  exit_environment_ = environment()->CopyAsUnreachable();
186  catch_environment_ = environment()->CopyAsUnreachable();
187  catch_environment_->Push(the_hole());
188}
189
190
191void TryCatchBuilder::Throw(Node* exception) {
192  environment()->Push(exception);
193  catch_environment_->Merge(environment());
194  environment()->Pop();
195  environment()->MarkAsUnreachable();
196}
197
198
199void TryCatchBuilder::EndTry() {
200  exit_environment_->Merge(environment());
201  exception_node_ = catch_environment_->Pop();
202  set_environment(catch_environment_);
203}
204
205
206void TryCatchBuilder::EndCatch() {
207  exit_environment_->Merge(environment());
208  set_environment(exit_environment_);
209}
210
211
212void TryFinallyBuilder::BeginTry() {
213  finally_environment_ = environment()->CopyAsUnreachable();
214  finally_environment_->Push(the_hole());
215  finally_environment_->Push(the_hole());
216}
217
218
219void TryFinallyBuilder::LeaveTry(Node* token, Node* value) {
220  environment()->Push(value);
221  environment()->Push(token);
222  finally_environment_->Merge(environment());
223  environment()->Drop(2);
224}
225
226
227void TryFinallyBuilder::EndTry(Node* fallthrough_token, Node* value) {
228  environment()->Push(value);
229  environment()->Push(fallthrough_token);
230  finally_environment_->Merge(environment());
231  environment()->Drop(2);
232  token_node_ = finally_environment_->Pop();
233  value_node_ = finally_environment_->Pop();
234  set_environment(finally_environment_);
235}
236
237
238void TryFinallyBuilder::EndFinally() {
239  // Nothing to be done here.
240}
241
242}  // namespace compiler
243}  // namespace internal
244}  // namespace v8
245