| OLD | NEW | 
|---|
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 3574 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 3585   } | 3585   } | 
| 3586 } | 3586 } | 
| 3587 | 3587 | 
| 3588 | 3588 | 
| 3589 void StackCheckStub::Generate(MacroAssembler* masm) { | 3589 void StackCheckStub::Generate(MacroAssembler* masm) { | 
| 3590   __ TailCallRuntime(Runtime::kStackGuard, 0, 1); | 3590   __ TailCallRuntime(Runtime::kStackGuard, 0, 1); | 
| 3591 } | 3591 } | 
| 3592 | 3592 | 
| 3593 | 3593 | 
| 3594 void MathPowStub::Generate(MacroAssembler* masm) { | 3594 void MathPowStub::Generate(MacroAssembler* masm) { | 
| 3595   Label call_runtime; | 3595   CpuFeatures::Scope fpu_scope(FPU); | 
| 3596 | 3596   const Register base = a1; | 
| 3597   if (CpuFeatures::IsSupported(FPU)) { | 3597   const Register exponent = a2; | 
| 3598     CpuFeatures::Scope scope(FPU); | 3598   const Register heapnumbermap = t1; | 
| 3599 | 3599   const Register heapnumber = v0; | 
| 3600     Label base_not_smi; | 3600   const DoubleRegister double_base = f2; | 
| 3601     Label exponent_not_smi; | 3601   const DoubleRegister double_exponent = f4; | 
| 3602     Label convert_exponent; | 3602   const DoubleRegister double_result = f0; | 
| 3603 | 3603   const DoubleRegister double_scratch = f6; | 
| 3604     const Register base = a0; | 3604   const FPURegister single_scratch = f8; | 
| 3605     const Register exponent = a2; | 3605   const Register scratch = t5; | 
| 3606     const Register heapnumbermap = t1; | 3606   const Register scratch2 = t3; | 
| 3607     const Register heapnumber = s0;  // Callee-saved register. | 3607 | 
| 3608     const Register scratch = t2; | 3608   Label call_runtime, done, exponent_not_smi, int_exponent; | 
| 3609     const Register scratch2 = t3; | 3609   if (exponent_type_ == ON_STACK) { | 
| 3610 | 3610     Label base_is_smi, unpack_exponent; | 
| 3611     // Alocate FP values in the ABI-parameter-passing regs. | 3611     // The exponent and base are supplied as arguments on the stack. | 
| 3612     const DoubleRegister double_base = f12; | 3612     // This can only happen if the stub is called from non-optimized code. | 
| 3613     const DoubleRegister double_exponent = f14; | 3613     // Load input parameters from stack to double registers. | 
| 3614     const DoubleRegister double_result = f0; |  | 
| 3615     const DoubleRegister double_scratch = f2; |  | 
| 3616 |  | 
| 3617     __ LoadRoot(heapnumbermap, Heap::kHeapNumberMapRootIndex); |  | 
| 3618     __ lw(base, MemOperand(sp, 1 * kPointerSize)); | 3614     __ lw(base, MemOperand(sp, 1 * kPointerSize)); | 
| 3619     __ lw(exponent, MemOperand(sp, 0 * kPointerSize)); | 3615     __ lw(exponent, MemOperand(sp, 0 * kPointerSize)); | 
| 3620 | 3616 | 
| 3621     // Convert base to double value and store it in f0. | 3617     __ LoadRoot(heapnumbermap, Heap::kHeapNumberMapRootIndex); | 
| 3622     __ JumpIfNotSmi(base, &base_not_smi); | 3618 | 
| 3623     // Base is a Smi. Untag and convert it. | 3619     __ JumpIfSmi(base, &base_is_smi); | 
| 3624     __ SmiUntag(base); |  | 
| 3625     __ mtc1(base, double_scratch); |  | 
| 3626     __ cvt_d_w(double_base, double_scratch); |  | 
| 3627     __ Branch(&convert_exponent); |  | 
| 3628 |  | 
| 3629     __ bind(&base_not_smi); |  | 
| 3630     __ lw(scratch, FieldMemOperand(base, JSObject::kMapOffset)); | 3620     __ lw(scratch, FieldMemOperand(base, JSObject::kMapOffset)); | 
| 3631     __ Branch(&call_runtime, ne, scratch, Operand(heapnumbermap)); | 3621     __ Branch(&call_runtime, ne, scratch, Operand(heapnumbermap)); | 
| 3632     // Base is a heapnumber. Load it into double register. | 3622 | 
| 3633     __ ldc1(double_base, FieldMemOperand(base, HeapNumber::kValueOffset)); | 3623     __ ldc1(double_base, FieldMemOperand(base, HeapNumber::kValueOffset)); | 
| 3634 | 3624     __ jmp(&unpack_exponent); | 
| 3635     __ bind(&convert_exponent); | 3625 | 
|  | 3626     __ bind(&base_is_smi); | 
|  | 3627     __ SmiUntag(base); | 
|  | 3628     __ mtc1(base, single_scratch); | 
|  | 3629     __ cvt_d_w(double_base, single_scratch); | 
|  | 3630     __ bind(&unpack_exponent); | 
|  | 3631 | 
| 3636     __ JumpIfNotSmi(exponent, &exponent_not_smi); | 3632     __ JumpIfNotSmi(exponent, &exponent_not_smi); | 
| 3637     __ SmiUntag(exponent); | 3633     __ SmiUntag(exponent); | 
| 3638 | 3634     __ jmp(&int_exponent); | 
| 3639     // The base is in a double register and the exponent is |  | 
| 3640     // an untagged smi. Allocate a heap number and call a |  | 
| 3641     // C function for integer exponents. The register containing |  | 
| 3642     // the heap number is callee-saved. |  | 
| 3643     __ AllocateHeapNumber(heapnumber, |  | 
| 3644                           scratch, |  | 
| 3645                           scratch2, |  | 
| 3646                           heapnumbermap, |  | 
| 3647                           &call_runtime); |  | 
| 3648     __ push(ra); |  | 
| 3649     __ PrepareCallCFunction(1, 1, scratch); |  | 
| 3650     __ SetCallCDoubleArguments(double_base, exponent); |  | 
| 3651     { |  | 
| 3652       AllowExternalCallThatCantCauseGC scope(masm); |  | 
| 3653       __ CallCFunction( |  | 
| 3654           ExternalReference::power_double_int_function(masm->isolate()), 1, 1); |  | 
| 3655       __ pop(ra); |  | 
| 3656       __ GetCFunctionDoubleResult(double_result); |  | 
| 3657     } |  | 
| 3658     __ sdc1(double_result, |  | 
| 3659             FieldMemOperand(heapnumber, HeapNumber::kValueOffset)); |  | 
| 3660     __ mov(v0, heapnumber); |  | 
| 3661     __ DropAndRet(2 * kPointerSize); |  | 
| 3662 | 3635 | 
| 3663     __ bind(&exponent_not_smi); | 3636     __ bind(&exponent_not_smi); | 
| 3664     __ lw(scratch, FieldMemOperand(exponent, JSObject::kMapOffset)); | 3637     __ lw(scratch, FieldMemOperand(exponent, JSObject::kMapOffset)); | 
| 3665     __ Branch(&call_runtime, ne, scratch, Operand(heapnumbermap)); | 3638     __ Branch(&call_runtime, ne, scratch, Operand(heapnumbermap)); | 
| 3666     // Exponent is a heapnumber. Load it into double register. |  | 
| 3667     __ ldc1(double_exponent, | 3639     __ ldc1(double_exponent, | 
| 3668             FieldMemOperand(exponent, HeapNumber::kValueOffset)); | 3640             FieldMemOperand(exponent, HeapNumber::kValueOffset)); | 
| 3669 | 3641   } else if (exponent_type_ == TAGGED) { | 
| 3670     // The base and the exponent are in double registers. | 3642     // Base is already in double_base. | 
| 3671     // Allocate a heap number and call a C function for | 3643     __ JumpIfNotSmi(exponent, &exponent_not_smi); | 
| 3672     // double exponents. The register containing | 3644     __ SmiUntag(exponent); | 
| 3673     // the heap number is callee-saved. | 3645     __ jmp(&int_exponent); | 
| 3674     __ AllocateHeapNumber(heapnumber, | 3646 | 
| 3675                           scratch, | 3647     __ bind(&exponent_not_smi); | 
| 3676                           scratch2, | 3648     __ ldc1(double_exponent, | 
| 3677                           heapnumbermap, | 3649             FieldMemOperand(exponent, HeapNumber::kValueOffset)); | 
| 3678                           &call_runtime); | 3650   } | 
|  | 3651 | 
|  | 3652   if (exponent_type_ != INTEGER) { | 
|  | 3653     Label int_exponent_convert; | 
|  | 3654     // Detect integer exponents stored as double. | 
|  | 3655     __ EmitFPUTruncate(kRoundToMinusInf, | 
|  | 3656                        single_scratch, | 
|  | 3657                        double_exponent, | 
|  | 3658                        scratch, | 
|  | 3659                        scratch2, | 
|  | 3660                        kCheckForInexactConversion); | 
|  | 3661     // scratch2 == 0 means there was no conversion error. | 
|  | 3662     __ Branch(&int_exponent_convert, eq, scratch2, Operand(zero_reg)); | 
|  | 3663 | 
|  | 3664     if (exponent_type_ == ON_STACK) { | 
|  | 3665       // Detect square root case.  Crankshaft detects constant +/-0.5 at | 
|  | 3666       // compile time and uses DoMathPowHalf instead.  We then skip this check | 
|  | 3667       // for non-constant cases of +/-0.5 as these hardly occur. | 
|  | 3668       Label not_plus_half; | 
|  | 3669 | 
|  | 3670       // Test for 0.5. | 
|  | 3671       __ Move(double_scratch, 0.5); | 
|  | 3672       __ BranchF(USE_DELAY_SLOT, | 
|  | 3673                  ¬_plus_half, | 
|  | 3674                  NULL, | 
|  | 3675                  ne, | 
|  | 3676                  double_exponent, | 
|  | 3677                  double_scratch); | 
|  | 3678 | 
|  | 3679       // Calculates square root of base.  Check for the special case of | 
|  | 3680       // Math.pow(-Infinity, 0.5) == Infinity (ECMA spec, 15.8.2.13). | 
|  | 3681       __ Move(double_scratch, -V8_INFINITY); | 
|  | 3682       __ BranchF(USE_DELAY_SLOT, &done, NULL, eq, double_base, double_scratch); | 
|  | 3683       __ neg_d(double_result, double_scratch); | 
|  | 3684 | 
|  | 3685       // Add +0 to convert -0 to +0. | 
|  | 3686       __ add_d(double_scratch, double_base, kDoubleRegZero); | 
|  | 3687       __ sqrt_d(double_result, double_scratch); | 
|  | 3688       __ jmp(&done); | 
|  | 3689 | 
|  | 3690       __ bind(¬_plus_half); | 
|  | 3691       __ Move(double_scratch, -0.5); | 
|  | 3692       __ BranchF(USE_DELAY_SLOT, | 
|  | 3693                  &call_runtime, | 
|  | 3694                  NULL, | 
|  | 3695                  ne, | 
|  | 3696                  double_exponent, | 
|  | 3697                  double_scratch); | 
|  | 3698 | 
|  | 3699       // Calculates square root of base.  Check for the special case of | 
|  | 3700       // Math.pow(-Infinity, -0.5) == 0 (ECMA spec, 15.8.2.13). | 
|  | 3701       __ Move(double_scratch, -V8_INFINITY); | 
|  | 3702       __ BranchF(USE_DELAY_SLOT, &done, NULL, eq, double_base, double_scratch); | 
|  | 3703       __ Move(double_result, kDoubleRegZero); | 
|  | 3704 | 
|  | 3705       // Add +0 to convert -0 to +0. | 
|  | 3706       __ add_d(double_scratch, double_base, kDoubleRegZero); | 
|  | 3707       __ Move(double_result, 1); | 
|  | 3708       __ sqrt_d(double_scratch, double_scratch); | 
|  | 3709       __ div_d(double_result, double_result, double_scratch); | 
|  | 3710       __ jmp(&done); | 
|  | 3711     } | 
|  | 3712 | 
| 3679     __ push(ra); | 3713     __ push(ra); | 
| 3680     __ PrepareCallCFunction(0, 2, scratch); |  | 
| 3681     // ABI (o32) for func(double a, double b): a in f12, b in f14. |  | 
| 3682     ASSERT(double_base.is(f12)); |  | 
| 3683     ASSERT(double_exponent.is(f14)); |  | 
| 3684     __ SetCallCDoubleArguments(double_base, double_exponent); |  | 
| 3685     { | 3714     { | 
| 3686       AllowExternalCallThatCantCauseGC scope(masm); | 3715       AllowExternalCallThatCantCauseGC scope(masm); | 
|  | 3716       __ PrepareCallCFunction(0, 2, scratch); | 
|  | 3717       __ SetCallCDoubleArguments(double_base, double_exponent); | 
| 3687       __ CallCFunction( | 3718       __ CallCFunction( | 
| 3688           ExternalReference::power_double_double_function(masm->isolate()), | 3719           ExternalReference::power_double_double_function(masm->isolate()), | 
| 3689           0, | 3720           0, 2); | 
| 3690           2); |  | 
| 3691       __ pop(ra); |  | 
| 3692       __ GetCFunctionDoubleResult(double_result); |  | 
| 3693     } | 3721     } | 
|  | 3722     __ pop(ra); | 
|  | 3723     __ GetCFunctionDoubleResult(double_result); | 
|  | 3724     __ jmp(&done); | 
|  | 3725 | 
|  | 3726     __ bind(&int_exponent_convert); | 
|  | 3727     __ mfc1(exponent, single_scratch); | 
|  | 3728   } | 
|  | 3729 | 
|  | 3730   // Calculate power with integer exponent. | 
|  | 3731   __ bind(&int_exponent); | 
|  | 3732 | 
|  | 3733   __ mov(scratch, exponent);  // Back up exponent. | 
|  | 3734   __ mov_d(double_scratch, double_base);  // Back up base. | 
|  | 3735   __ Move(double_result, 1.0); | 
|  | 3736 | 
|  | 3737   // Get absolute value of exponent. | 
|  | 3738   Label positive_exponent; | 
|  | 3739   __ Branch(&positive_exponent, ge, scratch, Operand(zero_reg)); | 
|  | 3740   __ Subu(scratch, zero_reg, scratch); | 
|  | 3741   __ bind(&positive_exponent); | 
|  | 3742 | 
|  | 3743   Label while_true, no_carry, loop_end; | 
|  | 3744   __ bind(&while_true); | 
|  | 3745 | 
|  | 3746   __ And(scratch2, scratch, 1); | 
|  | 3747 | 
|  | 3748   __ Branch(&no_carry, eq, scratch2, Operand(zero_reg)); | 
|  | 3749   __ mul_d(double_result, double_result, double_scratch); | 
|  | 3750   __ bind(&no_carry); | 
|  | 3751 | 
|  | 3752   __ sra(scratch, scratch, 1); | 
|  | 3753 | 
|  | 3754   __ Branch(&loop_end, eq, scratch, Operand(zero_reg)); | 
|  | 3755   __ mul_d(double_scratch, double_scratch, double_scratch); | 
|  | 3756 | 
|  | 3757   __ Branch(&while_true); | 
|  | 3758 | 
|  | 3759   __ bind(&loop_end); | 
|  | 3760 | 
|  | 3761   __ Branch(&done, ge, exponent, Operand(zero_reg)); | 
|  | 3762   __ Move(double_scratch, 1.0); | 
|  | 3763   __ div_d(double_result, double_scratch, double_result); | 
|  | 3764   // Test whether result is zero.  Bail out to check for subnormal result. | 
|  | 3765   // Due to subnormals, x^-y == (1/x)^y does not hold in all cases. | 
|  | 3766   __ BranchF(&done, NULL, ne, double_result, kDoubleRegZero); | 
|  | 3767 | 
|  | 3768   // double_exponent may not contain the exponent value if the input was a | 
|  | 3769   // smi.  We set it with exponent value before bailing out. | 
|  | 3770   __ mtc1(exponent, single_scratch); | 
|  | 3771   __ cvt_d_w(double_exponent, single_scratch); | 
|  | 3772 | 
|  | 3773   // Returning or bailing out. | 
|  | 3774   Counters* counters = masm->isolate()->counters(); | 
|  | 3775   if (exponent_type_ == ON_STACK) { | 
|  | 3776     // The arguments are still on the stack. | 
|  | 3777     __ bind(&call_runtime); | 
|  | 3778     __ TailCallRuntime(Runtime::kMath_pow_cfunction, 2, 1); | 
|  | 3779 | 
|  | 3780     // The stub is called from non-optimized code, which expects the result | 
|  | 3781     // as heap number in exponent. | 
|  | 3782     __ bind(&done); | 
|  | 3783     __ AllocateHeapNumber( | 
|  | 3784         heapnumber, scratch, scratch2, heapnumbermap, &call_runtime); | 
| 3694     __ sdc1(double_result, | 3785     __ sdc1(double_result, | 
| 3695             FieldMemOperand(heapnumber, HeapNumber::kValueOffset)); | 3786             FieldMemOperand(heapnumber, HeapNumber::kValueOffset)); | 
| 3696     __ mov(v0, heapnumber); | 3787     ASSERT(heapnumber.is(v0)); | 
| 3697     __ DropAndRet(2 * kPointerSize); | 3788     __ IncrementCounter(counters->math_pow(), 1, scratch, scratch2); | 
|  | 3789     __ DropAndRet(2); | 
|  | 3790   } else { | 
|  | 3791     __ push(ra); | 
|  | 3792     { | 
|  | 3793       AllowExternalCallThatCantCauseGC scope(masm); | 
|  | 3794       __ PrepareCallCFunction(0, 2, scratch); | 
|  | 3795       __ SetCallCDoubleArguments(double_base, double_exponent); | 
|  | 3796       __ CallCFunction( | 
|  | 3797           ExternalReference::power_double_double_function(masm->isolate()), | 
|  | 3798           0, 2); | 
|  | 3799     } | 
|  | 3800     __ pop(ra); | 
|  | 3801     __ GetCFunctionDoubleResult(double_result); | 
|  | 3802 | 
|  | 3803     __ bind(&done); | 
|  | 3804     __ IncrementCounter(counters->math_pow(), 1, scratch, scratch2); | 
|  | 3805     __ Ret(); | 
| 3698   } | 3806   } | 
| 3699 |  | 
| 3700   __ bind(&call_runtime); |  | 
| 3701   __ TailCallRuntime(Runtime::kMath_pow_cfunction, 2, 1); |  | 
| 3702 } | 3807 } | 
| 3703 | 3808 | 
| 3704 | 3809 | 
| 3705 bool CEntryStub::NeedsImmovableCode() { | 3810 bool CEntryStub::NeedsImmovableCode() { | 
| 3706   return true; | 3811   return true; | 
| 3707 } | 3812 } | 
| 3708 | 3813 | 
| 3709 | 3814 | 
| 3710 bool CEntryStub::IsPregenerated() { | 3815 bool CEntryStub::IsPregenerated() { | 
| 3711   return (!save_doubles_ || ISOLATE->fp_stubs_generated()) && | 3816   return (!save_doubles_ || ISOLATE->fp_stubs_generated()) && | 
| (...skipping 3820 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 7532   __ Ret(USE_DELAY_SLOT); | 7637   __ Ret(USE_DELAY_SLOT); | 
| 7533   __ mov(v0, a0); | 7638   __ mov(v0, a0); | 
| 7534 } | 7639 } | 
| 7535 | 7640 | 
| 7536 | 7641 | 
| 7537 #undef __ | 7642 #undef __ | 
| 7538 | 7643 | 
| 7539 } }  // namespace v8::internal | 7644 } }  // namespace v8::internal | 
| 7540 | 7645 | 
| 7541 #endif  // V8_TARGET_ARCH_MIPS | 7646 #endif  // V8_TARGET_ARCH_MIPS | 
| OLD | NEW | 
|---|