Chromium Code Reviews| 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..fd6383f38aae2fc886904c0f37546e1e4fce3cdf 100644 |
| --- a/src/ia32/code-stubs-ia32.cc |
| +++ b/src/ia32/code-stubs-ia32.cc |
| @@ -2946,70 +2946,45 @@ 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) { |
| @@ -3030,6 +3005,7 @@ void MathPowStub::Generate(MacroAssembler* masm) { |
| // compile time and uses DoMathPowHalf instead. We then skip this check |
| // for non-constant cases of +/-0.5 as these hardly occur. |
| + Label continue_sqrt, continue_rsqrt; |
| // Test for -0.5. |
| // Load xmm4 with -0.5. |
| __ mov(ecx, Immediate(0xBF000000u)); |
| @@ -3039,10 +3015,24 @@ void MathPowStub::Generate(MacroAssembler* masm) { |
| __ ucomisd(xmm4, xmm2); |
| __ j(not_equal, ¬_minus_half, Label::kNear); |
| - // Calculates reciprocal of square root.eax |
| + // 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(xmm2, xmm2); |
| - __ addsd(xmm2, xmm1); |
| + __ addsd(xmm2, xmm1); // Convert -0 to +0. |
| __ sqrtsd(xmm2, xmm2); |
| __ divsd(xmm3, xmm2); |
| __ jmp(&done); |
| @@ -3055,10 +3045,26 @@ void MathPowStub::Generate(MacroAssembler* masm) { |
| // xmm2 now has 0.5. |
|
ulan
2011/12/06 11:55:19
Typo in the comment xmm2 -> xmm4.
|
| __ ucomisd(xmm4, xmm2); |
| __ j(not_equal, &fast_power, Label::kNear); |
| - // Calculates square root. |
| + |
| + // 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(xmm4, xmm4); |
| - __ addsd(xmm4, xmm1); |
| + __ addsd(xmm4, xmm1); // Convert -0 to +0. |
| __ sqrtsd(xmm3, xmm4); |
| __ jmp(&done); |
| } |