| Index: src/x64/code-stubs-x64.cc
|
| diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
|
| index 0c0c2725cbf3e559c11c5a709985559ae3c4d528..fb557f95d57036e428bd60b737f51805940e58dc 100644
|
| --- a/src/x64/code-stubs-x64.cc
|
| +++ b/src/x64/code-stubs-x64.cc
|
| @@ -607,71 +607,87 @@ class FloatingPointHelper : public AllStatic {
|
| };
|
|
|
|
|
| -// Get the integer part of a heap number.
|
| -// Overwrites the contents of rdi, rbx and rcx. Result cannot be rdi or rbx.
|
| -void IntegerConvert(MacroAssembler* masm,
|
| - Register result,
|
| - Register source) {
|
| - // Result may be rcx. If result and source are the same register, source will
|
| - // be overwritten.
|
| - ASSERT(!result.is(rdi) && !result.is(rbx));
|
| - // TODO(lrn): When type info reaches here, if value is a 32-bit integer, use
|
| - // cvttsd2si (32-bit version) directly.
|
| - Register double_exponent = rbx;
|
| - Register double_value = rdi;
|
| - Label done, exponent_63_plus;
|
| - // Get double and extract exponent.
|
| - __ movq(double_value, FieldOperand(source, HeapNumber::kValueOffset));
|
| - // Clear result preemptively, in case we need to return zero.
|
| - __ xorl(result, result);
|
| - __ movq(xmm0, double_value); // Save copy in xmm0 in case we need it there.
|
| - // Double to remove sign bit, shift exponent down to least significant bits.
|
| - // and subtract bias to get the unshifted, unbiased exponent.
|
| - __ lea(double_exponent, Operand(double_value, double_value, times_1, 0));
|
| - __ shr(double_exponent, Immediate(64 - HeapNumber::kExponentBits));
|
| - __ subl(double_exponent, Immediate(HeapNumber::kExponentBias));
|
| - // Check whether the exponent is too big for a 63 bit unsigned integer.
|
| - __ cmpl(double_exponent, Immediate(63));
|
| - __ j(above_equal, &exponent_63_plus, Label::kNear);
|
| - // Handle exponent range 0..62.
|
| - __ cvttsd2siq(result, xmm0);
|
| - __ jmp(&done, Label::kNear);
|
| +void DoubleToIStub::Generate(MacroAssembler* masm) {
|
| + Register input_reg = this->source();
|
| + Register final_result_reg = this->destination();
|
| + ASSERT(is_truncating());
|
|
|
| - __ bind(&exponent_63_plus);
|
| - // Exponent negative or 63+.
|
| - __ cmpl(double_exponent, Immediate(83));
|
| - // If exponent negative or above 83, number contains no significant bits in
|
| - // the range 0..2^31, so result is zero, and rcx already holds zero.
|
| - __ j(above, &done, Label::kNear);
|
| -
|
| - // Exponent in rage 63..83.
|
| - // Mantissa * 2^exponent contains bits in the range 2^0..2^31, namely
|
| - // the least significant exponent-52 bits.
|
| -
|
| - // Negate low bits of mantissa if value is negative.
|
| - __ addq(double_value, double_value); // Move sign bit to carry.
|
| - __ sbbl(result, result); // And convert carry to -1 in result register.
|
| - // if scratch2 is negative, do (scratch2-1)^-1, otherwise (scratch2-0)^0.
|
| - __ addl(double_value, result);
|
| - // Do xor in opposite directions depending on where we want the result
|
| - // (depending on whether result is rcx or not).
|
| -
|
| - if (result.is(rcx)) {
|
| - __ xorl(double_value, result);
|
| - // Left shift mantissa by (exponent - mantissabits - 1) to save the
|
| - // bits that have positional values below 2^32 (the extra -1 comes from the
|
| - // doubling done above to move the sign bit into the carry flag).
|
| - __ leal(rcx, Operand(double_exponent, -HeapNumber::kMantissaBits - 1));
|
| - __ shll_cl(double_value);
|
| - __ movl(result, double_value);
|
| - } else {
|
| - // As the then-branch, but move double-value to result before shifting.
|
| - __ xorl(result, double_value);
|
| - __ leal(rcx, Operand(double_exponent, -HeapNumber::kMantissaBits - 1));
|
| - __ shll_cl(result);
|
| - }
|
| + Label check_negative, process_64_bits, done;
|
|
|
| - __ bind(&done);
|
| + int double_offset = offset();
|
| +
|
| + // Account for return address and saved regs if input is rsp.
|
| + if (input_reg.is(rsp)) double_offset += 3 * kPointerSize;
|
| +
|
| + MemOperand mantissa_operand(MemOperand(input_reg, double_offset));
|
| + MemOperand exponent_operand(MemOperand(input_reg,
|
| + double_offset + kDoubleSize / 2));
|
| +
|
| + Register scratch1;
|
| + Register scratch_candidates[3] = { rbx, rdx, rdi };
|
| + for (int i = 0; i < 3; i++) {
|
| + scratch1 = scratch_candidates[i];
|
| + if (!final_result_reg.is(scratch1) && !input_reg.is(scratch1)) break;
|
| + }
|
| +
|
| + // Since we must use rcx for shifts below, use some other register (rax)
|
| + // to calculate the result if ecx is the requested return register.
|
| + Register result_reg = final_result_reg.is(rcx) ? rax : final_result_reg;
|
| + // Save ecx if it isn't the return register and therefore volatile, or if it
|
| + // is the return register, then save the temp register we use in its stead
|
| + // for the result.
|
| + Register save_reg = final_result_reg.is(rcx) ? rax : rcx;
|
| + __ push(scratch1);
|
| + __ push(save_reg);
|
| +
|
| + bool stash_exponent_copy = !input_reg.is(rsp);
|
| + __ movl(scratch1, mantissa_operand);
|
| + __ movsd(xmm0, mantissa_operand);
|
| + __ movl(rcx, exponent_operand);
|
| + if (stash_exponent_copy) __ push(rcx);
|
| +
|
| + __ andl(rcx, Immediate(HeapNumber::kExponentMask));
|
| + __ shrl(rcx, Immediate(HeapNumber::kExponentShift));
|
| + __ leal(result_reg, MemOperand(rcx, -HeapNumber::kExponentBias));
|
| + __ cmpl(result_reg, Immediate(HeapNumber::kMantissaBits));
|
| + __ j(below, &process_64_bits);
|
| +
|
| + // Result is entirely in lower 32-bits of mantissa
|
| + int delta = HeapNumber::kExponentBias + Double::kPhysicalSignificandSize;
|
| + __ subl(rcx, Immediate(delta));
|
| + __ xorl(result_reg, result_reg);
|
| + __ cmpl(rcx, Immediate(31));
|
| + __ j(above, &done);
|
| + __ shll_cl(scratch1);
|
| + __ jmp(&check_negative);
|
| +
|
| + __ bind(&process_64_bits);
|
| + __ cvttsd2siq(result_reg, xmm0);
|
| + __ jmp(&done, Label::kNear);
|
| +
|
| + // If the double was negative, negate the integer result.
|
| + __ bind(&check_negative);
|
| + __ movl(result_reg, scratch1);
|
| + __ negl(result_reg);
|
| + if (stash_exponent_copy) {
|
| + __ cmpl(MemOperand(rsp, 0), Immediate(0));
|
| + } else {
|
| + __ cmpl(exponent_operand, Immediate(0));
|
| + }
|
| + __ cmovl(greater, result_reg, scratch1);
|
| +
|
| + // Restore registers
|
| + __ bind(&done);
|
| + if (stash_exponent_copy) {
|
| + __ addq(rsp, Immediate(kDoubleSize));
|
| + }
|
| + if (!final_result_reg.is(result_reg)) {
|
| + ASSERT(final_result_reg.is(rcx));
|
| + __ movl(final_result_reg, result_reg);
|
| + }
|
| + __ pop(save_reg);
|
| + __ pop(scratch1);
|
| + __ ret(0);
|
| }
|
|
|
|
|
| @@ -1557,12 +1573,18 @@ void FloatingPointHelper::LoadNumbersAsIntegers(MacroAssembler* masm) {
|
| __ JumpIfSmi(rax, &rax_is_smi);
|
|
|
| __ bind(&rax_is_object);
|
| - IntegerConvert(masm, rcx, rax); // Uses rdi, rcx and rbx.
|
| + DoubleToIStub stub1(rax, rcx, HeapNumber::kValueOffset - kHeapObjectTag,
|
| + true);
|
| + __ call(stub1.GetCode(masm->isolate()), RelocInfo::CODE_TARGET);
|
| +
|
| __ jmp(&done);
|
|
|
| __ bind(&rdx_is_object);
|
| - IntegerConvert(masm, rdx, rdx); // Uses rdi, rcx and rbx.
|
| + DoubleToIStub stub2(rdx, rdx, HeapNumber::kValueOffset - kHeapObjectTag,
|
| + true);
|
| + __ call(stub1.GetCode(masm->isolate()), RelocInfo::CODE_TARGET);
|
| __ JumpIfNotSmi(rax, &rax_is_object);
|
| +
|
| __ bind(&rax_is_smi);
|
| __ SmiToInteger32(rcx, rax);
|
|
|
| @@ -1597,7 +1619,9 @@ void FloatingPointHelper::LoadAsIntegers(MacroAssembler* masm,
|
| __ cmpq(FieldOperand(rdx, HeapObject::kMapOffset), heap_number_map);
|
| __ j(not_equal, &check_undefined_arg1);
|
| // Get the untagged integer version of the rdx heap number in rcx.
|
| - IntegerConvert(masm, r8, rdx);
|
| + DoubleToIStub stub1(rdx, r8, HeapNumber::kValueOffset - kHeapObjectTag,
|
| + true);
|
| + __ call(stub1.GetCode(masm->isolate()), RelocInfo::CODE_TARGET);
|
|
|
| // Here r8 has the untagged integer, rax has a Smi or a heap number.
|
| __ bind(&load_arg2);
|
| @@ -1617,7 +1641,10 @@ void FloatingPointHelper::LoadAsIntegers(MacroAssembler* masm,
|
| __ cmpq(FieldOperand(rax, HeapObject::kMapOffset), heap_number_map);
|
| __ j(not_equal, &check_undefined_arg2);
|
| // Get the untagged integer version of the rax heap number in rcx.
|
| - IntegerConvert(masm, rcx, rax);
|
| + DoubleToIStub stub2(rax, rcx, HeapNumber::kValueOffset - kHeapObjectTag,
|
| + true);
|
| + __ call(stub2.GetCode(masm->isolate()), RelocInfo::CODE_TARGET);
|
| +
|
| __ bind(&done);
|
| __ movl(rax, r8);
|
| }
|
| @@ -3336,7 +3363,7 @@ void ICCompareStub::GenerateGeneric(MacroAssembler* masm) {
|
| Label first_non_object;
|
| __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx);
|
| __ j(below, &first_non_object, Label::kNear);
|
| - // Return non-zero (eax (not rax) is not zero)
|
| + // Return non-zero (rax (not rax) is not zero)
|
| Label return_not_equal;
|
| STATIC_ASSERT(kHeapObjectTag != 0);
|
| __ bind(&return_not_equal);
|
| @@ -3398,7 +3425,7 @@ void ICCompareStub::GenerateGeneric(MacroAssembler* masm) {
|
| masm, &check_for_strings, rdx, kScratchRegister);
|
|
|
| // We've already checked for object identity, so if both operands are
|
| - // internalized strings they aren't equal. Register eax (not rax) already
|
| + // internalized strings they aren't equal. Register rax (not rax) already
|
| // holds a non-zero value, which indicates not equal, so just return.
|
| __ ret(0);
|
| }
|
|
|