Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(419)

Unified Diff: src/x64/codegen-x64.cc

Issue 2048007: X64: Made bit-fiddling fallback for double-to-int32 conversion. (Closed)
Patch Set: Addressed review comments. Removed setcc. Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/x64/assembler-x64.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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);
}
« no previous file with comments | « src/x64/assembler-x64.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698