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

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

Issue 12385014: Hydrogen stubs for array constructors (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: REBASE Created 7 years, 8 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 | Annotate | Revision Log
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
89 Isolate* isolate, 89 Isolate* isolate,
90 CodeStubInterfaceDescriptor* descriptor) { 90 CodeStubInterfaceDescriptor* descriptor) {
91 static Register registers[] = { rax, rbx }; 91 static Register registers[] = { rax, rbx };
92 descriptor->register_param_count_ = 2; 92 descriptor->register_param_count_ = 2;
93 descriptor->register_params_ = registers; 93 descriptor->register_params_ = registers;
94 descriptor->deoptimization_handler_ = 94 descriptor->deoptimization_handler_ =
95 Runtime::FunctionForId(Runtime::kTransitionElementsKind)->entry; 95 Runtime::FunctionForId(Runtime::kTransitionElementsKind)->entry;
96 } 96 }
97 97
98 98
99 static void InitializeArrayConstructorDescriptor(Isolate* isolate, 99 static void InitializeArrayConstructorDescriptor(
100 CodeStubInterfaceDescriptor* descriptor) { 100 Isolate* isolate,
101 CodeStubInterfaceDescriptor* descriptor,
102 int constant_stack_parameter_count) {
101 // register state 103 // register state
102 // rdi -- constructor function
103 // rbx -- type info cell with elements kind 104 // rbx -- type info cell with elements kind
104 // rax -- number of arguments to the constructor function 105 static Register registers[] = { rbx };
105 static Register registers[] = { rdi, rbx }; 106 descriptor->register_param_count_ = 1;
106 descriptor->register_param_count_ = 2; 107 if (constant_stack_parameter_count != 0) {
107 // stack param count needs (constructor pointer, and single argument) 108 // stack param count needs (constructor pointer, and single argument)
108 descriptor->stack_parameter_count_ = &rax; 109 descriptor->stack_parameter_count_ = &rax;
110 }
111 descriptor->hint_stack_parameter_count_ = constant_stack_parameter_count;
109 descriptor->register_params_ = registers; 112 descriptor->register_params_ = registers;
110 descriptor->function_mode_ = JS_FUNCTION_STUB_MODE; 113 descriptor->function_mode_ = JS_FUNCTION_STUB_MODE;
111 descriptor->deoptimization_handler_ = 114 descriptor->deoptimization_handler_ =
112 FUNCTION_ADDR(ArrayConstructor_StubFailure); 115 FUNCTION_ADDR(ArrayConstructor_StubFailure);
113 } 116 }
114 117
115 118
116 void ArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor( 119 void ArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor(
117 Isolate* isolate, 120 Isolate* isolate,
118 CodeStubInterfaceDescriptor* descriptor) { 121 CodeStubInterfaceDescriptor* descriptor) {
119 InitializeArrayConstructorDescriptor(isolate, descriptor); 122 InitializeArrayConstructorDescriptor(isolate, descriptor, 0);
120 } 123 }
121 124
122 125
123 void ArraySingleArgumentConstructorStub::InitializeInterfaceDescriptor( 126 void ArraySingleArgumentConstructorStub::InitializeInterfaceDescriptor(
124 Isolate* isolate, 127 Isolate* isolate,
125 CodeStubInterfaceDescriptor* descriptor) { 128 CodeStubInterfaceDescriptor* descriptor) {
126 InitializeArrayConstructorDescriptor(isolate, descriptor); 129 InitializeArrayConstructorDescriptor(isolate, descriptor, 1);
127 } 130 }
128 131
129 132
130 void ArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor( 133 void ArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor(
131 Isolate* isolate, 134 Isolate* isolate,
132 CodeStubInterfaceDescriptor* descriptor) { 135 CodeStubInterfaceDescriptor* descriptor) {
133 InitializeArrayConstructorDescriptor(isolate, descriptor); 136 InitializeArrayConstructorDescriptor(isolate, descriptor, -1);
134 } 137 }
135 138
136 139
137 #define __ ACCESS_MASM(masm) 140 #define __ ACCESS_MASM(masm)
138 141
139 void ToNumberStub::Generate(MacroAssembler* masm) { 142 void ToNumberStub::Generate(MacroAssembler* masm) {
140 // The ToNumber stub takes one argument in eax. 143 // The ToNumber stub takes one argument in eax.
141 Label check_heap_number, call_builtin; 144 Label check_heap_number, call_builtin;
142 __ SmiTest(rax); 145 __ SmiTest(rax);
143 __ j(not_zero, &check_heap_number, Label::kNear); 146 __ j(not_zero, &check_heap_number, Label::kNear);
(...skipping 3645 matching lines...) Expand 10 before | Expand all | Expand 10 after
3789 __ Cmp(rcx, TypeFeedbackCells::MegamorphicSentinel(isolate)); 3792 __ Cmp(rcx, TypeFeedbackCells::MegamorphicSentinel(isolate));
3790 __ j(equal, &done); 3793 __ j(equal, &done);
3791 3794
3792 // Special handling of the Array() function, which caches not only the 3795 // Special handling of the Array() function, which caches not only the
3793 // monomorphic Array function but the initial ElementsKind with special 3796 // monomorphic Array function but the initial ElementsKind with special
3794 // sentinels 3797 // sentinels
3795 Handle<Object> terminal_kind_sentinel = 3798 Handle<Object> terminal_kind_sentinel =
3796 TypeFeedbackCells::MonomorphicArraySentinel(isolate, 3799 TypeFeedbackCells::MonomorphicArraySentinel(isolate,
3797 LAST_FAST_ELEMENTS_KIND); 3800 LAST_FAST_ELEMENTS_KIND);
3798 __ Cmp(rcx, terminal_kind_sentinel); 3801 __ Cmp(rcx, terminal_kind_sentinel);
3799 __ j(not_equal, &miss); 3802 __ j(above, &miss);
3800 // Make sure the function is the Array() function 3803 // Make sure the function is the Array() function
3801 __ LoadArrayFunction(rcx); 3804 __ LoadArrayFunction(rcx);
3802 __ cmpq(rdi, rcx); 3805 __ cmpq(rdi, rcx);
3803 __ j(not_equal, &megamorphic); 3806 __ j(not_equal, &megamorphic);
3804 __ jmp(&done); 3807 __ jmp(&done);
3805 3808
3806 __ bind(&miss); 3809 __ bind(&miss);
3807 3810
3808 // A monomorphic miss (i.e, here the cache is not uninitialized) goes 3811 // A monomorphic miss (i.e, here the cache is not uninitialized) goes
3809 // megamorphic. 3812 // megamorphic.
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
4001 #endif 4004 #endif
4002 } 4005 }
4003 4006
4004 4007
4005 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { 4008 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) {
4006 CEntryStub::GenerateAheadOfTime(isolate); 4009 CEntryStub::GenerateAheadOfTime(isolate);
4007 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); 4010 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate);
4008 StubFailureTrampolineStub::GenerateAheadOfTime(isolate); 4011 StubFailureTrampolineStub::GenerateAheadOfTime(isolate);
4009 // It is important that the store buffer overflow stubs are generated first. 4012 // It is important that the store buffer overflow stubs are generated first.
4010 RecordWriteStub::GenerateFixedRegStubsAheadOfTime(isolate); 4013 RecordWriteStub::GenerateFixedRegStubsAheadOfTime(isolate);
4014 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
4011 } 4015 }
4012 4016
4013 4017
4014 void CodeStub::GenerateFPStubs(Isolate* isolate) { 4018 void CodeStub::GenerateFPStubs(Isolate* isolate) {
4015 } 4019 }
4016 4020
4017 4021
4018 void CEntryStub::GenerateAheadOfTime(Isolate* isolate) { 4022 void CEntryStub::GenerateAheadOfTime(Isolate* isolate) {
4019 CEntryStub stub(1, kDontSaveFPRegs); 4023 CEntryStub stub(1, kDontSaveFPRegs);
4020 stub.GetCode(isolate)->set_is_pregenerated(true); 4024 stub.GetCode(isolate)->set_is_pregenerated(true);
(...skipping 2717 matching lines...) Expand 10 before | Expand all | Expand 10 after
6738 __ pop(rcx); 6742 __ pop(rcx);
6739 #else 6743 #else
6740 __ pop(rsi); 6744 __ pop(rsi);
6741 __ pop(rdi); 6745 __ pop(rdi);
6742 __ pop(rcx); 6746 __ pop(rcx);
6743 #endif 6747 #endif
6744 6748
6745 __ Ret(); 6749 __ Ret();
6746 } 6750 }
6747 6751
6752
6753 template<class T>
6754 static void CreateArrayDispatch(MacroAssembler* masm) {
6755 int last_index = GetSequenceIndexFromFastElementsKind(
6756 TERMINAL_FAST_ELEMENTS_KIND);
6757 for (int i = 0; i <= last_index; ++i) {
6758 Label next;
6759 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
6760 __ cmpl(rdx, Immediate(kind));
6761 __ j(not_equal, &next);
6762 T stub(kind);
6763 __ TailCallStub(&stub);
6764 __ bind(&next);
6765 }
6766
6767 // If we reached this point there is a problem.
6768 __ Abort("Unexpected ElementsKind in array constructor");
6769 }
6770
6771
6772 static void CreateArrayDispatchOneArgument(MacroAssembler* masm) {
6773 // rbx - type info cell
6774 // rdx - kind
6775 // rax - number of arguments
6776 // rdi - constructor?
6777 // esp[0] - return address
6778 // esp[4] - last argument
6779 ASSERT(FAST_SMI_ELEMENTS == 0);
6780 ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
6781 ASSERT(FAST_ELEMENTS == 2);
6782 ASSERT(FAST_HOLEY_ELEMENTS == 3);
6783 ASSERT(FAST_DOUBLE_ELEMENTS == 4);
6784 ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == 5);
6785
6786 Handle<Object> undefined_sentinel(
6787 masm->isolate()->heap()->undefined_value(),
6788 masm->isolate());
6789
6790 // is the low bit set? If so, we are holey and that is good.
6791 __ testb(rdx, Immediate(1));
6792 Label normal_sequence;
6793 __ j(not_zero, &normal_sequence);
6794
6795 // look at the first argument
6796 __ movq(rcx, Operand(rsp, kPointerSize));
6797 __ testq(rcx, rcx);
6798 __ j(zero, &normal_sequence);
6799
6800 // We are going to create a holey array, but our kind is non-holey.
6801 // Fix kind and retry
6802 __ incl(rdx);
6803 __ Cmp(rbx, undefined_sentinel);
6804 __ j(equal, &normal_sequence);
6805
6806 // Save the resulting elements kind in type info
6807 __ Integer32ToSmi(rdx, rdx);
6808 __ movq(FieldOperand(rbx, kPointerSize), rdx);
6809 __ SmiToInteger32(rdx, rdx);
6810
6811 __ bind(&normal_sequence);
6812 int last_index = GetSequenceIndexFromFastElementsKind(
6813 TERMINAL_FAST_ELEMENTS_KIND);
6814 for (int i = 0; i <= last_index; ++i) {
6815 Label next;
6816 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
6817 __ cmpl(rdx, Immediate(kind));
6818 __ j(not_equal, &next);
6819 ArraySingleArgumentConstructorStub stub(kind);
6820 __ TailCallStub(&stub);
6821 __ bind(&next);
6822 }
6823
6824 // If we reached this point there is a problem.
6825 __ Abort("Unexpected ElementsKind in array constructor");
6826 }
6827
6828
6829 template<class T>
6830 static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) {
6831 int to_index = GetSequenceIndexFromFastElementsKind(
6832 TERMINAL_FAST_ELEMENTS_KIND);
6833 for (int i = 0; i <= to_index; ++i) {
6834 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
6835 T stub(kind);
6836 stub.GetCode(isolate)->set_is_pregenerated(true);
6837 }
6838 }
6839
6840
6841 void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) {
6842 ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>(
6843 isolate);
6844 ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>(
6845 isolate);
6846 ArrayConstructorStubAheadOfTimeHelper<ArrayNArgumentsConstructorStub>(
6847 isolate);
6848 }
6849
6850
6851
6852 void ArrayConstructorStub::Generate(MacroAssembler* masm) {
6853 // ----------- S t a t e -------------
6854 // -- rax : argc
6855 // -- rbx : type info cell
6856 // -- rdi : constructor
6857 // -- rsp[0] : return address
6858 // -- rsp[4] : last argument
6859 // -----------------------------------
6860 Handle<Object> undefined_sentinel(
6861 masm->isolate()->heap()->undefined_value(),
6862 masm->isolate());
6863
6864 if (FLAG_debug_code) {
6865 // The array construct code is only set for the global and natives
6866 // builtin Array functions which always have maps.
6867
6868 // Initial map for the builtin Array function should be a map.
6869 __ movq(rcx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset));
6870 // Will both indicate a NULL and a Smi.
6871 STATIC_ASSERT(kSmiTag == 0);
6872 Condition not_smi = NegateCondition(masm->CheckSmi(rcx));
6873 __ Check(not_smi, "Unexpected initial map for Array function");
6874 __ CmpObjectType(rcx, MAP_TYPE, rcx);
6875 __ Check(equal, "Unexpected initial map for Array function");
6876
6877 // We should either have undefined in ebx or a valid jsglobalpropertycell
6878 Label okay_here;
6879 Handle<Map> global_property_cell_map(
6880 masm->isolate()->heap()->global_property_cell_map());
6881 __ Cmp(rbx, undefined_sentinel);
6882 __ j(equal, &okay_here);
6883 __ Cmp(FieldOperand(rbx, 0), global_property_cell_map);
6884 __ Assert(equal, "Expected property cell in register rbx");
6885 __ bind(&okay_here);
6886 }
6887
6888 if (FLAG_optimize_constructed_arrays) {
6889 Label no_info, switch_ready;
6890 // Get the elements kind and case on that.
6891 __ Cmp(rbx, undefined_sentinel);
6892 __ j(equal, &no_info);
6893 __ movq(rdx, FieldOperand(rbx, kPointerSize));
6894
6895 // There is no info if the call site went megamorphic either
6896
6897 // TODO(mvstanton): Really? I thought if it was the array function that
6898 // the cell wouldn't get stamped as megamorphic.
6899 __ Cmp(rdx, TypeFeedbackCells::MegamorphicSentinel(masm->isolate()));
6900 __ j(equal, &no_info);
6901 __ SmiToInteger32(rdx, rdx);
6902 __ jmp(&switch_ready);
6903 __ bind(&no_info);
6904 __ movq(rdx, Immediate(GetInitialFastElementsKind()));
6905 __ bind(&switch_ready);
6906
6907 if (argument_count_ == ANY) {
6908 Label not_zero_case, not_one_case;
6909 __ testq(rax, rax);
6910 __ j(not_zero, &not_zero_case);
6911 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm);
6912
6913 __ bind(&not_zero_case);
6914 __ cmpl(rax, Immediate(1));
6915 __ j(greater, &not_one_case);
6916 CreateArrayDispatchOneArgument(masm);
6917
6918 __ bind(&not_one_case);
6919 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm);
6920 } else if (argument_count_ == NONE) {
6921 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm);
6922 } else if (argument_count_ == ONE) {
6923 CreateArrayDispatchOneArgument(masm);
6924 } else if (argument_count_ == MORE_THAN_ONE) {
6925 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm);
6926 } else {
6927 UNREACHABLE();
6928 }
6929 } else {
6930 Label generic_constructor;
6931 // Run the native code for the Array function called as constructor.
6932 ArrayNativeCode(masm, &generic_constructor);
6933
6934 // Jump to the generic construct code in case the specialized code cannot
6935 // handle the construction.
6936 __ bind(&generic_constructor);
6937 Handle<Code> generic_construct_stub =
6938 masm->isolate()->builtins()->JSConstructStubGeneric();
6939 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET);
6940 }
6941 }
6942
6943
6748 #undef __ 6944 #undef __
6749 6945
6750 } } // namespace v8::internal 6946 } } // namespace v8::internal
6751 6947
6752 #endif // V8_TARGET_ARCH_X64 6948 #endif // V8_TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698