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 
7 namespace v8 {
8 namespace internal {
9 namespace compiler {
10 
11 
If(Node * condition,BranchHint hint)12 void IfBuilder::If(Node* condition, BranchHint hint) {
13   builder_->NewBranch(condition, hint);
14   else_environment_ = environment()->CopyForConditional();
15 }
16 
17 
Then()18 void IfBuilder::Then() { builder_->NewIfTrue(); }
19 
20 
Else()21 void IfBuilder::Else() {
22   builder_->NewMerge();
23   then_environment_ = environment();
24   set_environment(else_environment_);
25   builder_->NewIfFalse();
26 }
27 
28 
End()29 void IfBuilder::End() {
30   then_environment_->Merge(environment());
31   set_environment(then_environment_);
32 }
33 
34 
BeginLoop(BitVector * assigned,bool is_osr)35 void 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 
Continue()43 void LoopBuilder::Continue() {
44   continue_environment_->Merge(environment());
45   environment()->MarkAsUnreachable();
46 }
47 
48 
Break()49 void LoopBuilder::Break() {
50   break_environment_->Merge(environment());
51   environment()->MarkAsUnreachable();
52 }
53 
54 
EndBody()55 void LoopBuilder::EndBody() {
56   continue_environment_->Merge(environment());
57   set_environment(continue_environment_);
58 }
59 
60 
EndLoop()61 void LoopBuilder::EndLoop() {
62   loop_environment_->Merge(environment());
63   set_environment(break_environment_);
64   ExitLoop();
65 }
66 
67 
BreakUnless(Node * condition)68 void 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 
BreakWhen(Node * condition)78 void 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 
ExitLoop(Node ** extra_value_to_rename)87 void 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 
BeginSwitch()98 void SwitchBuilder::BeginSwitch() {
99   body_environment_ = environment()->CopyAsUnreachable();
100   label_environment_ = environment()->CopyAsUnreachable();
101   break_environment_ = environment()->CopyAsUnreachable();
102 }
103 
104 
BeginLabel(int index,Node * condition)105 void 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 
EndLabel()113 void SwitchBuilder::EndLabel() {
114   set_environment(label_environment_);
115   builder_->NewIfFalse();
116 }
117 
118 
DefaultAt(int index)119 void SwitchBuilder::DefaultAt(int index) {
120   label_environment_ = environment()->CopyAsUnreachable();
121   body_environments_[index] = environment();
122 }
123 
124 
BeginCase(int index)125 void SwitchBuilder::BeginCase(int index) {
126   set_environment(body_environments_[index]);
127   environment()->Merge(body_environment_);
128 }
129 
130 
Break()131 void SwitchBuilder::Break() {
132   break_environment_->Merge(environment());
133   environment()->MarkAsUnreachable();
134 }
135 
136 
EndCase()137 void SwitchBuilder::EndCase() { body_environment_ = environment(); }
138 
139 
EndSwitch()140 void SwitchBuilder::EndSwitch() {
141   break_environment_->Merge(label_environment_);
142   break_environment_->Merge(environment());
143   set_environment(break_environment_);
144 }
145 
146 
BeginBlock()147 void BlockBuilder::BeginBlock() {
148   break_environment_ = environment()->CopyAsUnreachable();
149 }
150 
151 
Break()152 void BlockBuilder::Break() {
153   break_environment_->Merge(environment());
154   environment()->MarkAsUnreachable();
155 }
156 
157 
BreakWhen(Node * condition,BranchHint hint)158 void 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 
BreakUnless(Node * condition,BranchHint hint)168 void 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 
EndBlock()178 void BlockBuilder::EndBlock() {
179   break_environment_->Merge(environment());
180   set_environment(break_environment_);
181 }
182 
183 
BeginTry()184 void TryCatchBuilder::BeginTry() {
185   exit_environment_ = environment()->CopyAsUnreachable();
186   catch_environment_ = environment()->CopyAsUnreachable();
187   catch_environment_->Push(the_hole());
188 }
189 
190 
Throw(Node * exception)191 void TryCatchBuilder::Throw(Node* exception) {
192   environment()->Push(exception);
193   catch_environment_->Merge(environment());
194   environment()->Pop();
195   environment()->MarkAsUnreachable();
196 }
197 
198 
EndTry()199 void TryCatchBuilder::EndTry() {
200   exit_environment_->Merge(environment());
201   exception_node_ = catch_environment_->Pop();
202   set_environment(catch_environment_);
203 }
204 
205 
EndCatch()206 void TryCatchBuilder::EndCatch() {
207   exit_environment_->Merge(environment());
208   set_environment(exit_environment_);
209 }
210 
211 
BeginTry()212 void TryFinallyBuilder::BeginTry() {
213   finally_environment_ = environment()->CopyAsUnreachable();
214   finally_environment_->Push(the_hole());
215   finally_environment_->Push(the_hole());
216 }
217 
218 
LeaveTry(Node * token,Node * value)219 void 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 
EndTry(Node * fallthrough_token,Node * value)227 void 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 
EndFinally()238 void TryFinallyBuilder::EndFinally() {
239   // Nothing to be done here.
240 }
241 
242 }  // namespace compiler
243 }  // namespace internal
244 }  // namespace v8
245