| Index: src/hydrogen.cc
|
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc
|
| index 95090d5160ca096a9391e6d39d10548a37ea193a..f127680804f5f5748365d0662a21f7873c097f03 100644
|
| --- a/src/hydrogen.cc
|
| +++ b/src/hydrogen.cc
|
| @@ -828,7 +828,6 @@ void HGraphBuilder::IfBuilder::Else() {
|
| ASSERT(!captured_);
|
| ASSERT(!finished_);
|
| last_true_block_ = builder_->current_block();
|
| - ASSERT(first_true_block_ == NULL || !last_true_block_->IsFinished());
|
| builder_->set_current_block(first_false_block_);
|
| did_else_ = true;
|
| }
|
| @@ -864,9 +863,11 @@ void HGraphBuilder::IfBuilder::End() {
|
| if (!did_else_) {
|
| last_true_block_ = builder_->current_block();
|
| }
|
| - if (first_true_block_ == NULL) {
|
| + if (last_true_block_ == NULL || last_true_block_->IsFinished()) {
|
| + ASSERT(did_else_);
|
| // Return on true. Nothing to do, just continue the false block.
|
| - } else if (first_false_block_ == NULL) {
|
| + } else if (first_false_block_ == NULL ||
|
| + (did_else_ && builder_->current_block()->IsFinished())) {
|
| // Deopt on false. Nothing to do except switching to the true block.
|
| builder_->set_current_block(last_true_block_);
|
| } else {
|
| @@ -906,6 +907,24 @@ HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder,
|
| header_block_ = builder->CreateLoopHeaderBlock();
|
| body_block_ = NULL;
|
| exit_block_ = NULL;
|
| + exit_trampoline_block_ = NULL;
|
| + increment_amount_ = builder_->graph()->GetConstant1();
|
| +}
|
| +
|
| +
|
| +HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder,
|
| + HValue* context,
|
| + LoopBuilder::Direction direction,
|
| + HValue* increment_amount)
|
| + : builder_(builder),
|
| + context_(context),
|
| + direction_(direction),
|
| + finished_(false) {
|
| + header_block_ = builder->CreateLoopHeaderBlock();
|
| + body_block_ = NULL;
|
| + exit_block_ = NULL;
|
| + exit_trampoline_block_ = NULL;
|
| + increment_amount_ = increment_amount;
|
| }
|
|
|
|
|
| @@ -921,12 +940,14 @@ HValue* HGraphBuilder::LoopBuilder::BeginBody(
|
|
|
| HEnvironment* body_env = env->Copy();
|
| HEnvironment* exit_env = env->Copy();
|
| - body_block_ = builder_->CreateBasicBlock(body_env);
|
| - exit_block_ = builder_->CreateBasicBlock(exit_env);
|
| // Remove the phi from the expression stack
|
| body_env->Pop();
|
| + exit_env->Pop();
|
| + body_block_ = builder_->CreateBasicBlock(body_env);
|
| + exit_block_ = builder_->CreateBasicBlock(exit_env);
|
|
|
| builder_->set_current_block(header_block_);
|
| + env->Pop();
|
| HCompareNumericAndBranch* compare =
|
| new(zone()) HCompareNumericAndBranch(phi_, terminating, token);
|
| compare->SetSuccessorAt(0, body_block_);
|
| @@ -950,15 +971,26 @@ HValue* HGraphBuilder::LoopBuilder::BeginBody(
|
| }
|
|
|
|
|
| +void HGraphBuilder::LoopBuilder::Break() {
|
| + if (exit_trampoline_block_ == NULL) {
|
| + // Its the first time we saw a break.
|
| + HEnvironment* env = exit_block_->last_environment()->Copy();
|
| + exit_trampoline_block_ = builder_->CreateBasicBlock(env);
|
| + exit_block_->GotoNoSimulate(exit_trampoline_block_);
|
| + }
|
| +
|
| + builder_->current_block()->GotoNoSimulate(exit_trampoline_block_);
|
| +}
|
| +
|
| +
|
| void HGraphBuilder::LoopBuilder::EndBody() {
|
| ASSERT(!finished_);
|
|
|
| if (direction_ == kPostIncrement || direction_ == kPostDecrement) {
|
| - HValue* one = builder_->graph()->GetConstant1();
|
| if (direction_ == kPostIncrement) {
|
| - increment_ = HAdd::New(zone(), context_, phi_, one);
|
| + increment_ = HAdd::New(zone(), context_, phi_, increment_amount_);
|
| } else {
|
| - increment_ = HSub::New(zone(), context_, phi_, one);
|
| + increment_ = HSub::New(zone(), context_, phi_, increment_amount_);
|
| }
|
| increment_->ClearFlag(HValue::kCanOverflow);
|
| builder_->AddInstruction(increment_);
|
| @@ -970,9 +1002,11 @@ void HGraphBuilder::LoopBuilder::EndBody() {
|
| last_block->GotoNoSimulate(header_block_);
|
| header_block_->loop_information()->RegisterBackEdge(last_block);
|
|
|
| - builder_->set_current_block(exit_block_);
|
| - // Pop the phi from the expression stack
|
| - builder_->environment()->Pop();
|
| + if (exit_trampoline_block_ != NULL) {
|
| + builder_->set_current_block(exit_trampoline_block_);
|
| + } else {
|
| + builder_->set_current_block(exit_block_);
|
| + }
|
| finished_ = true;
|
| }
|
|
|
|
|