| Index: src/x64/code-stubs-x64.cc
|
| ===================================================================
|
| --- src/x64/code-stubs-x64.cc (revision 6962)
|
| +++ src/x64/code-stubs-x64.cc (working copy)
|
| @@ -2017,8 +2017,8 @@
|
| __ AbortIfSmi(rax);
|
| }
|
|
|
| - __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset));
|
| - __ CompareRoot(rdx, Heap::kHeapNumberMapRootIndex);
|
| + __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
|
| + Heap::kHeapNumberMapRootIndex);
|
| __ j(not_equal, &slow);
|
| // Operand is a float, negate its value by flipping sign bit.
|
| __ movq(rdx, FieldOperand(rax, HeapNumber::kValueOffset));
|
| @@ -2047,8 +2047,8 @@
|
| }
|
|
|
| // Check if the operand is a heap number.
|
| - __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset));
|
| - __ CompareRoot(rdx, Heap::kHeapNumberMapRootIndex);
|
| + __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
|
| + Heap::kHeapNumberMapRootIndex);
|
| __ j(not_equal, &slow);
|
|
|
| // Convert the heap number in rax to an untagged integer in rcx.
|
| @@ -2081,6 +2081,157 @@
|
| }
|
|
|
|
|
| +void MathPowStub::Generate(MacroAssembler* masm) {
|
| + // Registers are used as follows:
|
| + // rdx = base
|
| + // rax = exponent
|
| + // rcx = temporary, result
|
| +
|
| + Label allocate_return, call_runtime;
|
| +
|
| + // Load input parameters.
|
| + __ movq(rdx, Operand(rsp, 2 * kPointerSize));
|
| + __ movq(rax, Operand(rsp, 1 * kPointerSize));
|
| +
|
| + // Save 1 in xmm3 - we need this several times later on.
|
| + __ movl(rcx, Immediate(1));
|
| + __ cvtlsi2sd(xmm3, rcx);
|
| +
|
| + Label exponent_nonsmi;
|
| + Label base_nonsmi;
|
| + // If the exponent is a heap number go to that specific case.
|
| + __ JumpIfNotSmi(rax, &exponent_nonsmi);
|
| + __ JumpIfNotSmi(rdx, &base_nonsmi);
|
| +
|
| + // Optimized version when both exponent and base are smis.
|
| + Label powi;
|
| + __ SmiToInteger32(rdx, rdx);
|
| + __ cvtlsi2sd(xmm0, rdx);
|
| + __ jmp(&powi);
|
| + // Exponent is a smi and base is a heapnumber.
|
| + __ bind(&base_nonsmi);
|
| + __ CompareRoot(FieldOperand(rdx, HeapObject::kMapOffset),
|
| + Heap::kHeapNumberMapRootIndex);
|
| + __ j(not_equal, &call_runtime);
|
| +
|
| + __ movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset));
|
| +
|
| + // Optimized version of pow if exponent is a smi.
|
| + // xmm0 contains the base.
|
| + __ bind(&powi);
|
| + __ SmiToInteger32(rax, rax);
|
| +
|
| + // Save exponent in base as we need to check if exponent is negative later.
|
| + // We know that base and exponent are in different registers.
|
| + __ movq(rdx, rax);
|
| +
|
| + // Get absolute value of exponent.
|
| + NearLabel no_neg;
|
| + __ cmpl(rax, Immediate(0));
|
| + __ j(greater_equal, &no_neg);
|
| + __ negl(rax);
|
| + __ bind(&no_neg);
|
| +
|
| + // Load xmm1 with 1.
|
| + __ movsd(xmm1, xmm3);
|
| + NearLabel while_true;
|
| + NearLabel no_multiply;
|
| +
|
| + __ bind(&while_true);
|
| + __ shrl(rax, Immediate(1));
|
| + __ j(not_carry, &no_multiply);
|
| + __ mulsd(xmm1, xmm0);
|
| + __ bind(&no_multiply);
|
| + __ mulsd(xmm0, xmm0);
|
| + __ j(not_zero, &while_true);
|
| +
|
| + // Base has the original value of the exponent - if the exponent is
|
| + // negative return 1/result.
|
| + __ testl(rdx, rdx);
|
| + __ j(positive, &allocate_return);
|
| + // Special case if xmm1 has reached infinity.
|
| + __ divsd(xmm3, xmm1);
|
| + __ movsd(xmm1, xmm3);
|
| + __ xorpd(xmm0, xmm0);
|
| + __ ucomisd(xmm0, xmm1);
|
| + __ j(equal, &call_runtime);
|
| +
|
| + __ jmp(&allocate_return);
|
| +
|
| + // Exponent (or both) is a heapnumber - no matter what we should now work
|
| + // on doubles.
|
| + __ bind(&exponent_nonsmi);
|
| + __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
|
| + Heap::kHeapNumberMapRootIndex);
|
| + __ j(not_equal, &call_runtime);
|
| + __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset));
|
| + // Test if exponent is nan.
|
| + __ ucomisd(xmm1, xmm1);
|
| + __ j(parity_even, &call_runtime);
|
| +
|
| + NearLabel base_not_smi;
|
| + NearLabel handle_special_cases;
|
| + __ JumpIfNotSmi(rdx, &base_not_smi);
|
| + __ SmiToInteger32(rdx, rdx);
|
| + __ cvtlsi2sd(xmm0, rdx);
|
| + __ jmp(&handle_special_cases);
|
| +
|
| + __ bind(&base_not_smi);
|
| + __ CompareRoot(FieldOperand(rdx, HeapObject::kMapOffset),
|
| + Heap::kHeapNumberMapRootIndex);
|
| + __ j(not_equal, &call_runtime);
|
| + __ movl(rcx, FieldOperand(rdx, HeapNumber::kExponentOffset));
|
| + __ andl(rcx, Immediate(HeapNumber::kExponentMask));
|
| + __ cmpl(rcx, Immediate(HeapNumber::kExponentMask));
|
| + // base is NaN or +/-Infinity
|
| + __ j(greater_equal, &call_runtime);
|
| + __ movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset));
|
| +
|
| + // base is in xmm0 and exponent is in xmm1.
|
| + __ bind(&handle_special_cases);
|
| + NearLabel not_minus_half;
|
| + // Test for -0.5.
|
| + // Load xmm2 with -0.5.
|
| + __ movq(rcx, V8_UINT64_C(0xBFE0000000000000), RelocInfo::NONE);
|
| + __ movq(xmm2, rcx);
|
| + // xmm2 now has -0.5.
|
| + __ ucomisd(xmm2, xmm1);
|
| + __ j(not_equal, ¬_minus_half);
|
| +
|
| + // Calculates reciprocal of square root.
|
| + // sqrtsd returns -0 when input is -0. ECMA spec requires +0.
|
| + __ xorpd(xmm1, xmm1);
|
| + __ addsd(xmm1, xmm0);
|
| + __ sqrtsd(xmm1, xmm1);
|
| + __ divsd(xmm3, xmm1);
|
| + __ movsd(xmm1, xmm3);
|
| + __ jmp(&allocate_return);
|
| +
|
| + // Test for 0.5.
|
| + __ bind(¬_minus_half);
|
| + // Load xmm2 with 0.5.
|
| + // Since xmm3 is 1 and xmm2 is -0.5 this is simply xmm2 + xmm3.
|
| + __ addsd(xmm2, xmm3);
|
| + // xmm2 now has 0.5.
|
| + __ ucomisd(xmm2, xmm1);
|
| + __ j(not_equal, &call_runtime);
|
| + // Calculates square root.
|
| + // sqrtsd returns -0 when input is -0. ECMA spec requires +0.
|
| + __ xorpd(xmm1, xmm1);
|
| + __ addsd(xmm1, xmm0);
|
| + __ sqrtsd(xmm1, xmm1);
|
| +
|
| + __ bind(&allocate_return);
|
| + __ AllocateHeapNumber(rcx, rax, &call_runtime);
|
| + __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm1);
|
| + __ movq(rax, rcx);
|
| + __ ret(2 * kPointerSize);
|
| +
|
| + __ bind(&call_runtime);
|
| + __ TailCallRuntime(Runtime::kMath_pow_cfunction, 2, 1);
|
| +}
|
| +
|
| +
|
| void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
|
| // The key is in rdx and the parameter count is in rax.
|
|
|
|
|