| Index: src/a64/macro-assembler-a64.cc
|
| diff --git a/src/a64/macro-assembler-a64.cc b/src/a64/macro-assembler-a64.cc
|
| index b51e9277c4e4969212417284b84033a4dc60c1e4..c5184e891521420db1966d6a391c90d9d53401b3 100644
|
| --- a/src/a64/macro-assembler-a64.cc
|
| +++ b/src/a64/macro-assembler-a64.cc
|
| @@ -2473,26 +2473,20 @@ void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
|
| }
|
|
|
|
|
| -void MacroAssembler::ECMA262ToInt32(Register result,
|
| - DoubleRegister input,
|
| - Register scratch1,
|
| - Register scratch2,
|
| - ECMA262ToInt32Result format) {
|
| - ASSERT(!AreAliased(result, scratch1, scratch2));
|
| - ASSERT(result.Is64Bits() && scratch1.Is64Bits() && scratch2.Is64Bits());
|
| +void MacroAssembler::TryInlineTruncateDoubleToI(Register result,
|
| + DoubleRegister double_input,
|
| + Label* done) {
|
| STATIC_ASSERT(kSmiTag == 0);
|
| STATIC_ASSERT(kSmiValueSize == 32);
|
|
|
| - Label done, tag, manual_conversion;
|
| -
|
| - // 1. Try to convert with a FPU convert instruction. It's trivial to compute
|
| - // the modulo operation on an integer register so we convert to a 64-bit
|
| - // integer, then find the 32-bit result from that.
|
| + // Try to convert with a FPU convert instruction. It's trivial to compute
|
| + // the modulo operation on an integer register so we convert to a 64-bit
|
| + // integer, then find the 32-bit result from that.
|
| //
|
| // Fcvtzs will saturate to INT64_MIN (0x800...00) or INT64_MAX (0x7ff...ff)
|
| // when the double is out of range. NaNs and infinities will be converted to 0
|
| // (as ECMA-262 requires).
|
| - Fcvtzs(result, input);
|
| + Fcvtzs(result, double_input);
|
|
|
| // The values INT64_MIN (0x800...00) or INT64_MAX (0x7ff...ff) are not
|
| // representable using a double, so if the result is one of those then we know
|
| @@ -2502,83 +2496,64 @@ void MacroAssembler::ECMA262ToInt32(Register result,
|
| // 1 will cause signed overflow.
|
| Cmp(result, 1);
|
| Ccmp(result, -1, VFlag, vc);
|
| - B(vc, &tag);
|
|
|
| - // 2. Manually convert the input to an int32.
|
| - Fmov(result, input);
|
| + B(vc, done);
|
| +}
|
|
|
| - // Extract the exponent.
|
| - Register exponent = scratch1;
|
| - Ubfx(exponent, result, HeapNumber::kMantissaBits, HeapNumber::kExponentBits);
|
|
|
| - // It the exponent is >= 84 (kMantissaBits + 32), the result is always 0 since
|
| - // the mantissa gets shifted completely out of the int32_t result.
|
| - Cmp(exponent, HeapNumber::kExponentBias + HeapNumber::kMantissaBits + 32);
|
| - CzeroX(result, ge);
|
| - B(ge, &done);
|
| +void MacroAssembler::TruncateDoubleToI(Register result,
|
| + DoubleRegister double_input) {
|
| + Label done;
|
| + ASSERT(jssp.Is(StackPointer()));
|
|
|
| - // The Fcvtzs sequence handles all cases except where the conversion causes
|
| - // signed overflow in the int64_t target. Since we've already handled
|
| - // exponents >= 84, we can guarantee that 63 <= exponent < 84.
|
| + TryInlineTruncateDoubleToI(result, double_input, &done);
|
|
|
| - if (emit_debug_code()) {
|
| - Cmp(exponent, HeapNumber::kExponentBias + 63);
|
| - // Exponents less than this should have been handled by the Fcvt case.
|
| - Check(ge, kUnexpectedValue);
|
| - }
|
| -
|
| - // Isolate the mantissa bits, and set the implicit '1'.
|
| - Register mantissa = scratch2;
|
| - Ubfx(mantissa, result, 0, HeapNumber::kMantissaBits);
|
| - Orr(mantissa, mantissa, 1UL << HeapNumber::kMantissaBits);
|
| -
|
| - // Negate the mantissa if necessary.
|
| - Tst(result, kXSignMask);
|
| - Cneg(mantissa, mantissa, ne);
|
| -
|
| - // Shift the mantissa bits in the correct place. We know that we have to shift
|
| - // it left here, because exponent >= 63 >= kMantissaBits.
|
| - Sub(exponent, exponent,
|
| - HeapNumber::kExponentBias + HeapNumber::kMantissaBits);
|
| - Lsl(result, mantissa, exponent);
|
| -
|
| - Bind(&tag);
|
| - switch (format) {
|
| - case INT32_IN_W:
|
| - // There is nothing to do; the upper 32 bits are undefined.
|
| - if (emit_debug_code()) {
|
| - __ Mov(scratch1, 0x55555555);
|
| - __ Bfi(result, scratch1, 32, 32);
|
| - }
|
| - break;
|
| - case INT32_IN_X:
|
| - Sxtw(result, result);
|
| - break;
|
| - case SMI:
|
| - SmiTag(result);
|
| - break;
|
| - }
|
| + // If we fell through then inline version didn't succeed - call stub instead.
|
| + Push(lr);
|
| + Push(double_input); // Put input on stack.
|
| +
|
| + DoubleToIStub stub(jssp,
|
| + result,
|
| + 0,
|
| + true, // is_truncating
|
| + true); // skip_fastpath
|
| + CallStub(&stub); // DoubleToIStub preserves any registers it needs to clobber
|
| +
|
| + Drop(1, kDoubleSize); // Drop the double input on the stack.
|
| + Pop(lr);
|
|
|
| Bind(&done);
|
| +
|
| + // TODO(rmcilroy): Remove this Sxtw once the following bug is fixed:
|
| + // https://code.google.com/p/v8/issues/detail?id=3149
|
| + Sxtw(result, result.W());
|
| }
|
|
|
|
|
| -void MacroAssembler::HeapNumberECMA262ToInt32(Register result,
|
| - Register heap_number,
|
| - Register scratch1,
|
| - Register scratch2,
|
| - DoubleRegister double_scratch,
|
| - ECMA262ToInt32Result format) {
|
| - if (emit_debug_code()) {
|
| - // Verify we indeed have a HeapNumber.
|
| - Label ok;
|
| - JumpIfHeapNumber(heap_number, &ok);
|
| - Abort(kExpectedHeapNumber);
|
| - Bind(&ok);
|
| - }
|
| +void MacroAssembler::TruncateHeapNumberToI(Register result,
|
| + Register object) {
|
| + Label done;
|
| + ASSERT(!result.is(object));
|
| + ASSERT(jssp.Is(StackPointer()));
|
| +
|
| + Ldr(fp_scratch, FieldMemOperand(object, HeapNumber::kValueOffset));
|
| + TryInlineTruncateDoubleToI(result, fp_scratch, &done);
|
| +
|
| + // If we fell through then inline version didn't succeed - call stub instead.
|
| + Push(lr);
|
| + DoubleToIStub stub(object,
|
| + result,
|
| + HeapNumber::kValueOffset - kHeapObjectTag,
|
| + true, // is_truncating
|
| + true); // skip_fastpath
|
| + CallStub(&stub); // DoubleToIStub preserves any registers it needs to clobber
|
| + Pop(lr);
|
| +
|
| + Bind(&done);
|
|
|
| - Ldr(double_scratch, FieldMemOperand(heap_number, HeapNumber::kValueOffset));
|
| - ECMA262ToInt32(result, double_scratch, scratch1, scratch2, format);
|
| + // TODO(rmcilroy): Remove this Sxtw once the following bug is fixed:
|
| + // https://code.google.com/p/v8/issues/detail?id=3149
|
| + Sxtw(result, result.W());
|
| }
|
|
|
|
|
|
|