Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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, ¬_zero_case); | |
| 7863 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm); | |
| 7864 | |
| 7865 __ bind(¬_zero_case); | |
| 7866 __ cmp(eax, 1); | |
| 7867 __ j(greater, ¬_one_case); | |
| 7868 CreateArrayDispatchOneArgument(masm); | |
| 7869 | |
| 7870 __ bind(¬_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 |
| OLD | NEW |