Index: src/ia32/code-stubs-ia32.cc |
diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc |
index c9d8cfd4d5941883c545982ad5464417d198ba8e..b1d0dce7f124382abf8ef17169c7a1af305db91a 100644 |
--- a/src/ia32/code-stubs-ia32.cc |
+++ b/src/ia32/code-stubs-ia32.cc |
@@ -2946,74 +2946,49 @@ void MathPowStub::Generate(MacroAssembler* masm) { |
__ mov(ecx, Immediate(1)); |
__ cvtsi2sd(xmm3, ecx); |
- switch (exponent_type_) { |
- case ON_STACK: |
- // The exponent (and base) are supplied as arguments on the stack. |
- // This can only happen if the stub is called from non-optimized code. |
- // Load input parameters from stack |
- __ mov(edx, Operand(esp, 2 * kPointerSize)); |
- __ mov(eax, Operand(esp, 1 * kPointerSize)); |
- // edx: base (smi or heap number) |
- // eax: exponent (smi or heap number) |
- __ JumpIfSmi(edx, &base_is_smi, Label::kNear); |
- __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
- factory->heap_number_map()); |
- __ j(not_equal, &generic_runtime); |
- |
- // Check base for NaN or +/-Infinity |
- __ mov(ecx, FieldOperand(edx, HeapNumber::kExponentOffset)); |
- __ and_(ecx, HeapNumber::kExponentMask); |
- __ cmp(ecx, Immediate(HeapNumber::kExponentMask)); |
- __ j(equal, &generic_runtime); |
- __ movdbl(xmm1, FieldOperand(edx, HeapNumber::kValueOffset)); |
- __ jmp(&unpack_exponent, Label::kNear); |
- |
- __ bind(&base_is_smi); |
- __ SmiUntag(edx); |
- __ cvtsi2sd(xmm1, edx); |
- __ bind(&unpack_exponent); |
- |
- __ JumpIfNotSmi(eax, &exponent_not_smi, Label::kNear); |
- __ SmiUntag(eax); |
- __ jmp(&int_exponent); |
- |
- __ bind(&exponent_not_smi); |
- __ cmp(FieldOperand(eax, HeapObject::kMapOffset), |
- factory->heap_number_map()); |
- __ j(not_equal, &generic_runtime); |
- __ movdbl(xmm2, FieldOperand(eax, HeapNumber::kValueOffset)); |
- break; |
- |
- case TAGGED: |
- // xmm1: base as double |
- // eax: exponent (smi or heap number) |
- __ JumpIfNotSmi(eax, &exponent_not_smi, Label::kNear); |
- __ SmiUntag(eax); |
- __ jmp(&int_exponent); |
- |
- __ bind(&exponent_not_smi); |
- __ movdbl(xmm2, FieldOperand(eax, HeapNumber::kValueOffset)); |
- // Fall through intended |
- case INTEGER: |
- // xmm1: base as double |
- // eax: exponent as untagged integer |
- case DOUBLE: |
- // xmm1: base as double |
- // xmm2: exponent as double |
- // Check base in xmm1 for NaN or +/-Infinity |
- const int kExponentShift = kBitsPerByte * |
- (HeapNumber::kExponentOffset - HeapNumber::kMantissaOffset); |
- __ movsd(xmm4, xmm1); |
- __ psrlq(xmm4, kExponentShift); |
- __ movd(ecx, xmm4); |
- __ and_(ecx, HeapNumber::kExponentMask); |
- __ cmp(ecx, Immediate(HeapNumber::kExponentMask)); |
- __ j(equal, &generic_runtime); |
- break; |
+ if (exponent_type_ == ON_STACK) { |
+ // The exponent (and base) are supplied as arguments on the stack. |
+ // This can only happen if the stub is called from non-optimized code. |
+ // Load input parameters from stack |
+ __ mov(edx, Operand(esp, 2 * kPointerSize)); |
+ __ mov(eax, Operand(esp, 1 * kPointerSize)); |
+ // edx: base (smi or heap number) |
+ // eax: exponent (smi or heap number) |
+ __ JumpIfSmi(edx, &base_is_smi, Label::kNear); |
+ __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
+ factory->heap_number_map()); |
+ __ j(not_equal, &generic_runtime); |
+ |
+ __ movdbl(xmm1, FieldOperand(edx, HeapNumber::kValueOffset)); |
+ __ jmp(&unpack_exponent, Label::kNear); |
+ |
+ __ bind(&base_is_smi); |
+ __ SmiUntag(edx); |
+ __ cvtsi2sd(xmm1, edx); |
+ __ bind(&unpack_exponent); |
+ |
+ __ JumpIfNotSmi(eax, &exponent_not_smi, Label::kNear); |
+ __ SmiUntag(eax); |
+ __ jmp(&int_exponent); |
+ |
+ __ bind(&exponent_not_smi); |
+ __ cmp(FieldOperand(eax, HeapObject::kMapOffset), |
+ factory->heap_number_map()); |
+ __ j(not_equal, &generic_runtime); |
+ __ movdbl(xmm2, FieldOperand(eax, HeapNumber::kValueOffset)); |
+ } else if (exponent_type_ == TAGGED) { |
+ // xmm1: base as double |
+ // eax: exponent (smi or heap number) |
+ __ JumpIfNotSmi(eax, &exponent_not_smi, Label::kNear); |
+ __ SmiUntag(eax); |
+ __ jmp(&int_exponent); |
+ |
+ __ bind(&exponent_not_smi); |
+ __ movdbl(xmm2, FieldOperand(eax, HeapNumber::kValueOffset)); |
} |
if (exponent_type_ != INTEGER) { |
- Label not_minus_half, fast_power; |
+ Label fast_power; |
// xmm1: base as double that is not +/- Infinity or NaN |
// xmm2: exponent as double |
// Detect integer exponents stored as double. |
@@ -3029,37 +3004,67 @@ void MathPowStub::Generate(MacroAssembler* masm) { |
// Detect square root case. Crankshaft detects constant +/-0.5 at |
// compile time and uses DoMathPowHalf instead. We then skip this check |
// for non-constant cases of +/-0.5 as these hardly occur. |
- |
- // Test for -0.5. |
- // Load xmm4 with -0.5. |
- __ mov(ecx, Immediate(0xBF000000u)); |
+ Label continue_sqrt, continue_rsqrt, not_plus_half; |
+ // Test for 0.5. |
+ // Load xmm4 with 0.5. |
+ __ mov(ecx, Immediate(0x3F000000u)); |
__ movd(xmm4, ecx); |
__ cvtss2sd(xmm4, xmm4); |
- // xmm3 now has -0.5. |
+ // xmm3 now has 0.5. |
__ ucomisd(xmm4, xmm2); |
- __ j(not_equal, ¬_minus_half, Label::kNear); |
+ __ j(not_equal, ¬_plus_half, Label::kNear); |
- // Calculates reciprocal of square root.eax |
+ // Calculates square root. Check for the special case of |
+ // Math.pow(-Infinity, 0.5) == Infinity (ECMA spec, 15.8.2.13). |
+ // According to IEEE-754, single-precision -Infinity has the highest |
+ // 9 bits set and the lowest 23 bits cleared. |
+ __ mov(ecx, 0xFF800000u); |
+ __ movd(xmm4, ecx); |
+ __ cvtss2sd(xmm4, xmm4); |
+ __ ucomisd(xmm1, xmm4); |
+ __ j(not_equal, &continue_sqrt, Label::kNear); |
+ |
+ // Set result to Infinity in the special case. |
+ __ xorps(xmm3, xmm3); |
+ __ subsd(xmm3, xmm4); |
+ __ jmp(&done); |
+ |
+ __ bind(&continue_sqrt); |
// sqrtsd returns -0 when input is -0. ECMA spec requires +0. |
- __ xorps(xmm2, xmm2); |
- __ addsd(xmm2, xmm1); |
- __ sqrtsd(xmm2, xmm2); |
- __ divsd(xmm3, xmm2); |
+ __ xorps(xmm4, xmm4); |
+ __ addsd(xmm4, xmm1); // Convert -0 to +0. |
+ __ sqrtsd(xmm3, xmm4); |
__ jmp(&done); |
- // Test for 0.5. |
- __ bind(¬_minus_half); |
- // Load xmm2 with 0.5. |
- // Since xmm3 is 1 and xmm4 is -0.5 this is simply xmm4 + xmm3. |
- __ addsd(xmm4, xmm3); |
- // xmm2 now has 0.5. |
+ // Test for -0.5. |
+ __ bind(¬_plus_half); |
+ // Load xmm2 with -0.5. |
+ // Since xmm3 is 1 and xmm4 is 0.5 this is simply xmm4 - xmm3. |
+ __ subsd(xmm4, xmm3); |
+ // xmm2 now has -0.5. |
__ ucomisd(xmm4, xmm2); |
__ j(not_equal, &fast_power, Label::kNear); |
- // Calculates square root. |
+ |
+ // Calculates reciprocal of square root. Check for the special case of |
+ // Math.pow(-Infinity, -0.5) == 0 (ECMA spec, 15.8.2.13). |
+ // According to IEEE-754, single-precision -Infinity has the highest |
+ // 9 bits set and the lowest 23 bits cleared. |
+ __ mov(ecx, 0xFF800000u); |
+ __ movd(xmm4, ecx); |
+ __ cvtss2sd(xmm4, xmm4); |
+ __ ucomisd(xmm1, xmm4); |
+ __ j(not_equal, &continue_rsqrt, Label::kNear); |
+ |
+ // Set result to 0 in the special case. |
+ __ xorps(xmm3, xmm3); |
+ __ jmp(&done); |
+ |
+ __ bind(&continue_rsqrt); |
// sqrtsd returns -0 when input is -0. ECMA spec requires +0. |
- __ xorps(xmm4, xmm4); |
- __ addsd(xmm4, xmm1); |
- __ sqrtsd(xmm3, xmm4); |
+ __ xorps(xmm2, xmm2); |
+ __ addsd(xmm2, xmm1); // Convert -0 to +0. |
+ __ sqrtsd(xmm2, xmm2); |
+ __ divsd(xmm3, xmm2); |
__ jmp(&done); |
} |