| Index: src/ia32/code-stubs-ia32.cc
|
| diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc
|
| index 6bea2dc685c8329dcb53eab5cd7cf3b0f7d6d859..35c24e2f8989e0868be09cdd872290e8b5eedb14 100644
|
| --- a/src/ia32/code-stubs-ia32.cc
|
| +++ b/src/ia32/code-stubs-ia32.cc
|
| @@ -2940,64 +2940,72 @@ void FloatingPointHelper::CheckFloatOperandsAreInt32(MacroAssembler* masm,
|
| void MathPowStub::Generate(MacroAssembler* masm) {
|
| CpuFeatures::Scope use_sse2(SSE2);
|
| Factory* factory = masm->isolate()->factory();
|
| + const Register exponent = eax;
|
| + const Register base = edx;
|
| + const Register scratch = ecx;
|
| + const XMMRegister double_result = xmm3;
|
| + const XMMRegister double_base = xmm2;
|
| + const XMMRegister double_exponent = xmm1;
|
| + const XMMRegister double_scratch = xmm4;
|
| +
|
| Label double_int_runtime, generic_runtime, done;
|
| - Label base_is_smi, unpack_exponent, exponent_not_smi, int_exponent;
|
| - // Save 1 in xmm3 - we need this several times later on.
|
| - __ mov(ecx, Immediate(1));
|
| - __ cvtsi2sd(xmm3, ecx);
|
| + Label exponent_not_smi, int_exponent;
|
| +
|
| + // Save 1 in double_result - we need this several times later on.
|
| + __ mov(scratch, Immediate(1));
|
| + __ cvtsi2sd(double_result, scratch);
|
|
|
| if (exponent_type_ == ON_STACK) {
|
| - // The exponent (and base) are supplied as arguments on the stack.
|
| + Label base_is_smi, unpack_exponent;
|
| + // 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),
|
| + // Load input parameters from stack.
|
| + __ mov(base, Operand(esp, 2 * kPointerSize));
|
| + __ mov(exponent, Operand(esp, 1 * kPointerSize));
|
| +
|
| + __ JumpIfSmi(base, &base_is_smi, Label::kNear);
|
| + __ cmp(FieldOperand(base, HeapObject::kMapOffset),
|
| factory->heap_number_map());
|
| __ j(not_equal, &generic_runtime);
|
|
|
| - __ movdbl(xmm1, FieldOperand(edx, HeapNumber::kValueOffset));
|
| + __ movdbl(double_base, FieldOperand(base, HeapNumber::kValueOffset));
|
| __ jmp(&unpack_exponent, Label::kNear);
|
|
|
| __ bind(&base_is_smi);
|
| - __ SmiUntag(edx);
|
| - __ cvtsi2sd(xmm1, edx);
|
| + __ SmiUntag(base);
|
| + __ cvtsi2sd(double_base, base);
|
| __ bind(&unpack_exponent);
|
|
|
| - __ JumpIfNotSmi(eax, &exponent_not_smi, Label::kNear);
|
| - __ SmiUntag(eax);
|
| + __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear);
|
| + __ SmiUntag(exponent);
|
| __ jmp(&int_exponent);
|
|
|
| __ bind(&exponent_not_smi);
|
| - __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
|
| + __ cmp(FieldOperand(exponent, HeapObject::kMapOffset),
|
| factory->heap_number_map());
|
| __ j(not_equal, &generic_runtime);
|
| - __ movdbl(xmm2, FieldOperand(eax, HeapNumber::kValueOffset));
|
| + __ movdbl(double_exponent,
|
| + FieldOperand(exponent, 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);
|
| + __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear);
|
| + __ SmiUntag(exponent);
|
| __ jmp(&int_exponent);
|
|
|
| __ bind(&exponent_not_smi);
|
| - __ movdbl(xmm2, FieldOperand(eax, HeapNumber::kValueOffset));
|
| + __ movdbl(double_exponent,
|
| + FieldOperand(exponent, HeapNumber::kValueOffset));
|
| }
|
|
|
| if (exponent_type_ != INTEGER) {
|
| Label fast_power;
|
| - // xmm1: base as double that is not +/- Infinity or NaN
|
| - // xmm2: exponent as double
|
| // Detect integer exponents stored as double.
|
| - __ cvttsd2si(eax, Operand(xmm2));
|
| + __ cvttsd2si(exponent, Operand(double_exponent));
|
| // Skip to runtime if possibly NaN (indicated by the indefinite integer).
|
| - __ cmp(eax, Immediate(0x80000000u));
|
| + __ cmp(exponent, Immediate(0x80000000u));
|
| __ j(equal, &generic_runtime);
|
| - __ cvtsi2sd(xmm4, eax);
|
| - __ ucomisd(xmm2, xmm4); // Already ruled out NaNs for exponent.
|
| + __ cvtsi2sd(double_scratch, exponent);
|
| + // Already ruled out NaNs for exponent.
|
| + __ ucomisd(double_exponent, double_scratch);
|
| __ j(equal, &int_exponent);
|
|
|
| if (exponent_type_ == ON_STACK) {
|
| @@ -3006,71 +3014,70 @@ void MathPowStub::Generate(MacroAssembler* masm) {
|
| // for non-constant cases of +/-0.5 as these hardly occur.
|
| 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);
|
| - // xmm4 now has 0.5.
|
| - __ ucomisd(xmm4, xmm2); // Already ruled out NaNs for exponent.
|
| + // Load double_scratch with 0.5.
|
| + __ mov(scratch, Immediate(0x3F000000u));
|
| + __ movd(double_scratch, scratch);
|
| + __ cvtss2sd(double_scratch, double_scratch);
|
| + // Already ruled out NaNs for exponent.
|
| + __ ucomisd(double_scratch, double_exponent);
|
| __ j(not_equal, ¬_plus_half, Label::kNear);
|
|
|
| // Calculates square root of base. 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);
|
| + __ mov(scratch, 0xFF800000u);
|
| + __ movd(double_scratch, scratch);
|
| + __ cvtss2sd(double_scratch, double_scratch);
|
| + __ ucomisd(double_base, double_scratch);
|
| // Comparing -Infinity with NaN results in "unordered", which sets the
|
| // zero flag as if both were equal. However, it also sets the carry flag.
|
| __ j(not_equal, &continue_sqrt, Label::kNear);
|
| __ j(carry, &continue_sqrt, Label::kNear);
|
|
|
| // Set result to Infinity in the special case.
|
| - __ xorps(xmm3, xmm3);
|
| - __ subsd(xmm3, xmm4);
|
| + __ xorps(double_result, double_result);
|
| + __ subsd(double_result, double_scratch);
|
| __ jmp(&done);
|
|
|
| __ bind(&continue_sqrt);
|
| // sqrtsd returns -0 when input is -0. ECMA spec requires +0.
|
| - __ xorps(xmm4, xmm4);
|
| - __ addsd(xmm4, xmm1); // Convert -0 to +0.
|
| - __ sqrtsd(xmm3, xmm4);
|
| + __ xorps(double_scratch, double_scratch);
|
| + __ addsd(double_scratch, double_base); // Convert -0 to +0.
|
| + __ sqrtsd(double_result, double_scratch);
|
| __ jmp(&done);
|
|
|
| // 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);
|
| - // xmm4 now has -0.5.
|
| - __ ucomisd(xmm4, xmm2); // Already ruled out NaNs for exponent.
|
| + // Load double_exponent with -0.5 by substracting 1.
|
| + __ subsd(double_scratch, double_result);
|
| + // Already ruled out NaNs for exponent.
|
| + __ ucomisd(double_scratch, double_exponent);
|
| __ j(not_equal, &fast_power, Label::kNear);
|
|
|
| // Calculates reciprocal of square root of base. 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);
|
| + __ mov(scratch, 0xFF800000u);
|
| + __ movd(double_scratch, scratch);
|
| + __ cvtss2sd(double_scratch, double_scratch);
|
| + __ ucomisd(double_base, double_scratch);
|
| // Comparing -Infinity with NaN results in "unordered", which sets the
|
| // zero flag as if both were equal. However, it also sets the carry flag.
|
| __ j(not_equal, &continue_rsqrt, Label::kNear);
|
| __ j(carry, &continue_rsqrt, Label::kNear);
|
|
|
| // Set result to 0 in the special case.
|
| - __ xorps(xmm3, xmm3);
|
| + __ xorps(double_result, double_result);
|
| __ jmp(&done);
|
|
|
| __ bind(&continue_rsqrt);
|
| // sqrtsd returns -0 when input is -0. ECMA spec requires +0.
|
| - __ xorps(xmm2, xmm2);
|
| - __ addsd(xmm2, xmm1); // Convert -0 to +0.
|
| - __ sqrtsd(xmm2, xmm2);
|
| - __ divsd(xmm3, xmm2);
|
| + __ xorps(double_exponent, double_exponent);
|
| + __ addsd(double_exponent, double_base); // Convert -0 to +0.
|
| + __ sqrtsd(double_exponent, double_exponent);
|
| + __ divsd(double_result, double_exponent);
|
| __ jmp(&done);
|
| }
|
|
|
| @@ -3080,9 +3087,9 @@ void MathPowStub::Generate(MacroAssembler* masm) {
|
| __ fnclex(); // Clear flags to catch exceptions later.
|
| // Transfer (B)ase and (E)xponent onto the FPU register stack.
|
| __ sub(esp, Immediate(kDoubleSize));
|
| - __ movdbl(Operand(esp, 0), xmm2);
|
| + __ movdbl(Operand(esp, 0), double_exponent);
|
| __ fld_d(Operand(esp, 0)); // E
|
| - __ movdbl(Operand(esp, 0), xmm1);
|
| + __ movdbl(Operand(esp, 0), double_base);
|
| __ fld_d(Operand(esp, 0)); // B, E
|
|
|
| // Exponent is in st(1) and base is in st(0)
|
| @@ -3102,10 +3109,10 @@ void MathPowStub::Generate(MacroAssembler* masm) {
|
| __ fstp(1);
|
| // Bail out to runtime in case of exceptions in the status word.
|
| __ fnstsw_ax();
|
| - __ test_b(eax, 0x5F); // We check for all but precision exception.
|
| + __ test_b(exponent, 0x5F); // We check for all but precision exception.
|
| __ j(not_zero, &fast_power_failed, Label::kNear);
|
| __ fstp_d(Operand(esp, 0));
|
| - __ movdbl(xmm3, Operand(esp, 0));
|
| + __ movdbl(double_result, Operand(esp, 0));
|
| __ add(esp, Immediate(kDoubleSize));
|
| __ jmp(&done);
|
|
|
| @@ -3117,49 +3124,46 @@ void MathPowStub::Generate(MacroAssembler* masm) {
|
|
|
| // Calculate power with integer exponent.
|
| __ bind(&int_exponent);
|
| - // xmm1: base as double that is not +/- Infinity or NaN
|
| - // eax: exponent as untagged integer
|
| - __ mov(ecx, eax); // Back up exponent.
|
| - __ movsd(xmm4, xmm1); // Back up base.
|
| - __ movsd(xmm2, xmm3); // Load xmm2 with 1.
|
| -
|
| + const XMMRegister double_scratch2 = double_exponent;
|
| + __ mov(scratch, exponent); // Back up exponent.
|
| + __ movsd(double_scratch, double_base); // Back up base.
|
| + __ movsd(double_scratch2, double_result); // Load double_exponent with 1.
|
|
|
| // Get absolute value of exponent.
|
| Label no_neg, while_true, no_multiply;
|
| - __ cmp(eax, 0);
|
| + __ cmp(exponent, 0);
|
| __ j(greater_equal, &no_neg, Label::kNear);
|
| - __ neg(eax);
|
| + __ neg(exponent);
|
| __ bind(&no_neg);
|
|
|
| __ bind(&while_true);
|
| - __ shr(eax, 1);
|
| + __ shr(exponent, 1);
|
| __ j(not_carry, &no_multiply, Label::kNear);
|
| - __ mulsd(xmm3, xmm1);
|
| + __ mulsd(double_result, double_base);
|
| __ bind(&no_multiply);
|
|
|
| - __ mulsd(xmm1, xmm1);
|
| + __ mulsd(double_base, double_base);
|
| __ j(not_zero, &while_true);
|
|
|
| - // base has the original value of the exponent - if the exponent is
|
| - // negative return 1/result.
|
| - __ test(ecx, ecx);
|
| + // scratch has the original value of the exponent - if the exponent is
|
| + // negative, return 1/result.
|
| + __ test(scratch, scratch);
|
| __ j(positive, &done);
|
| - __ divsd(xmm2, xmm3);
|
| - __ movsd(xmm3, xmm2);
|
| + __ divsd(double_scratch2, double_result);
|
| + __ movsd(double_result, double_scratch2);
|
| // Test whether result is zero. Bail out to check for subnormal result.
|
| // Due to subnormals, x^-y == (1/x)^y does not hold in all cases.
|
| - __ xorps(xmm2, xmm2);
|
| - __ ucomisd(xmm2, xmm3); // Result cannot be NaN.
|
| + __ xorps(double_scratch2, double_scratch2);
|
| + __ ucomisd(double_scratch2, double_result); // Result cannot be NaN.
|
| __ j(equal, &double_int_runtime);
|
|
|
| // Returning or bailing out.
|
| if (exponent_type_ == ON_STACK) {
|
| // The stub is called from non-optimized code, which expects the result
|
| - // as heap number in eax.
|
| + // as heap number in exponent.
|
| __ bind(&done);
|
| - // xmm3: result
|
| - __ AllocateHeapNumber(eax, ecx, edx, &generic_runtime);
|
| - __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm3);
|
| + __ AllocateHeapNumber(exponent, scratch, base, &generic_runtime);
|
| + __ movdbl(FieldOperand(exponent, HeapNumber::kValueOffset), double_result);
|
| __ ret(2 * kPointerSize);
|
|
|
| // The arguments are still on the stack.
|
| @@ -3170,28 +3174,23 @@ void MathPowStub::Generate(MacroAssembler* masm) {
|
| __ jmp(&done);
|
|
|
| Label return_from_runtime;
|
| - StubRuntimeCallHelper callhelper;
|
| __ bind(&generic_runtime);
|
| - // xmm1: base
|
| - // xmm2: exponent
|
| {
|
| AllowExternalCallThatCantCauseGC scope(masm);
|
| - __ PrepareCallCFunction(4, eax);
|
| - __ movdbl(Operand(esp, 0 * kDoubleSize), xmm1);
|
| - __ movdbl(Operand(esp, 1 * kDoubleSize), xmm2);
|
| + __ PrepareCallCFunction(4, exponent);
|
| + __ movdbl(Operand(esp, 0 * kDoubleSize), double_base);
|
| + __ movdbl(Operand(esp, 1 * kDoubleSize), double_exponent);
|
| __ CallCFunction(
|
| ExternalReference::power_double_double_function(masm->isolate()), 4);
|
| }
|
| __ jmp(&return_from_runtime, Label::kNear);
|
|
|
| __ bind(&double_int_runtime);
|
| - // xmm4: base
|
| - // ecx: exponent
|
| {
|
| AllowExternalCallThatCantCauseGC scope(masm);
|
| - __ PrepareCallCFunction(4, eax);
|
| - __ movdbl(Operand(esp, 0 * kDoubleSize), xmm4);
|
| - __ mov(Operand(esp, 1 * kDoubleSize), ecx);
|
| + __ PrepareCallCFunction(4, exponent);
|
| + __ movdbl(Operand(esp, 0 * kDoubleSize), double_scratch);
|
| + __ mov(Operand(esp, 1 * kDoubleSize), scratch);
|
| __ CallCFunction(
|
| ExternalReference::power_double_int_function(masm->isolate()), 4);
|
| }
|
| @@ -3201,10 +3200,9 @@ void MathPowStub::Generate(MacroAssembler* masm) {
|
| // Store it into the (fixed) result register.
|
| __ sub(esp, Immediate(kDoubleSize));
|
| __ fstp_d(Operand(esp, 0));
|
| - __ movdbl(xmm3, Operand(esp, 0));
|
| + __ movdbl(double_result, Operand(esp, 0));
|
| __ add(esp, Immediate(kDoubleSize));
|
|
|
| - // xmm3: result
|
| __ bind(&done);
|
| __ ret(0);
|
| }
|
|
|