Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(127)

Side by Side Diff: src/mips/code-stubs-mips.cc

Issue 8896021: MIPS: Port Math.pow inlining to ARM. (Closed)
Patch Set: Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/mips/full-codegen-mips.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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 &not_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(&not_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
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
OLDNEW
« no previous file with comments | « no previous file | src/mips/full-codegen-mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698