Index: src/ia32/fast-codegen-ia32.cc |
=================================================================== |
--- src/ia32/fast-codegen-ia32.cc (revision 3241) |
+++ src/ia32/fast-codegen-ia32.cc (working copy) |
@@ -410,6 +410,7 @@ |
Comment cmnt(masm_, "[ VariableProxy"); |
Expression* rewrite = expr->var()->rewrite(); |
if (rewrite == NULL) { |
+ ASSERT(expr->var()->is_global()); |
Comment cmnt(masm_, "Global variable"); |
// Use inline caching. Variable name is passed in ecx and the global |
// object on the stack. |
@@ -425,8 +426,48 @@ |
DropAndMove(expr->context(), eax); |
} else { |
- Comment cmnt(masm_, "Stack slot"); |
- Move(expr->context(), rewrite->AsSlot()); |
+ Slot* slot = rewrite->AsSlot(); |
+ ASSERT_NE(NULL, slot); |
+ switch (slot->type()) { |
+ case Slot::LOCAL: |
+ case Slot::PARAMETER: { |
+ Comment cmnt(masm_, "Stack slot"); |
+ Move(expr->context(), slot); |
+ break; |
+ } |
+ |
+ case Slot::CONTEXT: { |
+ Comment cmnt(masm_, "Context slot"); |
+ int chain_length = |
+ function_->scope()->ContextChainLength(slot->var()->scope()); |
+ if (chain_length > 0) { |
+ // Move up the chain of contexts to the context containing the slot. |
+ __ mov(eax, |
+ Operand(esi, Context::SlotOffset(Context::CLOSURE_INDEX))); |
+ // Load the function context (which is the incoming, outer context). |
+ __ mov(eax, FieldOperand(eax, JSFunction::kContextOffset)); |
+ for (int i = 1; i < chain_length; i++) { |
+ __ mov(eax, |
+ Operand(eax, Context::SlotOffset(Context::CLOSURE_INDEX))); |
+ __ mov(eax, FieldOperand(eax, JSFunction::kContextOffset)); |
+ } |
+ // The context may be an intermediate context, not a function context. |
+ __ mov(eax, |
+ Operand(eax, Context::SlotOffset(Context::FCONTEXT_INDEX))); |
+ } else { // Slot is in the current function context. |
+ // The context may be an intermediate context, not a function context. |
+ __ mov(eax, |
+ Operand(esi, Context::SlotOffset(Context::FCONTEXT_INDEX))); |
+ } |
+ __ mov(eax, Operand(eax, Context::SlotOffset(slot->index()))); |
+ Move(expr->context(), eax); |
+ break; |
+ } |
+ |
+ case Slot::LOOKUP: |
+ UNREACHABLE(); |
+ break; |
+ } |
} |
} |
@@ -693,44 +734,96 @@ |
DropAndMove(expr->context(), eax); |
} else { |
- switch (expr->context()) { |
- case Expression::kUninitialized: |
- UNREACHABLE(); |
- case Expression::kEffect: |
- // Perform assignment and discard value. |
- __ pop(Operand(ebp, SlotOffset(var->slot()))); |
+ Slot* slot = var->slot(); |
+ ASSERT_NOT_NULL(slot); // Variables rewritten as properties not handled. |
+ switch (slot->type()) { |
+ case Slot::LOCAL: |
+ case Slot::PARAMETER: { |
+ switch (expr->context()) { |
+ case Expression::kUninitialized: |
+ UNREACHABLE(); |
+ case Expression::kEffect: |
+ // Perform assignment and discard value. |
+ __ pop(Operand(ebp, SlotOffset(var->slot()))); |
+ break; |
+ case Expression::kValue: |
+ // Perform assignment and preserve value. |
+ __ mov(eax, Operand(esp, 0)); |
+ __ mov(Operand(ebp, SlotOffset(var->slot())), eax); |
+ break; |
+ case Expression::kTest: |
+ // Perform assignment and test (and discard) value. |
+ __ pop(eax); |
+ __ mov(Operand(ebp, SlotOffset(var->slot())), eax); |
+ TestAndBranch(eax, true_label_, false_label_); |
+ break; |
+ case Expression::kValueTest: { |
+ Label discard; |
+ __ mov(eax, Operand(esp, 0)); |
+ __ mov(Operand(ebp, SlotOffset(var->slot())), eax); |
+ TestAndBranch(eax, true_label_, &discard); |
+ __ bind(&discard); |
+ __ add(Operand(esp), Immediate(kPointerSize)); |
+ __ jmp(false_label_); |
+ break; |
+ } |
+ case Expression::kTestValue: { |
+ Label discard; |
+ __ mov(eax, Operand(esp, 0)); |
+ __ mov(Operand(ebp, SlotOffset(var->slot())), eax); |
+ TestAndBranch(eax, &discard, false_label_); |
+ __ bind(&discard); |
+ __ add(Operand(esp), Immediate(kPointerSize)); |
+ __ jmp(true_label_); |
+ break; |
+ } |
+ } |
break; |
- case Expression::kValue: |
- // Perform assignment and preserve value. |
- __ mov(eax, Operand(esp, 0)); |
- __ mov(Operand(ebp, SlotOffset(var->slot())), eax); |
+ } |
+ |
+ case Slot::CONTEXT: { |
+ int chain_length = |
+ function_->scope()->ContextChainLength(slot->var()->scope()); |
+ if (chain_length > 0) { |
+ // Move up the context chain to the context containing the slot. |
+ __ mov(eax, |
+ Operand(esi, Context::SlotOffset(Context::CLOSURE_INDEX))); |
+ // Load the function context (which is the incoming, outer context). |
+ __ mov(eax, FieldOperand(eax, JSFunction::kContextOffset)); |
+ for (int i = 1; i < chain_length; i++) { |
+ __ mov(eax, |
+ Operand(eax, Context::SlotOffset(Context::CLOSURE_INDEX))); |
+ __ mov(eax, FieldOperand(eax, JSFunction::kContextOffset)); |
+ } |
+ } else { // Slot is in the current context. Generate optimized code. |
+ __ mov(eax, esi); // RecordWrite destroys the object register. |
+ } |
+ if (FLAG_debug_code) { |
+ __ cmp(eax, |
+ Operand(eax, Context::SlotOffset(Context::FCONTEXT_INDEX))); |
+ __ Check(equal, "Context Slot chain length wrong."); |
+ } |
+ __ pop(ecx); |
+ __ mov(Operand(eax, Context::SlotOffset(slot->index())), ecx); |
+ |
+ // RecordWrite may destroy all its register arguments. |
+ if (expr->context() == Expression::kValue) { |
+ __ push(ecx); |
+ } else if (expr->context() != Expression::kEffect) { |
+ __ mov(edx, ecx); |
+ } |
+ int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; |
+ __ RecordWrite(eax, offset, ecx, ebx); |
+ if (expr->context() != Expression::kEffect && |
+ expr->context() != Expression::kValue) { |
+ Move(expr->context(), edx); |
+ } |
break; |
- case Expression::kTest: |
- // Perform assignment and test (and discard) value. |
- __ pop(eax); |
- __ mov(Operand(ebp, SlotOffset(var->slot())), eax); |
- TestAndBranch(eax, true_label_, false_label_); |
- break; |
- case Expression::kValueTest: { |
- Label discard; |
- __ mov(eax, Operand(esp, 0)); |
- __ mov(Operand(ebp, SlotOffset(var->slot())), eax); |
- TestAndBranch(eax, true_label_, &discard); |
- __ bind(&discard); |
- __ add(Operand(esp), Immediate(kPointerSize)); |
- __ jmp(false_label_); |
- break; |
} |
- case Expression::kTestValue: { |
- Label discard; |
- __ mov(eax, Operand(esp, 0)); |
- __ mov(Operand(ebp, SlotOffset(var->slot())), eax); |
- TestAndBranch(eax, &discard, false_label_); |
- __ bind(&discard); |
- __ add(Operand(esp), Immediate(kPointerSize)); |
- __ jmp(true_label_); |
+ |
+ case Slot::LOOKUP: |
+ UNREACHABLE(); |
break; |
- } |
} |
} |
} |