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

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

Powered by Google App Engine
This is Rietveld 408576698