Chromium Code Reviews| Index: src/hydrogen.cc |
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc |
| index 53cf97ceb479eb54daccbceff411c45f3ece0394..3eecaa42d4e0f9fd7a13fe8a451bf71e11f5f5bc 100644 |
| --- a/src/hydrogen.cc |
| +++ b/src/hydrogen.cc |
| @@ -2952,16 +2952,19 @@ 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); |
| + int context_chain_length = |
| + graph()->info()->scope()->ContextChainLength(variable->scope()); |
| + int index = variable->AsSlot()->index(); |
| // TODO(antonm): if slot's value is not modified by closures, instead |
| // of reading it out of context, we could just embed the value as |
| // a constant. |
| - HLoadContextSlot* instr = |
| - new HLoadContextSlot(context_chain_length, slot->index()); |
| + HInstruction* context = new HContext; |
| + AddInstruction(context); |
| + for (int i = 0; i < context_chain_length; ++i) { |
| + context = new HOuterContext(context); |
| + AddInstruction(context); |
| + } |
| + HLoadContextSlot* instr = new HLoadContextSlot(context, index); |
| ast_context()->ReturnInstruction(instr, expr->id()); |
| } else if (variable->is_global()) { |
| LookupResult lookup; |
| @@ -3500,35 +3503,55 @@ 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) { |
| + int context_chain_length = |
|
antonm
2011/01/27 14:00:07
should we refactor the code that builds context va
Kevin Millikin (Chromium)
2011/02/03 08:37:23
Yes, because we'll need it for compound assignment
|
| + graph()->info()->scope()->ContextChainLength(var->scope()); |
| + int index = var->AsSlot()->index(); |
| + HInstruction* context = new HContext; |
| + AddInstruction(context); |
| + for (int i = 0; i < context_chain_length; ++i) { |
| + context = new HOuterContext(context); |
| + AddInstruction(context); |
| + } |
| + VISIT_FOR_VALUE(expr->value()); |
| + 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"); |
| } |
| } |
| @@ -4405,7 +4428,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; |
| @@ -4414,7 +4440,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); |
| @@ -4441,7 +4467,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; |
| @@ -4449,7 +4477,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; |