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 6950 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6961 __ mov(sp, s5); | 6961 __ mov(sp, s5); |
6962 } | 6962 } |
6963 | 6963 |
6964 // Also pop ra to get Ret(0). | 6964 // Also pop ra to get Ret(0). |
6965 __ MultiPop(kSavedRegs | ra.bit()); | 6965 __ MultiPop(kSavedRegs | ra.bit()); |
6966 __ Ret(); | 6966 __ Ret(); |
6967 } | 6967 } |
6968 | 6968 |
6969 | 6969 |
6970 template<class T> | 6970 template<class T> |
6971 static void CreateArrayDispatch(MacroAssembler* masm) { | 6971 static void CreateArrayDispatch(MacroAssembler* masm, |
6972 int last_index = GetSequenceIndexFromFastElementsKind( | 6972 AllocationSiteOverrideMode mode) { |
6973 TERMINAL_FAST_ELEMENTS_KIND); | 6973 if (mode == DISABLE_ALLOCATION_SITES) { |
6974 for (int i = 0; i <= last_index; ++i) { | 6974 T stub(GetInitialFastElementsKind(), |
6975 Label next; | 6975 CONTEXT_CHECK_REQUIRED, |
6976 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); | 6976 mode); |
6977 __ Branch(&next, ne, a3, Operand(kind)); | |
6978 T stub(kind); | |
6979 __ TailCallStub(&stub); | 6977 __ TailCallStub(&stub); |
6980 __ bind(&next); | 6978 } else if (mode == DONT_OVERRIDE) { |
| 6979 int last_index = GetSequenceIndexFromFastElementsKind( |
| 6980 TERMINAL_FAST_ELEMENTS_KIND); |
| 6981 for (int i = 0; i <= last_index; ++i) { |
| 6982 Label next; |
| 6983 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); |
| 6984 __ Branch(&next, ne, a3, Operand(kind)); |
| 6985 T stub(kind); |
| 6986 __ TailCallStub(&stub); |
| 6987 __ bind(&next); |
| 6988 } |
| 6989 |
| 6990 // If we reached this point there is a problem. |
| 6991 __ Abort(kUnexpectedElementsKindInArrayConstructor); |
| 6992 } else { |
| 6993 UNREACHABLE(); |
6981 } | 6994 } |
6982 | |
6983 // If we reached this point there is a problem. | |
6984 __ Abort(kUnexpectedElementsKindInArrayConstructor); | |
6985 } | 6995 } |
6986 | 6996 |
6987 | 6997 |
6988 static void CreateArrayDispatchOneArgument(MacroAssembler* masm) { | 6998 static void CreateArrayDispatchOneArgument(MacroAssembler* masm, |
6989 // a2 - type info cell | 6999 AllocationSiteOverrideMode mode) { |
6990 // a3 - kind | 7000 // a2 - type info cell (if mode != DISABLE_ALLOCATION_SITES) |
| 7001 // a3 - kind (if mode != DISABLE_ALLOCATION_SITES) |
6991 // a0 - number of arguments | 7002 // a0 - number of arguments |
6992 // a1 - constructor? | 7003 // a1 - constructor? |
6993 // sp[0] - last argument | 7004 // sp[0] - last argument |
6994 ASSERT(FAST_SMI_ELEMENTS == 0); | 7005 Label normal_sequence; |
6995 ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); | 7006 if (mode == DONT_OVERRIDE) { |
6996 ASSERT(FAST_ELEMENTS == 2); | 7007 ASSERT(FAST_SMI_ELEMENTS == 0); |
6997 ASSERT(FAST_HOLEY_ELEMENTS == 3); | 7008 ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); |
6998 ASSERT(FAST_DOUBLE_ELEMENTS == 4); | 7009 ASSERT(FAST_ELEMENTS == 2); |
6999 ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == 5); | 7010 ASSERT(FAST_HOLEY_ELEMENTS == 3); |
| 7011 ASSERT(FAST_DOUBLE_ELEMENTS == 4); |
| 7012 ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == 5); |
7000 | 7013 |
7001 // is the low bit set? If so, we are holey and that is good. | 7014 // is the low bit set? If so, we are holey and that is good. |
7002 Label normal_sequence; | 7015 __ And(at, a3, Operand(1)); |
7003 __ And(at, a3, Operand(1)); | 7016 __ Branch(&normal_sequence, ne, at, Operand(zero_reg)); |
7004 __ Branch(&normal_sequence, ne, at, Operand(zero_reg)); | 7017 } |
7005 | 7018 |
7006 // look at the first argument | 7019 // look at the first argument |
7007 __ lw(t1, MemOperand(sp, 0)); | 7020 __ lw(t1, MemOperand(sp, 0)); |
7008 __ Branch(&normal_sequence, eq, t1, Operand(zero_reg)); | 7021 __ Branch(&normal_sequence, eq, t1, Operand(zero_reg)); |
7009 | 7022 |
7010 // We are going to create a holey array, but our kind is non-holey. | 7023 if (mode == DISABLE_ALLOCATION_SITES) { |
7011 // Fix kind and retry (only if we have an allocation site in the cell). | 7024 ElementsKind initial = GetInitialFastElementsKind(); |
7012 __ Addu(a3, a3, Operand(1)); | 7025 ElementsKind holey_initial = GetHoleyElementsKind(initial); |
7013 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); | |
7014 __ Branch(&normal_sequence, eq, a2, Operand(at)); | |
7015 __ lw(t1, FieldMemOperand(a2, Cell::kValueOffset)); | |
7016 __ lw(t1, FieldMemOperand(t1, 0)); | |
7017 __ LoadRoot(at, Heap::kAllocationSiteMapRootIndex); | |
7018 __ Branch(&normal_sequence, ne, t1, Operand(at)); | |
7019 | 7026 |
7020 // Save the resulting elements kind in type info | 7027 ArraySingleArgumentConstructorStub stub_holey(holey_initial, |
7021 __ SmiTag(a3); | 7028 CONTEXT_CHECK_REQUIRED, |
7022 __ lw(t1, FieldMemOperand(a2, Cell::kValueOffset)); | 7029 DISABLE_ALLOCATION_SITES); |
7023 __ sw(a3, FieldMemOperand(t1, AllocationSite::kTransitionInfoOffset)); | 7030 __ TailCallStub(&stub_holey); |
7024 __ SmiUntag(a3); | |
7025 | 7031 |
7026 __ bind(&normal_sequence); | 7032 __ bind(&normal_sequence); |
7027 int last_index = GetSequenceIndexFromFastElementsKind( | 7033 ArraySingleArgumentConstructorStub stub(initial, |
7028 TERMINAL_FAST_ELEMENTS_KIND); | 7034 CONTEXT_CHECK_REQUIRED, |
7029 for (int i = 0; i <= last_index; ++i) { | 7035 DISABLE_ALLOCATION_SITES); |
7030 Label next; | |
7031 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); | |
7032 __ Branch(&next, ne, a3, Operand(kind)); | |
7033 ArraySingleArgumentConstructorStub stub(kind); | |
7034 __ TailCallStub(&stub); | 7036 __ TailCallStub(&stub); |
7035 __ bind(&next); | 7037 } else if (mode == DONT_OVERRIDE) { |
| 7038 // We are going to create a holey array, but our kind is non-holey. |
| 7039 // Fix kind and retry (only if we have an allocation site in the cell). |
| 7040 __ Addu(a3, a3, Operand(1)); |
| 7041 __ lw(t1, FieldMemOperand(a2, Cell::kValueOffset)); |
| 7042 |
| 7043 if (FLAG_debug_code) { |
| 7044 __ lw(t1, FieldMemOperand(t1, 0)); |
| 7045 __ LoadRoot(at, Heap::kAllocationSiteMapRootIndex); |
| 7046 __ Assert(eq, kExpectedAllocationSiteInCell, t1, Operand(at)); |
| 7047 __ lw(t1, FieldMemOperand(a2, Cell::kValueOffset)); |
| 7048 } |
| 7049 |
| 7050 // Save the resulting elements kind in type info |
| 7051 __ SmiTag(a3); |
| 7052 __ lw(t1, FieldMemOperand(a2, Cell::kValueOffset)); |
| 7053 __ sw(a3, FieldMemOperand(t1, AllocationSite::kTransitionInfoOffset)); |
| 7054 __ SmiUntag(a3); |
| 7055 |
| 7056 __ bind(&normal_sequence); |
| 7057 int last_index = GetSequenceIndexFromFastElementsKind( |
| 7058 TERMINAL_FAST_ELEMENTS_KIND); |
| 7059 for (int i = 0; i <= last_index; ++i) { |
| 7060 Label next; |
| 7061 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); |
| 7062 __ Branch(&next, ne, a3, Operand(kind)); |
| 7063 ArraySingleArgumentConstructorStub stub(kind); |
| 7064 __ TailCallStub(&stub); |
| 7065 __ bind(&next); |
| 7066 } |
| 7067 |
| 7068 // If we reached this point there is a problem. |
| 7069 __ Abort(kUnexpectedElementsKindInArrayConstructor); |
| 7070 } else { |
| 7071 UNREACHABLE(); |
7036 } | 7072 } |
7037 | |
7038 // If we reached this point there is a problem. | |
7039 __ Abort(kUnexpectedElementsKindInArrayConstructor); | |
7040 } | 7073 } |
7041 | 7074 |
7042 | 7075 |
7043 template<class T> | 7076 template<class T> |
7044 static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) { | 7077 static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) { |
| 7078 ElementsKind initial_kind = GetInitialFastElementsKind(); |
| 7079 ElementsKind initial_holey_kind = GetHoleyElementsKind(initial_kind); |
| 7080 |
7045 int to_index = GetSequenceIndexFromFastElementsKind( | 7081 int to_index = GetSequenceIndexFromFastElementsKind( |
7046 TERMINAL_FAST_ELEMENTS_KIND); | 7082 TERMINAL_FAST_ELEMENTS_KIND); |
7047 for (int i = 0; i <= to_index; ++i) { | 7083 for (int i = 0; i <= to_index; ++i) { |
7048 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); | 7084 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); |
7049 T stub(kind); | 7085 T stub(kind); |
7050 stub.GetCode(isolate)->set_is_pregenerated(true); | 7086 stub.GetCode(isolate)->set_is_pregenerated(true); |
7051 if (AllocationSite::GetMode(kind) != DONT_TRACK_ALLOCATION_SITE) { | 7087 if (AllocationSite::GetMode(kind) != DONT_TRACK_ALLOCATION_SITE || |
| 7088 (!FLAG_track_allocation_sites && |
| 7089 (kind == initial_kind || kind == initial_holey_kind))) { |
7052 T stub1(kind, CONTEXT_CHECK_REQUIRED, DISABLE_ALLOCATION_SITES); | 7090 T stub1(kind, CONTEXT_CHECK_REQUIRED, DISABLE_ALLOCATION_SITES); |
7053 stub1.GetCode(isolate)->set_is_pregenerated(true); | 7091 stub1.GetCode(isolate)->set_is_pregenerated(true); |
7054 } | 7092 } |
7055 } | 7093 } |
7056 } | 7094 } |
7057 | 7095 |
7058 | 7096 |
7059 void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) { | 7097 void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) { |
7060 ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>( | 7098 ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>( |
7061 isolate); | 7099 isolate); |
(...skipping 12 matching lines...) Expand all Loading... |
7074 InternalArrayNoArgumentConstructorStub stubh1(kinds[i]); | 7112 InternalArrayNoArgumentConstructorStub stubh1(kinds[i]); |
7075 stubh1.GetCode(isolate)->set_is_pregenerated(true); | 7113 stubh1.GetCode(isolate)->set_is_pregenerated(true); |
7076 InternalArraySingleArgumentConstructorStub stubh2(kinds[i]); | 7114 InternalArraySingleArgumentConstructorStub stubh2(kinds[i]); |
7077 stubh2.GetCode(isolate)->set_is_pregenerated(true); | 7115 stubh2.GetCode(isolate)->set_is_pregenerated(true); |
7078 InternalArrayNArgumentsConstructorStub stubh3(kinds[i]); | 7116 InternalArrayNArgumentsConstructorStub stubh3(kinds[i]); |
7079 stubh3.GetCode(isolate)->set_is_pregenerated(true); | 7117 stubh3.GetCode(isolate)->set_is_pregenerated(true); |
7080 } | 7118 } |
7081 } | 7119 } |
7082 | 7120 |
7083 | 7121 |
| 7122 void ArrayConstructorStub::GenerateDispatchToArrayStub( |
| 7123 MacroAssembler* masm, |
| 7124 AllocationSiteOverrideMode mode) { |
| 7125 if (argument_count_ == ANY) { |
| 7126 Label not_zero_case, not_one_case; |
| 7127 __ And(at, a0, a0); |
| 7128 __ Branch(¬_zero_case, ne, at, Operand(zero_reg)); |
| 7129 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); |
| 7130 |
| 7131 __ bind(¬_zero_case); |
| 7132 __ Branch(¬_one_case, gt, a0, Operand(1)); |
| 7133 CreateArrayDispatchOneArgument(masm, mode); |
| 7134 |
| 7135 __ bind(¬_one_case); |
| 7136 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); |
| 7137 } else if (argument_count_ == NONE) { |
| 7138 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); |
| 7139 } else if (argument_count_ == ONE) { |
| 7140 CreateArrayDispatchOneArgument(masm, mode); |
| 7141 } else if (argument_count_ == MORE_THAN_ONE) { |
| 7142 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); |
| 7143 } else { |
| 7144 UNREACHABLE(); |
| 7145 } |
| 7146 } |
| 7147 |
| 7148 |
7084 void ArrayConstructorStub::Generate(MacroAssembler* masm) { | 7149 void ArrayConstructorStub::Generate(MacroAssembler* masm) { |
7085 // ----------- S t a t e ------------- | 7150 // ----------- S t a t e ------------- |
7086 // -- a0 : argc (only if argument_count_ == ANY) | 7151 // -- a0 : argc (only if argument_count_ == ANY) |
7087 // -- a1 : constructor | 7152 // -- a1 : constructor |
7088 // -- a2 : type info cell | 7153 // -- a2 : type info cell |
7089 // -- sp[0] : return address | 7154 // -- sp[0] : return address |
7090 // -- sp[4] : last argument | 7155 // -- sp[4] : last argument |
7091 // ----------------------------------- | 7156 // ----------------------------------- |
7092 if (FLAG_debug_code) { | 7157 if (FLAG_debug_code) { |
7093 // The array construct code is only set for the global and natives | 7158 // The array construct code is only set for the global and natives |
(...skipping 13 matching lines...) Expand all Loading... |
7107 Label okay_here; | 7172 Label okay_here; |
7108 Handle<Map> cell_map = masm->isolate()->factory()->cell_map(); | 7173 Handle<Map> cell_map = masm->isolate()->factory()->cell_map(); |
7109 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); | 7174 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); |
7110 __ Branch(&okay_here, eq, a2, Operand(at)); | 7175 __ Branch(&okay_here, eq, a2, Operand(at)); |
7111 __ lw(a3, FieldMemOperand(a2, 0)); | 7176 __ lw(a3, FieldMemOperand(a2, 0)); |
7112 __ Assert(eq, kExpectedPropertyCellInRegisterA2, | 7177 __ Assert(eq, kExpectedPropertyCellInRegisterA2, |
7113 a3, Operand(cell_map)); | 7178 a3, Operand(cell_map)); |
7114 __ bind(&okay_here); | 7179 __ bind(&okay_here); |
7115 } | 7180 } |
7116 | 7181 |
7117 Label no_info, switch_ready; | 7182 Label no_info; |
7118 // Get the elements kind and case on that. | 7183 // Get the elements kind and case on that. |
7119 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); | 7184 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); |
7120 __ Branch(&no_info, eq, a2, Operand(at)); | 7185 __ Branch(&no_info, eq, a2, Operand(at)); |
7121 __ lw(a3, FieldMemOperand(a2, Cell::kValueOffset)); | 7186 __ lw(a3, FieldMemOperand(a2, Cell::kValueOffset)); |
7122 | 7187 |
7123 // The type cell may have undefined in its value. | 7188 // If the type cell is undefined, or contains anything other than an |
7124 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); | 7189 // AllocationSite, call an array constructor that doesn't use AllocationSites. |
7125 __ Branch(&no_info, eq, a3, Operand(at)); | |
7126 | |
7127 // The type cell has either an AllocationSite or a JSFunction. | |
7128 __ lw(t0, FieldMemOperand(a3, 0)); | 7190 __ lw(t0, FieldMemOperand(a3, 0)); |
7129 __ LoadRoot(at, Heap::kAllocationSiteMapRootIndex); | 7191 __ LoadRoot(at, Heap::kAllocationSiteMapRootIndex); |
7130 __ Branch(&no_info, ne, t0, Operand(at)); | 7192 __ Branch(&no_info, ne, t0, Operand(at)); |
7131 | 7193 |
7132 __ lw(a3, FieldMemOperand(a3, AllocationSite::kTransitionInfoOffset)); | 7194 __ lw(a3, FieldMemOperand(a3, AllocationSite::kTransitionInfoOffset)); |
7133 __ SmiUntag(a3); | 7195 __ SmiUntag(a3); |
7134 __ jmp(&switch_ready); | 7196 GenerateDispatchToArrayStub(masm, DONT_OVERRIDE); |
| 7197 |
7135 __ bind(&no_info); | 7198 __ bind(&no_info); |
7136 __ li(a3, Operand(GetInitialFastElementsKind())); | 7199 GenerateDispatchToArrayStub(masm, DISABLE_ALLOCATION_SITES); |
7137 __ bind(&switch_ready); | |
7138 | |
7139 if (argument_count_ == ANY) { | |
7140 Label not_zero_case, not_one_case; | |
7141 __ And(at, a0, a0); | |
7142 __ Branch(¬_zero_case, ne, at, Operand(zero_reg)); | |
7143 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm); | |
7144 | |
7145 __ bind(¬_zero_case); | |
7146 __ Branch(¬_one_case, gt, a0, Operand(1)); | |
7147 CreateArrayDispatchOneArgument(masm); | |
7148 | |
7149 __ bind(¬_one_case); | |
7150 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm); | |
7151 } else if (argument_count_ == NONE) { | |
7152 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm); | |
7153 } else if (argument_count_ == ONE) { | |
7154 CreateArrayDispatchOneArgument(masm); | |
7155 } else if (argument_count_ == MORE_THAN_ONE) { | |
7156 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm); | |
7157 } else { | |
7158 UNREACHABLE(); | |
7159 } | |
7160 } | 7200 } |
7161 | 7201 |
7162 | 7202 |
7163 void InternalArrayConstructorStub::GenerateCase( | 7203 void InternalArrayConstructorStub::GenerateCase( |
7164 MacroAssembler* masm, ElementsKind kind) { | 7204 MacroAssembler* masm, ElementsKind kind) { |
7165 Label not_zero_case, not_one_case; | 7205 Label not_zero_case, not_one_case; |
7166 Label normal_sequence; | 7206 Label normal_sequence; |
7167 | 7207 |
7168 __ Branch(¬_zero_case, ne, a0, Operand(zero_reg)); | 7208 __ Branch(¬_zero_case, ne, a0, Operand(zero_reg)); |
7169 InternalArrayNoArgumentConstructorStub stub0(kind); | 7209 InternalArrayNoArgumentConstructorStub stub0(kind); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7241 __ bind(&fast_elements_case); | 7281 __ bind(&fast_elements_case); |
7242 GenerateCase(masm, FAST_ELEMENTS); | 7282 GenerateCase(masm, FAST_ELEMENTS); |
7243 } | 7283 } |
7244 | 7284 |
7245 | 7285 |
7246 #undef __ | 7286 #undef __ |
7247 | 7287 |
7248 } } // namespace v8::internal | 7288 } } // namespace v8::internal |
7249 | 7289 |
7250 #endif // V8_TARGET_ARCH_MIPS | 7290 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |