| 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);
|
|
|