| Index: src/hydrogen.cc
|
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc
|
| index 8d3a0ac813a90a6014ac6185473406c2ca5e8927..7c5c5e9b4eeac6d8a33a318416d2a29bd9bc41cb 100644
|
| --- a/src/hydrogen.cc
|
| +++ b/src/hydrogen.cc
|
| @@ -4740,7 +4740,7 @@ void HOptimizedGraphBuilder::VisitBlock(Block* stmt) {
|
| if (stmt->scope() != NULL) {
|
| return Bailout("ScopedBlock");
|
| }
|
| - BreakAndContinueInfo break_info(stmt);
|
| + BreakAndContinueInfo break_info(stmt, 0);
|
| { BreakAndContinueScope push(&break_info, this);
|
| CHECK_BAILOUT(VisitStatements(stmt->statements()));
|
| }
|
| @@ -4808,20 +4808,41 @@ void HOptimizedGraphBuilder::VisitIfStatement(IfStatement* stmt) {
|
| }
|
|
|
|
|
| -HBasicBlock* HOptimizedGraphBuilder::BreakAndContinueScope::Get(
|
| - BreakableStatement* stmt,
|
| - BreakType type,
|
| - int* drop_extra) {
|
| - *drop_extra = 0;
|
| +void HOptimizedGraphBuilder::BreakAndContinueScope::UnwindReturn() {
|
| BreakAndContinueScope* current = this;
|
| - while (current != NULL && current->info()->target() != stmt) {
|
| - *drop_extra += current->info()->drop_extra();
|
| + while (current != NULL) {
|
| + TryCatchStatement* try_catch =
|
| + current->info()->statement()->AsTryCatchStatement();
|
| + if (try_catch != NULL) {
|
| + HLeaveTry* leave = new(owner()->zone()) HLeaveTry;
|
| + owner()->AddInstruction(leave);
|
| + owner()->environment()->RemoveExceptionHandler();
|
| + owner()->AddSimulate(try_catch->TryExitId());
|
| + }
|
| + current = current->next();
|
| + }
|
| +}
|
| +
|
| +
|
| +void HOptimizedGraphBuilder::BreakAndContinueScope::Unwind(BreakableStatement* target,
|
| + BreakType type) {
|
| + BreakAndContinueScope* current = this;
|
| + while (current != NULL && current->info()->statement() != target) {
|
| + TryCatchStatement* try_catch =
|
| + current->info()->statement()->AsTryCatchStatement();
|
| + if (try_catch != NULL) {
|
| + HLeaveTry* leave = new(owner()->zone()) HLeaveTry;
|
| + owner()->AddInstruction(leave);
|
| + owner()->environment()->RemoveExceptionHandler();
|
| + owner()->AddSimulate(try_catch->TryExitId());
|
| + }
|
| + owner()->Drop(current->info()->drop_extra());
|
| current = current->next();
|
| }
|
| ASSERT(current != NULL); // Always found (unless stack is malformed).
|
|
|
| if (type == BREAK) {
|
| - *drop_extra += current->info()->drop_extra();
|
| + owner()->Drop(current->info()->drop_extra());
|
| }
|
|
|
| HBasicBlock* block = NULL;
|
| @@ -4842,8 +4863,8 @@ HBasicBlock* HOptimizedGraphBuilder::BreakAndContinueScope::Get(
|
| }
|
| break;
|
| }
|
| -
|
| - return block;
|
| + owner()->current_block()->Goto(block);
|
| + owner()->set_current_block(NULL);
|
| }
|
|
|
|
|
| @@ -4852,12 +4873,7 @@ void HOptimizedGraphBuilder::VisitContinueStatement(
|
| ASSERT(!HasStackOverflow());
|
| ASSERT(current_block() != NULL);
|
| ASSERT(current_block()->HasPredecessor());
|
| - int drop_extra = 0;
|
| - HBasicBlock* continue_block = break_scope()->Get(
|
| - stmt->target(), BreakAndContinueScope::CONTINUE, &drop_extra);
|
| - Drop(drop_extra);
|
| - current_block()->Goto(continue_block);
|
| - set_current_block(NULL);
|
| + break_scope()->Unwind(stmt->target(), BreakAndContinueScope::CONTINUE);
|
| }
|
|
|
|
|
| @@ -4865,12 +4881,7 @@ void HOptimizedGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
|
| ASSERT(!HasStackOverflow());
|
| ASSERT(current_block() != NULL);
|
| ASSERT(current_block()->HasPredecessor());
|
| - int drop_extra = 0;
|
| - HBasicBlock* break_block = break_scope()->Get(
|
| - stmt->target(), BreakAndContinueScope::BREAK, &drop_extra);
|
| - Drop(drop_extra);
|
| - current_block()->Goto(break_block);
|
| - set_current_block(NULL);
|
| + break_scope()->Unwind(stmt->target(), BreakAndContinueScope::BREAK);
|
| }
|
|
|
|
|
| @@ -4884,6 +4895,7 @@ void HOptimizedGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
|
| // Not an inlined return, so an actual one.
|
| CHECK_ALIVE(VisitForValue(stmt->expression()));
|
| HValue* result = environment()->Pop();
|
| + break_scope()->UnwindReturn();
|
| AddReturn(result);
|
| } else if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) {
|
| // Return from an inlined construct call. In a test context the return value
|
| @@ -5053,7 +5065,7 @@ void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
|
| HBasicBlock* curr_test_block = first_test_block;
|
| HBasicBlock* fall_through_block = NULL;
|
|
|
| - BreakAndContinueInfo break_info(stmt);
|
| + BreakAndContinueInfo break_info(stmt, 0);
|
| { BreakAndContinueScope push(&break_info, this);
|
| for (int i = 0; i < clause_count; ++i) {
|
| CaseClause* clause = clauses->at(i);
|
| @@ -5198,7 +5210,7 @@ void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
|
| set_current_block(loop_entry);
|
| if (osr_entry) graph()->set_osr_loop_entry(loop_entry);
|
|
|
| - BreakAndContinueInfo break_info(stmt);
|
| + BreakAndContinueInfo break_info(stmt, 0);
|
| CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info));
|
| HBasicBlock* body_exit =
|
| JoinContinue(stmt, current_block(), break_info.continue_block());
|
| @@ -5259,7 +5271,7 @@ void HOptimizedGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
|
| }
|
| }
|
|
|
| - BreakAndContinueInfo break_info(stmt);
|
| + BreakAndContinueInfo break_info(stmt, 0);
|
| if (current_block() != NULL) {
|
| CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info));
|
| }
|
| @@ -5304,7 +5316,7 @@ void HOptimizedGraphBuilder::VisitForStatement(ForStatement* stmt) {
|
| }
|
| }
|
|
|
| - BreakAndContinueInfo break_info(stmt);
|
| + BreakAndContinueInfo break_info(stmt, 0);
|
| if (current_block() != NULL) {
|
| CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info));
|
| }
|
| @@ -5459,7 +5471,24 @@ void HOptimizedGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
|
| ASSERT(!HasStackOverflow());
|
| ASSERT(current_block() != NULL);
|
| ASSERT(current_block()->HasPredecessor());
|
| - return Bailout("TryCatchStatement");
|
| + if (!FLAG_crankshaft_try_support) {
|
| + Bailout("try statement support disabled");
|
| + return;
|
| + }
|
| + HEnterTry* enter = new(zone()) HEnterTry(stmt->index());
|
| + AddInstruction(enter);
|
| + environment()->AddExceptionHandler();
|
| + AddSimulate(stmt->TryEntryId());
|
| + BreakAndContinueInfo try_info(stmt, 0);
|
| + { BreakAndContinueScope push(&try_info, this);
|
| + CHECK_BAILOUT(Visit(stmt->try_block()));
|
| + }
|
| + if (current_block() != NULL) {
|
| + HLeaveTry* leave = new(zone()) HLeaveTry;
|
| + AddInstruction(leave);
|
| + environment()->RemoveExceptionHandler();
|
| + AddSimulate(stmt->TryExitId());
|
| + }
|
| }
|
|
|
|
|
| @@ -10916,6 +10945,7 @@ HEnvironment::HEnvironment(HEnvironment* outer,
|
| parameter_count_(0),
|
| specials_count_(1),
|
| local_count_(0),
|
| + handler_count_(0),
|
| outer_(outer),
|
| entry_(NULL),
|
| pop_count_(0),
|
| @@ -10948,6 +10978,7 @@ HEnvironment::HEnvironment(const HEnvironment* other, Zone* zone)
|
| parameter_count_(0),
|
| specials_count_(0),
|
| local_count_(0),
|
| + handler_count_(0),
|
| outer_(NULL),
|
| entry_(NULL),
|
| pop_count_(0),
|
| @@ -10969,6 +11000,7 @@ HEnvironment::HEnvironment(HEnvironment* outer,
|
| parameter_count_(arguments),
|
| specials_count_(0),
|
| local_count_(0),
|
| + handler_count_(0),
|
| outer_(outer),
|
| entry_(NULL),
|
| pop_count_(0),
|
| @@ -10998,6 +11030,7 @@ void HEnvironment::Initialize(const HEnvironment* other) {
|
| frame_type_ = other->frame_type_;
|
| parameter_count_ = other->parameter_count_;
|
| local_count_ = other->local_count_;
|
| + handler_count_ = other->handler_count_;
|
| if (other->outer_ != NULL) outer_ = other->outer_->Copy(); // Deep copy.
|
| entry_ = other->entry_;
|
| pop_count_ = other->pop_count_;
|
| @@ -11010,6 +11043,7 @@ void HEnvironment::Initialize(const HEnvironment* other) {
|
| void HEnvironment::AddIncomingEdge(HBasicBlock* block, HEnvironment* other) {
|
| ASSERT(!block->IsLoopHeader());
|
| ASSERT(values_.length() == other->values_.length());
|
| + ASSERT(handler_count_ == other->handler_count_);
|
|
|
| int length = values_.length();
|
| for (int i = 0; i < length; ++i) {
|
|
|