| Index: src/hydrogen.cc
|
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc
|
| index 36d62d271ce7d1b8451324cc923827a2586b6f26..a3f4b0b2a53d80ca7d2742590712a014cb141c8e 100644
|
| --- a/src/hydrogen.cc
|
| +++ b/src/hydrogen.cc
|
| @@ -4247,13 +4247,52 @@ void HOptimizedGraphBuilder::VisitBlock(Block* stmt) {
|
| ASSERT(!HasStackOverflow());
|
| ASSERT(current_block() != NULL);
|
| ASSERT(current_block()->HasPredecessor());
|
| - if (stmt->scope() != NULL) {
|
| - return Bailout(kScopedBlock);
|
| - }
|
| - BreakAndContinueInfo break_info(stmt);
|
| +
|
| + Scope* outer_scope = scope();
|
| + Scope* scope = stmt->scope();
|
| + BreakAndContinueInfo break_info(stmt, outer_scope);
|
| +
|
| { BreakAndContinueScope push(&break_info, this);
|
| + if (scope != NULL) {
|
| + // Load the function object.
|
| + Scope* declaration_scope = scope->DeclarationScope();
|
| + HInstruction* function;
|
| + HValue* outer_context = environment()->context();
|
| + if (declaration_scope->is_global_scope() ||
|
| + declaration_scope->is_eval_scope()) {
|
| + function = new(zone()) HLoadContextSlot(
|
| + outer_context, Context::CLOSURE_INDEX, HLoadContextSlot::kNoCheck);
|
| + } else {
|
| + function = New<HThisFunction>();
|
| + }
|
| + AddInstruction(function);
|
| + // Allocate a block context and store it to the stack frame.
|
| + HInstruction* inner_context = Add<HAllocateBlockContext>(
|
| + outer_context, function, scope->GetScopeInfo());
|
| + HInstruction* instr = Add<HStoreFrameContext>(inner_context);
|
| + if (instr->HasObservableSideEffects()) {
|
| + AddSimulate(stmt->EntryId(), REMOVABLE_SIMULATE);
|
| + }
|
| + set_scope(scope);
|
| + environment()->BindContext(inner_context);
|
| + VisitDeclarations(scope->declarations());
|
| + AddSimulate(stmt->DeclsId(), REMOVABLE_SIMULATE);
|
| + }
|
| CHECK_BAILOUT(VisitStatements(stmt->statements()));
|
| }
|
| + set_scope(outer_scope);
|
| + if (scope != NULL && current_block() != NULL) {
|
| + HValue* inner_context = environment()->context();
|
| + HValue* outer_context = Add<HLoadNamedField>(
|
| + inner_context, static_cast<HValue*>(NULL),
|
| + HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
|
| +
|
| + HInstruction* instr = Add<HStoreFrameContext>(outer_context);
|
| + if (instr->HasObservableSideEffects()) {
|
| + AddSimulate(stmt->ExitId(), REMOVABLE_SIMULATE);
|
| + }
|
| + environment()->BindContext(outer_context);
|
| + }
|
| HBasicBlock* break_block = break_info.break_block();
|
| if (break_block != NULL) {
|
| if (current_block() != NULL) Goto(break_block);
|
| @@ -4321,6 +4360,7 @@ void HOptimizedGraphBuilder::VisitIfStatement(IfStatement* stmt) {
|
| HBasicBlock* HOptimizedGraphBuilder::BreakAndContinueScope::Get(
|
| BreakableStatement* stmt,
|
| BreakType type,
|
| + Scope** scope,
|
| int* drop_extra) {
|
| *drop_extra = 0;
|
| BreakAndContinueScope* current = this;
|
| @@ -4329,6 +4369,7 @@ HBasicBlock* HOptimizedGraphBuilder::BreakAndContinueScope::Get(
|
| current = current->next();
|
| }
|
| ASSERT(current != NULL); // Always found (unless stack is malformed).
|
| + *scope = current->info()->scope();
|
|
|
| if (type == BREAK) {
|
| *drop_extra += current->info()->drop_extra();
|
| @@ -4362,10 +4403,29 @@ void HOptimizedGraphBuilder::VisitContinueStatement(
|
| ASSERT(!HasStackOverflow());
|
| ASSERT(current_block() != NULL);
|
| ASSERT(current_block()->HasPredecessor());
|
| + Scope* outer_scope = NULL;
|
| + Scope* inner_scope = scope();
|
| int drop_extra = 0;
|
| HBasicBlock* continue_block = break_scope()->Get(
|
| - stmt->target(), BreakAndContinueScope::CONTINUE, &drop_extra);
|
| + stmt->target(), BreakAndContinueScope::CONTINUE,
|
| + &outer_scope, &drop_extra);
|
| + HValue* context = environment()->context();
|
| Drop(drop_extra);
|
| + int context_pop_count = inner_scope->ContextChainLength(outer_scope);
|
| + if (context_pop_count > 0) {
|
| + while (context_pop_count-- > 0) {
|
| + HInstruction* context_instruction = Add<HLoadNamedField>(
|
| + context, static_cast<HValue*>(NULL),
|
| + HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
|
| + context = context_instruction;
|
| + }
|
| + HInstruction* instr = Add<HStoreFrameContext>(context);
|
| + if (instr->HasObservableSideEffects()) {
|
| + AddSimulate(stmt->target()->EntryId(), REMOVABLE_SIMULATE);
|
| + }
|
| + environment()->BindContext(context);
|
| + }
|
| +
|
| Goto(continue_block);
|
| set_current_block(NULL);
|
| }
|
| @@ -4375,10 +4435,28 @@ void HOptimizedGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
|
| ASSERT(!HasStackOverflow());
|
| ASSERT(current_block() != NULL);
|
| ASSERT(current_block()->HasPredecessor());
|
| + Scope* outer_scope = NULL;
|
| + Scope* inner_scope = scope();
|
| int drop_extra = 0;
|
| HBasicBlock* break_block = break_scope()->Get(
|
| - stmt->target(), BreakAndContinueScope::BREAK, &drop_extra);
|
| + stmt->target(), BreakAndContinueScope::BREAK,
|
| + &outer_scope, &drop_extra);
|
| + HValue* context = environment()->context();
|
| Drop(drop_extra);
|
| + int context_pop_count = inner_scope->ContextChainLength(outer_scope);
|
| + if (context_pop_count > 0) {
|
| + while (context_pop_count-- > 0) {
|
| + HInstruction* context_instruction = Add<HLoadNamedField>(
|
| + context, static_cast<HValue*>(NULL),
|
| + HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
|
| + context = context_instruction;
|
| + }
|
| + HInstruction* instr = Add<HStoreFrameContext>(context);
|
| + if (instr->HasObservableSideEffects()) {
|
| + AddSimulate(stmt->target()->ExitId(), REMOVABLE_SIMULATE);
|
| + }
|
| + environment()->BindContext(context);
|
| + }
|
| Goto(break_block);
|
| set_current_block(NULL);
|
| }
|
| @@ -4533,7 +4611,7 @@ void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
|
| // translating the clause bodies.
|
| HBasicBlock* fall_through_block = NULL;
|
|
|
| - BreakAndContinueInfo break_info(stmt);
|
| + BreakAndContinueInfo break_info(stmt, scope());
|
| { BreakAndContinueScope push(&break_info, this);
|
| for (int i = 0; i < clause_count; ++i) {
|
| CaseClause* clause = clauses->at(i);
|
| @@ -4580,9 +4658,7 @@ void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
|
|
|
|
|
| void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt,
|
| - HBasicBlock* loop_entry,
|
| - BreakAndContinueInfo* break_info) {
|
| - BreakAndContinueScope push(break_info, this);
|
| + HBasicBlock* loop_entry) {
|
| Add<HSimulate>(stmt->StackCheckId());
|
| HStackCheck* stack_check =
|
| HStackCheck::cast(Add<HStackCheck>(HStackCheck::kBackwardsBranch));
|
| @@ -4599,8 +4675,11 @@ void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
|
| ASSERT(current_block() != NULL);
|
| HBasicBlock* loop_entry = BuildLoopEntry(stmt);
|
|
|
| - BreakAndContinueInfo break_info(stmt);
|
| - CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info));
|
| + BreakAndContinueInfo break_info(stmt, scope());
|
| + {
|
| + BreakAndContinueScope push(&break_info, this);
|
| + CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry));
|
| + }
|
| HBasicBlock* body_exit =
|
| JoinContinue(stmt, current_block(), break_info.continue_block());
|
| HBasicBlock* loop_successor = NULL;
|
| @@ -4661,9 +4740,10 @@ void HOptimizedGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
|
| }
|
| }
|
|
|
| - BreakAndContinueInfo break_info(stmt);
|
| + BreakAndContinueInfo break_info(stmt, scope());
|
| if (current_block() != NULL) {
|
| - CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info));
|
| + BreakAndContinueScope push(&break_info, this);
|
| + CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry));
|
| }
|
| HBasicBlock* body_exit =
|
| JoinContinue(stmt, current_block(), break_info.continue_block());
|
| @@ -4702,9 +4782,10 @@ void HOptimizedGraphBuilder::VisitForStatement(ForStatement* stmt) {
|
| }
|
| }
|
|
|
| - BreakAndContinueInfo break_info(stmt);
|
| + BreakAndContinueInfo break_info(stmt, scope());
|
| if (current_block() != NULL) {
|
| - CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info));
|
| + BreakAndContinueScope push(&break_info, this);
|
| + CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry));
|
| }
|
| HBasicBlock* body_exit =
|
| JoinContinue(stmt, current_block(), break_info.continue_block());
|
| @@ -4803,8 +4884,11 @@ void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
|
|
|
| Bind(each_var, key);
|
|
|
| - BreakAndContinueInfo break_info(stmt, 5);
|
| - CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info));
|
| + BreakAndContinueInfo break_info(stmt, scope(), 5);
|
| + {
|
| + BreakAndContinueScope push(&break_info, this);
|
| + CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry));
|
| + }
|
|
|
| HBasicBlock* body_exit =
|
| JoinContinue(stmt, current_block(), break_info.continue_block());
|
| @@ -4949,7 +5033,7 @@ HOptimizedGraphBuilder::GlobalPropertyAccess
|
| HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) {
|
| ASSERT(var->IsContextSlot());
|
| HValue* context = environment()->context();
|
| - int length = current_info()->scope()->ContextChainLength(var->scope());
|
| + int length = scope()->ContextChainLength(var->scope());
|
| while (length-- > 0) {
|
| context = Add<HLoadNamedField>(
|
| context, static_cast<HValue*>(NULL),
|
| @@ -5033,7 +5117,21 @@ void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
|
|
|
| case Variable::CONTEXT: {
|
| HValue* context = BuildContextChainWalk(variable);
|
| - HLoadContextSlot* instr = new(zone()) HLoadContextSlot(context, variable);
|
| + HLoadContextSlot::Mode mode;
|
| + switch (variable->mode()) {
|
| + case LET:
|
| + case CONST:
|
| + mode = HLoadContextSlot::kCheckDeoptimize;
|
| + break;
|
| + case CONST_LEGACY:
|
| + mode = HLoadContextSlot::kCheckReturnUndefined;
|
| + break;
|
| + default:
|
| + mode = HLoadContextSlot::kNoCheck;
|
| + break;
|
| + }
|
| + HLoadContextSlot* instr =
|
| + new(zone()) HLoadContextSlot(context, variable->index(), mode);
|
| return ast_context()->ReturnInstruction(instr, expr->id());
|
| }
|
|
|
| @@ -7462,7 +7560,8 @@ bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target,
|
| Add<HSimulate>(BailoutId::None());
|
|
|
| current_block()->UpdateEnvironment(inner_env);
|
| -
|
| + Scope* saved_scope = scope();
|
| + set_scope(target_info.scope());
|
| HEnterInlined* enter_inlined =
|
| Add<HEnterInlined>(return_id, target, arguments_count, function,
|
| function_state()->inlining_kind(),
|
| @@ -7472,6 +7571,7 @@ bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target,
|
|
|
| VisitDeclarations(target_info.scope()->declarations());
|
| VisitStatements(function->body());
|
| + set_scope(saved_scope);
|
| if (HasStackOverflow()) {
|
| // Bail out if the inline function did, as we cannot residualize a call
|
| // instead.
|
| @@ -11432,7 +11532,9 @@ HEnvironment::HEnvironment(HEnvironment* outer,
|
| push_count_(0),
|
| ast_id_(BailoutId::None()),
|
| zone_(zone) {
|
| - Initialize(scope->num_parameters() + 1, scope->num_stack_slots(), 0);
|
| + Scope* declaration_scope = scope->DeclarationScope();
|
| + Initialize(declaration_scope->num_parameters() + 1,
|
| + declaration_scope->num_stack_slots(), 0);
|
| }
|
|
|
|
|
|
|