| Index: src/x64/codegen-x64.cc
|
| diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc
|
| index 7ee8359bb1e5344dc599a737368737d0f56dae1d..40eeb77ed0bf31e171d0960aa2e2df63ed06cf47 100644
|
| --- a/src/x64/codegen-x64.cc
|
| +++ b/src/x64/codegen-x64.cc
|
| @@ -8058,28 +8058,70 @@ void TranscendentalCacheStub::GenerateOperation(MacroAssembler* masm,
|
|
|
|
|
| // Get the integer part of a heap number.
|
| -// Trashes rdi and rbx. Dest is rcx. Source cannot be rcx or one of the
|
| -// trashed registers.
|
| +// Overwrites the contents of rdi, rbx and rcx. Result cannot be rdi or rbx.
|
| void IntegerConvert(MacroAssembler* masm,
|
| - Register source,
|
| - Label* conversion_failure) {
|
| - ASSERT(!source.is(rcx) && !source.is(rdi) && !source.is(rbx));
|
| - Register scratch = rbx;
|
| - Register scratch2 = rdi;
|
| - // Get exponent word.
|
| - __ movq(scratch2, FieldOperand(source, HeapNumber::kValueOffset));
|
| - // Get exponent alone in scratch2.
|
| - __ movq(xmm0, scratch2);
|
| - __ shr(scratch2, Immediate(HeapNumber::kMantissaBits));
|
| - __ andl(scratch2, Immediate((1 << HeapNumber::KExponentBits) - 1));
|
| + 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.
|
| - // (Notice: Doesn't handle MIN_SMI).
|
| - __ cmpl(scratch2, Immediate(63 + HeapNumber::kExponentBias));
|
| - __ j(greater_equal, conversion_failure);
|
| - // Handle exponent range -inf..62.
|
| - __ cvttsd2siq(rcx, xmm0);
|
| - // TODO(lrn): Do bit-fiddling for exponents in range 63..84 and return
|
| - // zero for everything else (also including negative exponents).
|
| + __ cmpl(double_exponent, Immediate(63));
|
| + __ j(above_equal, &exponent_63_plus);
|
| + // Handle exponent range 0..62.
|
| + __ cvttsd2siq(result, xmm0);
|
| + __ jmp(&done);
|
| +
|
| + __ 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);
|
| +
|
| + // 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);
|
| + }
|
| +
|
| + __ bind(&done);
|
| }
|
|
|
|
|
| @@ -8129,14 +8171,11 @@ void GenericUnaryOpStub::Generate(MacroAssembler* masm) {
|
| __ j(not_equal, &slow);
|
|
|
| // Convert the heap number in rax to an untagged integer in rcx.
|
| - IntegerConvert(masm, rax, &slow);
|
| + IntegerConvert(masm, rax, rax);
|
|
|
| - // Do the bitwise operation and check if the result fits in a smi.
|
| - Label try_float;
|
| - __ not_(rcx);
|
| - // Tag the result as a smi and we're done.
|
| - ASSERT(kSmiTagSize == 1);
|
| - __ Integer32ToSmi(rax, rcx);
|
| + // Do the bitwise operation and smi tag the result.
|
| + __ notl(rax);
|
| + __ Integer32ToSmi(rax, rax);
|
| }
|
|
|
| // Return from the stub.
|
| @@ -9732,8 +9771,7 @@ void FloatingPointHelper::LoadAsIntegers(MacroAssembler* masm,
|
| __ CompareRoot(rbx, Heap::kHeapNumberMapRootIndex);
|
| __ j(not_equal, &check_undefined_arg1);
|
| // Get the untagged integer version of the edx heap number in rcx.
|
| - IntegerConvert(masm, rdx, conversion_failure);
|
| - __ movl(rdx, rcx);
|
| + IntegerConvert(masm, rdx, rdx);
|
|
|
| // Here rdx has the untagged integer, rax has a Smi or a heap number.
|
| __ bind(&load_arg2);
|
| @@ -9755,7 +9793,7 @@ void FloatingPointHelper::LoadAsIntegers(MacroAssembler* masm,
|
| __ CompareRoot(rbx, Heap::kHeapNumberMapRootIndex);
|
| __ j(not_equal, &check_undefined_arg2);
|
| // Get the untagged integer version of the eax heap number in ecx.
|
| - IntegerConvert(masm, rax, conversion_failure);
|
| + IntegerConvert(masm, rcx, rax);
|
| __ bind(&done);
|
| __ movl(rax, rdx);
|
| }
|
|
|