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

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

Powered by Google App Engine
This is Rietveld 408576698