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

Side by Side Diff: src/ia32/code-stubs-ia32.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 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 Isolate* isolate, 94 Isolate* isolate,
95 CodeStubInterfaceDescriptor* descriptor) { 95 CodeStubInterfaceDescriptor* descriptor) {
96 static Register registers[] = { eax, ebx }; 96 static Register registers[] = { eax, ebx };
97 descriptor->register_param_count_ = 2; 97 descriptor->register_param_count_ = 2;
98 descriptor->register_params_ = registers; 98 descriptor->register_params_ = registers;
99 descriptor->deoptimization_handler_ = 99 descriptor->deoptimization_handler_ =
100 Runtime::FunctionForId(Runtime::kTransitionElementsKind)->entry; 100 Runtime::FunctionForId(Runtime::kTransitionElementsKind)->entry;
101 } 101 }
102 102
103 103
104 static void InitializeArrayConstructorDescriptor(Isolate* isolate, 104 static void InitializeArrayConstructorDescriptor(
105 CodeStubInterfaceDescriptor* descriptor) { 105 Isolate* isolate,
106 CodeStubInterfaceDescriptor* descriptor,
107 int constant_stack_parameter_count) {
106 // register state 108 // register state
107 // edi -- constructor function 109 // edi -- constructor function
108 // ebx -- type info cell with elements kind 110 // ebx -- type info cell with elements kind
109 // eax -- number of arguments to the constructor function 111 static Register registers[] = { ebx };
110 static Register registers[] = { edi, ebx }; 112 descriptor->register_param_count_ = 1;
111 descriptor->register_param_count_ = 2; 113
112 // stack param count needs (constructor pointer, and single argument) 114 if (constant_stack_parameter_count != 0) {
113 descriptor->stack_parameter_count_ = &eax; 115 // stack param count needs (constructor pointer, and single argument)
116 descriptor->stack_parameter_count_ = &eax;
117 }
118 descriptor->hint_stack_parameter_count_ = constant_stack_parameter_count;
114 descriptor->register_params_ = registers; 119 descriptor->register_params_ = registers;
115 descriptor->function_mode_ = JS_FUNCTION_STUB_MODE; 120 descriptor->function_mode_ = JS_FUNCTION_STUB_MODE;
116 descriptor->deoptimization_handler_ = 121 descriptor->deoptimization_handler_ =
117 FUNCTION_ADDR(ArrayConstructor_StubFailure); 122 FUNCTION_ADDR(ArrayConstructor_StubFailure);
118 } 123 }
119 124
120 125
121 void ArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor( 126 void ArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor(
122 Isolate* isolate, 127 Isolate* isolate,
123 CodeStubInterfaceDescriptor* descriptor) { 128 CodeStubInterfaceDescriptor* descriptor) {
124 InitializeArrayConstructorDescriptor(isolate, descriptor); 129 InitializeArrayConstructorDescriptor(isolate, descriptor, 0);
125 } 130 }
126 131
127 132
128 void ArraySingleArgumentConstructorStub::InitializeInterfaceDescriptor( 133 void ArraySingleArgumentConstructorStub::InitializeInterfaceDescriptor(
129 Isolate* isolate, 134 Isolate* isolate,
130 CodeStubInterfaceDescriptor* descriptor) { 135 CodeStubInterfaceDescriptor* descriptor) {
131 InitializeArrayConstructorDescriptor(isolate, descriptor); 136 InitializeArrayConstructorDescriptor(isolate, descriptor, 1);
132 } 137 }
133 138
134 139
135 void ArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor( 140 void ArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor(
136 Isolate* isolate, 141 Isolate* isolate,
137 CodeStubInterfaceDescriptor* descriptor) { 142 CodeStubInterfaceDescriptor* descriptor) {
138 InitializeArrayConstructorDescriptor(isolate, descriptor); 143 InitializeArrayConstructorDescriptor(isolate, descriptor, -1);
139 } 144 }
140 145
141 146
142 #define __ ACCESS_MASM(masm) 147 #define __ ACCESS_MASM(masm)
143 148
144 149
145 void HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm) { 150 void HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm) {
146 // Update the static counter each time a new code stub is generated. 151 // Update the static counter each time a new code stub is generated.
147 Isolate* isolate = masm->isolate(); 152 Isolate* isolate = masm->isolate();
148 isolate->counters()->code_stubs()->Increment(); 153 isolate->counters()->code_stubs()->Increment();
(...skipping 4796 matching lines...) Expand 10 before | Expand all | Expand 10 after
4945 result_size_ == 1; 4950 result_size_ == 1;
4946 } 4951 }
4947 4952
4948 4953
4949 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { 4954 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) {
4950 CEntryStub::GenerateAheadOfTime(isolate); 4955 CEntryStub::GenerateAheadOfTime(isolate);
4951 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); 4956 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate);
4952 StubFailureTrampolineStub::GenerateAheadOfTime(isolate); 4957 StubFailureTrampolineStub::GenerateAheadOfTime(isolate);
4953 // It is important that the store buffer overflow stubs are generated first. 4958 // It is important that the store buffer overflow stubs are generated first.
4954 RecordWriteStub::GenerateFixedRegStubsAheadOfTime(isolate); 4959 RecordWriteStub::GenerateFixedRegStubsAheadOfTime(isolate);
4960 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
4955 } 4961 }
4956 4962
4957 4963
4958 void CodeStub::GenerateFPStubs(Isolate* isolate) { 4964 void CodeStub::GenerateFPStubs(Isolate* isolate) {
4959 if (CpuFeatures::IsSupported(SSE2)) { 4965 if (CpuFeatures::IsSupported(SSE2)) {
4960 CEntryStub save_doubles(1, kSaveFPRegs); 4966 CEntryStub save_doubles(1, kSaveFPRegs);
4961 // Stubs might already be in the snapshot, detect that and don't regenerate, 4967 // Stubs might already be in the snapshot, detect that and don't regenerate,
4962 // which would lead to code stub initialization state being messed up. 4968 // which would lead to code stub initialization state being messed up.
4963 Code* save_doubles_code; 4969 Code* save_doubles_code;
4964 if (!save_doubles.FindCodeInCache(&save_doubles_code, isolate)) { 4970 if (!save_doubles.FindCodeInCache(&save_doubles_code, isolate)) {
(...skipping 2739 matching lines...) Expand 10 before | Expand all | Expand 10 after
7704 // Call the entry hook. 7710 // Call the entry hook.
7705 int32_t hook_location = reinterpret_cast<int32_t>(&entry_hook_); 7711 int32_t hook_location = reinterpret_cast<int32_t>(&entry_hook_);
7706 __ call(Operand(hook_location, RelocInfo::NONE32)); 7712 __ call(Operand(hook_location, RelocInfo::NONE32));
7707 __ add(esp, Immediate(2 * kPointerSize)); 7713 __ add(esp, Immediate(2 * kPointerSize));
7708 7714
7709 // Restore ecx. 7715 // Restore ecx.
7710 __ pop(ecx); 7716 __ pop(ecx);
7711 __ ret(0); 7717 __ ret(0);
7712 } 7718 }
7713 7719
7720
7721 template<class T>
7722 static void CreateArrayDispatch(MacroAssembler* masm) {
7723 int last_index = GetSequenceIndexFromFastElementsKind(
7724 TERMINAL_FAST_ELEMENTS_KIND);
7725 for (int i = 0; i <= last_index; ++i) {
7726 Label next;
7727 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
7728 __ cmp(edx, kind);
7729 __ j(not_equal, &next);
7730 T stub(kind);
7731 __ TailCallStub(&stub);
7732 __ bind(&next);
7733 }
7734
7735 // If we reached this point there is a problem.
7736 __ Abort("Unexpected ElementsKind in array constructor");
7737 }
7738
7739
7740 static void CreateArrayDispatchOneArgument(MacroAssembler* masm) {
7741 // ebx - type info cell
7742 // edx - kind
7743 // eax - number of arguments
7744 // edi - constructor?
7745 // esp[0] - return address
7746 // esp[4] - last argument
7747 ASSERT(FAST_SMI_ELEMENTS == 0);
7748 ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
7749 ASSERT(FAST_ELEMENTS == 2);
7750 ASSERT(FAST_HOLEY_ELEMENTS == 3);
7751 ASSERT(FAST_DOUBLE_ELEMENTS == 4);
7752 ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == 5);
7753
7754 Handle<Object> undefined_sentinel(
7755 masm->isolate()->heap()->undefined_value(),
7756 masm->isolate());
7757
7758 // is the low bit set? If so, we are holey and that is good.
7759 __ test_b(edx, 1);
7760 Label normal_sequence;
7761 __ j(not_zero, &normal_sequence);
7762
7763 // look at the first argument
7764 __ mov(ecx, Operand(esp, kPointerSize));
7765 __ test(ecx, ecx);
7766 __ j(zero, &normal_sequence);
7767
7768 // We are going to create a holey array, but our kind is non-holey.
7769 // Fix kind and retry
7770 __ inc(edx);
7771 __ cmp(ebx, Immediate(undefined_sentinel));
7772 __ j(equal, &normal_sequence);
7773
7774 // Save the resulting elements kind in type info
7775 __ SmiTag(edx);
7776 __ mov(FieldOperand(ebx, kPointerSize), edx);
7777 __ SmiUntag(edx);
7778
7779 __ bind(&normal_sequence);
7780 int last_index = GetSequenceIndexFromFastElementsKind(
7781 TERMINAL_FAST_ELEMENTS_KIND);
7782 for (int i = 0; i <= last_index; ++i) {
7783 Label next;
7784 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
7785 __ cmp(edx, kind);
7786 __ j(not_equal, &next);
7787 ArraySingleArgumentConstructorStub stub(kind);
7788 __ TailCallStub(&stub);
7789 __ bind(&next);
7790 }
7791
7792 // If we reached this point there is a problem.
7793 __ Abort("Unexpected ElementsKind in array constructor");
7794 }
7795
7796
7797 template<class T>
7798 static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) {
7799 int to_index = GetSequenceIndexFromFastElementsKind(
7800 TERMINAL_FAST_ELEMENTS_KIND);
7801 for (int i = 0; i <= to_index; ++i) {
7802 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
7803 T stub(kind);
7804 stub.GetCode(isolate)->set_is_pregenerated(true);
7805 }
7806 }
7807
7808
7809 void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) {
7810 ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>(
7811 isolate);
7812 ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>(
7813 isolate);
7814 ArrayConstructorStubAheadOfTimeHelper<ArrayNArgumentsConstructorStub>(
7815 isolate);
7816 }
7817
7818
7819 void ArrayConstructorStub::Generate(MacroAssembler* masm) {
7820 // ----------- S t a t e -------------
7821 // -- eax : argc (only if argument_count_ == ANY)
7822 // -- ebx : type info cell
7823 // -- edi : constructor
7824 // -- esp[0] : return address
7825 // -- esp[4] : last argument
7826 // -----------------------------------
7827 Handle<Object> undefined_sentinel(
7828 masm->isolate()->heap()->undefined_value(),
7829 masm->isolate());
7830
7831 if (FLAG_debug_code) {
7832 // The array construct code is only set for the global and natives
7833 // builtin Array functions which always have maps.
7834
7835 // Initial map for the builtin Array function should be a map.
7836 __ mov(ecx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset));
7837 // Will both indicate a NULL and a Smi.
7838 __ test(ecx, Immediate(kSmiTagMask));
7839 __ Assert(not_zero, "Unexpected initial map for Array function");
7840 __ CmpObjectType(ecx, MAP_TYPE, ecx);
7841 __ Assert(equal, "Unexpected initial map for Array function");
7842
7843 // We should either have undefined in ebx or a valid jsglobalpropertycell
7844 Label okay_here;
7845 Handle<Map> global_property_cell_map(
7846 masm->isolate()->heap()->global_property_cell_map());
7847 __ cmp(ebx, Immediate(undefined_sentinel));
7848 __ j(equal, &okay_here);
7849 __ cmp(FieldOperand(ebx, 0), Immediate(global_property_cell_map));
7850 __ Assert(equal, "Expected property cell in register ebx");
7851 __ bind(&okay_here);
7852 }
7853
7854 if (FLAG_optimize_constructed_arrays) {
7855 Label no_info, switch_ready;
7856 // Get the elements kind and case on that.
7857 __ cmp(ebx, Immediate(undefined_sentinel));
7858 __ j(equal, &no_info);
7859 __ mov(edx, FieldOperand(ebx, kPointerSize));
7860
7861 // There is no info if the call site went megamorphic either
7862
7863 // TODO(mvstanton): Really? I thought if it was the array function that
7864 // the cell wouldn't get stamped as megamorphic.
7865 __ cmp(edx, Immediate(TypeFeedbackCells::MegamorphicSentinel(
7866 masm->isolate())));
7867 __ j(equal, &no_info);
7868 __ SmiUntag(edx);
7869 __ jmp(&switch_ready);
7870 __ bind(&no_info);
7871 __ mov(edx, Immediate(GetInitialFastElementsKind()));
7872 __ bind(&switch_ready);
7873
7874 if (argument_count_ == ANY) {
7875 Label not_zero_case, not_one_case;
7876 __ test(eax, eax);
7877 __ j(not_zero, &not_zero_case);
7878 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm);
7879
7880 __ bind(&not_zero_case);
7881 __ cmp(eax, 1);
7882 __ j(greater, &not_one_case);
7883 CreateArrayDispatchOneArgument(masm);
7884
7885 __ bind(&not_one_case);
7886 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm);
7887 } else if (argument_count_ == NONE) {
7888 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm);
7889 } else if (argument_count_ == ONE) {
7890 CreateArrayDispatchOneArgument(masm);
7891 } else if (argument_count_ == MORE_THAN_ONE) {
7892 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm);
7893 } else {
7894 UNREACHABLE();
7895 }
7896 } else {
7897 Label generic_constructor;
7898 // Run the native code for the Array function called as constructor.
7899 ArrayNativeCode(masm, true, &generic_constructor);
7900
7901 // Jump to the generic construct code in case the specialized code cannot
7902 // handle the construction.
7903 __ bind(&generic_constructor);
7904 Handle<Code> generic_construct_stub =
7905 masm->isolate()->builtins()->JSConstructStubGeneric();
7906 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET);
7907 }
7908 }
7909
7910
7714 #undef __ 7911 #undef __
7715 7912
7716 } } // namespace v8::internal 7913 } } // namespace v8::internal
7717 7914
7718 #endif // V8_TARGET_ARCH_IA32 7915 #endif // V8_TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698