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; |