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 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
103 static Register registers[] = { a0 }; | 103 static Register registers[] = { a0 }; |
104 descriptor->register_param_count_ = 1; | 104 descriptor->register_param_count_ = 1; |
105 descriptor->register_params_ = registers; | 105 descriptor->register_params_ = registers; |
106 descriptor->deoptimization_handler_ = | 106 descriptor->deoptimization_handler_ = |
107 FUNCTION_ADDR(CompareNilIC_Miss); | 107 FUNCTION_ADDR(CompareNilIC_Miss); |
108 descriptor->miss_handler_ = | 108 descriptor->miss_handler_ = |
109 ExternalReference(IC_Utility(IC::kCompareNilIC_Miss), isolate); | 109 ExternalReference(IC_Utility(IC::kCompareNilIC_Miss), isolate); |
110 } | 110 } |
111 | 111 |
112 | 112 |
113 static void InitializeArrayConstructorDescriptor(Isolate* isolate, | 113 static void InitializeArrayConstructorDescriptor( |
114 CodeStubInterfaceDescriptor* descriptor) { | 114 Isolate* isolate, |
| 115 CodeStubInterfaceDescriptor* descriptor, |
| 116 int constant_stack_parameter_count) { |
115 // register state | 117 // register state |
116 // a1 -- constructor function | 118 // a0 -- number of arguments |
117 // a2 -- type info cell with elements kind | 119 // a2 -- type info cell with elements kind |
118 // a0 -- number of arguments to the constructor function | 120 static Register registers[] = { a2 }; |
119 static Register registers[] = { a1, a2 }; | 121 descriptor->register_param_count_ = 1; |
120 descriptor->register_param_count_ = 2; | 122 if (constant_stack_parameter_count != 0) { |
121 // stack param count needs (constructor pointer, and single argument) | 123 // stack param count needs (constructor pointer, and single argument) |
122 descriptor->stack_parameter_count_ = &a0; | 124 descriptor->stack_parameter_count_ = &a0; |
| 125 } |
| 126 descriptor->hint_stack_parameter_count_ = constant_stack_parameter_count; |
123 descriptor->register_params_ = registers; | 127 descriptor->register_params_ = registers; |
124 descriptor->function_mode_ = JS_FUNCTION_STUB_MODE; | 128 descriptor->function_mode_ = JS_FUNCTION_STUB_MODE; |
125 descriptor->deoptimization_handler_ = | 129 descriptor->deoptimization_handler_ = |
126 FUNCTION_ADDR(ArrayConstructor_StubFailure); | 130 FUNCTION_ADDR(ArrayConstructor_StubFailure); |
127 } | 131 } |
128 | 132 |
129 | 133 |
130 void ArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor( | 134 void ArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor( |
131 Isolate* isolate, | 135 Isolate* isolate, |
132 CodeStubInterfaceDescriptor* descriptor) { | 136 CodeStubInterfaceDescriptor* descriptor) { |
133 InitializeArrayConstructorDescriptor(isolate, descriptor); | 137 InitializeArrayConstructorDescriptor(isolate, descriptor, 0); |
134 } | 138 } |
135 | 139 |
136 | 140 |
137 void ArraySingleArgumentConstructorStub::InitializeInterfaceDescriptor( | 141 void ArraySingleArgumentConstructorStub::InitializeInterfaceDescriptor( |
138 Isolate* isolate, | 142 Isolate* isolate, |
139 CodeStubInterfaceDescriptor* descriptor) { | 143 CodeStubInterfaceDescriptor* descriptor) { |
140 InitializeArrayConstructorDescriptor(isolate, descriptor); | 144 InitializeArrayConstructorDescriptor(isolate, descriptor, 1); |
141 } | 145 } |
142 | 146 |
143 | 147 |
144 void ArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor( | 148 void ArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor( |
145 Isolate* isolate, | 149 Isolate* isolate, |
146 CodeStubInterfaceDescriptor* descriptor) { | 150 CodeStubInterfaceDescriptor* descriptor) { |
147 InitializeArrayConstructorDescriptor(isolate, descriptor); | 151 InitializeArrayConstructorDescriptor(isolate, descriptor, -1); |
148 } | 152 } |
149 | 153 |
150 | 154 |
151 #define __ ACCESS_MASM(masm) | 155 #define __ ACCESS_MASM(masm) |
152 | 156 |
153 static void EmitIdenticalObjectComparison(MacroAssembler* masm, | 157 static void EmitIdenticalObjectComparison(MacroAssembler* masm, |
154 Label* slow, | 158 Label* slow, |
155 Condition cc); | 159 Condition cc); |
156 static void EmitSmiNonsmiComparison(MacroAssembler* masm, | 160 static void EmitSmiNonsmiComparison(MacroAssembler* masm, |
157 Register lhs, | 161 Register lhs, |
(...skipping 3177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3335 result_size_ == 1; | 3339 result_size_ == 1; |
3336 } | 3340 } |
3337 | 3341 |
3338 | 3342 |
3339 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { | 3343 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { |
3340 CEntryStub::GenerateAheadOfTime(isolate); | 3344 CEntryStub::GenerateAheadOfTime(isolate); |
3341 WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime(isolate); | 3345 WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime(isolate); |
3342 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); | 3346 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); |
3343 StubFailureTrampolineStub::GenerateAheadOfTime(isolate); | 3347 StubFailureTrampolineStub::GenerateAheadOfTime(isolate); |
3344 RecordWriteStub::GenerateFixedRegStubsAheadOfTime(isolate); | 3348 RecordWriteStub::GenerateFixedRegStubsAheadOfTime(isolate); |
| 3349 if (FLAG_optimize_constructed_arrays) { |
| 3350 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate); |
| 3351 } |
3345 } | 3352 } |
3346 | 3353 |
3347 | 3354 |
3348 void CodeStub::GenerateFPStubs(Isolate* isolate) { | 3355 void CodeStub::GenerateFPStubs(Isolate* isolate) { |
3349 SaveFPRegsMode mode = kSaveFPRegs; | 3356 SaveFPRegsMode mode = kSaveFPRegs; |
3350 CEntryStub save_doubles(1, mode); | 3357 CEntryStub save_doubles(1, mode); |
3351 StoreBufferOverflowStub stub(mode); | 3358 StoreBufferOverflowStub stub(mode); |
3352 // These stubs might already be in the snapshot, detect that and don't | 3359 // These stubs might already be in the snapshot, detect that and don't |
3353 // regenerate, which would lead to code stub initialization state being messed | 3360 // regenerate, which would lead to code stub initialization state being messed |
3354 // up. | 3361 // up. |
(...skipping 1734 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5089 __ Branch(&done, eq, a3, Operand(a1)); | 5096 __ Branch(&done, eq, a3, Operand(a1)); |
5090 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); | 5097 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); |
5091 __ Branch(&done, eq, a3, Operand(at)); | 5098 __ Branch(&done, eq, a3, Operand(at)); |
5092 | 5099 |
5093 // Special handling of the Array() function, which caches not only the | 5100 // Special handling of the Array() function, which caches not only the |
5094 // monomorphic Array function but the initial ElementsKind with special | 5101 // monomorphic Array function but the initial ElementsKind with special |
5095 // sentinels | 5102 // sentinels |
5096 Handle<Object> terminal_kind_sentinel = | 5103 Handle<Object> terminal_kind_sentinel = |
5097 TypeFeedbackCells::MonomorphicArraySentinel(masm->isolate(), | 5104 TypeFeedbackCells::MonomorphicArraySentinel(masm->isolate(), |
5098 LAST_FAST_ELEMENTS_KIND); | 5105 LAST_FAST_ELEMENTS_KIND); |
5099 __ Branch(&miss, ne, a3, Operand(terminal_kind_sentinel)); | 5106 __ Branch(&miss, gt, a3, Operand(terminal_kind_sentinel)); |
5100 // Make sure the function is the Array() function | 5107 // Make sure the function is the Array() function |
5101 __ LoadArrayFunction(a3); | 5108 __ LoadArrayFunction(a3); |
5102 __ Branch(&megamorphic, ne, a1, Operand(a3)); | 5109 __ Branch(&megamorphic, ne, a1, Operand(a3)); |
5103 __ jmp(&done); | 5110 __ jmp(&done); |
5104 | 5111 |
5105 __ bind(&miss); | 5112 __ bind(&miss); |
5106 | 5113 |
5107 // A monomorphic miss (i.e, here the cache is not uninitialized) goes | 5114 // A monomorphic miss (i.e, here the cache is not uninitialized) goes |
5108 // megamorphic. | 5115 // megamorphic. |
5109 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 5116 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
(...skipping 2445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7555 // Restore the stack pointer if needed. | 7562 // Restore the stack pointer if needed. |
7556 if (frame_alignment > kPointerSize) { | 7563 if (frame_alignment > kPointerSize) { |
7557 __ mov(sp, t1); | 7564 __ mov(sp, t1); |
7558 } | 7565 } |
7559 | 7566 |
7560 __ Pop(ra, t1, a1); | 7567 __ Pop(ra, t1, a1); |
7561 __ Ret(); | 7568 __ Ret(); |
7562 } | 7569 } |
7563 | 7570 |
7564 | 7571 |
| 7572 template<class T> |
| 7573 static void CreateArrayDispatch(MacroAssembler* masm) { |
| 7574 int last_index = GetSequenceIndexFromFastElementsKind( |
| 7575 TERMINAL_FAST_ELEMENTS_KIND); |
| 7576 for (int i = 0; i <= last_index; ++i) { |
| 7577 Label next; |
| 7578 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); |
| 7579 __ Branch(&next, ne, a3, Operand(kind)); |
| 7580 T stub(kind); |
| 7581 __ TailCallStub(&stub); |
| 7582 __ bind(&next); |
| 7583 } |
| 7584 |
| 7585 // If we reached this point there is a problem. |
| 7586 __ Abort("Unexpected ElementsKind in array constructor"); |
| 7587 } |
| 7588 |
| 7589 |
| 7590 static void CreateArrayDispatchOneArgument(MacroAssembler* masm) { |
| 7591 // a2 - type info cell |
| 7592 // a3 - kind |
| 7593 // a0 - number of arguments |
| 7594 // a1 - constructor? |
| 7595 // sp[0] - last argument |
| 7596 ASSERT(FAST_SMI_ELEMENTS == 0); |
| 7597 ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); |
| 7598 ASSERT(FAST_ELEMENTS == 2); |
| 7599 ASSERT(FAST_HOLEY_ELEMENTS == 3); |
| 7600 ASSERT(FAST_DOUBLE_ELEMENTS == 4); |
| 7601 ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == 5); |
| 7602 |
| 7603 Handle<Object> undefined_sentinel( |
| 7604 masm->isolate()->heap()->undefined_value(), |
| 7605 masm->isolate()); |
| 7606 |
| 7607 // is the low bit set? If so, we are holey and that is good. |
| 7608 Label normal_sequence; |
| 7609 __ And(at, a3, Operand(1)); |
| 7610 __ Branch(&normal_sequence, ne, at, Operand(zero_reg)); |
| 7611 |
| 7612 // look at the first argument |
| 7613 __ lw(t1, MemOperand(sp, 0)); |
| 7614 __ Branch(&normal_sequence, eq, t1, Operand(zero_reg)); |
| 7615 |
| 7616 // We are going to create a holey array, but our kind is non-holey. |
| 7617 // Fix kind and retry |
| 7618 __ Addu(a3, a3, Operand(1)); |
| 7619 __ Branch(&normal_sequence, eq, a2, Operand(undefined_sentinel)); |
| 7620 |
| 7621 // Save the resulting elements kind in type info |
| 7622 __ SmiTag(a3); |
| 7623 __ sw(a3, FieldMemOperand(a2, kPointerSize)); |
| 7624 __ SmiUntag(a3); |
| 7625 |
| 7626 __ bind(&normal_sequence); |
| 7627 int last_index = GetSequenceIndexFromFastElementsKind( |
| 7628 TERMINAL_FAST_ELEMENTS_KIND); |
| 7629 for (int i = 0; i <= last_index; ++i) { |
| 7630 Label next; |
| 7631 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); |
| 7632 __ Branch(&next, ne, a3, Operand(kind)); |
| 7633 ArraySingleArgumentConstructorStub stub(kind); |
| 7634 __ TailCallStub(&stub); |
| 7635 __ bind(&next); |
| 7636 } |
| 7637 |
| 7638 // If we reached this point there is a problem. |
| 7639 __ Abort("Unexpected ElementsKind in array constructor"); |
| 7640 } |
| 7641 |
| 7642 |
| 7643 template<class T> |
| 7644 static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) { |
| 7645 int to_index = GetSequenceIndexFromFastElementsKind( |
| 7646 TERMINAL_FAST_ELEMENTS_KIND); |
| 7647 for (int i = 0; i <= to_index; ++i) { |
| 7648 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); |
| 7649 T stub(kind); |
| 7650 stub.GetCode(isolate)->set_is_pregenerated(true); |
| 7651 } |
| 7652 } |
| 7653 |
| 7654 |
| 7655 void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) { |
| 7656 ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>( |
| 7657 isolate); |
| 7658 ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>( |
| 7659 isolate); |
| 7660 ArrayConstructorStubAheadOfTimeHelper<ArrayNArgumentsConstructorStub>( |
| 7661 isolate); |
| 7662 } |
| 7663 |
| 7664 |
| 7665 void ArrayConstructorStub::Generate(MacroAssembler* masm) { |
| 7666 // ----------- S t a t e ------------- |
| 7667 // -- a0 : argc (only if argument_count_ == ANY) |
| 7668 // -- a1 : constructor |
| 7669 // -- a2 : type info cell |
| 7670 // -- sp[0] : return address |
| 7671 // -- sp[4] : last argument |
| 7672 // ----------------------------------- |
| 7673 Handle<Object> undefined_sentinel( |
| 7674 masm->isolate()->heap()->undefined_value(), |
| 7675 masm->isolate()); |
| 7676 |
| 7677 if (FLAG_debug_code) { |
| 7678 // The array construct code is only set for the global and natives |
| 7679 // builtin Array functions which always have maps. |
| 7680 |
| 7681 // Initial map for the builtin Array function should be a map. |
| 7682 __ lw(a3, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset)); |
| 7683 // Will both indicate a NULL and a Smi. |
| 7684 __ And(at, a3, Operand(kSmiTagMask)); |
| 7685 __ Assert(ne, "Unexpected initial map for Array function", |
| 7686 at, Operand(zero_reg)); |
| 7687 __ GetObjectType(a3, a3, t0); |
| 7688 __ Assert(eq, "Unexpected initial map for Array function", |
| 7689 t0, Operand(MAP_TYPE)); |
| 7690 |
| 7691 // We should either have undefined in ebx or a valid jsglobalpropertycell |
| 7692 Label okay_here; |
| 7693 Handle<Map> global_property_cell_map( |
| 7694 masm->isolate()->heap()->global_property_cell_map()); |
| 7695 __ Branch(&okay_here, eq, a2, Operand(undefined_sentinel)); |
| 7696 __ lw(a3, FieldMemOperand(a2, 0)); |
| 7697 __ Assert(eq, "Expected property cell in register ebx", |
| 7698 a3, Operand(global_property_cell_map)); |
| 7699 __ bind(&okay_here); |
| 7700 } |
| 7701 |
| 7702 if (FLAG_optimize_constructed_arrays) { |
| 7703 Label no_info, switch_ready; |
| 7704 // Get the elements kind and case on that. |
| 7705 __ Branch(&no_info, eq, a2, Operand(undefined_sentinel)); |
| 7706 __ lw(a3, FieldMemOperand(a2, kPointerSize)); |
| 7707 |
| 7708 // There is no info if the call site went megamorphic either |
| 7709 // TODO(mvstanton): Really? I thought if it was the array function that |
| 7710 // the cell wouldn't get stamped as megamorphic. |
| 7711 __ Branch(&no_info, eq, a3, |
| 7712 Operand(TypeFeedbackCells::MegamorphicSentinel(masm->isolate()))); |
| 7713 __ SmiUntag(a3); |
| 7714 __ jmp(&switch_ready); |
| 7715 __ bind(&no_info); |
| 7716 __ li(a3, Operand(GetInitialFastElementsKind())); |
| 7717 __ bind(&switch_ready); |
| 7718 |
| 7719 if (argument_count_ == ANY) { |
| 7720 Label not_zero_case, not_one_case; |
| 7721 __ And(at, a0, a0); |
| 7722 __ Branch(¬_zero_case, ne, at, Operand(zero_reg)); |
| 7723 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm); |
| 7724 |
| 7725 __ bind(¬_zero_case); |
| 7726 __ Branch(¬_one_case, gt, a0, Operand(1)); |
| 7727 CreateArrayDispatchOneArgument(masm); |
| 7728 |
| 7729 __ bind(¬_one_case); |
| 7730 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm); |
| 7731 } else if (argument_count_ == NONE) { |
| 7732 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm); |
| 7733 } else if (argument_count_ == ONE) { |
| 7734 CreateArrayDispatchOneArgument(masm); |
| 7735 } else if (argument_count_ == MORE_THAN_ONE) { |
| 7736 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm); |
| 7737 } else { |
| 7738 UNREACHABLE(); |
| 7739 } |
| 7740 } else { |
| 7741 Label generic_constructor; |
| 7742 // Run the native code for the Array function called as a constructor. |
| 7743 ArrayNativeCode(masm, &generic_constructor); |
| 7744 |
| 7745 // Jump to the generic construct code in case the specialized code cannot |
| 7746 // handle the construction. |
| 7747 __ bind(&generic_constructor); |
| 7748 Handle<Code> generic_construct_stub = |
| 7749 masm->isolate()->builtins()->JSConstructStubGeneric(); |
| 7750 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET); |
| 7751 } |
| 7752 } |
| 7753 |
| 7754 |
7565 #undef __ | 7755 #undef __ |
7566 | 7756 |
7567 } } // namespace v8::internal | 7757 } } // namespace v8::internal |
7568 | 7758 |
7569 #endif // V8_TARGET_ARCH_MIPS | 7759 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |