Index: src/x64/macro-assembler-x64.cc |
=================================================================== |
--- src/x64/macro-assembler-x64.cc (revision 4579) |
+++ src/x64/macro-assembler-x64.cc (working copy) |
@@ -596,6 +596,11 @@ |
} |
+void MacroAssembler::SmiCompare(Register dst, const Operand& src) { |
+ cmpq(dst, src); |
+} |
+ |
+ |
void MacroAssembler::SmiCompare(const Operand& dst, Register src) { |
cmpq(dst, src); |
} |
@@ -731,7 +736,17 @@ |
Register src2, |
Label* on_not_smi_result) { |
ASSERT(!dst.is(src2)); |
- if (dst.is(src1)) { |
+ if (on_not_smi_result == NULL) { |
+ // No overflow checking. Use only when it's known that |
+ // overflowing is impossible. |
+ if (dst.is(src1)) { |
+ addq(dst, src2); |
+ } else { |
+ movq(dst, src1); |
+ addq(dst, src2); |
+ } |
+ Assert(no_overflow, "Smi addition onverflow"); |
+ } else if (dst.is(src1)) { |
addq(dst, src2); |
Label smi_result; |
j(no_overflow, &smi_result); |
@@ -778,6 +793,35 @@ |
} |
+void MacroAssembler::SmiSub(Register dst, |
+ Register src1, |
+ Operand const& src2, |
+ Label* on_not_smi_result) { |
+ if (on_not_smi_result == NULL) { |
+ // No overflow checking. Use only when it's known that |
+ // overflowing is impossible (e.g., subtracting two positive smis). |
+ if (dst.is(src1)) { |
+ subq(dst, src2); |
+ } else { |
+ movq(dst, src1); |
+ subq(dst, src2); |
+ } |
+ Assert(no_overflow, "Smi substraction onverflow"); |
+ } else 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, |
@@ -2526,11 +2570,16 @@ |
Label* gc_required) { |
// Calculate the number of bytes needed for the characters in the string while |
// observing object alignment. |
- ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0); |
+ const int kHeaderAlignment = SeqTwoByteString::kHeaderSize & |
+ kObjectAlignmentMask; |
ASSERT(kShortSize == 2); |
// scratch1 = length * 2 + kObjectAlignmentMask. |
- lea(scratch1, Operand(length, length, times_1, kObjectAlignmentMask)); |
+ lea(scratch1, Operand(length, length, times_1, kObjectAlignmentMask + |
+ kHeaderAlignment)); |
and_(scratch1, Immediate(~kObjectAlignmentMask)); |
+ if (kHeaderAlignment > 0) { |
+ subq(scratch1, Immediate(kHeaderAlignment)); |
+ } |
// Allocate two byte string in new space. |
AllocateInNewSpace(SeqTwoByteString::kHeaderSize, |
@@ -2545,7 +2594,8 @@ |
// Set the map, length and hash field. |
LoadRoot(kScratchRegister, Heap::kStringMapRootIndex); |
movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister); |
- movl(FieldOperand(result, String::kLengthOffset), length); |
+ Integer32ToSmi(scratch1, length); |
+ movq(FieldOperand(result, String::kLengthOffset), scratch1); |
movl(FieldOperand(result, String::kHashFieldOffset), |
Immediate(String::kEmptyHashField)); |
} |
@@ -2559,11 +2609,15 @@ |
Label* gc_required) { |
// Calculate the number of bytes needed for the characters in the string while |
// observing object alignment. |
- ASSERT((SeqAsciiString::kHeaderSize & kObjectAlignmentMask) == 0); |
+ const int kHeaderAlignment = SeqAsciiString::kHeaderSize & |
+ kObjectAlignmentMask; |
movl(scratch1, length); |
ASSERT(kCharSize == 1); |
- addq(scratch1, Immediate(kObjectAlignmentMask)); |
+ addq(scratch1, Immediate(kObjectAlignmentMask + kHeaderAlignment)); |
and_(scratch1, Immediate(~kObjectAlignmentMask)); |
+ if (kHeaderAlignment > 0) { |
+ subq(scratch1, Immediate(kHeaderAlignment)); |
+ } |
// Allocate ascii string in new space. |
AllocateInNewSpace(SeqAsciiString::kHeaderSize, |
@@ -2578,7 +2632,8 @@ |
// Set the map, length and hash field. |
LoadRoot(kScratchRegister, Heap::kAsciiStringMapRootIndex); |
movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister); |
- movl(FieldOperand(result, String::kLengthOffset), length); |
+ Integer32ToSmi(scratch1, length); |
+ movq(FieldOperand(result, String::kLengthOffset), scratch1); |
movl(FieldOperand(result, String::kHashFieldOffset), |
Immediate(String::kEmptyHashField)); |
} |