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

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: We still generated the arrays with feature flag off. Fixed. 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
« no previous file with comments | « src/ia32/code-stubs-ia32.h ('k') | src/ia32/lithium-codegen-ia32.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 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 // eax -- number of arguments
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 if (FLAG_optimize_constructed_arrays) {
4961 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
4962 }
4955 } 4963 }
4956 4964
4957 4965
4958 void CodeStub::GenerateFPStubs(Isolate* isolate) { 4966 void CodeStub::GenerateFPStubs(Isolate* isolate) {
4959 if (CpuFeatures::IsSupported(SSE2)) { 4967 if (CpuFeatures::IsSupported(SSE2)) {
4960 CEntryStub save_doubles(1, kSaveFPRegs); 4968 CEntryStub save_doubles(1, kSaveFPRegs);
4961 // Stubs might already be in the snapshot, detect that and don't regenerate, 4969 // 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. 4970 // which would lead to code stub initialization state being messed up.
4963 Code* save_doubles_code; 4971 Code* save_doubles_code;
4964 if (!save_doubles.FindCodeInCache(&save_doubles_code, isolate)) { 4972 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. 7712 // Call the entry hook.
7705 int32_t hook_location = reinterpret_cast<int32_t>(&entry_hook_); 7713 int32_t hook_location = reinterpret_cast<int32_t>(&entry_hook_);
7706 __ call(Operand(hook_location, RelocInfo::NONE32)); 7714 __ call(Operand(hook_location, RelocInfo::NONE32));
7707 __ add(esp, Immediate(2 * kPointerSize)); 7715 __ add(esp, Immediate(2 * kPointerSize));
7708 7716
7709 // Restore ecx. 7717 // Restore ecx.
7710 __ pop(ecx); 7718 __ pop(ecx);
7711 __ ret(0); 7719 __ ret(0);
7712 } 7720 }
7713 7721
7722
7723 template<class T>
7724 static void CreateArrayDispatch(MacroAssembler* masm) {
7725 int last_index = GetSequenceIndexFromFastElementsKind(
7726 TERMINAL_FAST_ELEMENTS_KIND);
7727 for (int i = 0; i <= last_index; ++i) {
7728 Label next;
7729 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
7730 __ cmp(edx, kind);
7731 __ j(not_equal, &next);
7732 T stub(kind);
7733 __ TailCallStub(&stub);
7734 __ bind(&next);
7735 }
7736
7737 // If we reached this point there is a problem.
7738 __ Abort("Unexpected ElementsKind in array constructor");
7739 }
7740
7741
7742 static void CreateArrayDispatchOneArgument(MacroAssembler* masm) {
7743 // ebx - type info cell
7744 // edx - kind
7745 // eax - number of arguments
7746 // edi - constructor?
7747 // esp[0] - return address
7748 // esp[4] - last argument
7749 ASSERT(FAST_SMI_ELEMENTS == 0);
7750 ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
7751 ASSERT(FAST_ELEMENTS == 2);
7752 ASSERT(FAST_HOLEY_ELEMENTS == 3);
7753 ASSERT(FAST_DOUBLE_ELEMENTS == 4);
7754 ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == 5);
7755
7756 Handle<Object> undefined_sentinel(
7757 masm->isolate()->heap()->undefined_value(),
7758 masm->isolate());
7759
7760 // is the low bit set? If so, we are holey and that is good.
7761 __ test_b(edx, 1);
7762 Label normal_sequence;
7763 __ j(not_zero, &normal_sequence);
7764
7765 // look at the first argument
7766 __ mov(ecx, Operand(esp, kPointerSize));
7767 __ test(ecx, ecx);
7768 __ j(zero, &normal_sequence);
7769
7770 // We are going to create a holey array, but our kind is non-holey.
7771 // Fix kind and retry
7772 __ inc(edx);
7773 __ cmp(ebx, Immediate(undefined_sentinel));
7774 __ j(equal, &normal_sequence);
7775
7776 // Save the resulting elements kind in type info
7777 __ SmiTag(edx);
7778 __ mov(FieldOperand(ebx, kPointerSize), edx);
7779 __ SmiUntag(edx);
7780
7781 __ bind(&normal_sequence);
7782 int last_index = GetSequenceIndexFromFastElementsKind(
7783 TERMINAL_FAST_ELEMENTS_KIND);
7784 for (int i = 0; i <= last_index; ++i) {
7785 Label next;
7786 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
7787 __ cmp(edx, kind);
7788 __ j(not_equal, &next);
7789 ArraySingleArgumentConstructorStub stub(kind);
7790 __ TailCallStub(&stub);
7791 __ bind(&next);
7792 }
7793
7794 // If we reached this point there is a problem.
7795 __ Abort("Unexpected ElementsKind in array constructor");
7796 }
7797
7798
7799 template<class T>
7800 static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) {
7801 int to_index = GetSequenceIndexFromFastElementsKind(
7802 TERMINAL_FAST_ELEMENTS_KIND);
7803 for (int i = 0; i <= to_index; ++i) {
7804 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
7805 T stub(kind);
7806 stub.GetCode(isolate)->set_is_pregenerated(true);
7807 }
7808 }
7809
7810
7811 void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) {
7812 ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>(
7813 isolate);
7814 ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>(
7815 isolate);
7816 ArrayConstructorStubAheadOfTimeHelper<ArrayNArgumentsConstructorStub>(
7817 isolate);
7818 }
7819
7820
7821 void ArrayConstructorStub::Generate(MacroAssembler* masm) {
7822 // ----------- S t a t e -------------
7823 // -- eax : argc (only if argument_count_ == ANY)
7824 // -- ebx : type info cell
7825 // -- edi : constructor
7826 // -- esp[0] : return address
7827 // -- esp[4] : last argument
7828 // -----------------------------------
7829 Handle<Object> undefined_sentinel(
7830 masm->isolate()->heap()->undefined_value(),
7831 masm->isolate());
7832
7833 if (FLAG_debug_code) {
7834 // The array construct code is only set for the global and natives
7835 // builtin Array functions which always have maps.
7836
7837 // Initial map for the builtin Array function should be a map.
7838 __ mov(ecx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset));
7839 // Will both indicate a NULL and a Smi.
7840 __ test(ecx, Immediate(kSmiTagMask));
7841 __ Assert(not_zero, "Unexpected initial map for Array function");
7842 __ CmpObjectType(ecx, MAP_TYPE, ecx);
7843 __ Assert(equal, "Unexpected initial map for Array function");
7844
7845 // We should either have undefined in ebx or a valid jsglobalpropertycell
7846 Label okay_here;
7847 Handle<Map> global_property_cell_map(
7848 masm->isolate()->heap()->global_property_cell_map());
7849 __ cmp(ebx, Immediate(undefined_sentinel));
7850 __ j(equal, &okay_here);
7851 __ cmp(FieldOperand(ebx, 0), Immediate(global_property_cell_map));
7852 __ Assert(equal, "Expected property cell in register ebx");
7853 __ bind(&okay_here);
7854 }
7855
7856 if (FLAG_optimize_constructed_arrays) {
7857 Label no_info, switch_ready;
7858 // Get the elements kind and case on that.
7859 __ cmp(ebx, Immediate(undefined_sentinel));
7860 __ j(equal, &no_info);
7861 __ mov(edx, FieldOperand(ebx, kPointerSize));
7862
7863 // There is no info if the call site went megamorphic either
7864
7865 // TODO(mvstanton): Really? I thought if it was the array function that
7866 // the cell wouldn't get stamped as megamorphic.
7867 __ cmp(edx, Immediate(TypeFeedbackCells::MegamorphicSentinel(
7868 masm->isolate())));
7869 __ j(equal, &no_info);
7870 __ SmiUntag(edx);
7871 __ jmp(&switch_ready);
7872 __ bind(&no_info);
7873 __ mov(edx, Immediate(GetInitialFastElementsKind()));
7874 __ bind(&switch_ready);
7875
7876 if (argument_count_ == ANY) {
7877 Label not_zero_case, not_one_case;
7878 __ test(eax, eax);
7879 __ j(not_zero, &not_zero_case);
7880 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm);
7881
7882 __ bind(&not_zero_case);
7883 __ cmp(eax, 1);
7884 __ j(greater, &not_one_case);
7885 CreateArrayDispatchOneArgument(masm);
7886
7887 __ bind(&not_one_case);
7888 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm);
7889 } else if (argument_count_ == NONE) {
7890 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm);
7891 } else if (argument_count_ == ONE) {
7892 CreateArrayDispatchOneArgument(masm);
7893 } else if (argument_count_ == MORE_THAN_ONE) {
7894 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm);
7895 } else {
7896 UNREACHABLE();
7897 }
7898 } else {
7899 Label generic_constructor;
7900 // Run the native code for the Array function called as constructor.
7901 ArrayNativeCode(masm, true, &generic_constructor);
7902
7903 // Jump to the generic construct code in case the specialized code cannot
7904 // handle the construction.
7905 __ bind(&generic_constructor);
7906 Handle<Code> generic_construct_stub =
7907 masm->isolate()->builtins()->JSConstructStubGeneric();
7908 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET);
7909 }
7910 }
7911
7912
7714 #undef __ 7913 #undef __
7715 7914
7716 } } // namespace v8::internal 7915 } } // namespace v8::internal
7717 7916
7718 #endif // V8_TARGET_ARCH_IA32 7917 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/code-stubs-ia32.h ('k') | src/ia32/lithium-codegen-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698