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

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

Powered by Google App Engine
This is Rietveld 408576698