Index: src/x64/code-stubs-x64.cc |
diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc |
index 551a71690e7a45400ec4d078ef7fcf4e89e39f0b..7e580d387beed838a49aa914db62a3756d985b54 100644 |
--- a/src/x64/code-stubs-x64.cc |
+++ b/src/x64/code-stubs-x64.cc |
@@ -723,12 +723,19 @@ static void BinaryOpStub_GenerateSmiCode( |
const Register left = rdx; |
const Register right = rax; |
+#if !V8_USE_31_BITS_SMI_VALUE |
// We only generate heapnumber answers for overflowing calculations |
// for the four basic arithmetic operations and logical right shift by 0. |
bool generate_inline_heapnumber_results = |
(allow_heapnumber_results == BinaryOpStub::ALLOW_HEAPNUMBER_RESULTS) && |
(op == Token::ADD || op == Token::SUB || |
op == Token::MUL || op == Token::DIV || op == Token::SHR); |
+#else |
+ bool generate_inline_heapnumber_results = |
+ (allow_heapnumber_results == BinaryOpStub::ALLOW_HEAPNUMBER_RESULTS) && |
+ (op == Token::ADD || op == Token::SUB || op == Token::SHL || |
+ op == Token::MUL || op == Token::DIV || op == Token::SHR); |
+#endif |
// Smi check of both operands. If op is BIT_OR, the check is delayed |
// until after the OR operation. |
@@ -791,7 +798,13 @@ static void BinaryOpStub_GenerateSmiCode( |
break; |
case Token::SHL: |
+#if !V8_USE_31_BITS_SMI_VALUE |
__ SmiShiftLeft(left, left, right); |
+#else |
+ __ push(left); |
+ __ push(right); |
+ __ SmiShiftLeft(left, left, right, &use_fp_on_smis); |
+#endif |
__ movq(rax, left); |
break; |
@@ -801,6 +814,10 @@ static void BinaryOpStub_GenerateSmiCode( |
break; |
case Token::SHR: |
+#if V8_USE_31_BITS_SMI_VALUE |
+ __ push(left); |
+ __ push(right); |
+#endif |
__ SmiShiftLogicalRight(left, left, right, &use_fp_on_smis); |
__ movq(rax, left); |
break; |
@@ -810,6 +827,12 @@ static void BinaryOpStub_GenerateSmiCode( |
} |
// 5. Emit return of result in rax. Some operations have registers pushed. |
+#ifdef V8_USE_31_BITS_SMI_VALUE |
+ if (op == Token::SHL || op == Token::SHR) { |
+ // drop arguments. |
+ __ addq(rsp, Immediate(2 * kRegisterSize)); |
+ } |
+#endif |
__ ret(0); |
if (use_fp_on_smis.is_linked()) { |
@@ -824,12 +847,31 @@ static void BinaryOpStub_GenerateSmiCode( |
} |
if (generate_inline_heapnumber_results) { |
+#if !V8_USE_31_BITS_SMI_VALUE |
__ AllocateHeapNumber(rcx, rbx, slow); |
Comment perform_float(masm, "-- Perform float operation on smis"); |
if (op == Token::SHR) { |
__ SmiToInteger32(left, left); |
__ cvtqsi2sd(xmm0, left); |
} else { |
+#else |
+ Label goto_slow; |
+ __ AllocateHeapNumber(rcx, rbx, &goto_slow); |
+ Comment perform_float(masm, "-- Perform float operation on smis"); |
+ if (op == Token::SHL) { |
+ __ cvtlsi2sd(xmm0, left); |
+ // drop arguments. |
+ __ addq(rsp, Immediate(2 * kRegisterSize)); |
+ } else if (op == Token::SHR) { |
+ // The value of left is from MacroAssembler::SmiShiftLogicalRight |
+ // We allow logical shift value: |
+ // 0 : might turn a signed integer into unsigned integer |
+ // 1 : the value might be above 2^30 - 1 |
+ __ cvtqsi2sd(xmm0, left); |
+ // drop arguments. |
+ __ addq(rsp, Immediate(2 * kRegisterSize)); |
+ } else { |
+#endif |
FloatingPointHelper::LoadSSE2SmiOperands(masm); |
switch (op) { |
case Token::ADD: __ addsd(xmm0, xmm1); break; |
@@ -842,7 +884,22 @@ static void BinaryOpStub_GenerateSmiCode( |
__ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0); |
__ movq(rax, rcx); |
__ ret(0); |
+#if !V8_USE_31_BITS_SMI_VALUE |
} else { |
+#else |
+ __ bind(&goto_slow); |
+ if (op == Token::SHL || op == Token::SHR) { |
+ __ pop(right); |
+ __ pop(left); |
+ } |
+ __ jmp(slow); |
+ } else { |
+ // Restore the orignial left value |
+ if (op == Token::SHL || op == Token::SHR) { |
+ __ pop(right); |
+ __ pop(left); |
+ } |
+#endif |
__ jmp(&fail); |
} |
} |
@@ -881,6 +938,11 @@ static void BinaryOpStub_GenerateFloatingPointCode(MacroAssembler* masm, |
Label* allocation_failure, |
Label* non_numeric_failure, |
Token::Value op, |
+#if V8_USE_31_BITS_SMI_VALUE |
+ BinaryOpIC::TypeInfo |
+ result_type, |
+ Label* non_int32_failure, |
+#endif |
OverwriteMode mode) { |
switch (op) { |
case Token::ADD: |
@@ -896,6 +958,18 @@ static void BinaryOpStub_GenerateFloatingPointCode(MacroAssembler* masm, |
case Token::DIV: __ divsd(xmm0, xmm1); break; |
default: UNREACHABLE(); |
} |
+#if V8_USE_31_BITS_SMI_VALUE |
+ if (non_int32_failure != NULL) { |
+ if (result_type <= BinaryOpIC::INT32) { |
+ __ cvttsd2si(kScratchRegister, xmm0); |
+ __ cvtlsi2sd(xmm2, kScratchRegister); |
+ __ pcmpeqd(xmm2, xmm0); |
+ __ movmskpd(rcx, xmm2); |
+ __ testl(rcx, Immediate(1)); |
+ __ j(zero, non_int32_failure); |
+ } |
+ } |
+#endif |
BinaryOpStub_GenerateHeapResultAllocation( |
masm, allocation_failure, mode); |
__ movsd(FieldOperand(rax, HeapNumber::kValueOffset), xmm0); |
@@ -915,9 +989,20 @@ static void BinaryOpStub_GenerateFloatingPointCode(MacroAssembler* masm, |
case Token::SHR: { |
Label non_smi_shr_result; |
Register heap_number_map = r9; |
+#if V8_USE_31_BITS_SMI_VALUE |
+ Label goto_non_numeric_failure; |
+ // Push arguments on stack |
+ __ push(rdx); |
+ __ push(rax); |
+#endif |
__ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); |
+#if !V8_USE_31_BITS_SMI_VALUE |
FloatingPointHelper::LoadAsIntegers(masm, non_numeric_failure, |
heap_number_map); |
+#else |
+ FloatingPointHelper::LoadAsIntegers(masm, &goto_non_numeric_failure, |
+ heap_number_map); |
+#endif |
switch (op) { |
case Token::BIT_OR: __ orl(rax, rcx); break; |
case Token::BIT_AND: __ andl(rax, rcx); break; |
@@ -926,19 +1011,43 @@ static void BinaryOpStub_GenerateFloatingPointCode(MacroAssembler* masm, |
case Token::SHL: __ shll_cl(rax); break; |
case Token::SHR: { |
__ shrl_cl(rax); |
+#if !V8_USE_31_BITS_SMI_VALUE |
// Check if result is negative. This can only happen for a shift |
// by zero. |
__ testl(rax, rax); |
__ j(negative, &non_smi_shr_result); |
+#endif |
break; |
} |
default: UNREACHABLE(); |
} |
+#if !V8_USE_31_BITS_SMI_VALUE |
STATIC_ASSERT(kSmiValueSize == 32); |
+#else |
+ STATIC_ASSERT(kSmiValueSize == 31); |
+ if (op == Token::SHR) { |
+ __ testl(rax, Immediate(0xc0000000)); |
+ __ j(not_zero, &non_smi_shr_result); |
+ } else { |
+ __ cmpl(rax, Immediate(0xc0000000)); |
+ __ j(negative, &non_smi_shr_result, Label::kNear); |
+ } |
+ // drop arguments. |
+ __ addq(rsp, Immediate(2 * kRegisterSize)); |
+#endif |
// Tag smi result and return. |
__ Integer32ToSmi(rax, rax); |
__ Ret(); |
+#ifdef V8_USE_31_BITS_SMI_VALUE |
+ __ bind(&goto_non_numeric_failure); |
+ // drop arguments. |
+ __ pop(rax); |
+ __ pop(rdx); |
+ __ jmp(non_numeric_failure); |
+#endif |
+ |
+#if !V8_USE_31_BITS_SMI_VALUE |
// Logical shift right can produce an unsigned int32 that is not |
// an int32, and so is not in the smi range. Allocate a heap number |
// in that case. |
@@ -968,6 +1077,58 @@ static void BinaryOpStub_GenerateFloatingPointCode(MacroAssembler* masm, |
__ Integer32ToSmi(rdx, rbx); |
__ jmp(allocation_failure); |
} |
+#else |
+ __ bind(&non_smi_shr_result); |
+ Label allocation_failed; |
+ __ movl(rbx, rax); // rbx holds result value (uint32 value as int64). |
+ // Allocate heap number in new space. |
+ // Not using AllocateHeapNumber macro in order to reuse |
+ // already loaded heap_number_map. |
+ Label skip_allocation; |
+ switch (mode) { |
+ case OVERWRITE_LEFT: { |
+ __ movq(rax, Operand(rsp, 1 * kRegisterSize)); |
+ __ JumpIfNotSmi(rax, &skip_allocation); |
+ __ Allocate(HeapNumber::kSize, rax, r8, no_reg, &allocation_failed, |
+ TAG_OBJECT); |
+ __ bind(&skip_allocation); |
+ break; |
+ } |
+ case OVERWRITE_RIGHT: |
+ __ movq(rax, Operand(rsp, 0 * kRegisterSize)); |
+ __ JumpIfNotSmi(rax, &skip_allocation); |
+ // Fall through! |
+ case NO_OVERWRITE: |
+ __ Allocate(HeapNumber::kSize, rax, r8, no_reg, &allocation_failed, |
+ TAG_OBJECT); |
+ __ bind(&skip_allocation); |
+ break; |
+ default: UNREACHABLE(); |
+ } |
+ // Set the map. |
+ __ AssertRootValue(heap_number_map, |
+ Heap::kHeapNumberMapRootIndex, |
+ "HeapNumberMap register clobbered."); |
+ __ movq(FieldOperand(rax, HeapObject::kMapOffset), |
+ heap_number_map); |
+ if (op == Token::SHR) { |
+ __ cvtqsi2sd(xmm0, rbx); |
+ } else { |
+ // All other operations returns a signed int32, so we |
+ // use lsi2sd here to retain the sign bit. |
+ __ cvtlsi2sd(xmm0, rbx); |
+ } |
+ __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), xmm0); |
+ // drop arguments. |
+ __ addq(rsp, Immediate(2 * kRegisterSize)); |
+ __ Ret(); |
+ |
+ __ bind(&allocation_failed); |
+ // Restore arguments from stack. |
+ __ pop(rax); |
+ __ pop(rdx); |
+ __ jmp(allocation_failure); |
+#endif |
break; |
} |
default: UNREACHABLE(); break; |
@@ -1063,9 +1224,29 @@ void BinaryOpStub::GenerateSmiStub(MacroAssembler* masm) { |
void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { |
+#if !V8_USE_31_BITS_SMI_VALUE |
// The int32 case is identical to the Smi case. We avoid creating this |
// ic state on x64. |
UNREACHABLE(); |
+#else |
+ ASSERT(Max(left_type_, right_type_) == BinaryOpIC::INT32); |
+ |
+ Label gc_required, not_number, not_int32; |
+ BinaryOpStub_GenerateFloatingPointCode(masm, &gc_required, ¬_number, |
+ op_, result_type_, ¬_int32, mode_); |
+ |
+ __ bind(¬_number); |
+ __ bind(¬_int32); |
+ GenerateTypeTransition(masm); |
+ |
+ __ bind(&gc_required); |
+ { |
+ FrameScope scope(masm, StackFrame::INTERNAL); |
+ GenerateRegisterArgsPush(masm); |
+ GenerateCallRuntime(masm); |
+ } |
+ __ Ret(); |
+#endif |
} |
@@ -1170,8 +1351,13 @@ void BinaryOpStub::GenerateNumberStub(MacroAssembler* masm) { |
BinaryOpStub_CheckSmiInput(masm, rax, ¬_number); |
} |
+#if !V8_USE_31_BITS_SMI_VALUE |
BinaryOpStub_GenerateFloatingPointCode( |
masm, &gc_required, ¬_number, op_, mode_); |
+#else |
+ BinaryOpStub_GenerateFloatingPointCode( |
+ masm, &gc_required, ¬_number, op_, result_type_, NULL, mode_); |
+#endif |
__ bind(¬_number); |
GenerateTypeTransition(masm); |
@@ -1192,8 +1378,14 @@ void BinaryOpStub::GenerateGeneric(MacroAssembler* masm) { |
BinaryOpStub_GenerateSmiCode( |
masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS, op_); |
+#if !V8_USE_31_BITS_SMI_VALUE |
BinaryOpStub_GenerateFloatingPointCode( |
masm, &call_runtime, &call_string_add_or_runtime, op_, mode_); |
+#else |
+ BinaryOpStub_GenerateFloatingPointCode( |
+ masm, &call_runtime, &call_string_add_or_runtime, op_, |
+ result_type_, NULL, mode_); |
+#endif |
__ bind(&call_string_add_or_runtime); |
if (op_ == Token::ADD) { |
@@ -1744,6 +1936,10 @@ void FloatingPointHelper::NumbersToSmis(MacroAssembler* masm, |
__ movq(kScratchRegister, xmm1); |
__ cmpq(scratch2, kScratchRegister); |
__ j(not_equal, on_not_smis); |
+#if V8_USE_31_BITS_SMI_VALUE |
+ __ cmpl(smi_result, Immediate(0xc0000000)); |
+ __ j(negative, on_not_smis); |
+#endif |
__ Integer32ToSmi(first, smi_result); |
__ bind(&first_done); |
@@ -1763,6 +1959,10 @@ void FloatingPointHelper::NumbersToSmis(MacroAssembler* masm, |
__ movq(kScratchRegister, xmm1); |
__ cmpq(scratch2, kScratchRegister); |
__ j(not_equal, on_not_smis); |
+#if V8_USE_31_BITS_SMI_VALUE |
+ __ cmpl(smi_result, Immediate(0xc0000000)); |
+ __ j(negative, on_not_smis); |
+#endif |
__ Integer32ToSmi(second, smi_result); |
if (on_success != NULL) { |
__ jmp(on_success); |
@@ -3260,10 +3460,21 @@ void ICCompareStub::GenerateGeneric(MacroAssembler* masm) { |
// Compare two smis. |
Label non_smi, smi_done; |
__ JumpIfNotBothSmi(rax, rdx, &non_smi); |
+#if !V8_USE_31_BITS_SMI_VALUE |
__ subq(rdx, rax); |
+#else |
+ __ subl(rdx, rax); |
+#endif |
__ j(no_overflow, &smi_done); |
+#if !V8_USE_31_BITS_SMI_VALUE |
__ not_(rdx); // Correct sign in case of overflow. rdx cannot be 0 here. |
+#else |
+ __ notl(rdx); |
+#endif |
__ bind(&smi_done); |
+#if V8_USE_31_BITS_SMI_VALUE |
+ __ movsxlq(rdx, rdx); |
+#endif |
__ movq(rax, rdx); |
__ ret(0); |
__ bind(&non_smi); |
@@ -4572,8 +4783,12 @@ void StringAddStub::Generate(MacroAssembler* masm) { |
__ movzxbl(r9, FieldOperand(r9, Map::kInstanceTypeOffset)); |
// Look at the length of the result of adding the two strings. |
+#ifndef V8_USE_31_BITS_SMI_VALUE |
STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue / 2); |
__ SmiAdd(rbx, rbx, rcx); |
+#else |
+ __ SmiAdd(rbx, rbx, rcx, &call_runtime); |
+#endif |
// Use the string table when adding two one character strings, as it |
// helps later optimizations to return an internalized string here. |
__ SmiCompare(rbx, Smi::FromInt(2)); |
@@ -5551,11 +5766,22 @@ void ICCompareStub::GenerateSmis(MacroAssembler* masm) { |
__ subq(rax, rdx); |
} else { |
Label done; |
+#if !V8_USE_31_BITS_SMI_VALUE |
__ subq(rdx, rax); |
+#else |
+ __ subl(rdx, rax); |
+#endif |
__ j(no_overflow, &done, Label::kNear); |
+#if !V8_USE_31_BITS_SMI_VALUE |
// Correct sign of result in case of overflow. |
__ not_(rdx); |
+#else |
+ __ notl(rdx); |
+#endif |
__ bind(&done); |
+#if V8_USE_31_BITS_SMI_VALUE |
+ __ movsxlq(rdx, rdx); |
+#endif |
__ movq(rax, rdx); |
} |
__ ret(0); |