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

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

Issue 2103733003: [turbofan] Introduce Float64Pow and NumberPow operators. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: REBASE on ARM64 bug fix. Created 4 years, 5 months 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 | « src/arm/code-stubs-arm.cc ('k') | src/assembler.h » ('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 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #if V8_TARGET_ARCH_ARM64 5 #if V8_TARGET_ARCH_ARM64
6 6
7 #include "src/code-stubs.h" 7 #include "src/code-stubs.h"
8 #include "src/api-arguments.h" 8 #include "src/api-arguments.h"
9 #include "src/bootstrapper.h" 9 #include "src/bootstrapper.h"
10 #include "src/codegen.h" 10 #include "src/codegen.h"
(...skipping 665 matching lines...) Expand 10 before | Expand all | Expand 10 after
676 void RestoreRegistersStateStub::Generate(MacroAssembler* masm) { 676 void RestoreRegistersStateStub::Generate(MacroAssembler* masm) {
677 MacroAssembler::NoUseRealAbortsScope no_use_real_aborts(masm); 677 MacroAssembler::NoUseRealAbortsScope no_use_real_aborts(masm);
678 UseScratchRegisterScope temps(masm); 678 UseScratchRegisterScope temps(masm);
679 Register return_address = temps.AcquireX(); 679 Register return_address = temps.AcquireX();
680 // Preserve the return address (lr will be clobbered by the pop). 680 // Preserve the return address (lr will be clobbered by the pop).
681 __ Mov(return_address, lr); 681 __ Mov(return_address, lr);
682 __ PopSafepointRegisters(); 682 __ PopSafepointRegisters();
683 __ Ret(return_address); 683 __ Ret(return_address);
684 } 684 }
685 685
686
687 void MathPowStub::Generate(MacroAssembler* masm) { 686 void MathPowStub::Generate(MacroAssembler* masm) {
688 // Stack on entry: 687 // Stack on entry:
689 // jssp[0]: Exponent (as a tagged value). 688 // jssp[0]: Exponent (as a tagged value).
690 // jssp[1]: Base (as a tagged value). 689 // jssp[1]: Base (as a tagged value).
691 // 690 //
692 // The (tagged) result will be returned in x0, as a heap number. 691 // The (tagged) result will be returned in x0, as a heap number.
693 692
694 Register result_tagged = x0; 693 Register result_tagged = x0;
695 Register base_tagged = x10;
696 Register exponent_tagged = MathPowTaggedDescriptor::exponent(); 694 Register exponent_tagged = MathPowTaggedDescriptor::exponent();
697 DCHECK(exponent_tagged.is(x11)); 695 DCHECK(exponent_tagged.is(x11));
698 Register exponent_integer = MathPowIntegerDescriptor::exponent(); 696 Register exponent_integer = MathPowIntegerDescriptor::exponent();
699 DCHECK(exponent_integer.is(x12)); 697 DCHECK(exponent_integer.is(x12));
700 Register scratch1 = x14;
701 Register scratch0 = x15;
702 Register saved_lr = x19; 698 Register saved_lr = x19;
703 FPRegister result_double = d0; 699 FPRegister result_double = d0;
704 FPRegister base_double = d0; 700 FPRegister base_double = d0;
705 FPRegister exponent_double = d1; 701 FPRegister exponent_double = d1;
706 FPRegister base_double_copy = d2; 702 FPRegister base_double_copy = d2;
707 FPRegister scratch1_double = d6; 703 FPRegister scratch1_double = d6;
708 FPRegister scratch0_double = d7; 704 FPRegister scratch0_double = d7;
709 705
710 // A fast-path for integer exponents. 706 // A fast-path for integer exponents.
711 Label exponent_is_smi, exponent_is_integer; 707 Label exponent_is_smi, exponent_is_integer;
712 // Bail out to runtime.
713 Label call_runtime;
714 // Allocate a heap number for the result, and return it. 708 // Allocate a heap number for the result, and return it.
715 Label done; 709 Label done;
716 710
717 // Unpack the inputs. 711 // Unpack the inputs.
718 if (exponent_type() == ON_STACK) { 712 if (exponent_type() == TAGGED) {
719 Label base_is_smi;
720 Label unpack_exponent;
721
722 __ Pop(exponent_tagged, base_tagged);
723
724 __ JumpIfSmi(base_tagged, &base_is_smi);
725 __ JumpIfNotHeapNumber(base_tagged, &call_runtime);
726 // base_tagged is a heap number, so load its double value.
727 __ Ldr(base_double, FieldMemOperand(base_tagged, HeapNumber::kValueOffset));
728 __ B(&unpack_exponent);
729 __ Bind(&base_is_smi);
730 // base_tagged is a SMI, so untag it and convert it to a double.
731 __ SmiUntagToDouble(base_double, base_tagged);
732
733 __ Bind(&unpack_exponent);
734 // x10 base_tagged The tagged base (input).
735 // x11 exponent_tagged The tagged exponent (input).
736 // d1 base_double The base as a double.
737 __ JumpIfSmi(exponent_tagged, &exponent_is_smi);
738 __ JumpIfNotHeapNumber(exponent_tagged, &call_runtime);
739 // exponent_tagged is a heap number, so load its double value.
740 __ Ldr(exponent_double,
741 FieldMemOperand(exponent_tagged, HeapNumber::kValueOffset));
742 } else if (exponent_type() == TAGGED) {
743 __ JumpIfSmi(exponent_tagged, &exponent_is_smi); 713 __ JumpIfSmi(exponent_tagged, &exponent_is_smi);
744 __ Ldr(exponent_double, 714 __ Ldr(exponent_double,
745 FieldMemOperand(exponent_tagged, HeapNumber::kValueOffset)); 715 FieldMemOperand(exponent_tagged, HeapNumber::kValueOffset));
746 } 716 }
747 717
748 // Handle double (heap number) exponents. 718 // Handle double (heap number) exponents.
749 if (exponent_type() != INTEGER) { 719 if (exponent_type() != INTEGER) {
750 // Detect integer exponents stored as doubles and handle those in the 720 // Detect integer exponents stored as doubles and handle those in the
751 // integer fast-path. 721 // integer fast-path.
752 __ TryRepresentDoubleAsInt64(exponent_integer, exponent_double, 722 __ TryRepresentDoubleAsInt64(exponent_integer, exponent_double,
753 scratch0_double, &exponent_is_integer); 723 scratch0_double, &exponent_is_integer);
754 724
755 if (exponent_type() == ON_STACK) {
756 FPRegister half_double = d3;
757 FPRegister minus_half_double = d4;
758 // Detect square root case. Crankshaft detects constant +/-0.5 at compile
759 // time and uses DoMathPowHalf instead. We then skip this check for
760 // non-constant cases of +/-0.5 as these hardly occur.
761
762 __ Fmov(minus_half_double, -0.5);
763 __ Fmov(half_double, 0.5);
764 __ Fcmp(minus_half_double, exponent_double);
765 __ Fccmp(half_double, exponent_double, NZFlag, ne);
766 // Condition flags at this point:
767 // 0.5; nZCv // Identified by eq && pl
768 // -0.5: NZcv // Identified by eq && mi
769 // other: ?z?? // Identified by ne
770 __ B(ne, &call_runtime);
771
772 // The exponent is 0.5 or -0.5.
773
774 // Given that exponent is known to be either 0.5 or -0.5, the following
775 // special cases could apply (according to ECMA-262 15.8.2.13):
776 //
777 // base.isNaN(): The result is NaN.
778 // (base == +INFINITY) || (base == -INFINITY)
779 // exponent == 0.5: The result is +INFINITY.
780 // exponent == -0.5: The result is +0.
781 // (base == +0) || (base == -0)
782 // exponent == 0.5: The result is +0.
783 // exponent == -0.5: The result is +INFINITY.
784 // (base < 0) && base.isFinite(): The result is NaN.
785 //
786 // Fsqrt (and Fdiv for the -0.5 case) can handle all of those except
787 // where base is -INFINITY or -0.
788
789 // Add +0 to base. This has no effect other than turning -0 into +0.
790 __ Fadd(base_double, base_double, fp_zero);
791 // The operation -0+0 results in +0 in all cases except where the
792 // FPCR rounding mode is 'round towards minus infinity' (RM). The
793 // ARM64 simulator does not currently simulate FPCR (where the rounding
794 // mode is set), so test the operation with some debug code.
795 if (masm->emit_debug_code()) {
796 UseScratchRegisterScope temps(masm);
797 Register temp = temps.AcquireX();
798 __ Fneg(scratch0_double, fp_zero);
799 // Verify that we correctly generated +0.0 and -0.0.
800 // bits(+0.0) = 0x0000000000000000
801 // bits(-0.0) = 0x8000000000000000
802 __ Fmov(temp, fp_zero);
803 __ CheckRegisterIsClear(temp, kCouldNotGenerateZero);
804 __ Fmov(temp, scratch0_double);
805 __ Eor(temp, temp, kDSignMask);
806 __ CheckRegisterIsClear(temp, kCouldNotGenerateNegativeZero);
807 // Check that -0.0 + 0.0 == +0.0.
808 __ Fadd(scratch0_double, scratch0_double, fp_zero);
809 __ Fmov(temp, scratch0_double);
810 __ CheckRegisterIsClear(temp, kExpectedPositiveZero);
811 }
812
813 // If base is -INFINITY, make it +INFINITY.
814 // * Calculate base - base: All infinities will become NaNs since both
815 // -INFINITY+INFINITY and +INFINITY-INFINITY are NaN in ARM64.
816 // * If the result is NaN, calculate abs(base).
817 __ Fsub(scratch0_double, base_double, base_double);
818 __ Fcmp(scratch0_double, 0.0);
819 __ Fabs(scratch1_double, base_double);
820 __ Fcsel(base_double, scratch1_double, base_double, vs);
821
822 // Calculate the square root of base.
823 __ Fsqrt(result_double, base_double);
824 __ Fcmp(exponent_double, 0.0);
825 __ B(ge, &done); // Finish now for exponents of 0.5.
826 // Find the inverse for exponents of -0.5.
827 __ Fmov(scratch0_double, 1.0);
828 __ Fdiv(result_double, scratch0_double, result_double);
829 __ B(&done);
830 }
831
832 { 725 {
833 AllowExternalCallThatCantCauseGC scope(masm); 726 AllowExternalCallThatCantCauseGC scope(masm);
834 __ Mov(saved_lr, lr); 727 __ Mov(saved_lr, lr);
835 __ CallCFunction( 728 __ CallCFunction(
836 ExternalReference::power_double_double_function(isolate()), 729 ExternalReference::power_double_double_function(isolate()), 0, 2);
837 0, 2);
838 __ Mov(lr, saved_lr); 730 __ Mov(lr, saved_lr);
839 __ B(&done); 731 __ B(&done);
840 } 732 }
841 733
842 // Handle SMI exponents. 734 // Handle SMI exponents.
843 __ Bind(&exponent_is_smi); 735 __ Bind(&exponent_is_smi);
844 // x10 base_tagged The tagged base (input). 736 // x10 base_tagged The tagged base (input).
845 // x11 exponent_tagged The tagged exponent (input). 737 // x11 exponent_tagged The tagged exponent (input).
846 // d1 base_double The base as a double. 738 // d1 base_double The base as a double.
847 __ SmiUntag(exponent_integer, exponent_tagged); 739 __ SmiUntag(exponent_integer, exponent_tagged);
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
896 __ Fdiv(result_double, scratch0_double, result_double); 788 __ Fdiv(result_double, scratch0_double, result_double);
897 // ECMA-262 only requires Math.pow to return an 'implementation-dependent 789 // ECMA-262 only requires Math.pow to return an 'implementation-dependent
898 // approximation' of base^exponent. However, mjsunit/math-pow uses Math.pow 790 // approximation' of base^exponent. However, mjsunit/math-pow uses Math.pow
899 // to calculate the subnormal value 2^-1074. This method of calculating 791 // to calculate the subnormal value 2^-1074. This method of calculating
900 // negative powers doesn't work because 2^1074 overflows to infinity. To 792 // negative powers doesn't work because 2^1074 overflows to infinity. To
901 // catch this corner-case, we bail out if the result was 0. (This can only 793 // catch this corner-case, we bail out if the result was 0. (This can only
902 // occur if the divisor is infinity or the base is zero.) 794 // occur if the divisor is infinity or the base is zero.)
903 __ Fcmp(result_double, 0.0); 795 __ Fcmp(result_double, 0.0);
904 __ B(&done, ne); 796 __ B(&done, ne);
905 797
906 if (exponent_type() == ON_STACK) { 798 AllowExternalCallThatCantCauseGC scope(masm);
907 // Bail out to runtime code. 799 __ Mov(saved_lr, lr);
908 __ Bind(&call_runtime); 800 __ Fmov(base_double, base_double_copy);
909 // Put the arguments back on the stack. 801 __ Scvtf(exponent_double, exponent_integer);
910 __ Push(base_tagged, exponent_tagged); 802 __ CallCFunction(ExternalReference::power_double_double_function(isolate()),
911 __ TailCallRuntime(Runtime::kMathPowRT); 803 0, 2);
912 804 __ Mov(lr, saved_lr);
913 // Return. 805 __ Bind(&done);
914 __ Bind(&done); 806 __ Ret();
915 __ AllocateHeapNumber(result_tagged, &call_runtime, scratch0, scratch1,
916 result_double);
917 DCHECK(result_tagged.is(x0));
918 __ Ret();
919 } else {
920 AllowExternalCallThatCantCauseGC scope(masm);
921 __ Mov(saved_lr, lr);
922 __ Fmov(base_double, base_double_copy);
923 __ Scvtf(exponent_double, exponent_integer);
924 __ CallCFunction(
925 ExternalReference::power_double_double_function(isolate()),
926 0, 2);
927 __ Mov(lr, saved_lr);
928 __ Bind(&done);
929 __ Ret();
930 }
931 } 807 }
932 808
933
934 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { 809 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) {
935 // It is important that the following stubs are generated in this order 810 // It is important that the following stubs are generated in this order
936 // because pregenerated stubs can only call other pregenerated stubs. 811 // because pregenerated stubs can only call other pregenerated stubs.
937 // RecordWriteStub uses StoreBufferOverflowStub, which in turn uses 812 // RecordWriteStub uses StoreBufferOverflowStub, which in turn uses
938 // CEntryStub. 813 // CEntryStub.
939 CEntryStub::GenerateAheadOfTime(isolate); 814 CEntryStub::GenerateAheadOfTime(isolate);
940 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); 815 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate);
941 StubFailureTrampolineStub::GenerateAheadOfTime(isolate); 816 StubFailureTrampolineStub::GenerateAheadOfTime(isolate);
942 CommonArrayConstructorStub::GenerateStubsAheadOfTime(isolate); 817 CommonArrayConstructorStub::GenerateStubsAheadOfTime(isolate);
943 CreateAllocationSiteStub::GenerateAheadOfTime(isolate); 818 CreateAllocationSiteStub::GenerateAheadOfTime(isolate);
(...skipping 4776 matching lines...) Expand 10 before | Expand all | Expand 10 after
5720 kStackUnwindSpace, NULL, spill_offset, 5595 kStackUnwindSpace, NULL, spill_offset,
5721 return_value_operand, NULL); 5596 return_value_operand, NULL);
5722 } 5597 }
5723 5598
5724 #undef __ 5599 #undef __
5725 5600
5726 } // namespace internal 5601 } // namespace internal
5727 } // namespace v8 5602 } // namespace v8
5728 5603
5729 #endif // V8_TARGET_ARCH_ARM64 5604 #endif // V8_TARGET_ARCH_ARM64
OLDNEW
« no previous file with comments | « src/arm/code-stubs-arm.cc ('k') | src/assembler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698