Chromium Code Reviews| Index: src/hydrogen.cc |
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc |
| index 9d5aa2be31fa7206456e93d1257eb4320e0abf30..4044f7fff130bc71fa0378dc105d10ac7fd044d5 100644 |
| --- a/src/hydrogen.cc |
| +++ b/src/hydrogen.cc |
| @@ -2955,6 +2955,19 @@ void HGraphBuilder::LookupGlobalPropertyCell(Variable* var, |
| } |
| +HValue* HGraphBuilder::BuildContextChainWalk(Variable* var) { |
| + ASSERT(var->IsContextSlot()); |
| + HInstruction* context = new HContext; |
| + AddInstruction(context); |
| + int length = graph()->info()->scope()->ContextChainLength(var->scope()); |
| + while (length-- > 0) { |
| + context = new HOuterContext(context); |
| + AddInstruction(context); |
| + } |
| + return context; |
| +} |
| + |
| + |
| void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) { |
| Variable* variable = expr->AsVariable(); |
| if (variable == NULL) { |
| @@ -2968,16 +2981,9 @@ void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) { |
| if (variable->mode() == Variable::CONST) { |
| BAILOUT("reference to const context slot"); |
| } |
| - Slot* slot = variable->AsSlot(); |
| - CompilationInfo* info = graph()->info(); |
| - int context_chain_length = info->function()->scope()-> |
| - ContextChainLength(slot->var()->scope()); |
| - ASSERT(context_chain_length >= 0); |
| - // TODO(antonm): if slot's value is not modified by closures, instead |
|
antonm
2011/02/03 13:14:30
may we keep this TODO?
|
| - // of reading it out of context, we could just embed the value as |
| - // a constant. |
| - HLoadContextSlot* instr = |
| - new HLoadContextSlot(context_chain_length, slot->index()); |
| + HValue* context = BuildContextChainWalk(variable); |
| + int index = variable->AsSlot()->index(); |
| + HLoadContextSlot* instr = new HLoadContextSlot(context, index); |
| ast_context()->ReturnInstruction(instr, expr->id()); |
| } else if (variable->is_global()) { |
| LookupResult lookup; |
| @@ -3515,35 +3521,48 @@ void HGraphBuilder::VisitAssignment(Assignment* expr) { |
| if (proxy->IsArguments()) BAILOUT("assignment to arguments"); |
| // Handle the assignment. |
| - if (var->is_global()) { |
| + if (var->IsStackAllocated()) { |
| + HValue* value = NULL; |
| + // Handle stack-allocated variables on the right-hand side directly. |
| + // We do not allow the arguments object to occur in a context where it |
| + // may escape, but assignments to stack-allocated locals are |
| + // permitted. Handling such assignments here bypasses the check for |
| + // the arguments object in VisitVariableProxy. |
| + Variable* rhs_var = expr->value()->AsVariableProxy()->AsVariable(); |
| + if (rhs_var != NULL && rhs_var->IsStackAllocated()) { |
| + value = environment()->Lookup(rhs_var); |
| + } else { |
| + VISIT_FOR_VALUE(expr->value()); |
| + value = Pop(); |
| + } |
| + Bind(var, value); |
| + ast_context()->ReturnValue(value); |
| + |
| + } else if (var->IsContextSlot() && var->mode() != Variable::CONST) { |
| + VISIT_FOR_VALUE(expr->value()); |
| + HValue* context = BuildContextChainWalk(var); |
| + int index = var->AsSlot()->index(); |
| + HStoreContextSlot* instr = new HStoreContextSlot(context, index, Top()); |
| + AddInstruction(instr); |
| + if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); |
| + ast_context()->ReturnValue(Pop()); |
| + |
| + } else if (var->is_global()) { |
| VISIT_FOR_VALUE(expr->value()); |
| HandleGlobalVariableAssignment(var, |
| Top(), |
| expr->position(), |
| expr->AssignmentId()); |
| - } else if (var->IsStackAllocated()) { |
| - // We allow reference to the arguments object only in assignemtns |
| - // to local variables to make sure that the arguments object does |
| - // not escape and is not modified. |
| - VariableProxy* rhs = expr->value()->AsVariableProxy(); |
| - if (rhs != NULL && |
| - rhs->var()->IsStackAllocated() && |
| - environment()->Lookup(rhs->var())->CheckFlag(HValue::kIsArguments)) { |
| - Push(environment()->Lookup(rhs->var())); |
| - } else { |
| - VISIT_FOR_VALUE(expr->value()); |
| - } |
| - Bind(proxy->var(), Top()); |
| + ast_context()->ReturnValue(Pop()); |
| + |
| } else { |
| - BAILOUT("Assigning to no non-stack-allocated/non-global variable"); |
| + BAILOUT("assignment to LOOKUP or const CONTEXT variable"); |
| } |
| - // Return the value. |
| - ast_context()->ReturnValue(Pop()); |
| } else if (prop != NULL) { |
| HandlePropertyAssignment(expr); |
| } else { |
| - BAILOUT("unsupported invalid lhs"); |
| + BAILOUT("invalid left-hand side in assignment"); |
| } |
| } |
| @@ -4422,7 +4441,10 @@ void HGraphBuilder::VisitCall(Call* expr) { |
| if (known_global_function) { |
| // Push the global object instead of the global receiver because |
| // code generated by the full code generator expects it. |
| - PushAndAdd(new HGlobalObject); |
| + HContext* context = new HContext; |
| + HGlobalObject* global_object = new HGlobalObject(context); |
| + AddInstruction(context); |
| + PushAndAdd(global_object); |
| VisitArgumentList(expr->arguments()); |
| CHECK_BAILOUT; |
| @@ -4431,7 +4453,7 @@ void HGraphBuilder::VisitCall(Call* expr) { |
| AddInstruction(new HCheckFunction(function, expr->target())); |
| // Replace the global object with the global receiver. |
| - HGlobalReceiver* global_receiver = new HGlobalReceiver; |
| + HGlobalReceiver* global_receiver = new HGlobalReceiver(global_object); |
| // Index of the receiver from the top of the expression stack. |
| const int receiver_index = argument_count - 1; |
| AddInstruction(global_receiver); |
| @@ -4458,7 +4480,9 @@ void HGraphBuilder::VisitCall(Call* expr) { |
| call = new HCallKnownGlobal(expr->target(), argument_count); |
| } else { |
| - PushAndAdd(new HGlobalObject); |
| + HContext* context = new HContext; |
| + AddInstruction(context); |
| + PushAndAdd(new HGlobalObject(context)); |
| VisitArgumentList(expr->arguments()); |
| CHECK_BAILOUT; |
| @@ -4466,7 +4490,11 @@ void HGraphBuilder::VisitCall(Call* expr) { |
| } |
| } else { |
| - PushAndAdd(new HGlobalReceiver); |
| + HContext* context = new HContext; |
| + HGlobalObject* global_object = new HGlobalObject(context); |
| + AddInstruction(context); |
| + AddInstruction(global_object); |
| + PushAndAdd(new HGlobalReceiver(global_object)); |
| VisitArgumentList(expr->arguments()); |
| CHECK_BAILOUT; |