Index: src/x64/cfg-x64.cc |
=================================================================== |
--- src/x64/cfg-x64.cc (revision 2620) |
+++ src/x64/cfg-x64.cc (working copy) |
@@ -29,6 +29,7 @@ |
#include "cfg.h" |
#include "codegen-inl.h" |
+#include "codegen-x64.h" |
#include "debug.h" |
#include "macro-assembler-x64.h" |
@@ -43,6 +44,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); |
} |
} |
@@ -113,34 +122,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; |
+ } |
+ |
+ // Push both operands and call the specialized stub. |
+ if (!val0_->is_on_stack()) { |
+ val0_->Push(masm); |
+ } |
+ val1_->Push(masm); |
+ GenericBinaryOpStub stub(op_, mode, SMI_CODE_IN_STUB); |
+ __ CallStub(&stub); |
+ loc_->Set(masm, rax); |
+} |
+ |
+ |
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, rax); |
+ value_->Get(masm, rax); |
} |
-void Constant::ToRegister(MacroAssembler* masm, Register reg) { |
+void Constant::Get(MacroAssembler* masm, Register reg) { |
__ Move(reg, handle_); |
} |
-void SlotLocation::ToRegister(MacroAssembler* masm, Register reg) { |
- switch (type_) { |
+void Constant::Push(MacroAssembler* masm) { |
+ __ Push(handle_); |
+} |
+ |
+ |
+static Operand ToOperand(SlotLocation* loc) { |
+ switch (loc->type()) { |
case Slot::PARAMETER: { |
int count = CfgGlobals::current()->fun()->scope()->num_parameters(); |
- __ movq(reg, Operand(rbp, (1 + count - index_) * kPointerSize)); |
- break; |
+ return Operand(rbp, (1 + count - loc->index()) * kPointerSize); |
} |
case Slot::LOCAL: { |
const int kOffset = JavaScriptFrameConstants::kLocal0Offset; |
- __ movq(reg, Operand(rbp, kOffset - index_ * kPointerSize)); |
- break; |
+ return Operand(rbp, kOffset - loc->index() * kPointerSize); |
} |
default: |
UNREACHABLE(); |
+ return Operand(rax, 0); |
} |
} |
+ |
+void SlotLocation::Get(MacroAssembler* masm, Register reg) { |
+ __ movq(reg, ToOperand(this)); |
+} |
+ |
+ |
+void SlotLocation::Set(MacroAssembler* masm, Register reg) { |
+ __ movq(ToOperand(this), reg); |
+} |
+ |
+ |
+void SlotLocation::Push(MacroAssembler* masm) { |
+ __ push(ToOperand(this)); |
+} |
+ |
+ |
+void TempLocation::Get(MacroAssembler* masm, Register reg) { |
+ switch (where_) { |
+ case ACCUMULATOR: |
+ if (!reg.is(rax)) __ movq(reg, rax); |
+ break; |
+ case STACK: |
+ __ pop(reg); |
+ break; |
+ case NOWHERE: |
+ UNREACHABLE(); |
+ break; |
+ } |
+} |
+ |
+ |
+void TempLocation::Set(MacroAssembler* masm, Register reg) { |
+ switch (where_) { |
+ case ACCUMULATOR: |
+ if (!reg.is(rax)) __ movq(rax, reg); |
+ break; |
+ case STACK: |
+ __ push(reg); |
+ break; |
+ case NOWHERE: |
+ UNREACHABLE(); |
+ break; |
+ } |
+} |
+ |
+ |
+void TempLocation::Push(MacroAssembler* masm) { |
+ switch (where_) { |
+ case ACCUMULATOR: |
+ __ push(rax); |
+ break; |
+ case STACK: |
+ case NOWHERE: |
+ UNREACHABLE(); |
+ break; |
+ } |
+} |
+ |
+ |
#undef __ |
} } // namespace v8::internal |