Index: src/x64/fast-codegen-x64.cc |
=================================================================== |
--- src/x64/fast-codegen-x64.cc (revision 3532) |
+++ src/x64/fast-codegen-x64.cc (working copy) |
@@ -270,30 +270,28 @@ |
} |
-template <> |
-Operand FastCodeGenerator::CreateSlotOperand<Operand>(Slot* source, |
- Register scratch) { |
- switch (source->type()) { |
+MemOperand FastCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { |
+ switch (slot->type()) { |
case Slot::PARAMETER: |
case Slot::LOCAL: |
- return Operand(rbp, SlotOffset(source)); |
+ return Operand(rbp, SlotOffset(slot)); |
case Slot::CONTEXT: { |
int context_chain_length = |
- function_->scope()->ContextChainLength(source->var()->scope()); |
+ function_->scope()->ContextChainLength(slot->var()->scope()); |
__ LoadContext(scratch, context_chain_length); |
- return CodeGenerator::ContextOperand(scratch, source->index()); |
+ return CodeGenerator::ContextOperand(scratch, slot->index()); |
} |
case Slot::LOOKUP: |
- UNIMPLEMENTED(); |
+ UNREACHABLE(); |
} |
UNREACHABLE(); |
return Operand(rax, 0); |
} |
-void FastCodeGenerator::Move(Register dst, Slot* source) { |
- Operand location = CreateSlotOperand<Operand>(source, dst); |
- __ movq(dst, location); |
+void FastCodeGenerator::Move(Register destination, Slot* source) { |
+ MemOperand location = EmitSlotSearch(source, destination); |
+ __ movq(destination, location); |
} |
@@ -306,7 +304,7 @@ |
case Expression::kEffect: |
break; |
case Expression::kValue: { |
- Operand location = CreateSlotOperand<Operand>(source, scratch); |
+ MemOperand location = EmitSlotSearch(source, scratch); |
__ push(location); |
break; |
} |
@@ -343,25 +341,14 @@ |
Register src, |
Register scratch1, |
Register scratch2) { |
- switch (dst->type()) { |
- case Slot::PARAMETER: |
- case Slot::LOCAL: |
- __ movq(Operand(rbp, SlotOffset(dst)), src); |
- break; |
- case Slot::CONTEXT: { |
- ASSERT(!src.is(scratch1)); |
- ASSERT(!src.is(scratch2)); |
- ASSERT(!scratch1.is(scratch2)); |
- int context_chain_length = |
- function_->scope()->ContextChainLength(dst->var()->scope()); |
- __ LoadContext(scratch1, context_chain_length); |
- __ movq(Operand(scratch1, Context::SlotOffset(dst->index())), src); |
- int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize; |
- __ RecordWrite(scratch1, offset, src, scratch2); |
- break; |
- } |
- case Slot::LOOKUP: |
- UNIMPLEMENTED(); |
+ ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented. |
+ ASSERT(!scratch1.is(src) && !scratch2.is(src)); |
+ MemOperand location = EmitSlotSearch(dst, scratch1); |
+ __ movq(location, src); |
+ // Emit the write barrier code if the location is in the heap. |
+ if (dst->type() == Slot::CONTEXT) { |
+ int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize; |
+ __ RecordWrite(scratch1, offset, src, scratch2); |
} |
} |
@@ -457,14 +444,17 @@ |
case Slot::LOCAL: |
if (decl->mode() == Variable::CONST) { |
__ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); |
- __ movq(Operand(rbp, SlotOffset(var->slot())), kScratchRegister); |
+ __ movq(Operand(rbp, SlotOffset(slot)), kScratchRegister); |
} else if (decl->fun() != NULL) { |
Visit(decl->fun()); |
- __ pop(Operand(rbp, SlotOffset(var->slot()))); |
+ __ pop(Operand(rbp, SlotOffset(slot))); |
} |
break; |
case Slot::CONTEXT: |
+ // We bypass the general EmitSlotSearch because we know more about |
+ // this specific context. |
+ |
// The variable in the decl always resides in the current context. |
ASSERT_EQ(0, function_->scope()->ContextChainLength(var->scope())); |
if (FLAG_debug_code) { |
@@ -908,34 +898,34 @@ |
// Overwrite the global object on the stack with the result if needed. |
DropAndMove(context, rax); |
- } else if (var->slot()) { |
+ } else if (var->slot() != NULL) { |
Slot* slot = var->slot(); |
- ASSERT_NOT_NULL(slot); // Variables rewritten as properties not handled. |
switch (slot->type()) { |
case Slot::LOCAL: |
case Slot::PARAMETER: { |
+ Operand target = Operand(rbp, SlotOffset(slot)); |
switch (context) { |
case Expression::kUninitialized: |
UNREACHABLE(); |
case Expression::kEffect: |
// Perform assignment and discard value. |
- __ pop(Operand(rbp, SlotOffset(var->slot()))); |
+ __ pop(target); |
break; |
case Expression::kValue: |
// Perform assignment and preserve value. |
__ movq(rax, Operand(rsp, 0)); |
- __ movq(Operand(rbp, SlotOffset(var->slot())), rax); |
+ __ movq(target, rax); |
break; |
case Expression::kTest: |
// Perform assignment and test (and discard) value. |
__ pop(rax); |
- __ movq(Operand(rbp, SlotOffset(var->slot())), rax); |
+ __ movq(target, rax); |
TestAndBranch(rax, true_label_, false_label_); |
break; |
case Expression::kValueTest: { |
Label discard; |
__ movq(rax, Operand(rsp, 0)); |
- __ movq(Operand(rbp, SlotOffset(var->slot())), rax); |
+ __ movq(target, rax); |
TestAndBranch(rax, true_label_, &discard); |
__ bind(&discard); |
__ addq(rsp, Immediate(kPointerSize)); |
@@ -945,7 +935,7 @@ |
case Expression::kTestValue: { |
Label discard; |
__ movq(rax, Operand(rsp, 0)); |
- __ movq(Operand(rbp, SlotOffset(var->slot())), rax); |
+ __ movq(target, rax); |
TestAndBranch(rax, &discard, false_label_); |
__ bind(&discard); |
__ addq(rsp, Immediate(kPointerSize)); |
@@ -957,38 +947,18 @@ |
} |
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. |
- __ movq(rax, |
- Operand(rsi, Context::SlotOffset(Context::CLOSURE_INDEX))); |
- // Load the function context (which is the incoming, outer context). |
- __ movq(rax, FieldOperand(rax, JSFunction::kContextOffset)); |
- for (int i = 1; i < chain_length; i++) { |
- __ movq(rax, |
- Operand(rax, Context::SlotOffset(Context::CLOSURE_INDEX))); |
- __ movq(rax, FieldOperand(rax, JSFunction::kContextOffset)); |
- } |
- } else { // Slot is in the current context. Generate optimized code. |
- __ movq(rax, rsi); // RecordWrite destroys the object register. |
- } |
- if (FLAG_debug_code) { |
- __ cmpq(rax, |
- Operand(rax, Context::SlotOffset(Context::FCONTEXT_INDEX))); |
- __ Check(equal, "Context Slot chain length wrong."); |
- } |
- __ pop(rcx); |
- __ movq(Operand(rax, Context::SlotOffset(slot->index())), rcx); |
+ MemOperand target = EmitSlotSearch(slot, rcx); |
+ __ pop(rax); |
+ __ movq(target, rax); |
// RecordWrite may destroy all its register arguments. |
if (context == Expression::kValue) { |
- __ push(rcx); |
+ __ push(rax); |
} else if (context != Expression::kEffect) { |
- __ movq(rdx, rcx); |
+ __ movq(rdx, rax); |
} |
int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; |
- __ RecordWrite(rax, offset, rcx, rbx); |
+ __ RecordWrite(rcx, offset, rax, rbx); |
if (context != Expression::kEffect && |
context != Expression::kValue) { |
Move(context, rdx); |
@@ -1000,6 +970,10 @@ |
UNREACHABLE(); |
break; |
} |
+ } else { |
+ // Variables rewritten as properties are not treated as variables in |
+ // assignments. |
+ UNREACHABLE(); |
} |
} |