Index: src/arm/fast-codegen-arm.cc |
=================================================================== |
--- src/arm/fast-codegen-arm.cc (revision 3532) |
+++ src/arm/fast-codegen-arm.cc (working copy) |
@@ -281,32 +281,29 @@ |
} |
-template <> |
-MemOperand FastCodeGenerator::CreateSlotOperand<MemOperand>( |
- Slot* source, |
- Register scratch) { |
- switch (source->type()) { |
+MemOperand FastCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { |
+ switch (slot->type()) { |
case Slot::PARAMETER: |
case Slot::LOCAL: |
- return MemOperand(fp, SlotOffset(source)); |
+ return MemOperand(fp, 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 MemOperand(r0, 0); |
} |
-void FastCodeGenerator::Move(Register dst, Slot* source) { |
- // Use dst as scratch. |
- MemOperand location = CreateSlotOperand<MemOperand>(source, dst); |
- __ ldr(dst, location); |
+void FastCodeGenerator::Move(Register destination, Slot* source) { |
+ // Use destination as scratch. |
+ MemOperand location = EmitSlotSearch(source, destination); |
+ __ ldr(destination, location); |
} |
@@ -351,23 +348,14 @@ |
Register src, |
Register scratch1, |
Register scratch2) { |
- switch (dst->type()) { |
- case Slot::PARAMETER: |
- case Slot::LOCAL: |
- __ str(src, MemOperand(fp, SlotOffset(dst))); |
- break; |
- case Slot::CONTEXT: { |
- int context_chain_length = |
- function_->scope()->ContextChainLength(dst->var()->scope()); |
- __ LoadContext(scratch1, context_chain_length); |
- int index = Context::SlotOffset(dst->index()); |
- __ mov(scratch2, Operand(index)); |
- __ str(src, MemOperand(scratch1, index)); |
- __ RecordWrite(scratch1, scratch2, src); |
- 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); |
+ __ str(src, location); |
+ // Emit the write barrier code if the location is in the heap. |
+ if (dst->type() == Slot::CONTEXT) { |
+ __ mov(scratch2, Operand(Context::SlotOffset(dst->index()))); |
+ __ RecordWrite(scratch1, scratch2, src); |
} |
} |
@@ -451,15 +439,18 @@ |
case Slot::LOCAL: |
if (decl->mode() == Variable::CONST) { |
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
- __ str(ip, MemOperand(fp, SlotOffset(var->slot()))); |
+ __ str(ip, MemOperand(fp, SlotOffset(slot))); |
} else if (decl->fun() != NULL) { |
Visit(decl->fun()); |
__ pop(ip); |
- __ str(ip, MemOperand(fp, SlotOffset(var->slot()))); |
+ __ str(ip, MemOperand(fp, 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) { |
@@ -912,35 +903,35 @@ |
// Overwrite the global object on the stack with the result if needed. |
DropAndMove(context, r0); |
- } 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: { |
+ MemOperand target = MemOperand(fp, SlotOffset(slot)); |
switch (context) { |
case Expression::kUninitialized: |
UNREACHABLE(); |
case Expression::kEffect: |
// Perform assignment and discard value. |
__ pop(r0); |
- __ str(r0, MemOperand(fp, SlotOffset(var->slot()))); |
+ __ str(r0, target); |
break; |
case Expression::kValue: |
// Perform assignment and preserve value. |
__ ldr(r0, MemOperand(sp)); |
- __ str(r0, MemOperand(fp, SlotOffset(var->slot()))); |
+ __ str(r0, target); |
break; |
case Expression::kTest: |
// Perform assignment and test (and discard) value. |
__ pop(r0); |
- __ str(r0, MemOperand(fp, SlotOffset(var->slot()))); |
+ __ str(r0, target); |
TestAndBranch(r0, true_label_, false_label_); |
break; |
case Expression::kValueTest: { |
Label discard; |
__ ldr(r0, MemOperand(sp)); |
- __ str(r0, MemOperand(fp, SlotOffset(var->slot()))); |
+ __ str(r0, target); |
TestAndBranch(r0, true_label_, &discard); |
__ bind(&discard); |
__ pop(); |
@@ -950,7 +941,7 @@ |
case Expression::kTestValue: { |
Label discard; |
__ ldr(r0, MemOperand(sp)); |
- __ str(r0, MemOperand(fp, SlotOffset(var->slot()))); |
+ __ str(r0, target); |
TestAndBranch(r0, &discard, false_label_); |
__ bind(&discard); |
__ pop(); |
@@ -962,31 +953,15 @@ |
} |
case Slot::CONTEXT: { |
- 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. |
- __ ldr(r0, CodeGenerator::ContextOperand(cp, Context::CLOSURE_INDEX)); |
- // Load the function context (which is the incoming, outer context). |
- __ ldr(r0, FieldMemOperand(r0, JSFunction::kContextOffset)); |
- for (int i = 1; i < chain_length; i++) { |
- __ ldr(r0, |
- CodeGenerator::ContextOperand(r0, Context::CLOSURE_INDEX)); |
- __ ldr(r0, FieldMemOperand(r0, JSFunction::kContextOffset)); |
- } |
- } else { // Slot is in the current context. Generate optimized code. |
- __ mov(r0, cp); |
- } |
- // The context may be an intermediate context, not a function context. |
- __ ldr(r0, CodeGenerator::ContextOperand(r0, Context::FCONTEXT_INDEX)); |
- __ pop(r1); |
- __ str(r1, CodeGenerator::ContextOperand(r0, slot->index())); |
+ MemOperand target = EmitSlotSearch(slot, r1); |
+ __ pop(r0); |
+ __ str(r0, target); |
// RecordWrite may destroy all its register arguments. |
if (context == Expression::kValue) { |
- __ push(r1); |
+ __ push(r0); |
} else if (context != Expression::kEffect) { |
- __ mov(r3, r1); |
+ __ mov(r3, r0); |
} |
int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; |
@@ -994,14 +969,13 @@ |
// register. Skip the write barrier if the value written (r1) is a smi. |
// The smi test is part of RecordWrite on other platforms, not on arm. |
Label exit; |
- __ tst(r1, Operand(kSmiTagMask)); |
+ __ tst(r0, Operand(kSmiTagMask)); |
__ b(eq, &exit); |
__ mov(r2, Operand(offset)); |
- __ RecordWrite(r0, r2, r1); |
+ __ RecordWrite(r1, r2, r0); |
__ bind(&exit); |
- if (context != Expression::kEffect && |
- context != Expression::kValue) { |
+ if (context != Expression::kEffect && context != Expression::kValue) { |
Move(context, r3); |
} |
break; |
@@ -1011,6 +985,10 @@ |
UNREACHABLE(); |
break; |
} |
+ } else { |
+ // Variables rewritten as properties are not treated as variables in |
+ // assignments. |
+ UNREACHABLE(); |
} |
} |