| 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 |