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

Powered by Google App Engine
This is Rietveld 408576698