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

Side by Side 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 unified diff | Download patch
« no previous file with comments | « src/x64/assembler-x64.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 8040 matching lines...) Expand 10 before | Expand all | Expand 10 after
8051 __ fcos(); 8051 __ fcos();
8052 break; 8052 break;
8053 default: 8053 default:
8054 UNREACHABLE(); 8054 UNREACHABLE();
8055 } 8055 }
8056 __ bind(&done); 8056 __ bind(&done);
8057 } 8057 }
8058 8058
8059 8059
8060 // Get the integer part of a heap number. 8060 // Get the integer part of a heap number.
8061 // Trashes rdi and rbx. Dest is rcx. Source cannot be rcx or one of the 8061 // Overwrites the contents of rdi, rbx and rcx. Result cannot be rdi or rbx.
8062 // trashed registers.
8063 void IntegerConvert(MacroAssembler* masm, 8062 void IntegerConvert(MacroAssembler* masm,
8064 Register source, 8063 Register result,
8065 Label* conversion_failure) { 8064 Register source) {
8066 ASSERT(!source.is(rcx) && !source.is(rdi) && !source.is(rbx)); 8065 // Result may be rcx. If result and source are the same register, source will
8067 Register scratch = rbx; 8066 // be overwritten.
8068 Register scratch2 = rdi; 8067 ASSERT(!result.is(rdi) && !result.is(rbx));
8069 // Get exponent word. 8068 // TODO(lrn): When type info reaches here, if value is a 32-bit integer, use
8070 __ movq(scratch2, FieldOperand(source, HeapNumber::kValueOffset)); 8069 // cvttsd2si (32-bit version) directly.
8071 // Get exponent alone in scratch2. 8070 Register double_exponent = rbx;
8072 __ movq(xmm0, scratch2); 8071 Register double_value = rdi;
8073 __ shr(scratch2, Immediate(HeapNumber::kMantissaBits)); 8072 Label done, exponent_63_plus;
8074 __ andl(scratch2, Immediate((1 << HeapNumber::KExponentBits) - 1)); 8073 // Get double and extract exponent.
8074 __ movq(double_value, FieldOperand(source, HeapNumber::kValueOffset));
8075 // Clear result preemptively, in case we need to return zero.
8076 __ xorl(result, result);
8077 __ movq(xmm0, double_value); // Save copy in xmm0 in case we need it there.
8078 // Double to remove sign bit, shift exponent down to least significant bits.
8079 // and subtract bias to get the unshifted, unbiased exponent.
8080 __ lea(double_exponent, Operand(double_value, double_value, times_1, 0));
8081 __ shr(double_exponent, Immediate(64 - HeapNumber::KExponentBits));
8082 __ subl(double_exponent, Immediate(HeapNumber::kExponentBias));
8075 // Check whether the exponent is too big for a 63 bit unsigned integer. 8083 // Check whether the exponent is too big for a 63 bit unsigned integer.
8076 // (Notice: Doesn't handle MIN_SMI). 8084 __ cmpl(double_exponent, Immediate(63));
8077 __ cmpl(scratch2, Immediate(63 + HeapNumber::kExponentBias)); 8085 __ j(above_equal, &exponent_63_plus);
8078 __ j(greater_equal, conversion_failure); 8086 // Handle exponent range 0..62.
8079 // Handle exponent range -inf..62. 8087 __ cvttsd2siq(result, xmm0);
8080 __ cvttsd2siq(rcx, xmm0); 8088 __ jmp(&done);
8081 // TODO(lrn): Do bit-fiddling for exponents in range 63..84 and return 8089
8082 // zero for everything else (also including negative exponents). 8090 __ bind(&exponent_63_plus);
8091 // Exponent negative or 63+.
8092 __ cmpl(double_exponent, Immediate(83));
8093 // If exponent negative or above 83, number contains no significant bits in
8094 // the range 0..2^31, so result is zero, and rcx already holds zero.
8095 __ j(above, &done);
8096
8097 // Exponent in rage 63..83.
8098 // Mantissa * 2^exponent contains bits in the range 2^0..2^31, namely
8099 // the least significant exponent-52 bits.
8100
8101 // Negate low bits of mantissa if value is negative.
8102 __ addq(double_value, double_value); // Move sign bit to carry.
8103 __ sbbl(result, result); // And convert carry to -1 in result register.
8104 // if scratch2 is negative, do (scratch2-1)^-1, otherwise (scratch2-0)^0.
8105 __ addl(double_value, result);
8106 // Do xor in opposite directions depending on where we want the result
8107 // (depending on whether result is rcx or not).
8108
8109 if (result.is(rcx)) {
8110 __ xorl(double_value, result);
8111 // Left shift mantissa by (exponent - mantissabits - 1) to save the
8112 // bits that have positional values below 2^32 (the extra -1 comes from the
8113 // doubling done above to move the sign bit into the carry flag).
8114 __ leal(rcx, Operand(double_exponent, -HeapNumber::kMantissaBits - 1));
8115 __ shll_cl(double_value);
8116 __ movl(result, double_value);
8117 } else {
8118 // As the then-branch, but move double-value to result before shifting.
8119 __ xorl(result, double_value);
8120 __ leal(rcx, Operand(double_exponent, -HeapNumber::kMantissaBits - 1));
8121 __ shll_cl(result);
8122 }
8123
8124 __ bind(&done);
8083 } 8125 }
8084 8126
8085 8127
8086 void GenericUnaryOpStub::Generate(MacroAssembler* masm) { 8128 void GenericUnaryOpStub::Generate(MacroAssembler* masm) {
8087 Label slow, done; 8129 Label slow, done;
8088 8130
8089 if (op_ == Token::SUB) { 8131 if (op_ == Token::SUB) {
8090 // Check whether the value is a smi. 8132 // Check whether the value is a smi.
8091 Label try_float; 8133 Label try_float;
8092 __ JumpIfNotSmi(rax, &try_float); 8134 __ JumpIfNotSmi(rax, &try_float);
(...skipping 29 matching lines...) Expand all
8122 __ movq(FieldOperand(rcx, HeapNumber::kValueOffset), rdx); 8164 __ movq(FieldOperand(rcx, HeapNumber::kValueOffset), rdx);
8123 __ movq(rax, rcx); 8165 __ movq(rax, rcx);
8124 } 8166 }
8125 } else if (op_ == Token::BIT_NOT) { 8167 } else if (op_ == Token::BIT_NOT) {
8126 // Check if the operand is a heap number. 8168 // Check if the operand is a heap number.
8127 __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset)); 8169 __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset));
8128 __ CompareRoot(rdx, Heap::kHeapNumberMapRootIndex); 8170 __ CompareRoot(rdx, Heap::kHeapNumberMapRootIndex);
8129 __ j(not_equal, &slow); 8171 __ j(not_equal, &slow);
8130 8172
8131 // Convert the heap number in rax to an untagged integer in rcx. 8173 // Convert the heap number in rax to an untagged integer in rcx.
8132 IntegerConvert(masm, rax, &slow); 8174 IntegerConvert(masm, rax, rax);
8133 8175
8134 // Do the bitwise operation and check if the result fits in a smi. 8176 // Do the bitwise operation and smi tag the result.
8135 Label try_float; 8177 __ notl(rax);
8136 __ not_(rcx); 8178 __ Integer32ToSmi(rax, rax);
8137 // Tag the result as a smi and we're done.
8138 ASSERT(kSmiTagSize == 1);
8139 __ Integer32ToSmi(rax, rcx);
8140 } 8179 }
8141 8180
8142 // Return from the stub. 8181 // Return from the stub.
8143 __ bind(&done); 8182 __ bind(&done);
8144 __ StubReturn(1); 8183 __ StubReturn(1);
8145 8184
8146 // Handle the slow case by jumping to the JavaScript builtin. 8185 // Handle the slow case by jumping to the JavaScript builtin.
8147 __ bind(&slow); 8186 __ bind(&slow);
8148 __ pop(rcx); // pop return address 8187 __ pop(rcx); // pop return address
8149 __ push(rax); 8188 __ push(rax);
(...skipping 1575 matching lines...) Expand 10 before | Expand all | Expand 10 after
9725 __ CompareRoot(rdx, Heap::kUndefinedValueRootIndex); 9764 __ CompareRoot(rdx, Heap::kUndefinedValueRootIndex);
9726 __ j(not_equal, conversion_failure); 9765 __ j(not_equal, conversion_failure);
9727 __ movl(rdx, Immediate(0)); 9766 __ movl(rdx, Immediate(0));
9728 __ jmp(&load_arg2); 9767 __ jmp(&load_arg2);
9729 9768
9730 __ bind(&arg1_is_object); 9769 __ bind(&arg1_is_object);
9731 __ movq(rbx, FieldOperand(rdx, HeapObject::kMapOffset)); 9770 __ movq(rbx, FieldOperand(rdx, HeapObject::kMapOffset));
9732 __ CompareRoot(rbx, Heap::kHeapNumberMapRootIndex); 9771 __ CompareRoot(rbx, Heap::kHeapNumberMapRootIndex);
9733 __ j(not_equal, &check_undefined_arg1); 9772 __ j(not_equal, &check_undefined_arg1);
9734 // Get the untagged integer version of the edx heap number in rcx. 9773 // Get the untagged integer version of the edx heap number in rcx.
9735 IntegerConvert(masm, rdx, conversion_failure); 9774 IntegerConvert(masm, rdx, rdx);
9736 __ movl(rdx, rcx);
9737 9775
9738 // Here rdx has the untagged integer, rax has a Smi or a heap number. 9776 // Here rdx has the untagged integer, rax has a Smi or a heap number.
9739 __ bind(&load_arg2); 9777 __ bind(&load_arg2);
9740 // Test if arg2 is a Smi. 9778 // Test if arg2 is a Smi.
9741 __ JumpIfNotSmi(rax, &arg2_is_object); 9779 __ JumpIfNotSmi(rax, &arg2_is_object);
9742 __ SmiToInteger32(rax, rax); 9780 __ SmiToInteger32(rax, rax);
9743 __ movl(rcx, rax); 9781 __ movl(rcx, rax);
9744 __ jmp(&done); 9782 __ jmp(&done);
9745 9783
9746 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). 9784 // If the argument is undefined it converts to zero (ECMA-262, section 9.5).
9747 __ bind(&check_undefined_arg2); 9785 __ bind(&check_undefined_arg2);
9748 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); 9786 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
9749 __ j(not_equal, conversion_failure); 9787 __ j(not_equal, conversion_failure);
9750 __ movl(rcx, Immediate(0)); 9788 __ movl(rcx, Immediate(0));
9751 __ jmp(&done); 9789 __ jmp(&done);
9752 9790
9753 __ bind(&arg2_is_object); 9791 __ bind(&arg2_is_object);
9754 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); 9792 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
9755 __ CompareRoot(rbx, Heap::kHeapNumberMapRootIndex); 9793 __ CompareRoot(rbx, Heap::kHeapNumberMapRootIndex);
9756 __ j(not_equal, &check_undefined_arg2); 9794 __ j(not_equal, &check_undefined_arg2);
9757 // Get the untagged integer version of the eax heap number in ecx. 9795 // Get the untagged integer version of the eax heap number in ecx.
9758 IntegerConvert(masm, rax, conversion_failure); 9796 IntegerConvert(masm, rcx, rax);
9759 __ bind(&done); 9797 __ bind(&done);
9760 __ movl(rax, rdx); 9798 __ movl(rax, rdx);
9761 } 9799 }
9762 9800
9763 9801
9764 void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm, 9802 void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm,
9765 Register lhs, 9803 Register lhs,
9766 Register rhs) { 9804 Register rhs) {
9767 Label load_smi_lhs, load_smi_rhs, done_load_lhs, done; 9805 Label load_smi_lhs, load_smi_rhs, done_load_lhs, done;
9768 __ JumpIfSmi(lhs, &load_smi_lhs); 9806 __ JumpIfSmi(lhs, &load_smi_lhs);
(...skipping 1803 matching lines...) Expand 10 before | Expand all | Expand 10 after
11572 // Call the function from C++. 11610 // Call the function from C++.
11573 return FUNCTION_CAST<ModuloFunction>(buffer); 11611 return FUNCTION_CAST<ModuloFunction>(buffer);
11574 } 11612 }
11575 11613
11576 #endif 11614 #endif
11577 11615
11578 11616
11579 #undef __ 11617 #undef __
11580 11618
11581 } } // namespace v8::internal 11619 } } // namespace v8::internal
OLDNEW
« 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