From: erik.corry@gmail.com Date: Tue, 16 Jun 2009 09:49:29 +0000 (+0000) Subject: Avoid going into runtime system for round-towards-zero operations on ARM. X-Git-Tag: upstream/4.7.83~23896 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=824140bde066251026b4eb9ffd9abeb36570f7d7;p=platform%2Fupstream%2Fv8.git Avoid going into runtime system for round-towards-zero operations on ARM. Review URL: http://codereview.chromium.org/126192 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2182 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc index 8c28b24..fe19a2c 100644 --- a/src/arm/codegen-arm.cc +++ b/src/arm/codegen-arm.cc @@ -4728,27 +4728,53 @@ static void HandleBinaryOpSlowCases(MacroAssembler* masm, // Tries to get a signed int32 out of a double precision floating point heap -// number. Rounds towards 0. Only succeeds for doubles that are in the ranges +// number. Rounds towards 0. Fastest for doubles that are in the ranges // -0x7fffffff to -0x40000000 or 0x40000000 to 0x7fffffff. This corresponds // almost to the range of signed int32 values that are not Smis. Jumps to the -// label if the double isn't in the range it can cope with. +// label 'slow' if the double isn't in the range -0x80000000.0 to 0x80000000.0 +// (excluding the endpoints). static void GetInt32(MacroAssembler* masm, Register source, Register dest, Register scratch, + Register scratch2, Label* slow) { - Register scratch2 = dest; + Label right_exponent, done; // Get exponent word. __ ldr(scratch, FieldMemOperand(source, HeapNumber::kExponentOffset)); // Get exponent alone in scratch2. __ and_(scratch2, scratch, Operand(HeapNumber::kExponentMask)); + // Load dest with zero. We use this either for the final shift or + // for the answer. + __ mov(dest, Operand(0)); // Check whether the exponent matches a 32 bit signed int that is not a Smi. - // A non-Smi integer is 1.xxx * 2^30 so the exponent is 30 (biased). + // A non-Smi integer is 1.xxx * 2^30 so the exponent is 30 (biased). This is + // the exponent that we are fastest at and also the highest exponent we can + // handle here. const uint32_t non_smi_exponent = (HeapNumber::kExponentBias + 30) << HeapNumber::kExponentShift; __ cmp(scratch2, Operand(non_smi_exponent)); - // If not, then we go slow. - __ b(ne, slow); + // If we have a match of the int32-but-not-Smi exponent then skip some logic. + __ b(eq, &right_exponent); + // If the exponent is higher than that then go to slow case. This catches + // numbers that don't fit in a signed int32, infinities and NaNs. + __ b(gt, slow); + + // We know the exponent is smaller than 30 (biased). If it is less than + // 0 (biased) then the number is smaller in magnitude than 1.0 * 2^0, ie + // it rounds to zero. + const uint32_t zero_exponent = + (HeapNumber::kExponentBias + 0) << HeapNumber::kExponentShift; + __ sub(scratch2, scratch2, Operand(zero_exponent), SetCC); + // Dest already has a Smi zero. + __ b(lt, &done); + // We have a shifted exponent between 0 and 30 in scratch2. + __ mov(dest, Operand(scratch2, LSR, HeapNumber::kExponentShift)); + // We now have the exponent in dest. Subtract from 30 to get + // how much to shift down. + __ rsb(dest, dest, Operand(30)); + + __ bind(&right_exponent); // Get the top bits of the mantissa. __ and_(scratch2, scratch, Operand(HeapNumber::kMantissaMask)); // Put back the implicit 1. @@ -4760,12 +4786,17 @@ static void GetInt32(MacroAssembler* masm, __ mov(scratch2, Operand(scratch2, LSL, shift_distance)); // Put sign in zero flag. __ tst(scratch, Operand(HeapNumber::kSignMask)); - // Get the second half of the double. + // Get the second half of the double. For some exponents we don't actually + // need this because the bits get shifted out again, but it's probably slower + // to test than just to do it. __ ldr(scratch, FieldMemOperand(source, HeapNumber::kMantissaOffset)); // Shift down 22 bits to get the last 10 bits. - __ orr(dest, scratch2, Operand(scratch, LSR, 32 - shift_distance)); + __ orr(scratch, scratch2, Operand(scratch, LSR, 32 - shift_distance)); + // Move down according to the exponent. + __ mov(dest, Operand(scratch, LSR, dest)); // Fix sign if sign bit was set. __ rsb(dest, dest, Operand(0), LeaveCC, ne); + __ bind(&done); } @@ -4785,7 +4816,7 @@ void GenericBinaryOpStub::HandleNonSmiBitwiseOp(MacroAssembler* masm) { __ b(eq, &r1_is_smi); // It's a Smi so don't check it's a heap number. __ CompareObjectType(r1, r4, r4, HEAP_NUMBER_TYPE); __ b(ne, &slow); - GetInt32(masm, r1, r3, r4, &slow); + GetInt32(masm, r1, r3, r4, r5, &slow); __ jmp(&done_checking_r1); __ bind(&r1_is_smi); __ mov(r3, Operand(r1, ASR, 1)); @@ -4795,7 +4826,7 @@ void GenericBinaryOpStub::HandleNonSmiBitwiseOp(MacroAssembler* masm) { __ b(eq, &r0_is_smi); // It's a Smi so don't check it's a heap number. __ CompareObjectType(r0, r4, r4, HEAP_NUMBER_TYPE); __ b(ne, &slow); - GetInt32(masm, r0, r2, r4, &slow); + GetInt32(masm, r0, r2, r4, r5, &slow); __ jmp(&done_checking_r0); __ bind(&r0_is_smi); __ mov(r2, Operand(r0, ASR, 1)); diff --git a/test/mjsunit/date-parse.js b/test/mjsunit/date-parse.js index 4464727..56ceba3 100644 --- a/test/mjsunit/date-parse.js +++ b/test/mjsunit/date-parse.js @@ -254,7 +254,7 @@ testCasesMisc.forEach(testDateParseMisc); for (var i = 0; i < 24 * 365 * 100; i += 95) { var ms = i * (3600 * 1000); var s = (new Date(ms)).toString(); - assertEquals(ms, Date.parse(s), s); + assertEquals(ms, Date.parse(s), "parse own: " + s); } // Negative tests. diff --git a/test/mjsunit/toint32.js b/test/mjsunit/toint32.js index a558295..9dad9c9 100644 --- a/test/mjsunit/toint32.js +++ b/test/mjsunit/toint32.js @@ -29,19 +29,19 @@ function toInt32(x) { return x | 0; } -assertEquals(0, toInt32(Infinity)); -assertEquals(0, toInt32(-Infinity)); -assertEquals(0, toInt32(NaN)); -assertEquals(0, toInt32(0.0)); -assertEquals(0, toInt32(-0.0)); +assertEquals(0, toInt32(Infinity), "Inf"); +assertEquals(0, toInt32(-Infinity), "-Inf"); +assertEquals(0, toInt32(NaN), "NaN"); +assertEquals(0, toInt32(0.0), "zero"); +assertEquals(0, toInt32(-0.0), "-zero"); assertEquals(0, toInt32(Number.MIN_VALUE)); assertEquals(0, toInt32(-Number.MIN_VALUE)); assertEquals(0, toInt32(0.1)); assertEquals(0, toInt32(-0.1)); -assertEquals(1, toInt32(1)); -assertEquals(1, toInt32(1.1)); -assertEquals(-1, toInt32(-1)); +assertEquals(1, toInt32(1), "one"); +assertEquals(1, toInt32(1.1), "onepointone"); +assertEquals(-1, toInt32(-1), "-one"); assertEquals(0, toInt32(0.6), "truncate positive (0.6)"); assertEquals(1, toInt32(1.6), "truncate positive (1.6)"); assertEquals(0, toInt32(-0.6), "truncate negative (-0.6)");