// Copyright 2013 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/compiler/control-builders.h"
namespace v8 {
namespace internal {
namespace compiler {
void IfBuilder::If(Node* condition, BranchHint hint) {
builder_->NewBranch(condition, hint);
else_environment_ = environment()->CopyForConditional();
}
void IfBuilder::Then() { builder_->NewIfTrue(); }
void IfBuilder::Else() {
builder_->NewMerge();
then_environment_ = environment();
set_environment(else_environment_);
builder_->NewIfFalse();
}
void IfBuilder::End() {
then_environment_->Merge(environment());
set_environment(then_environment_);
}
void LoopBuilder::BeginLoop(BitVector* assigned, bool is_osr) {
loop_environment_ = environment()->CopyForLoop(assigned, is_osr);
continue_environment_ = environment()->CopyAsUnreachable();
break_environment_ = environment()->CopyAsUnreachable();
assigned_ = assigned;
}
void LoopBuilder::Continue() {
continue_environment_->Merge(environment());
environment()->MarkAsUnreachable();
}
void LoopBuilder::Break() {
break_environment_->Merge(environment());
environment()->MarkAsUnreachable();
}
void LoopBuilder::EndBody() {
continue_environment_->Merge(environment());
set_environment(continue_environment_);
}
void LoopBuilder::EndLoop() {
loop_environment_->Merge(environment());
set_environment(break_environment_);
ExitLoop();
}
void LoopBuilder::BreakUnless(Node* condition) {
IfBuilder control_if(builder_);
control_if.If(condition);
control_if.Then();
control_if.Else();
Break();
control_if.End();
}
void LoopBuilder::BreakWhen(Node* condition) {
IfBuilder control_if(builder_);
control_if.If(condition);
control_if.Then();
Break();
control_if.Else();
control_if.End();
}
void LoopBuilder::ExitLoop(Node** extra_value_to_rename) {
if (extra_value_to_rename) {
environment()->Push(*extra_value_to_rename);
}
environment()->PrepareForLoopExit(loop_environment_->GetControlDependency(),
assigned_);
if (extra_value_to_rename) {
*extra_value_to_rename = environment()->Pop();
}
}
void SwitchBuilder::BeginSwitch() {
body_environment_ = environment()->CopyAsUnreachable();
label_environment_ = environment()->CopyAsUnreachable();
break_environment_ = environment()->CopyAsUnreachable();
}
void SwitchBuilder::BeginLabel(int index, Node* condition) {
builder_->NewBranch(condition);
label_environment_ = environment()->CopyForConditional();
builder_->NewIfTrue();
body_environments_[index] = environment();
}
void SwitchBuilder::EndLabel() {
set_environment(label_environment_);
builder_->NewIfFalse();
}
void SwitchBuilder::DefaultAt(int index) {
label_environment_ = environment()->CopyAsUnreachable();
body_environments_[index] = environment();
}
void SwitchBuilder::BeginCase(int index) {
set_environment(body_environments_[index]);
environment()->Merge(body_environment_);
}
void SwitchBuilder::Break() {
break_environment_->Merge(environment());
environment()->MarkAsUnreachable();
}
void SwitchBuilder::EndCase() { body_environment_ = environment(); }
void SwitchBuilder::EndSwitch() {
break_environment_->Merge(label_environment_);
break_environment_->Merge(environment());
set_environment(break_environment_);
}
void BlockBuilder::BeginBlock() {
break_environment_ = environment()->CopyAsUnreachable();
}
void BlockBuilder::Break() {
break_environment_->Merge(environment());
environment()->MarkAsUnreachable();
}
void BlockBuilder::BreakWhen(Node* condition, BranchHint hint) {
IfBuilder control_if(builder_);
control_if.If(condition, hint);
control_if.Then();
Break();
control_if.Else();
control_if.End();
}
void BlockBuilder::BreakUnless(Node* condition, BranchHint hint) {
IfBuilder control_if(builder_);
control_if.If(condition, hint);
control_if.Then();
control_if.Else();
Break();
control_if.End();
}
void BlockBuilder::EndBlock() {
break_environment_->Merge(environment());
set_environment(break_environment_);
}
void TryCatchBuilder::BeginTry() {
exit_environment_ = environment()->CopyAsUnreachable();
catch_environment_ = environment()->CopyAsUnreachable();
catch_environment_->Push(the_hole());
}
void TryCatchBuilder::Throw(Node* exception) {
environment()->Push(exception);
catch_environment_->Merge(environment());
environment()->Pop();
environment()->MarkAsUnreachable();
}
void TryCatchBuilder::EndTry() {
exit_environment_->Merge(environment());
exception_node_ = catch_environment_->Pop();
set_environment(catch_environment_);
}
void TryCatchBuilder::EndCatch() {
exit_environment_->Merge(environment());
set_environment(exit_environment_);
}
void TryFinallyBuilder::BeginTry() {
finally_environment_ = environment()->CopyAsUnreachable();
finally_environment_->Push(the_hole());
finally_environment_->Push(the_hole());
}
void TryFinallyBuilder::LeaveTry(Node* token, Node* value) {
environment()->Push(value);
environment()->Push(token);
finally_environment_->Merge(environment());
environment()->Drop(2);
}
void TryFinallyBuilder::EndTry(Node* fallthrough_token, Node* value) {
environment()->Push(value);
environment()->Push(fallthrough_token);
finally_environment_->Merge(environment());
environment()->Drop(2);
token_node_ = finally_environment_->Pop();
value_node_ = finally_environment_->Pop();
set_environment(finally_environment_);
}
void TryFinallyBuilder::EndFinally() {
// Nothing to be done here.
}
} // namespace compiler
} // namespace internal
} // namespace v8