Index: src/x64/macro-assembler-x64.cc |
diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc |
index 77a7198a49e396623e7026f7320fa423cd0186e2..76200d7e5482bfbeafa842ee31588c5700594e3f 100644 |
--- a/src/x64/macro-assembler-x64.cc |
+++ b/src/x64/macro-assembler-x64.cc |
@@ -467,7 +467,7 @@ void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) { |
void MacroAssembler::Set(Register dst, int64_t x) { |
if (x == 0) { |
- xor_(dst, dst); |
+ xorl(dst, dst); |
} else if (is_int32(x)) { |
movq(dst, Immediate(static_cast<int32_t>(x))); |
} else if (is_uint32(x)) { |
@@ -477,7 +477,6 @@ void MacroAssembler::Set(Register dst, int64_t x) { |
} |
} |
- |
void MacroAssembler::Set(const Operand& dst, int64_t x) { |
if (is_int32(x)) { |
movq(dst, Immediate(static_cast<int32_t>(x))); |
@@ -492,6 +491,78 @@ void MacroAssembler::Set(const Operand& dst, int64_t x) { |
static int kSmiShift = kSmiTagSize + kSmiShiftSize; |
+Register MacroAssembler::GetSmiConstant(Smi* source) { |
+ int value = source->value(); |
+ if (value == 0) { |
+ xorl(kScratchRegister, kScratchRegister); |
+ return kScratchRegister; |
+ } |
+ if (value == 1) { |
+ return kSmiConstantRegister; |
+ } |
+ LoadSmiConstant(kScratchRegister, source); |
+ return kScratchRegister; |
+} |
+ |
+void MacroAssembler::LoadSmiConstant(Register dst, Smi* source) { |
+ if (FLAG_debug_code) { |
+ movq(dst, |
+ reinterpret_cast<uint64_t>(Smi::FromInt(kSmiConstantRegisterValue)), |
+ RelocInfo::NONE); |
+ cmpq(dst, kSmiConstantRegister); |
+ if (allow_stub_calls()) { |
+ Assert(equal, "Uninitialized kSmiConstantRegister"); |
+ } else { |
+ Label ok; |
+ j(equal, &ok); |
+ int3(); |
+ bind(&ok); |
+ } |
+ } |
+ if (source->value() == 0) { |
+ xorl(dst, dst); |
+ return; |
+ } |
+ int value = source->value(); |
+ bool negative = value < 0; |
+ unsigned int uvalue = negative ? -value : value; |
+ |
+ switch (uvalue) { |
+ case 9: |
+ lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_8, 0)); |
+ break; |
+ case 8: |
+ xorl(dst, dst); |
+ lea(dst, Operand(dst, kSmiConstantRegister, times_8, 0)); |
+ break; |
+ case 4: |
+ xorl(dst, dst); |
+ lea(dst, Operand(dst, kSmiConstantRegister, times_4, 0)); |
+ break; |
+ case 5: |
+ lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_4, 0)); |
+ break; |
+ case 3: |
+ lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_2, 0)); |
+ break; |
+ case 2: |
+ lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_1, 0)); |
+ break; |
+ case 1: |
+ movq(dst, kSmiConstantRegister); |
+ break; |
+ case 0: |
+ UNREACHABLE(); |
+ return; |
+ default: |
+ movq(dst, reinterpret_cast<uint64_t>(source), RelocInfo::NONE); |
+ return; |
+ } |
+ if (negative) { |
+ neg(dst); |
+ } |
+} |
+ |
void MacroAssembler::Integer32ToSmi(Register dst, Register src) { |
ASSERT_EQ(0, kSmiTag); |
if (!dst.is(src)) { |
@@ -652,9 +723,10 @@ Condition MacroAssembler::CheckSmi(Register src) { |
Condition MacroAssembler::CheckPositiveSmi(Register src) { |
ASSERT_EQ(0, kSmiTag); |
+ // Make mask 0x8000000000000001 and test that both bits are zero. |
movq(kScratchRegister, src); |
rol(kScratchRegister, Immediate(1)); |
- testl(kScratchRegister, Immediate(0x03)); |
+ testb(kScratchRegister, Immediate(3)); |
return zero; |
} |
@@ -683,7 +755,6 @@ Condition MacroAssembler::CheckBothPositiveSmi(Register first, |
} |
- |
Condition MacroAssembler::CheckEitherSmi(Register first, Register second) { |
if (first.is(second)) { |
return CheckSmi(first); |
@@ -696,11 +767,10 @@ Condition MacroAssembler::CheckEitherSmi(Register first, Register second) { |
Condition MacroAssembler::CheckIsMinSmi(Register src) { |
- ASSERT(kSmiTag == 0 && kSmiTagSize == 1); |
- movq(kScratchRegister, src); |
- rol(kScratchRegister, Immediate(1)); |
- cmpq(kScratchRegister, Immediate(1)); |
- return equal; |
+ ASSERT(!src.is(kScratchRegister)); |
+ // If we overflow by subtracting one, it's the minimal smi value. |
+ cmpq(src, kSmiConstantRegister); |
+ return overflow; |
} |
@@ -713,8 +783,8 @@ Condition MacroAssembler::CheckInteger32ValidSmiValue(Register src) { |
Condition MacroAssembler::CheckUInteger32ValidSmiValue(Register src) { |
// An unsigned 32-bit integer value is valid as long as the high bit |
// is not set. |
- testq(src, Immediate(0x80000000)); |
- return zero; |
+ testl(src, src); |
+ return positive; |
} |
@@ -807,10 +877,10 @@ void MacroAssembler::SmiSub(Register dst, |
} |
Assert(no_overflow, "Smi subtraction overflow"); |
} else if (dst.is(src1)) { |
- movq(kScratchRegister, src1); |
- subq(kScratchRegister, src2); |
+ movq(kScratchRegister, src2); |
+ cmpq(src1, kScratchRegister); |
j(overflow, on_not_smi_result); |
- movq(src1, kScratchRegister); |
+ subq(src1, kScratchRegister); |
} else { |
movq(dst, src1); |
subq(dst, src2); |
@@ -883,7 +953,7 @@ void MacroAssembler::SmiTryAddConstant(Register dst, |
JumpIfNotSmi(src, on_not_smi_result); |
Register tmp = (dst.is(src) ? kScratchRegister : dst); |
- Move(tmp, constant); |
+ LoadSmiConstant(tmp, constant); |
addq(tmp, src); |
j(overflow, on_not_smi_result); |
if (dst.is(src)) { |
@@ -897,14 +967,46 @@ void MacroAssembler::SmiAddConstant(Register dst, Register src, Smi* constant) { |
if (!dst.is(src)) { |
movq(dst, src); |
} |
+ return; |
} else if (dst.is(src)) { |
ASSERT(!dst.is(kScratchRegister)); |
- |
- Move(kScratchRegister, constant); |
- addq(dst, kScratchRegister); |
+ switch (constant->value()) { |
+ case 1: |
+ addq(dst, kSmiConstantRegister); |
+ return; |
+ case 2: |
+ lea(dst, Operand(src, kSmiConstantRegister, times_2, 0)); |
+ return; |
+ case 4: |
+ lea(dst, Operand(src, kSmiConstantRegister, times_4, 0)); |
+ return; |
+ case 8: |
+ lea(dst, Operand(src, kSmiConstantRegister, times_8, 0)); |
+ return; |
+ default: |
+ Register constant_reg = GetSmiConstant(constant); |
+ addq(dst, constant_reg); |
+ return; |
+ } |
} else { |
- Move(dst, constant); |
- addq(dst, src); |
+ switch (constant->value()) { |
+ case 1: |
+ lea(dst, Operand(src, kSmiConstantRegister, times_1, 0)); |
+ return; |
+ case 2: |
+ lea(dst, Operand(src, kSmiConstantRegister, times_2, 0)); |
+ return; |
+ case 4: |
+ lea(dst, Operand(src, kSmiConstantRegister, times_4, 0)); |
+ return; |
+ case 8: |
+ lea(dst, Operand(src, kSmiConstantRegister, times_8, 0)); |
+ return; |
+ default: |
+ LoadSmiConstant(dst, constant); |
+ addq(dst, src); |
+ return; |
+ } |
} |
} |
@@ -927,12 +1029,12 @@ void MacroAssembler::SmiAddConstant(Register dst, |
} else if (dst.is(src)) { |
ASSERT(!dst.is(kScratchRegister)); |
- Move(kScratchRegister, constant); |
- addq(kScratchRegister, dst); |
+ LoadSmiConstant(kScratchRegister, constant); |
+ addq(kScratchRegister, src); |
j(overflow, on_not_smi_result); |
movq(dst, kScratchRegister); |
} else { |
- Move(dst, constant); |
+ LoadSmiConstant(dst, constant); |
addq(dst, src); |
j(overflow, on_not_smi_result); |
} |
@@ -946,19 +1048,17 @@ void MacroAssembler::SmiSubConstant(Register dst, Register src, Smi* constant) { |
} |
} else if (dst.is(src)) { |
ASSERT(!dst.is(kScratchRegister)); |
- |
- Move(kScratchRegister, constant); |
- subq(dst, kScratchRegister); |
+ Register constant_reg = GetSmiConstant(constant); |
+ subq(dst, constant_reg); |
} else { |
- // Subtract by adding the negative, to do it in two operations. |
if (constant->value() == Smi::kMinValue) { |
- Move(dst, constant); |
+ LoadSmiConstant(dst, constant); |
// Adding and subtracting the min-value gives the same result, it only |
// differs on the overflow bit, which we don't check here. |
addq(dst, src); |
} else { |
// Subtract by adding the negation. |
- Move(dst, Smi::FromInt(-constant->value())); |
+ LoadSmiConstant(dst, Smi::FromInt(-constant->value())); |
addq(dst, src); |
} |
} |
@@ -980,11 +1080,11 @@ void MacroAssembler::SmiSubConstant(Register dst, |
// We test the non-negativeness before doing the subtraction. |
testq(src, src); |
j(not_sign, on_not_smi_result); |
- Move(kScratchRegister, constant); |
+ LoadSmiConstant(kScratchRegister, constant); |
subq(dst, kScratchRegister); |
} else { |
// Subtract by adding the negation. |
- Move(kScratchRegister, Smi::FromInt(-constant->value())); |
+ LoadSmiConstant(kScratchRegister, Smi::FromInt(-constant->value())); |
addq(kScratchRegister, dst); |
j(overflow, on_not_smi_result); |
movq(dst, kScratchRegister); |
@@ -995,13 +1095,13 @@ void MacroAssembler::SmiSubConstant(Register dst, |
// We test the non-negativeness before doing the subtraction. |
testq(src, src); |
j(not_sign, on_not_smi_result); |
- Move(dst, constant); |
+ LoadSmiConstant(dst, constant); |
// Adding and subtracting the min-value gives the same result, it only |
// differs on the overflow bit, which we don't check here. |
addq(dst, src); |
} else { |
// Subtract by adding the negation. |
- Move(dst, Smi::FromInt(-(constant->value()))); |
+ LoadSmiConstant(dst, Smi::FromInt(-(constant->value()))); |
addq(dst, src); |
j(overflow, on_not_smi_result); |
} |
@@ -1155,10 +1255,10 @@ void MacroAssembler::SmiAndConstant(Register dst, Register src, Smi* constant) { |
xor_(dst, dst); |
} else if (dst.is(src)) { |
ASSERT(!dst.is(kScratchRegister)); |
- Move(kScratchRegister, constant); |
- and_(dst, kScratchRegister); |
+ Register constant_reg = GetSmiConstant(constant); |
+ and_(dst, constant_reg); |
} else { |
- Move(dst, constant); |
+ LoadSmiConstant(dst, constant); |
and_(dst, src); |
} |
} |
@@ -1175,10 +1275,10 @@ void MacroAssembler::SmiOr(Register dst, Register src1, Register src2) { |
void MacroAssembler::SmiOrConstant(Register dst, Register src, Smi* constant) { |
if (dst.is(src)) { |
ASSERT(!dst.is(kScratchRegister)); |
- Move(kScratchRegister, constant); |
- or_(dst, kScratchRegister); |
+ Register constant_reg = GetSmiConstant(constant); |
+ or_(dst, constant_reg); |
} else { |
- Move(dst, constant); |
+ LoadSmiConstant(dst, constant); |
or_(dst, src); |
} |
} |
@@ -1195,10 +1295,10 @@ void MacroAssembler::SmiXor(Register dst, Register src1, Register src2) { |
void MacroAssembler::SmiXorConstant(Register dst, Register src, Smi* constant) { |
if (dst.is(src)) { |
ASSERT(!dst.is(kScratchRegister)); |
- Move(kScratchRegister, constant); |
- xor_(dst, kScratchRegister); |
+ Register constant_reg = GetSmiConstant(constant); |
+ xor_(dst, constant_reg); |
} else { |
- Move(dst, constant); |
+ LoadSmiConstant(dst, constant); |
xor_(dst, src); |
} |
} |
@@ -1366,6 +1466,7 @@ void MacroAssembler::SelectNonSmi(Register dst, |
// If src1 is a smi, dst is src2, else it is src1, i.e., the non-smi. |
} |
+ |
SmiIndex MacroAssembler::SmiToIndex(Register dst, |
Register src, |
int shift) { |
@@ -1591,8 +1692,8 @@ void MacroAssembler::Push(Smi* source) { |
if (is_int32(smi)) { |
push(Immediate(static_cast<int32_t>(smi))); |
} else { |
- Set(kScratchRegister, smi); |
- push(kScratchRegister); |
+ Register constant = GetSmiConstant(source); |
+ push(constant); |
} |
} |
@@ -2132,10 +2233,10 @@ void MacroAssembler::EnterExitFrame(ExitFrame::Mode mode, int result_size) { |
movq(rax, rsi); |
store_rax(context_address); |
- // Setup argv in callee-saved register r15. It is reused in LeaveExitFrame, |
+ // Setup argv in callee-saved register r12. It is reused in LeaveExitFrame, |
// so it must be retained across the C-call. |
int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize; |
- lea(r15, Operand(rbp, r14, times_pointer_size, offset)); |
+ lea(r12, Operand(rbp, r14, times_pointer_size, offset)); |
#ifdef ENABLE_DEBUGGER_SUPPORT |
// Save the state of all registers to the stack from the memory |
@@ -2181,7 +2282,7 @@ void MacroAssembler::EnterExitFrame(ExitFrame::Mode mode, int result_size) { |
void MacroAssembler::LeaveExitFrame(ExitFrame::Mode mode, int result_size) { |
// Registers: |
- // r15 : argv |
+ // r12 : argv |
#ifdef ENABLE_DEBUGGER_SUPPORT |
// Restore the memory copy of the registers by digging them out from |
// the stack. This is needed to allow nested break points. |
@@ -2201,7 +2302,7 @@ void MacroAssembler::LeaveExitFrame(ExitFrame::Mode mode, int result_size) { |
// Pop everything up to and including the arguments and the receiver |
// from the caller stack. |
- lea(rsp, Operand(r15, 1 * kPointerSize)); |
+ lea(rsp, Operand(r12, 1 * kPointerSize)); |
// Restore current context from top and clear it in debug mode. |
ExternalReference context_address(Top::k_context_address); |