Index: src/arm/cfg-arm.cc |
=================================================================== |
--- src/arm/cfg-arm.cc (revision 2620) |
+++ src/arm/cfg-arm.cc (working copy) |
@@ -29,6 +29,7 @@ |
#include "cfg.h" |
#include "codegen-inl.h" |
+#include "codegen-arm.h" // Include after codegen-inl.h. |
#include "macro-assembler-arm.h" |
namespace v8 { |
@@ -42,6 +43,14 @@ |
{ |
Comment cmt(masm, "[ InstructionBlock"); |
for (int i = 0, len = instructions_.length(); i < len; i++) { |
+ // If the location of the current instruction is a temp, then the |
+ // instruction cannot be in tail position in the block. Allocate the |
+ // temp based on peeking ahead to the next instruction. |
+ Instruction* instr = instructions_[i]; |
+ Location* loc = instr->location(); |
+ if (loc->is_temporary()) { |
+ instructions_[i+1]->FastAllocate(TempLocation::cast(loc)); |
+ } |
instructions_[i]->Compile(masm); |
} |
} |
@@ -91,34 +100,123 @@ |
} |
+void BinaryOpInstr::Compile(MacroAssembler* masm) { |
+ // The right value should not be on the stack---if it is a |
+ // compiler-generated temporary it is in the accumulator. |
+ ASSERT(!val1_->is_on_stack()); |
+ |
+ // We can overwrite one of the operands if it is a temporary. |
+ OverwriteMode mode = NO_OVERWRITE; |
+ if (val0_->is_temporary()) { |
+ mode = OVERWRITE_LEFT; |
+ } else if (val1_->is_temporary()) { |
+ mode = OVERWRITE_RIGHT; |
+ } |
+ |
+ // Move left to r1 and right to r0. |
+ val0_->Get(masm, r1); |
+ val1_->Get(masm, r0); |
+ GenericBinaryOpStub stub(op_, mode); |
+ __ CallStub(&stub); |
+ loc_->Set(masm, r0); |
+} |
+ |
+ |
void ReturnInstr::Compile(MacroAssembler* masm) { |
+ // The location should be 'Effect'. As a side effect, move the value to |
+ // the accumulator. |
Comment cmnt(masm, "[ ReturnInstr"); |
- value_->ToRegister(masm, r0); |
+ value_->Get(masm, r0); |
} |
-void Constant::ToRegister(MacroAssembler* masm, Register reg) { |
+void Constant::Get(MacroAssembler* masm, Register reg) { |
__ mov(reg, Operand(handle_)); |
} |
-void SlotLocation::ToRegister(MacroAssembler* masm, Register reg) { |
- switch (type_) { |
+void Constant::Push(MacroAssembler* masm) { |
+ __ mov(ip, Operand(handle_)); |
+ __ push(ip); |
+} |
+ |
+ |
+static MemOperand ToMemOperand(SlotLocation* loc) { |
+ switch (loc->type()) { |
case Slot::PARAMETER: { |
int count = CfgGlobals::current()->fun()->scope()->num_parameters(); |
- __ ldr(reg, MemOperand(fp, (1 + count - index_) * kPointerSize)); |
- break; |
+ return MemOperand(fp, (1 + count - loc->index()) * kPointerSize); |
} |
case Slot::LOCAL: { |
const int kOffset = JavaScriptFrameConstants::kLocal0Offset; |
- __ ldr(reg, MemOperand(fp, kOffset - index_ * kPointerSize)); |
- break; |
+ return MemOperand(fp, kOffset - loc->index() * kPointerSize); |
} |
default: |
UNREACHABLE(); |
+ return MemOperand(r0); |
} |
} |
+ |
+void SlotLocation::Get(MacroAssembler* masm, Register reg) { |
+ __ ldr(reg, ToMemOperand(this)); |
+} |
+ |
+ |
+void SlotLocation::Set(MacroAssembler* masm, Register reg) { |
+ __ str(reg, ToMemOperand(this)); |
+} |
+ |
+ |
+void SlotLocation::Push(MacroAssembler* masm) { |
+ __ ldr(ip, ToMemOperand(this)); |
+ __ push(ip); // Push will not destroy ip. |
+} |
+ |
+ |
+void TempLocation::Get(MacroAssembler* masm, Register reg) { |
+ switch (where_) { |
+ case ACCUMULATOR: |
+ if (!reg.is(r0)) __ mov(reg, r0); |
+ break; |
+ case STACK: |
+ __ pop(reg); |
+ break; |
+ case NOWHERE: |
+ UNREACHABLE(); |
+ break; |
+ } |
+} |
+ |
+ |
+void TempLocation::Set(MacroAssembler* masm, Register reg) { |
+ switch (where_) { |
+ case ACCUMULATOR: |
+ if (!reg.is(r0)) __ mov(r0, reg); |
+ break; |
+ case STACK: |
+ __ push(reg); |
+ break; |
+ case NOWHERE: |
+ UNREACHABLE(); |
+ break; |
+ } |
+} |
+ |
+ |
+void TempLocation::Push(MacroAssembler* masm) { |
+ switch (where_) { |
+ case ACCUMULATOR: |
+ __ push(r0); |
+ break; |
+ case STACK: |
+ case NOWHERE: |
+ UNREACHABLE(); |
+ break; |
+ } |
+} |
+ |
+ |
#undef __ |
} } // namespace v8::internal |