Index: src/x64/macro-assembler-x64.cc |
diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc |
index 2689e388b6ea6cdff1d9e236df8438922c52ae0a..5f7fef332b18dbeef32453d0dbd27c668afd11d3 100644 |
--- a/src/x64/macro-assembler-x64.cc |
+++ b/src/x64/macro-assembler-x64.cc |
@@ -38,16 +38,15 @@ namespace v8 { |
namespace internal { |
MacroAssembler::MacroAssembler(void* buffer, int size) |
- : Assembler(buffer, size), |
- unresolved_(0), |
- generating_stub_(false), |
- allow_stub_calls_(true), |
- code_object_(Heap::undefined_value()) { |
+ : Assembler(buffer, size), |
+ unresolved_(0), |
+ generating_stub_(false), |
+ allow_stub_calls_(true), |
+ code_object_(Heap::undefined_value()) { |
} |
-void MacroAssembler::LoadRoot(Register destination, |
- Heap::RootListIndex index) { |
+void MacroAssembler::LoadRoot(Register destination, Heap::RootListIndex index) { |
movq(destination, Operand(r13, index << kPointerSizeLog2)); |
} |
@@ -57,14 +56,12 @@ void MacroAssembler::PushRoot(Heap::RootListIndex index) { |
} |
-void MacroAssembler::CompareRoot(Register with, |
- Heap::RootListIndex index) { |
+void MacroAssembler::CompareRoot(Register with, Heap::RootListIndex index) { |
cmpq(with, Operand(r13, index << kPointerSizeLog2)); |
} |
-void MacroAssembler::CompareRoot(Operand with, |
- Heap::RootListIndex index) { |
+void MacroAssembler::CompareRoot(Operand with, Heap::RootListIndex index) { |
LoadRoot(kScratchRegister, index); |
cmpq(with, kScratchRegister); |
} |
@@ -98,9 +95,8 @@ static void RecordWriteHelper(MacroAssembler* masm, |
// extra remembered set after the large object. |
// Load the array length into 'scratch'. |
- masm->movl(scratch, |
- Operand(page_start, |
- Page::kObjectStartOffset + FixedArray::kLengthOffset)); |
+ masm->movl(scratch, Operand(page_start, Page::kObjectStartOffset |
+ + FixedArray::kLengthOffset)); |
Register array_length = scratch; |
// Extra remembered set starts right after the large object (a FixedArray), at |
@@ -109,10 +105,10 @@ static void RecordWriteHelper(MacroAssembler* masm, |
// Add the delta between the end of the normal RSet and the start of the |
// extra RSet to 'page_start', so that addressing the bit using |
// 'pointer_offset' hits the extra RSet words. |
- masm->lea(page_start, |
- Operand(page_start, array_length, times_pointer_size, |
- Page::kObjectStartOffset + FixedArray::kHeaderSize |
- - Page::kRSetEndOffset)); |
+ masm->lea(page_start, Operand(page_start, array_length, times_pointer_size, |
+ Page::kObjectStartOffset |
+ + FixedArray::kHeaderSize |
+ - Page::kRSetEndOffset)); |
// NOTE: For now, we use the bit-test-and-set (bts) x86 instruction |
// to limit code size. We should probably evaluate this decision by |
@@ -126,7 +122,8 @@ static void RecordWriteHelper(MacroAssembler* masm, |
class RecordWriteStub : public CodeStub { |
public: |
RecordWriteStub(Register object, Register addr, Register scratch) |
- : object_(object), addr_(addr), scratch_(scratch) { } |
+ : object_(object), addr_(addr), scratch_(scratch) { |
+ } |
void Generate(MacroAssembler* masm); |
@@ -144,11 +141,13 @@ class RecordWriteStub : public CodeStub { |
// Minor key encoding in 12 bits of three registers (object, address and |
// scratch) OOOOAAAASSSS. |
- class ScratchBits: public BitField<uint32_t, 0, 4> {}; |
- class AddressBits: public BitField<uint32_t, 4, 4> {}; |
- class ObjectBits: public BitField<uint32_t, 8, 4> {}; |
+ class ScratchBits : public BitField<uint32_t, 0, 4> {}; |
+ class AddressBits : public BitField<uint32_t, 4, 4> {}; |
+ class ObjectBits : public BitField<uint32_t, 8, 4> {}; |
- Major MajorKey() { return RecordWrite; } |
+ Major MajorKey() { |
+ return RecordWrite; |
+ } |
int MinorKey() { |
// Encode the registers. |
@@ -158,42 +157,52 @@ class RecordWriteStub : public CodeStub { |
} |
}; |
- |
void RecordWriteStub::Generate(MacroAssembler* masm) { |
RecordWriteHelper(masm, object_, addr_, scratch_); |
masm->ret(0); |
} |
- |
// Set the remembered set bit for [object+offset]. |
// object is the object being stored into, value is the object being stored. |
-// If offset is zero, then the scratch register contains the array index into |
-// the elements array represented as a Smi. |
+// If offset is zero, then the smi_index register contains the array index into |
+// the elements array represented as a smi. Otherwise it can be used as a |
+// scratch register. |
// All registers are clobbered by the operation. |
void MacroAssembler::RecordWrite(Register object, |
int offset, |
Register value, |
- Register scratch) { |
+ Register smi_index) { |
// First, check if a remembered set write is even needed. The tests below |
// catch stores of Smis and stores into young gen (which does not have space |
// for the remembered set bits. |
Label done; |
+ JumpIfSmi(value, &done); |
+ |
+ RecordWriteNonSmi(object, offset, value, smi_index); |
+ bind(&done); |
+} |
+ |
+void MacroAssembler::RecordWriteNonSmi(Register object, |
+ int offset, |
+ Register scratch, |
+ Register smi_index) { |
+ Label done; |
// Test that the object address is not in the new space. We cannot |
// set remembered set bits in the new space. |
- movq(value, object); |
+ movq(scratch, object); |
ASSERT(is_int32(static_cast<int64_t>(Heap::NewSpaceMask()))); |
- and_(value, Immediate(static_cast<int32_t>(Heap::NewSpaceMask()))); |
+ and_(scratch, Immediate(static_cast<int32_t>(Heap::NewSpaceMask()))); |
movq(kScratchRegister, ExternalReference::new_space_start()); |
- cmpq(value, kScratchRegister); |
+ cmpq(scratch, kScratchRegister); |
j(equal, &done); |
if ((offset > 0) && (offset < Page::kMaxHeapObjectSize)) { |
// Compute the bit offset in the remembered set, leave it in 'value'. |
- lea(value, Operand(object, offset)); |
+ lea(scratch, Operand(object, offset)); |
ASSERT(is_int32(Page::kPageAlignmentMask)); |
- and_(value, Immediate(static_cast<int32_t>(Page::kPageAlignmentMask))); |
- shr(value, Immediate(kObjectAlignmentBits)); |
+ and_(scratch, Immediate(static_cast<int32_t>(Page::kPageAlignmentMask))); |
+ shr(scratch, Immediate(kObjectAlignmentBits)); |
// Compute the page address from the heap object pointer, leave it in |
// 'object' (immediate value is sign extended). |
@@ -203,24 +212,26 @@ void MacroAssembler::RecordWrite(Register object, |
// to limit code size. We should probably evaluate this decision by |
// measuring the performance of an equivalent implementation using |
// "simpler" instructions |
- bts(Operand(object, Page::kRSetOffset), value); |
+ bts(Operand(object, Page::kRSetOffset), scratch); |
} else { |
- Register dst = scratch; |
+ Register dst = smi_index; |
if (offset != 0) { |
lea(dst, Operand(object, offset)); |
} else { |
// array access: calculate the destination address in the same manner as |
- // KeyedStoreIC::GenerateGeneric. Multiply a smi by 4 to get an offset |
- // into an array of pointers. |
- lea(dst, Operand(object, dst, times_half_pointer_size, |
+ // KeyedStoreIC::GenerateGeneric. |
+ SmiIndex index = SmiToIndex(smi_index, smi_index, kPointerSizeLog2); |
+ lea(dst, Operand(object, |
+ index.reg, |
+ index.scale, |
FixedArray::kHeaderSize - kHeapObjectTag)); |
} |
// If we are already generating a shared stub, not inlining the |
// record write code isn't going to save us any memory. |
if (generating_stub()) { |
- RecordWriteHelper(this, object, dst, value); |
+ RecordWriteHelper(this, object, dst, scratch); |
} else { |
- RecordWriteStub stub(object, dst, value); |
+ RecordWriteStub stub(object, dst, scratch); |
CallStub(&stub); |
} |
} |
@@ -230,7 +241,8 @@ void MacroAssembler::RecordWrite(Register object, |
void MacroAssembler::Assert(Condition cc, const char* msg) { |
- if (FLAG_debug_code) Check(cc, msg); |
+ if (FLAG_debug_code) |
+ Check(cc, msg); |
} |
@@ -243,8 +255,7 @@ void MacroAssembler::Check(Condition cc, const char* msg) { |
} |
-void MacroAssembler::NegativeZeroTest(Register result, |
- Register op, |
+void MacroAssembler::NegativeZeroTest(Register result, Register op, |
Label* then_label) { |
Label ok; |
testl(result, result); |
@@ -325,8 +336,7 @@ void MacroAssembler::CallRuntime(Runtime::Function* f, int num_arguments) { |
void MacroAssembler::TailCallRuntime(ExternalReference const& ext, |
- int num_arguments, |
- int result_size) { |
+ int num_arguments, int result_size) { |
// ----------- S t a t e ------------- |
// -- rsp[0] : return address |
// -- rsp[8] : argument num_arguments - 1 |
@@ -370,7 +380,6 @@ void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) { |
addq(target, Immediate(Code::kHeaderSize - kHeapObjectTag)); |
} |
- |
Handle<Code> MacroAssembler::ResolveBuiltin(Builtins::JavaScript id, |
bool* resolved) { |
// Move the builtin function into the temporary function slot by |
@@ -384,7 +393,6 @@ Handle<Code> MacroAssembler::ResolveBuiltin(Builtins::JavaScript id, |
JSBuiltinsObject::kJSBuiltinsOffset + (id * kPointerSize); |
movq(rdi, FieldOperand(rdx, builtins_offset)); |
- |
return Builtins::GetCode(id, resolved); |
} |
@@ -416,68 +424,98 @@ void MacroAssembler::Set(const Operand& dst, int64_t x) { |
} |
} |
- |
// ---------------------------------------------------------------------------- |
// Smi tagging, untagging and tag detection. |
+#ifdef V8_LONG_SMI |
+ |
+static int kSmiShift = kSmiTagSize + kSmiShiftSize; |
void MacroAssembler::Integer32ToSmi(Register dst, Register src) { |
- ASSERT_EQ(1, kSmiTagSize); |
ASSERT_EQ(0, kSmiTag); |
-#ifdef DEBUG |
- cmpq(src, Immediate(0xC0000000u)); |
- Check(positive, "Smi conversion overflow"); |
-#endif |
- if (dst.is(src)) { |
- addl(dst, src); |
- } else { |
- lea(dst, Operand(src, src, times_1, 0)); |
+ if (!dst.is(src)) { |
+ movl(dst, src); |
} |
+ shl(dst, Immediate(kSmiShift)); |
} |
void MacroAssembler::Integer32ToSmi(Register dst, |
Register src, |
Label* on_overflow) { |
- ASSERT_EQ(1, kSmiTagSize); |
ASSERT_EQ(0, kSmiTag); |
+ // 32-bit integer always fits in a long smi. |
if (!dst.is(src)) { |
movl(dst, src); |
} |
- addl(dst, src); |
- j(overflow, on_overflow); |
+ shl(dst, Immediate(kSmiShift)); |
} |
-void MacroAssembler::Integer64AddToSmi(Register dst, |
- Register src, |
- int constant) { |
-#ifdef DEBUG |
- movl(kScratchRegister, src); |
- addl(kScratchRegister, Immediate(constant)); |
- Check(no_overflow, "Add-and-smi-convert overflow"); |
- Condition valid = CheckInteger32ValidSmiValue(kScratchRegister); |
- Check(valid, "Add-and-smi-convert overflow"); |
-#endif |
- lea(dst, Operand(src, src, times_1, constant << kSmiTagSize)); |
+void MacroAssembler::Integer64PlusConstantToSmi(Register dst, |
+ Register src, |
+ int constant) { |
+ if (dst.is(src)) { |
+ addq(dst, Immediate(constant)); |
+ } else { |
+ lea(dst, Operand(src, constant)); |
+ } |
+ shl(dst, Immediate(kSmiShift)); |
} |
void MacroAssembler::SmiToInteger32(Register dst, Register src) { |
- ASSERT_EQ(1, kSmiTagSize); |
ASSERT_EQ(0, kSmiTag); |
if (!dst.is(src)) { |
- movl(dst, src); |
+ movq(dst, src); |
} |
- sarl(dst, Immediate(kSmiTagSize)); |
+ shr(dst, Immediate(kSmiShift)); |
} |
void MacroAssembler::SmiToInteger64(Register dst, Register src) { |
- ASSERT_EQ(1, kSmiTagSize); |
ASSERT_EQ(0, kSmiTag); |
- movsxlq(dst, src); |
- sar(dst, Immediate(kSmiTagSize)); |
+ if (!dst.is(src)) { |
+ movq(dst, src); |
+ } |
+ sar(dst, Immediate(kSmiShift)); |
+} |
+ |
+ |
+void MacroAssembler::SmiTest(Register src) { |
+ testq(src, src); |
+} |
+ |
+ |
+void MacroAssembler::SmiCompare(Register dst, Register src) { |
+ cmpq(dst, src); |
+} |
+ |
+ |
+void MacroAssembler::SmiCompare(Register dst, Smi* src) { |
+ ASSERT(!dst.is(kScratchRegister)); |
+ if (src->value() == 0) { |
+ testq(dst, dst); |
+ } else { |
+ Move(kScratchRegister, src); |
+ cmpq(dst, kScratchRegister); |
+ } |
+} |
+ |
+ |
+void MacroAssembler::SmiCompare(const Operand& dst, Register src) { |
+ cmpq(dst, src); |
+} |
+ |
+ |
+void MacroAssembler::SmiCompare(const Operand& dst, Smi* src) { |
+ if (src->value() == 0) { |
+ // Only tagged long smi to have 32-bit representation. |
+ cmpq(dst, Immediate(0)); |
+ } else { |
+ Move(kScratchRegister, src); |
+ cmpq(dst, kScratchRegister); |
+ } |
} |
@@ -490,150 +528,834 @@ void MacroAssembler::PositiveSmiTimesPowerOfTwoToInteger64(Register dst, |
SmiToInteger64(dst, src); |
return; |
} |
- movsxlq(dst, src); |
- shl(dst, Immediate(power - 1)); |
+ if (!dst.is(src)) { |
+ movq(dst, src); |
+ } |
+ if (power < kSmiShift) { |
+ sar(dst, Immediate(kSmiShift - power)); |
+ } else if (power > kSmiShift) { |
+ shl(dst, Immediate(power - kSmiShift)); |
+ } |
} |
-void MacroAssembler::JumpIfSmi(Register src, Label* on_smi) { |
+ |
+Condition MacroAssembler::CheckSmi(Register src) { |
ASSERT_EQ(0, kSmiTag); |
- testl(src, Immediate(kSmiTagMask)); |
- j(zero, on_smi); |
+ testb(src, Immediate(kSmiTagMask)); |
+ return zero; |
} |
-void MacroAssembler::JumpIfNotSmi(Register src, Label* on_not_smi) { |
- Condition not_smi = CheckNotSmi(src); |
- j(not_smi, on_not_smi); |
+Condition MacroAssembler::CheckPositiveSmi(Register src) { |
+ ASSERT_EQ(0, kSmiTag); |
+ movq(kScratchRegister, src); |
+ rol(kScratchRegister, Immediate(1)); |
+ testl(kScratchRegister, Immediate(0x03)); |
+ return zero; |
} |
-void MacroAssembler::JumpIfNotPositiveSmi(Register src, |
- Label* on_not_positive_smi) { |
- Condition not_positive_smi = CheckNotPositiveSmi(src); |
- j(not_positive_smi, on_not_positive_smi); |
+Condition MacroAssembler::CheckBothSmi(Register first, Register second) { |
+ if (first.is(second)) { |
+ return CheckSmi(first); |
+ } |
+ movl(kScratchRegister, first); |
+ orl(kScratchRegister, second); |
+ testb(kScratchRegister, Immediate(kSmiTagMask)); |
+ return zero; |
} |
-void MacroAssembler::JumpIfSmiEqualsConstant(Register src, |
- int constant, |
- Label* on_equals) { |
- if (Smi::IsValid(constant)) { |
- Condition are_equal = CheckSmiEqualsConstant(src, constant); |
- j(are_equal, on_equals); |
+Condition MacroAssembler::CheckIsMinSmi(Register src) { |
+ ASSERT(kSmiTag == 0 && kSmiTagSize == 1); |
+ movq(kScratchRegister, src); |
+ rol(kScratchRegister, Immediate(1)); |
+ cmpq(kScratchRegister, Immediate(1)); |
+ return equal; |
+} |
+ |
+ |
+Condition MacroAssembler::CheckInteger32ValidSmiValue(Register src) { |
+ // A 32-bit integer value can always be converted to a smi. |
+ return always; |
+} |
+ |
+ |
+void MacroAssembler::SmiNeg(Register dst, Register src, Label* on_smi_result) { |
+ if (dst.is(src)) { |
+ ASSERT(!dst.is(kScratchRegister)); |
+ movq(kScratchRegister, src); |
+ neg(dst); // Low 32 bits are retained as zero by negation. |
+ // Test if result is zero or Smi::kMinValue. |
+ cmpq(dst, kScratchRegister); |
+ j(not_equal, on_smi_result); |
+ movq(src, kScratchRegister); |
+ } else { |
+ movq(dst, src); |
+ neg(dst); |
+ cmpq(dst, src); |
+ // If the result is zero or Smi::kMinValue, negation failed to create a smi. |
+ j(not_equal, on_smi_result); |
} |
} |
-void MacroAssembler::JumpIfSmiGreaterEqualsConstant(Register src, |
- int constant, |
- Label* on_greater_equals) { |
- if (Smi::IsValid(constant)) { |
- Condition are_greater_equal = CheckSmiGreaterEqualsConstant(src, constant); |
- j(are_greater_equal, on_greater_equals); |
- } else if (constant < Smi::kMinValue) { |
- jmp(on_greater_equals); |
+void MacroAssembler::SmiAdd(Register dst, |
+ Register src1, |
+ Register src2, |
+ Label* on_not_smi_result) { |
+ ASSERT(!dst.is(src2)); |
+ if (dst.is(src1)) { |
+ addq(dst, src2); |
+ Label smi_result; |
+ j(no_overflow, &smi_result); |
+ // Restore src1. |
+ subq(src1, src2); |
+ jmp(on_not_smi_result); |
+ bind(&smi_result); |
+ } else { |
+ movq(dst, src1); |
+ addq(dst, src2); |
+ j(overflow, on_not_smi_result); |
} |
} |
-void MacroAssembler::JumpIfNotValidSmiValue(Register src, Label* on_invalid) { |
- Condition is_valid = CheckInteger32ValidSmiValue(src); |
- j(ReverseCondition(is_valid), on_invalid); |
+void MacroAssembler::SmiSub(Register dst, |
+ Register src1, |
+ Register src2, |
+ Label* on_not_smi_result) { |
+ ASSERT(!dst.is(src2)); |
+ if (dst.is(src1)) { |
+ subq(dst, src2); |
+ Label smi_result; |
+ j(no_overflow, &smi_result); |
+ // Restore src1. |
+ addq(src1, src2); |
+ jmp(on_not_smi_result); |
+ bind(&smi_result); |
+ } else { |
+ movq(dst, src1); |
+ subq(dst, src2); |
+ j(overflow, on_not_smi_result); |
+ } |
} |
+void MacroAssembler::SmiMul(Register dst, |
+ Register src1, |
+ Register src2, |
+ Label* on_not_smi_result) { |
+ ASSERT(!dst.is(src2)); |
+ ASSERT(!dst.is(kScratchRegister)); |
+ ASSERT(!src1.is(kScratchRegister)); |
+ ASSERT(!src2.is(kScratchRegister)); |
-void MacroAssembler::JumpIfNotBothSmi(Register src1, |
- Register src2, |
- Label* on_not_both_smi) { |
- Condition not_both_smi = CheckNotBothSmi(src1, src2); |
- j(not_both_smi, on_not_both_smi); |
+ if (dst.is(src1)) { |
+ Label failure, zero_correct_result; |
+ movq(kScratchRegister, src1); // Create backup for later testing. |
+ SmiToInteger64(dst, src1); |
+ imul(dst, src2); |
+ j(overflow, &failure); |
+ |
+ // Check for negative zero result. If product is zero, and one |
+ // argument is negative, go to slow case. |
+ Label correct_result; |
+ testq(dst, dst); |
+ j(not_zero, &correct_result); |
+ |
+ movq(dst, kScratchRegister); |
+ xor_(dst, src2); |
+ j(positive, &zero_correct_result); // Result was positive zero. |
+ |
+ bind(&failure); // Reused failure exit, restores src1. |
+ movq(src1, kScratchRegister); |
+ jmp(on_not_smi_result); |
+ |
+ bind(&zero_correct_result); |
+ xor_(dst, dst); |
+ |
+ bind(&correct_result); |
+ } else { |
+ SmiToInteger64(dst, src1); |
+ imul(dst, src2); |
+ j(overflow, on_not_smi_result); |
+ // Check for negative zero result. If product is zero, and one |
+ // argument is negative, go to slow case. |
+ Label correct_result; |
+ testq(dst, dst); |
+ j(not_zero, &correct_result); |
+ // One of src1 and src2 is zero, the check whether the other is |
+ // negative. |
+ movq(kScratchRegister, src1); |
+ xor_(kScratchRegister, src2); |
+ j(negative, on_not_smi_result); |
+ bind(&correct_result); |
+ } |
} |
-Condition MacroAssembler::CheckSmi(Register src) { |
- testb(src, Immediate(kSmiTagMask)); |
- return zero; |
+ |
+void MacroAssembler::SmiTryAddConstant(Register dst, |
+ Register src, |
+ Smi* constant, |
+ Label* on_not_smi_result) { |
+ // Does not assume that src is a smi. |
+ ASSERT_EQ(1, kSmiTagMask); |
+ ASSERT_EQ(0, kSmiTag); |
+ ASSERT(!dst.is(kScratchRegister)); |
+ ASSERT(!src.is(kScratchRegister)); |
+ |
+ JumpIfNotSmi(src, on_not_smi_result); |
+ Register tmp = (dst.is(src) ? kScratchRegister : dst); |
+ Move(tmp, constant); |
+ addq(tmp, src); |
+ j(overflow, on_not_smi_result); |
+ if (dst.is(src)) { |
+ movq(dst, tmp); |
+ } |
+} |
+ |
+ |
+void MacroAssembler::SmiAddConstant(Register dst, Register src, Smi* constant) { |
+ if (constant->value() == 0) { |
+ if (!dst.is(src)) { |
+ movq(dst, src); |
+ } |
+ } else if (dst.is(src)) { |
+ ASSERT(!dst.is(kScratchRegister)); |
+ |
+ Move(kScratchRegister, constant); |
+ addq(dst, kScratchRegister); |
+ } else { |
+ Move(dst, constant); |
+ addq(dst, src); |
+ } |
+} |
+ |
+ |
+void MacroAssembler::SmiAddConstant(Register dst, |
+ Register src, |
+ Smi* constant, |
+ Label* on_not_smi_result) { |
+ if (constant->value() == 0) { |
+ if (!dst.is(src)) { |
+ movq(dst, src); |
+ } |
+ } else if (dst.is(src)) { |
+ ASSERT(!dst.is(kScratchRegister)); |
+ |
+ Move(kScratchRegister, constant); |
+ addq(dst, kScratchRegister); |
+ Label result_ok; |
+ j(no_overflow, &result_ok); |
+ subq(dst, kScratchRegister); |
+ jmp(on_not_smi_result); |
+ bind(&result_ok); |
+ } else { |
+ Move(dst, constant); |
+ addq(dst, src); |
+ j(overflow, on_not_smi_result); |
+ } |
+} |
+ |
+ |
+void MacroAssembler::SmiSubConstant(Register dst, Register src, Smi* constant) { |
+ if (constant->value() == 0) { |
+ if (!dst.is(src)) { |
+ movq(dst, src); |
+ } |
+ } else if (dst.is(src)) { |
+ ASSERT(!dst.is(kScratchRegister)); |
+ |
+ Move(kScratchRegister, constant); |
+ subq(dst, kScratchRegister); |
+ } else { |
+ // Subtract by adding the negative, to do it in two operations. |
+ if (constant->value() == Smi::kMinValue) { |
+ Move(kScratchRegister, constant); |
+ movq(dst, src); |
+ subq(dst, kScratchRegister); |
+ } else { |
+ Move(dst, Smi::FromInt(-constant->value())); |
+ addq(dst, src); |
+ } |
+ } |
+} |
+ |
+ |
+void MacroAssembler::SmiSubConstant(Register dst, |
+ Register src, |
+ Smi* constant, |
+ Label* on_not_smi_result) { |
+ if (constant->value() == 0) { |
+ if (!dst.is(src)) { |
+ movq(dst, src); |
+ } |
+ } else if (dst.is(src)) { |
+ ASSERT(!dst.is(kScratchRegister)); |
+ |
+ Move(kScratchRegister, constant); |
+ subq(dst, kScratchRegister); |
+ Label sub_success; |
+ j(no_overflow, &sub_success); |
+ addq(src, kScratchRegister); |
+ jmp(on_not_smi_result); |
+ bind(&sub_success); |
+ } else { |
+ if (constant->value() == Smi::kMinValue) { |
+ Move(kScratchRegister, constant); |
+ movq(dst, src); |
+ subq(dst, kScratchRegister); |
+ j(overflow, on_not_smi_result); |
+ } else { |
+ Move(dst, Smi::FromInt(-(constant->value()))); |
+ addq(dst, src); |
+ j(overflow, on_not_smi_result); |
+ } |
+ } |
+} |
+ |
+ |
+void MacroAssembler::SmiDiv(Register dst, |
+ Register src1, |
+ Register src2, |
+ Label* on_not_smi_result) { |
+ ASSERT(!src1.is(kScratchRegister)); |
+ ASSERT(!src2.is(kScratchRegister)); |
+ ASSERT(!dst.is(kScratchRegister)); |
+ ASSERT(!src2.is(rax)); |
+ ASSERT(!src2.is(rdx)); |
+ ASSERT(!src1.is(rdx)); |
+ |
+ // Check for 0 divisor (result is +/-Infinity). |
+ Label positive_divisor; |
+ testq(src2, src2); |
+ j(zero, on_not_smi_result); |
+ |
+ if (src1.is(rax)) { |
+ movq(kScratchRegister, src1); |
+ } |
+ SmiToInteger32(rax, src1); |
+ // We need to rule out dividing Smi::kMinValue by -1, since that would |
+ // overflow in idiv and raise an exception. |
+ // We combine this with negative zero test (negative zero only happens |
+ // when dividing zero by a negative number). |
+ |
+ // We overshoot a little and go to slow case if we divide min-value |
+ // by any negative value, not just -1. |
+ Label safe_div; |
+ testl(rax, Immediate(0x7fffffff)); |
+ j(not_zero, &safe_div); |
+ testq(src2, src2); |
+ if (src1.is(rax)) { |
+ j(positive, &safe_div); |
+ movq(src1, kScratchRegister); |
+ jmp(on_not_smi_result); |
+ } else { |
+ j(negative, on_not_smi_result); |
+ } |
+ bind(&safe_div); |
+ |
+ SmiToInteger32(src2, src2); |
+ // Sign extend src1 into edx:eax. |
+ cdq(); |
+ idivl(src2); |
+ Integer32ToSmi(src2, src2); |
+ // Check that the remainder is zero. |
+ testl(rdx, rdx); |
+ if (src1.is(rax)) { |
+ Label smi_result; |
+ j(zero, &smi_result); |
+ movq(src1, kScratchRegister); |
+ jmp(on_not_smi_result); |
+ bind(&smi_result); |
+ } else { |
+ j(not_zero, on_not_smi_result); |
+ } |
+ if (!dst.is(src1) && src1.is(rax)) { |
+ movq(src1, kScratchRegister); |
+ } |
+ Integer32ToSmi(dst, rax); |
+} |
+ |
+ |
+void MacroAssembler::SmiMod(Register dst, |
+ Register src1, |
+ Register src2, |
+ Label* on_not_smi_result) { |
+ ASSERT(!dst.is(kScratchRegister)); |
+ ASSERT(!src1.is(kScratchRegister)); |
+ ASSERT(!src2.is(kScratchRegister)); |
+ ASSERT(!src2.is(rax)); |
+ ASSERT(!src2.is(rdx)); |
+ ASSERT(!src1.is(rdx)); |
+ ASSERT(!src1.is(src2)); |
+ |
+ testq(src2, src2); |
+ j(zero, on_not_smi_result); |
+ |
+ if (src1.is(rax)) { |
+ movq(kScratchRegister, src1); |
+ } |
+ SmiToInteger32(rax, src1); |
+ SmiToInteger32(src2, src2); |
+ |
+ // Test for the edge case of dividing Smi::kMinValue by -1 (will overflow). |
+ Label safe_div; |
+ cmpl(rax, Immediate(Smi::kMinValue)); |
+ j(not_equal, &safe_div); |
+ cmpl(src2, Immediate(-1)); |
+ j(not_equal, &safe_div); |
+ // Retag inputs and go slow case. |
+ Integer32ToSmi(src2, src2); |
+ if (src1.is(rax)) { |
+ movq(src1, kScratchRegister); |
+ } |
+ jmp(on_not_smi_result); |
+ bind(&safe_div); |
+ |
+ // Sign extend eax into edx:eax. |
+ cdq(); |
+ idivl(src2); |
+ // Restore smi tags on inputs. |
+ Integer32ToSmi(src2, src2); |
+ if (src1.is(rax)) { |
+ movq(src1, kScratchRegister); |
+ } |
+ // Check for a negative zero result. If the result is zero, and the |
+ // dividend is negative, go slow to return a floating point negative zero. |
+ Label smi_result; |
+ testl(rdx, rdx); |
+ j(not_zero, &smi_result); |
+ testq(src1, src1); |
+ j(negative, on_not_smi_result); |
+ bind(&smi_result); |
+ Integer32ToSmi(dst, rdx); |
+} |
+ |
+ |
+void MacroAssembler::SmiNot(Register dst, Register src) { |
+ ASSERT(!dst.is(kScratchRegister)); |
+ ASSERT(!src.is(kScratchRegister)); |
+ // Set tag and padding bits before negating, so that they are zero afterwards. |
+ movl(kScratchRegister, Immediate(~0)); |
+ if (dst.is(src)) { |
+ xor_(dst, kScratchRegister); |
+ } else { |
+ lea(dst, Operand(src, kScratchRegister, times_1, 0)); |
+ } |
+ not_(dst); |
+} |
+ |
+ |
+void MacroAssembler::SmiAnd(Register dst, Register src1, Register src2) { |
+ ASSERT(!dst.is(src2)); |
+ if (!dst.is(src1)) { |
+ movq(dst, src1); |
+ } |
+ and_(dst, src2); |
+} |
+ |
+ |
+void MacroAssembler::SmiAndConstant(Register dst, Register src, Smi* constant) { |
+ if (constant->value() == 0) { |
+ xor_(dst, dst); |
+ } else if (dst.is(src)) { |
+ ASSERT(!dst.is(kScratchRegister)); |
+ Move(kScratchRegister, constant); |
+ and_(dst, kScratchRegister); |
+ } else { |
+ Move(dst, constant); |
+ and_(dst, src); |
+ } |
+} |
+ |
+ |
+void MacroAssembler::SmiOr(Register dst, Register src1, Register src2) { |
+ if (!dst.is(src1)) { |
+ movq(dst, src1); |
+ } |
+ or_(dst, src2); |
+} |
+ |
+ |
+void MacroAssembler::SmiOrConstant(Register dst, Register src, Smi* constant) { |
+ if (dst.is(src)) { |
+ ASSERT(!dst.is(kScratchRegister)); |
+ Move(kScratchRegister, constant); |
+ or_(dst, kScratchRegister); |
+ } else { |
+ Move(dst, constant); |
+ or_(dst, src); |
+ } |
+} |
+ |
+ |
+void MacroAssembler::SmiXor(Register dst, Register src1, Register src2) { |
+ if (!dst.is(src1)) { |
+ movq(dst, src1); |
+ } |
+ xor_(dst, src2); |
+} |
+ |
+ |
+void MacroAssembler::SmiXorConstant(Register dst, Register src, Smi* constant) { |
+ if (dst.is(src)) { |
+ ASSERT(!dst.is(kScratchRegister)); |
+ Move(kScratchRegister, constant); |
+ xor_(dst, kScratchRegister); |
+ } else { |
+ Move(dst, constant); |
+ xor_(dst, src); |
+ } |
+} |
+ |
+ |
+void MacroAssembler::SmiShiftArithmeticRightConstant(Register dst, |
+ Register src, |
+ int shift_value) { |
+ ASSERT(is_uint5(shift_value)); |
+ if (shift_value > 0) { |
+ if (dst.is(src)) { |
+ sar(dst, Immediate(shift_value + kSmiShift)); |
+ shl(dst, Immediate(kSmiShift)); |
+ } else { |
+ UNIMPLEMENTED(); // Not used. |
+ } |
+ } |
+} |
+ |
+ |
+void MacroAssembler::SmiShiftLogicalRightConstant(Register dst, |
+ Register src, |
+ int shift_value, |
+ Label* on_not_smi_result) { |
+ // Logic right shift interprets its result as an *unsigned* number. |
+ if (dst.is(src)) { |
+ UNIMPLEMENTED(); // Not used. |
+ } else { |
+ movq(dst, src); |
+ if (shift_value == 0) { |
+ testq(dst, dst); |
+ j(negative, on_not_smi_result); |
+ } |
+ shr(dst, Immediate(shift_value + kSmiShift)); |
+ shl(dst, Immediate(kSmiShift)); |
+ } |
} |
-Condition MacroAssembler::CheckNotSmi(Register src) { |
+void MacroAssembler::SmiShiftLeftConstant(Register dst, |
+ Register src, |
+ int shift_value, |
+ Label* on_not_smi_result) { |
+ if (!dst.is(src)) { |
+ movq(dst, src); |
+ } |
+ if (shift_value > 0) { |
+ shl(dst, Immediate(shift_value)); |
+ } |
+} |
+ |
+ |
+void MacroAssembler::SmiShiftLeft(Register dst, |
+ Register src1, |
+ Register src2, |
+ Label* on_not_smi_result) { |
+ ASSERT(!dst.is(rcx)); |
+ Label result_ok; |
+ // Untag shift amount. |
+ if (!dst.is(src1)) { |
+ movq(dst, src1); |
+ } |
+ SmiToInteger32(rcx, src2); |
+ // Shift amount specified by lower 5 bits, not six as the shl opcode. |
+ and_(rcx, Immediate(0x1f)); |
+ shl(dst); |
+} |
+ |
+ |
+void MacroAssembler::SmiShiftLogicalRight(Register dst, |
+ Register src1, |
+ Register src2, |
+ Label* on_not_smi_result) { |
+ ASSERT(!dst.is(kScratchRegister)); |
+ ASSERT(!src1.is(kScratchRegister)); |
+ ASSERT(!src2.is(kScratchRegister)); |
+ ASSERT(!dst.is(rcx)); |
+ Label result_ok; |
+ if (src1.is(rcx) || src2.is(rcx)) { |
+ movq(kScratchRegister, rcx); |
+ } |
+ if (!dst.is(src1)) { |
+ movq(dst, src1); |
+ } |
+ SmiToInteger32(rcx, src2); |
+ orl(rcx, Immediate(kSmiShift)); |
+ shr(dst); // Shift is rcx modulo 0x1f + 32. |
+ shl(dst, Immediate(kSmiShift)); |
+ testq(dst, dst); |
+ if (src1.is(rcx) || src2.is(rcx)) { |
+ Label positive_result; |
+ j(positive, &positive_result); |
+ if (src1.is(rcx)) { |
+ movq(src1, kScratchRegister); |
+ } else { |
+ movq(src2, kScratchRegister); |
+ } |
+ jmp(on_not_smi_result); |
+ bind(&positive_result); |
+ } else { |
+ j(negative, on_not_smi_result); // src2 was zero and src1 negative. |
+ } |
+} |
+ |
+ |
+void MacroAssembler::SmiShiftArithmeticRight(Register dst, |
+ Register src1, |
+ Register src2) { |
+ ASSERT(!dst.is(kScratchRegister)); |
+ ASSERT(!src1.is(kScratchRegister)); |
+ ASSERT(!src2.is(kScratchRegister)); |
+ ASSERT(!dst.is(rcx)); |
+ if (src1.is(rcx)) { |
+ movq(kScratchRegister, src1); |
+ } else if (src2.is(rcx)) { |
+ movq(kScratchRegister, src2); |
+ } |
+ if (!dst.is(src1)) { |
+ movq(dst, src1); |
+ } |
+ SmiToInteger32(rcx, src2); |
+ orl(rcx, Immediate(kSmiShift)); |
+ sar(dst); // Shift 32 + original rcx & 0x1f. |
+ shl(dst, Immediate(kSmiShift)); |
+ if (src1.is(rcx)) { |
+ movq(src1, kScratchRegister); |
+ } else if (src2.is(rcx)) { |
+ movq(src2, kScratchRegister); |
+ } |
+} |
+ |
+ |
+void MacroAssembler::SelectNonSmi(Register dst, |
+ Register src1, |
+ Register src2, |
+ Label* on_not_smis) { |
+ ASSERT(!dst.is(kScratchRegister)); |
+ ASSERT(!src1.is(kScratchRegister)); |
+ ASSERT(!src2.is(kScratchRegister)); |
+ ASSERT(!dst.is(src1)); |
+ ASSERT(!dst.is(src2)); |
+ // Both operands must not be smis. |
+#ifdef DEBUG |
+ if (allow_stub_calls()) { // Check contains a stub call. |
+ Condition not_both_smis = NegateCondition(CheckBothSmi(src1, src2)); |
+ Check(not_both_smis, "Both registers were smis in SelectNonSmi."); |
+ } |
+#endif |
ASSERT_EQ(0, kSmiTag); |
- testb(src, Immediate(kSmiTagMask)); |
- return not_zero; |
+ ASSERT_EQ(0, Smi::FromInt(0)); |
+ movl(kScratchRegister, Immediate(kSmiTagMask)); |
+ and_(kScratchRegister, src1); |
+ testl(kScratchRegister, src2); |
+ // If non-zero then both are smis. |
+ j(not_zero, on_not_smis); |
+ |
+ // Exactly one operand is a smi. |
+ ASSERT_EQ(1, static_cast<int>(kSmiTagMask)); |
+ // kScratchRegister still holds src1 & kSmiTag, which is either zero or one. |
+ subq(kScratchRegister, Immediate(1)); |
+ // If src1 is a smi, then scratch register all 1s, else it is all 0s. |
+ movq(dst, src1); |
+ xor_(dst, src2); |
+ and_(dst, kScratchRegister); |
+ // If src1 is a smi, dst holds src1 ^ src2, else it is zero. |
+ xor_(dst, src1); |
+ // 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) { |
+ ASSERT(is_uint6(shift)); |
+ // There is a possible optimization if shift is in the range 60-63, but that |
+ // will (and must) never happen. |
+ if (!dst.is(src)) { |
+ movq(dst, src); |
+ } |
+ if (shift < kSmiShift) { |
+ sar(dst, Immediate(kSmiShift - shift)); |
+ } else { |
+ shl(dst, Immediate(shift - kSmiShift)); |
+ } |
+ return SmiIndex(dst, times_1); |
+} |
-Condition MacroAssembler::CheckPositiveSmi(Register src) { |
+SmiIndex MacroAssembler::SmiToNegativeIndex(Register dst, |
+ Register src, |
+ int shift) { |
+ // Register src holds a positive smi. |
+ ASSERT(is_uint6(shift)); |
+ if (!dst.is(src)) { |
+ movq(dst, src); |
+ } |
+ neg(dst); |
+ if (shift < kSmiShift) { |
+ sar(dst, Immediate(kSmiShift - shift)); |
+ } else { |
+ shl(dst, Immediate(shift - kSmiShift)); |
+ } |
+ return SmiIndex(dst, times_1); |
+} |
+ |
+#else // ! V8_LONG_SMI |
+// 31 bit smi operations |
+ |
+// Extracts the low 32 bits of a Smi pointer, where the taqgged smi value |
+// is stored. |
+static int32_t SmiValue(Smi* smi) { |
+ return static_cast<int32_t>(reinterpret_cast<intptr_t>(smi)); |
+} |
+ |
+ |
+void MacroAssembler::Integer32ToSmi(Register dst, Register src) { |
+ ASSERT_EQ(1, kSmiTagSize); |
ASSERT_EQ(0, kSmiTag); |
- testl(src, Immediate(static_cast<uint32_t>(0x80000000u | kSmiTagMask))); |
- return zero; |
+#ifdef DEBUG |
+ if (allow_stub_calls()) { |
+ cmpl(src, Immediate(0xC0000000u)); |
+ Check(positive, "Smi conversion overflow"); |
+ } |
+#endif |
+ if (dst.is(src)) { |
+ addl(dst, src); |
+ } else { |
+ lea(dst, Operand(src, src, times_1, 0)); |
+ } |
} |
-Condition MacroAssembler::CheckNotPositiveSmi(Register src) { |
+void MacroAssembler::Integer32ToSmi(Register dst, |
+ Register src, |
+ Label* on_overflow) { |
+ ASSERT_EQ(1, kSmiTagSize); |
ASSERT_EQ(0, kSmiTag); |
- testl(src, Immediate(static_cast<uint32_t>(0x80000000u | kSmiTagMask))); |
- return not_zero; |
+ if (!dst.is(src)) { |
+ movl(dst, src); |
+ } |
+ addl(dst, src); |
+ j(overflow, on_overflow); |
} |
-Condition MacroAssembler::CheckBothSmi(Register first, Register second) { |
- if (first.is(second)) { |
- return CheckSmi(first); |
+void MacroAssembler::Integer64PlusConstantToSmi(Register dst, |
+ Register src, |
+ int constant) { |
+#ifdef DEBUG |
+ if (allow_stub_calls()) { |
+ movl(kScratchRegister, src); |
+ addl(kScratchRegister, Immediate(constant)); |
+ Check(no_overflow, "Add-and-smi-convert overflow"); |
+ Condition valid = CheckInteger32ValidSmiValue(kScratchRegister); |
+ Check(valid, "Add-and-smi-convert overflow"); |
} |
- movl(kScratchRegister, first); |
- orl(kScratchRegister, second); |
- return CheckSmi(kScratchRegister); |
+#endif |
+ lea(dst, Operand(src, src, times_1, constant << kSmiTagSize)); |
} |
-Condition MacroAssembler::CheckNotBothSmi(Register first, Register second) { |
+void MacroAssembler::SmiToInteger32(Register dst, Register src) { |
+ ASSERT_EQ(1, kSmiTagSize); |
ASSERT_EQ(0, kSmiTag); |
- if (first.is(second)) { |
- return CheckNotSmi(first); |
+ if (!dst.is(src)) { |
+ movl(dst, src); |
} |
- movl(kScratchRegister, first); |
- or_(kScratchRegister, second); |
- return CheckNotSmi(kScratchRegister); |
+ sarl(dst, Immediate(kSmiTagSize)); |
} |
-Condition MacroAssembler::CheckIsMinSmi(Register src) { |
- ASSERT(kSmiTag == 0 && kSmiTagSize == 1); |
- cmpl(src, Immediate(0x40000000)); |
- return equal; |
+void MacroAssembler::SmiToInteger64(Register dst, Register src) { |
+ ASSERT_EQ(1, kSmiTagSize); |
+ ASSERT_EQ(0, kSmiTag); |
+ movsxlq(dst, src); |
+ sar(dst, Immediate(kSmiTagSize)); |
+} |
+ |
+ |
+void MacroAssembler::SmiTest(Register src) { |
+ testl(src, src); |
+} |
+ |
+ |
+void MacroAssembler::SmiCompare(Register dst, Register src) { |
+ cmpl(dst, src); |
} |
-Condition MacroAssembler::CheckSmiEqualsConstant(Register src, int constant) { |
- if (constant == 0) { |
- testl(src, src); |
- return zero; |
+ |
+void MacroAssembler::SmiCompare(Register dst, Smi* src) { |
+ ASSERT(!dst.is(kScratchRegister)); |
+ if (src->value() == 0) { |
+ testl(dst, dst); |
+ } else { |
+ cmpl(dst, Immediate(SmiValue(src))); |
} |
- if (Smi::IsValid(constant)) { |
- cmpl(src, Immediate(Smi::FromInt(constant))); |
- return zero; |
+} |
+ |
+ |
+void MacroAssembler::SmiCompare(const Operand& dst, Register src) { |
+ cmpl(dst, src); |
+} |
+ |
+ |
+void MacroAssembler::SmiCompare(const Operand& dst, Smi* src) { |
+ if (src->value() == 0) { |
+ movl(kScratchRegister, dst); |
+ testl(kScratchRegister, kScratchRegister); |
+ } else { |
+ cmpl(dst, Immediate(SmiValue(src))); |
} |
- // Can't be equal. |
- UNREACHABLE(); |
- return no_condition; |
} |
-Condition MacroAssembler::CheckSmiGreaterEqualsConstant(Register src, |
- int constant) { |
- if (constant == 0) { |
- testl(src, Immediate(static_cast<uint32_t>(0x80000000u))); |
- return positive; |
+void MacroAssembler::PositiveSmiTimesPowerOfTwoToInteger64(Register dst, |
+ Register src, |
+ int power) { |
+ ASSERT(power >= 0); |
+ ASSERT(power < 64); |
+ if (power == 0) { |
+ SmiToInteger64(dst, src); |
+ return; |
} |
- if (Smi::IsValid(constant)) { |
- cmpl(src, Immediate(Smi::FromInt(constant))); |
- return greater_equal; |
+ movsxlq(dst, src); |
+ shl(dst, Immediate(power - 1)); |
+} |
+ |
+Condition MacroAssembler::CheckSmi(Register src) { |
+ testb(src, Immediate(kSmiTagMask)); |
+ return zero; |
+} |
+ |
+Condition MacroAssembler::CheckPositiveSmi(Register src) { |
+ ASSERT_EQ(0, kSmiTag); |
+ testl(src, Immediate(static_cast<uint32_t>(0x80000000u | kSmiTagMask))); |
+ return zero; |
+} |
+ |
+Condition MacroAssembler::CheckBothSmi(Register first, Register second) { |
+ if (first.is(second)) { |
+ return CheckSmi(first); |
} |
- // Can't be equal. |
- UNREACHABLE(); |
- return no_condition; |
+ movl(kScratchRegister, first); |
+ orl(kScratchRegister, second); |
+ return CheckSmi(kScratchRegister); |
} |
+Condition MacroAssembler::CheckIsMinSmi(Register src) { |
+ ASSERT(kSmiTag == 0 && kSmiTagSize == 1); |
+ cmpl(src, Immediate(0x80000000u)); |
+ return equal; |
+} |
Condition MacroAssembler::CheckInteger32ValidSmiValue(Register src) { |
// A 32-bit integer value can be converted to a smi if it is in the |
@@ -645,15 +1367,15 @@ Condition MacroAssembler::CheckInteger32ValidSmiValue(Register src) { |
void MacroAssembler::SmiNeg(Register dst, |
- Register src, |
- Label* on_not_smi_result) { |
+ Register src, |
+ Label* on_smi_result) { |
if (!dst.is(src)) { |
movl(dst, src); |
} |
negl(dst); |
testl(dst, Immediate(0x7fffffff)); |
// If the result is zero or 0x80000000, negation failed to create a smi. |
- j(equal, on_not_smi_result); |
+ j(not_equal, on_smi_result); |
} |
@@ -679,7 +1401,6 @@ void MacroAssembler::SmiAdd(Register dst, |
} |
- |
void MacroAssembler::SmiSub(Register dst, |
Register src1, |
Register src2, |
@@ -709,6 +1430,7 @@ void MacroAssembler::SmiMul(Register dst, |
ASSERT(!dst.is(src2)); |
if (dst.is(src1)) { |
+ // Copy src1 before overwriting. |
movq(kScratchRegister, src1); |
} |
SmiToInteger32(dst, src1); |
@@ -725,24 +1447,27 @@ void MacroAssembler::SmiMul(Register dst, |
j(not_zero, &non_zero_result); |
// Test whether either operand is negative (the other must be zero). |
+ if (!dst.is(src1)) { |
+ movl(kScratchRegister, src1); |
+ } |
orl(kScratchRegister, src2); |
j(negative, on_not_smi_result); |
+ |
bind(&non_zero_result); |
} |
void MacroAssembler::SmiTryAddConstant(Register dst, |
Register src, |
- int32_t constant, |
+ Smi* constant, |
Label* on_not_smi_result) { |
// Does not assume that src is a smi. |
ASSERT_EQ(1, kSmiTagMask); |
ASSERT_EQ(0, kSmiTag); |
- ASSERT(Smi::IsValid(constant)); |
Register tmp = (src.is(dst) ? kScratchRegister : dst); |
movl(tmp, src); |
- addl(tmp, Immediate(Smi::FromInt(constant))); |
+ addl(tmp, Immediate(SmiValue(constant))); |
if (tmp.is(kScratchRegister)) { |
j(overflow, on_not_smi_result); |
testl(tmp, Immediate(kSmiTagMask)); |
@@ -759,53 +1484,73 @@ void MacroAssembler::SmiTryAddConstant(Register dst, |
void MacroAssembler::SmiAddConstant(Register dst, |
Register src, |
- int32_t constant, |
+ Smi* constant) { |
+ ASSERT_EQ(1, kSmiTagMask); |
+ ASSERT_EQ(0, kSmiTag); |
+ int32_t smi_value = SmiValue(constant); |
+ if (dst.is(src)) { |
+ addl(dst, Immediate(smi_value)); |
+ } else { |
+ lea(dst, Operand(src, smi_value)); |
+ } |
+} |
+ |
+ |
+void MacroAssembler::SmiAddConstant(Register dst, |
+ Register src, |
+ Smi* constant, |
Label* on_not_smi_result) { |
- ASSERT(Smi::IsValid(constant)); |
- if (on_not_smi_result == NULL) { |
- if (dst.is(src)) { |
- movl(dst, src); |
- } else { |
- lea(dst, Operand(src, constant << kSmiTagSize)); |
- } |
+ ASSERT_EQ(1, kSmiTagMask); |
+ ASSERT_EQ(0, kSmiTag); |
+ int32_t smi_value = SmiValue(constant); |
+ if (!dst.is(src)) { |
+ movl(dst, src); |
+ addl(dst, Immediate(smi_value)); |
+ j(overflow, on_not_smi_result); |
} else { |
- if (!dst.is(src)) { |
- movl(dst, src); |
- } |
- addl(dst, Immediate(Smi::FromInt(constant))); |
- if (!dst.is(src)) { |
- j(overflow, on_not_smi_result); |
- } else { |
- Label result_ok; |
- j(no_overflow, &result_ok); |
- subl(dst, Immediate(Smi::FromInt(constant))); |
- jmp(on_not_smi_result); |
- bind(&result_ok); |
- } |
+ addl(dst, Immediate(smi_value)); |
+ Label result_ok; |
+ j(no_overflow, &result_ok); |
+ subl(dst, Immediate(smi_value)); |
+ jmp(on_not_smi_result); |
+ bind(&result_ok); |
} |
} |
void MacroAssembler::SmiSubConstant(Register dst, |
Register src, |
- int32_t constant, |
+ Smi* constant) { |
+ ASSERT_EQ(1, kSmiTagMask); |
+ ASSERT_EQ(0, kSmiTag); |
+ if (!dst.is(src)) { |
+ movl(dst, src); |
+ } |
+ subl(dst, Immediate(SmiValue(constant))); |
+} |
+ |
+ |
+void MacroAssembler::SmiSubConstant(Register dst, |
+ Register src, |
+ Smi* constant, |
Label* on_not_smi_result) { |
- ASSERT(Smi::IsValid(constant)); |
- Smi* smi_value = Smi::FromInt(constant); |
+ ASSERT_EQ(1, kSmiTagMask); |
+ ASSERT_EQ(0, kSmiTag); |
+ int32_t smi_value = SmiValue(constant); |
if (dst.is(src)) { |
// Optimistic subtract - may change value of dst register, |
// if it has garbage bits in the higher half, but will not change |
// the value as a tagged smi. |
subl(dst, Immediate(smi_value)); |
- if (on_not_smi_result != NULL) { |
- Label add_success; |
- j(no_overflow, &add_success); |
- addl(dst, Immediate(smi_value)); |
- jmp(on_not_smi_result); |
- bind(&add_success); |
- } |
+ Label add_success; |
+ j(no_overflow, &add_success); |
+ addl(dst, Immediate(smi_value)); |
+ jmp(on_not_smi_result); |
+ bind(&add_success); |
} else { |
- UNIMPLEMENTED(); // Not used yet. |
+ movl(dst, src); |
+ subl(dst, Immediate(smi_value)); |
+ j(overflow, on_not_smi_result); |
} |
} |
@@ -913,12 +1658,12 @@ void MacroAssembler::SmiAnd(Register dst, Register src1, Register src2) { |
} |
-void MacroAssembler::SmiAndConstant(Register dst, Register src, int constant) { |
- ASSERT(Smi::IsValid(constant)); |
+void MacroAssembler::SmiAndConstant(Register dst, Register src, Smi* constant) { |
if (!dst.is(src)) { |
movl(dst, src); |
} |
- and_(dst, Immediate(Smi::FromInt(constant))); |
+ int32_t smi_value = SmiValue(constant); |
+ and_(dst, Immediate(smi_value)); |
} |
@@ -930,14 +1675,15 @@ void MacroAssembler::SmiOr(Register dst, Register src1, Register src2) { |
} |
-void MacroAssembler::SmiOrConstant(Register dst, Register src, int constant) { |
- ASSERT(Smi::IsValid(constant)); |
+void MacroAssembler::SmiOrConstant(Register dst, Register src, Smi* constant) { |
if (!dst.is(src)) { |
movl(dst, src); |
} |
- or_(dst, Immediate(Smi::FromInt(constant))); |
+ int32_t smi_value = SmiValue(constant); |
+ or_(dst, Immediate(smi_value)); |
} |
+ |
void MacroAssembler::SmiXor(Register dst, Register src1, Register src2) { |
if (!dst.is(src1)) { |
movl(dst, src1); |
@@ -946,16 +1692,15 @@ void MacroAssembler::SmiXor(Register dst, Register src1, Register src2) { |
} |
-void MacroAssembler::SmiXorConstant(Register dst, Register src, int constant) { |
- ASSERT(Smi::IsValid(constant)); |
+void MacroAssembler::SmiXorConstant(Register dst, Register src, Smi* constant) { |
if (!dst.is(src)) { |
movl(dst, src); |
} |
- xor_(dst, Immediate(Smi::FromInt(constant))); |
+ int32_t smi_value = SmiValue(constant); |
+ xor_(dst, Immediate(smi_value)); |
} |
- |
void MacroAssembler::SmiShiftArithmeticRightConstant(Register dst, |
Register src, |
int shift_value) { |
@@ -1001,7 +1746,18 @@ void MacroAssembler::SmiShiftLeftConstant(Register dst, |
int shift_value, |
Label* on_not_smi_result) { |
if (dst.is(src)) { |
- UNIMPLEMENTED(); // Not used. |
+ if (shift_value > 0) { |
+ movq(kScratchRegister, src); |
+ // Treat scratch as an untagged integer value equal to two times the |
+ // smi value of src, i.e., already shifted left by one. |
+ if (shift_value > 1) { |
+ shll(kScratchRegister, Immediate(shift_value - 1)); |
+ } |
+ JumpIfNotValidSmiValue(kScratchRegister, on_not_smi_result); |
+ // Convert int result to Smi, checking that it is in smi range. |
+ ASSERT(kSmiTagSize == 1); // adjust code if not the case |
+ Integer32ToSmi(dst, kScratchRegister); |
+ } |
} else { |
movl(dst, src); |
if (shift_value > 0) { |
@@ -1025,6 +1781,9 @@ void MacroAssembler::SmiShiftLeft(Register dst, |
ASSERT(!dst.is(rcx)); |
Label result_ok; |
// Untag both operands. |
+ if (dst.is(src1) || src1.is(rcx)) { |
+ movq(kScratchRegister, src1); |
+ } |
SmiToInteger32(dst, src1); |
SmiToInteger32(rcx, src2); |
shll(dst); |
@@ -1033,11 +1792,12 @@ void MacroAssembler::SmiShiftLeft(Register dst, |
j(is_valid, &result_ok); |
// Restore the relevant bits of the source registers |
// and call the slow version. |
- if (dst.is(src1)) { |
- shrl(dst); |
- Integer32ToSmi(dst, dst); |
+ if (dst.is(src1) || src1.is(rcx)) { |
+ movq(src1, kScratchRegister); |
+ } |
+ if (src2.is(rcx)) { |
+ Integer32ToSmi(rcx, rcx); |
} |
- Integer32ToSmi(rcx, rcx); |
jmp(on_not_smi_result); |
bind(&result_ok); |
Integer32ToSmi(dst, dst); |
@@ -1048,9 +1808,15 @@ void MacroAssembler::SmiShiftLogicalRight(Register dst, |
Register src1, |
Register src2, |
Label* on_not_smi_result) { |
+ ASSERT(!dst.is(kScratchRegister)); |
+ ASSERT(!src1.is(kScratchRegister)); |
+ ASSERT(!src2.is(kScratchRegister)); |
ASSERT(!dst.is(rcx)); |
Label result_ok; |
// Untag both operands. |
+ if (src1.is(rcx)) { |
+ movq(kScratchRegister, src1); |
+ } |
SmiToInteger32(dst, src1); |
SmiToInteger32(rcx, src2); |
@@ -1070,8 +1836,11 @@ void MacroAssembler::SmiShiftLogicalRight(Register dst, |
if (dst.is(src1)) { |
shll(dst); |
Integer32ToSmi(dst, dst); |
+ } else if (src1.is(rcx)) { |
+ movq(rcx, kScratchRegister); |
+ } else if (src2.is(rcx)) { |
+ Integer32ToSmi(src2, src2); |
} |
- Integer32ToSmi(rcx, rcx); |
jmp(on_not_smi_result); |
bind(&result_ok); |
// Smi-tag the result in answer. |
@@ -1101,8 +1870,10 @@ void MacroAssembler::SelectNonSmi(Register dst, |
ASSERT(!dst.is(src2)); |
// Both operands must not be smis. |
#ifdef DEBUG |
- Condition not_both_smis = CheckNotBothSmi(src1, src2); |
- Check(not_both_smis, "Both registers were smis."); |
+ if (allow_stub_calls()) { |
+ Condition not_both_smis = NegateCondition(CheckBothSmi(src1, src2)); |
+ Check(not_both_smis, "Both registers were smis."); |
+ } |
#endif |
ASSERT_EQ(0, kSmiTag); |
ASSERT_EQ(0, Smi::FromInt(0)); |
@@ -1166,26 +1937,82 @@ SmiIndex MacroAssembler::SmiToNegativeIndex(Register dst, |
return SmiIndex(dst, times_1); |
} |
+#endif // V8_LONG_SMI |
+ |
+ |
+void MacroAssembler::JumpIfSmi(Register src, Label* on_smi) { |
+ ASSERT_EQ(0, kSmiTag); |
+ Condition smi = CheckSmi(src); |
+ j(smi, on_smi); |
+} |
+ |
+void MacroAssembler::JumpIfNotSmi(Register src, Label* on_not_smi) { |
+ Condition smi = CheckSmi(src); |
+ j(NegateCondition(smi), on_not_smi); |
+} |
+ |
+ |
+void MacroAssembler::JumpIfNotPositiveSmi(Register src, |
+ Label* on_not_positive_smi) { |
+ Condition positive_smi = CheckPositiveSmi(src); |
+ j(NegateCondition(positive_smi), on_not_positive_smi); |
+} |
+ |
+ |
+void MacroAssembler::JumpIfSmiEqualsConstant(Register src, |
+ Smi* constant, |
+ Label* on_equals) { |
+ SmiCompare(src, constant); |
+ j(equal, on_equals); |
+} |
+ |
+ |
+void MacroAssembler::JumpIfNotValidSmiValue(Register src, Label* on_invalid) { |
+ Condition is_valid = CheckInteger32ValidSmiValue(src); |
+ j(NegateCondition(is_valid), on_invalid); |
+} |
+ |
+ |
+void MacroAssembler::JumpIfNotBothSmi(Register src1, Register src2, |
+ Label* on_not_both_smi) { |
+ Condition both_smi = CheckBothSmi(src1, src2); |
+ j(NegateCondition(both_smi), on_not_both_smi); |
+} |
bool MacroAssembler::IsUnsafeSmi(Smi* value) { |
return false; |
} |
+ |
void MacroAssembler::LoadUnsafeSmi(Register dst, Smi* source) { |
UNIMPLEMENTED(); |
} |
+void MacroAssembler::Move(Register dst, Smi* source) { |
+ if (IsUnsafeSmi(source)) { |
+ LoadUnsafeSmi(dst, source); |
+ } else { |
+ Set(dst, reinterpret_cast<int64_t>(source)); |
+ } |
+} |
+ |
+ |
+void MacroAssembler::Move(const Operand& dst, Smi* source) { |
+ if (IsUnsafeSmi(source)) { |
+ LoadUnsafeSmi(kScratchRegister, source); |
+ movq(dst, kScratchRegister); |
+ } else { |
+ Set(dst, reinterpret_cast<int64_t>(source)); |
+ } |
+} |
+ |
+ |
void MacroAssembler::Move(Register dst, Handle<Object> source) { |
ASSERT(!source->IsFailure()); |
if (source->IsSmi()) { |
- if (IsUnsafeSmi(source)) { |
- LoadUnsafeSmi(dst, source); |
- } else { |
- int32_t smi = static_cast<int32_t>(reinterpret_cast<intptr_t>(*source)); |
- movq(dst, Immediate(smi)); |
- } |
+ Move(dst, Smi::cast(*source)); |
} else { |
movq(dst, source, RelocInfo::EMBEDDED_OBJECT); |
} |
@@ -1193,9 +2020,9 @@ void MacroAssembler::Move(Register dst, Handle<Object> source) { |
void MacroAssembler::Move(const Operand& dst, Handle<Object> source) { |
+ ASSERT(!source->IsFailure()); |
if (source->IsSmi()) { |
- int32_t smi = static_cast<int32_t>(reinterpret_cast<intptr_t>(*source)); |
- movq(dst, Immediate(smi)); |
+ Move(dst, Smi::cast(*source)); |
} else { |
movq(kScratchRegister, source, RelocInfo::EMBEDDED_OBJECT); |
movq(dst, kScratchRegister); |
@@ -1204,21 +2031,18 @@ void MacroAssembler::Move(const Operand& dst, Handle<Object> source) { |
void MacroAssembler::Cmp(Register dst, Handle<Object> source) { |
- Move(kScratchRegister, source); |
- cmpq(dst, kScratchRegister); |
+ if (source->IsSmi()) { |
+ SmiCompare(dst, Smi::cast(*source)); |
+ } else { |
+ Move(kScratchRegister, source); |
+ cmpq(dst, kScratchRegister); |
+ } |
} |
void MacroAssembler::Cmp(const Operand& dst, Handle<Object> source) { |
if (source->IsSmi()) { |
- if (IsUnsafeSmi(source)) { |
- LoadUnsafeSmi(kScratchRegister, source); |
- cmpl(dst, kScratchRegister); |
- } else { |
- // For smi-comparison, it suffices to compare the low 32 bits. |
- int32_t smi = static_cast<int32_t>(reinterpret_cast<intptr_t>(*source)); |
- cmpl(dst, Immediate(smi)); |
- } |
+ SmiCompare(dst, Smi::cast(*source)); |
} else { |
ASSERT(source->IsHeapObject()); |
movq(kScratchRegister, source, RelocInfo::EMBEDDED_OBJECT); |
@@ -1229,13 +2053,7 @@ void MacroAssembler::Cmp(const Operand& dst, Handle<Object> source) { |
void MacroAssembler::Push(Handle<Object> source) { |
if (source->IsSmi()) { |
- if (IsUnsafeSmi(source)) { |
- LoadUnsafeSmi(kScratchRegister, source); |
- push(kScratchRegister); |
- } else { |
- int32_t smi = static_cast<int32_t>(reinterpret_cast<intptr_t>(*source)); |
- push(Immediate(smi)); |
- } |
+ Push(Smi::cast(*source)); |
} else { |
ASSERT(source->IsHeapObject()); |
movq(kScratchRegister, source, RelocInfo::EMBEDDED_OBJECT); |
@@ -1249,8 +2067,29 @@ void MacroAssembler::Push(Smi* source) { |
LoadUnsafeSmi(kScratchRegister, source); |
push(kScratchRegister); |
} else { |
- int32_t smi = static_cast<int32_t>(reinterpret_cast<intptr_t>(source)); |
- push(Immediate(smi)); |
+ intptr_t smi = reinterpret_cast<intptr_t>(source); |
+ if (is_int32(smi)) { |
+ push(Immediate(static_cast<int32_t>(smi))); |
+ } else { |
+ Set(kScratchRegister, smi); |
+ push(kScratchRegister); |
+ } |
+ } |
+} |
+ |
+ |
+void MacroAssembler::Test(const Operand& src, Smi* source) { |
+ if (IsUnsafeSmi(source)) { |
+ LoadUnsafeSmi(kScratchRegister, source); |
+ testq(src, kScratchRegister); |
+ } else { |
+ intptr_t smi = reinterpret_cast<intptr_t>(source); |
+ if (is_int32(smi)) { |
+ testl(src, Immediate(static_cast<int32_t>(smi))); |
+ } else { |
+ Move(kScratchRegister, source); |
+ testq(src, kScratchRegister); |
+ } |
} |
} |
@@ -1301,11 +2140,11 @@ void MacroAssembler::PushTryHandler(CodeLocation try_location, |
// frame pointer and current handler. Check that they are expected |
// next on the stack, in that order. |
ASSERT_EQ(StackHandlerConstants::kStateOffset, |
- StackHandlerConstants::kPCOffset - kPointerSize); |
+ StackHandlerConstants::kPCOffset - kPointerSize); |
ASSERT_EQ(StackHandlerConstants::kFPOffset, |
- StackHandlerConstants::kStateOffset - kPointerSize); |
+ StackHandlerConstants::kStateOffset - kPointerSize); |
ASSERT_EQ(StackHandlerConstants::kNextOffset, |
- StackHandlerConstants::kFPOffset - kPointerSize); |
+ StackHandlerConstants::kFPOffset - kPointerSize); |
if (try_location == IN_JAVASCRIPT) { |
if (type == TRY_CATCH_HANDLER) { |
@@ -1351,8 +2190,7 @@ void MacroAssembler::FCmp() { |
} |
-void MacroAssembler::CmpObjectType(Register heap_object, |
- InstanceType type, |
+void MacroAssembler::CmpObjectType(Register heap_object, InstanceType type, |
Register map) { |
movq(map, FieldOperand(heap_object, HeapObject::kMapOffset)); |
CmpInstanceType(map, type); |
@@ -1366,8 +2204,7 @@ void MacroAssembler::CmpInstanceType(Register map, InstanceType type) { |
void MacroAssembler::TryGetFunctionPrototype(Register function, |
- Register result, |
- Label* miss) { |
+ Register result, Label* miss) { |
// Check that the receiver isn't a smi. |
testl(function, Immediate(kSmiTagMask)); |
j(zero, miss); |
@@ -1378,8 +2215,8 @@ void MacroAssembler::TryGetFunctionPrototype(Register function, |
// Make sure that the function has an instance prototype. |
Label non_instance; |
- testb(FieldOperand(result, Map::kBitFieldOffset), |
- Immediate(1 << Map::kHasNonInstancePrototype)); |
+ testb(FieldOperand(result, Map::kBitFieldOffset), Immediate(1 |
+ << Map::kHasNonInstancePrototype)); |
j(not_zero, &non_instance); |
// Get the prototype or initial map from the function. |
@@ -1446,7 +2283,6 @@ void MacroAssembler::DecrementCounter(StatsCounter* counter, int value) { |
} |
} |
- |
#ifdef ENABLE_DEBUGGER_SUPPORT |
void MacroAssembler::PushRegistersFromMemory(RegList regs) { |
@@ -1456,22 +2292,23 @@ void MacroAssembler::PushRegistersFromMemory(RegList regs) { |
int r = JSCallerSavedCode(i); |
if ((regs & (1 << r)) != 0) { |
ExternalReference reg_addr = |
- ExternalReference(Debug_Address::Register(i)); |
+ ExternalReference(Debug_Address::Register(i)); |
movq(kScratchRegister, reg_addr); |
push(Operand(kScratchRegister, 0)); |
} |
} |
} |
+ |
void MacroAssembler::SaveRegistersToMemory(RegList regs) { |
ASSERT((regs & ~kJSCallerSaved) == 0); |
// Copy the content of registers to memory location. |
for (int i = 0; i < kNumJSCallerSaved; i++) { |
int r = JSCallerSavedCode(i); |
if ((regs & (1 << r)) != 0) { |
- Register reg = { r }; |
+ Register reg = {r}; |
ExternalReference reg_addr = |
- ExternalReference(Debug_Address::Register(i)); |
+ ExternalReference(Debug_Address::Register(i)); |
movq(kScratchRegister, reg_addr); |
movq(Operand(kScratchRegister, 0), reg); |
} |
@@ -1485,9 +2322,9 @@ void MacroAssembler::RestoreRegistersFromMemory(RegList regs) { |
for (int i = kNumJSCallerSaved - 1; i >= 0; i--) { |
int r = JSCallerSavedCode(i); |
if ((regs & (1 << r)) != 0) { |
- Register reg = { r }; |
+ Register reg = {r}; |
ExternalReference reg_addr = |
- ExternalReference(Debug_Address::Register(i)); |
+ ExternalReference(Debug_Address::Register(i)); |
movq(kScratchRegister, reg_addr); |
movq(reg, Operand(kScratchRegister, 0)); |
} |
@@ -1502,7 +2339,7 @@ void MacroAssembler::PopRegistersToMemory(RegList regs) { |
int r = JSCallerSavedCode(i); |
if ((regs & (1 << r)) != 0) { |
ExternalReference reg_addr = |
- ExternalReference(Debug_Address::Register(i)); |
+ ExternalReference(Debug_Address::Register(i)); |
movq(kScratchRegister, reg_addr); |
pop(Operand(kScratchRegister, 0)); |
} |
@@ -1523,7 +2360,7 @@ void MacroAssembler::CopyRegistersFromStackToMemory(Register base, |
if ((regs & (1 << r)) != 0) { |
movq(scratch, Operand(base, 0)); |
ExternalReference reg_addr = |
- ExternalReference(Debug_Address::Register(i)); |
+ ExternalReference(Debug_Address::Register(i)); |
movq(kScratchRegister, reg_addr); |
movq(Operand(kScratchRegister, 0), scratch); |
lea(base, Operand(base, kPointerSize)); |
@@ -1545,8 +2382,8 @@ void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag) { |
// arguments match the expected number of arguments. Fake a |
// parameter count to avoid emitting code to do the check. |
ParameterCount expected(0); |
- InvokeCode(Handle<Code>(code), expected, expected, |
- RelocInfo::CODE_TARGET, flag); |
+ InvokeCode(Handle<Code>(code), expected, expected, RelocInfo::CODE_TARGET, |
+ flag); |
const char* name = Builtins::GetName(id); |
int argc = Builtins::GetArgumentsCount(id); |
@@ -1577,8 +2414,8 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected, |
definitely_matches = true; |
} else { |
movq(rax, Immediate(actual.immediate())); |
- if (expected.immediate() == |
- SharedFunctionInfo::kDontAdaptArgumentsSentinel) { |
+ if (expected.immediate() |
+ == SharedFunctionInfo::kDontAdaptArgumentsSentinel) { |
// Don't worry about adapting arguments for built-ins that |
// don't want that done. Skip adaption code by making it look |
// like we have a match between expected and actual number of |
@@ -1668,8 +2505,8 @@ void MacroAssembler::InvokeFunction(Register function, |
ASSERT(function.is(rdi)); |
movq(rdx, FieldOperand(function, JSFunction::kSharedFunctionInfoOffset)); |
movq(rsi, FieldOperand(function, JSFunction::kContextOffset)); |
- movsxlq(rbx, |
- FieldOperand(rdx, SharedFunctionInfo::kFormalParameterCountOffset)); |
+ movsxlq(rbx, FieldOperand(rdx, |
+ SharedFunctionInfo::kFormalParameterCountOffset)); |
movq(rdx, FieldOperand(rdx, SharedFunctionInfo::kCodeOffset)); |
// Advances rdx to the end of the Code object header, to the start of |
// the executable code. |
@@ -1684,12 +2521,11 @@ void MacroAssembler::EnterFrame(StackFrame::Type type) { |
push(rbp); |
movq(rbp, rsp); |
push(rsi); // Context. |
- push(Immediate(Smi::FromInt(type))); |
+ Push(Smi::FromInt(type)); |
movq(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT); |
push(kScratchRegister); |
if (FLAG_debug_code) { |
- movq(kScratchRegister, |
- Factory::undefined_value(), |
+ movq(kScratchRegister, Factory::undefined_value(), |
RelocInfo::EMBEDDED_OBJECT); |
cmpq(Operand(rsp, 0), kScratchRegister); |
Check(not_equal, "code object not properly patched"); |
@@ -1699,7 +2535,7 @@ void MacroAssembler::EnterFrame(StackFrame::Type type) { |
void MacroAssembler::LeaveFrame(StackFrame::Type type) { |
if (FLAG_debug_code) { |
- movq(kScratchRegister, Immediate(Smi::FromInt(type))); |
+ Move(kScratchRegister, Smi::FromInt(type)); |
cmpq(Operand(rbp, StandardFrameConstants::kMarkerOffset), kScratchRegister); |
Check(equal, "stack frame types must match"); |
} |
@@ -1708,7 +2544,6 @@ void MacroAssembler::LeaveFrame(StackFrame::Type type) { |
} |
- |
void MacroAssembler::EnterExitFrame(StackFrame::Type type, int result_size) { |
ASSERT(type == StackFrame::EXIT || type == StackFrame::EXIT_DEBUG); |
@@ -1716,12 +2551,12 @@ void MacroAssembler::EnterExitFrame(StackFrame::Type type, int result_size) { |
// All constants are relative to the frame pointer of the exit frame. |
ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize); |
ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize); |
- ASSERT(ExitFrameConstants::kCallerFPOffset == 0 * kPointerSize); |
+ ASSERT(ExitFrameConstants::kCallerFPOffset == 0 * kPointerSize); |
push(rbp); |
movq(rbp, rsp); |
// Reserve room for entry stack pointer and push the debug marker. |
- ASSERT(ExitFrameConstants::kSPOffset == -1 * kPointerSize); |
+ ASSERT(ExitFrameConstants::kSPOffset == -1 * kPointerSize); |
push(Immediate(0)); // saved entry sp, patched before call |
push(Immediate(type == StackFrame::EXIT_DEBUG ? 1 : 0)); |
@@ -1765,7 +2600,7 @@ void MacroAssembler::EnterExitFrame(StackFrame::Type type, int result_size) { |
// we only pass one or two parameter, and it is in a register. |
int argument_mirror_space = 4 * kPointerSize; |
int total_stack_space = |
- argument_mirror_space + argument_stack_space + result_stack_space; |
+ argument_mirror_space + argument_stack_space + result_stack_space; |
subq(rsp, Immediate(total_stack_space)); |
#endif |
@@ -1834,8 +2669,10 @@ void MacroAssembler::LeaveExitFrame(StackFrame::Type type, int result_size) { |
} |
-Register MacroAssembler::CheckMaps(JSObject* object, Register object_reg, |
- JSObject* holder, Register holder_reg, |
+Register MacroAssembler::CheckMaps(JSObject* object, |
+ Register object_reg, |
+ JSObject* holder, |
+ Register holder_reg, |
Register scratch, |
Label* miss) { |
// Make sure there's no overlap between scratch and the other |
@@ -1901,8 +2738,7 @@ Register MacroAssembler::CheckMaps(JSObject* object, Register object_reg, |
} |
// Check the holder map. |
- Cmp(FieldOperand(reg, HeapObject::kMapOffset), |
- Handle<Map>(holder->map())); |
+ Cmp(FieldOperand(reg, HeapObject::kMapOffset), Handle<Map>(holder->map())); |
j(not_equal, miss); |
// Log the check depth. |
@@ -1919,8 +2755,6 @@ Register MacroAssembler::CheckMaps(JSObject* object, Register object_reg, |
} |
- |
- |
void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, |
Register scratch, |
Label* miss) { |
@@ -1974,8 +2808,8 @@ void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, |
movq(kScratchRegister, |
FieldOperand(holder_reg, JSGlobalProxy::kContextOffset)); |
- int token_offset = Context::kHeaderSize + |
- Context::SECURITY_TOKEN_INDEX * kPointerSize; |
+ int token_offset = Context::kHeaderSize + Context::SECURITY_TOKEN_INDEX |
+ * kPointerSize; |
movq(scratch, FieldOperand(scratch, token_offset)); |
cmpq(scratch, FieldOperand(kScratchRegister, token_offset)); |
j(not_equal, miss); |
@@ -2160,5 +2994,4 @@ CodePatcher::~CodePatcher() { |
ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); |
} |
- |
} } // namespace v8::internal |