OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #if V8_TARGET_ARCH_MIPS | 5 #if V8_TARGET_ARCH_MIPS |
6 | 6 |
7 #include "src/ic/ic.h" | 7 #include "src/ic/ic.h" |
8 #include "src/ic/ic-compiler.h" | 8 #include "src/ic/ic-compiler.h" |
9 | 9 |
10 namespace v8 { | 10 namespace v8 { |
11 namespace internal { | 11 namespace internal { |
12 | 12 |
13 #define __ ACCESS_MASM(masm()) | |
14 | |
15 | |
16 Handle<Code> PropertyICCompiler::CompilePolymorphic(MapHandleList* maps, | |
17 CodeHandleList* handlers, | |
18 Handle<Name> name, | |
19 Code::StubType type, | |
20 IcCheckType check) { | |
21 Label miss; | |
22 | |
23 if (check == PROPERTY && | |
24 (kind() == Code::KEYED_LOAD_IC || kind() == Code::KEYED_STORE_IC)) { | |
25 // In case we are compiling an IC for dictionary loads or stores, just | |
26 // check whether the name is unique. | |
27 if (name.is_identical_to(isolate()->factory()->normal_ic_symbol())) { | |
28 // Keyed loads with dictionaries shouldn't be here, they go generic. | |
29 // The DCHECK is to protect assumptions when --vector-ics is on. | |
30 DCHECK(kind() != Code::KEYED_LOAD_IC); | |
31 Register tmp = scratch1(); | |
32 __ JumpIfSmi(this->name(), &miss); | |
33 __ lw(tmp, FieldMemOperand(this->name(), HeapObject::kMapOffset)); | |
34 __ lbu(tmp, FieldMemOperand(tmp, Map::kInstanceTypeOffset)); | |
35 __ JumpIfNotUniqueNameInstanceType(tmp, &miss); | |
36 } else { | |
37 __ Branch(&miss, ne, this->name(), Operand(name)); | |
38 } | |
39 } | |
40 | |
41 Label number_case; | |
42 Register match = scratch2(); | |
43 Label* smi_target = IncludesNumberMap(maps) ? &number_case : &miss; | |
44 __ JumpIfSmi(receiver(), smi_target, match); // Reg match is 0 if Smi. | |
45 | |
46 // Polymorphic keyed stores may use the map register | |
47 Register map_reg = scratch1(); | |
48 DCHECK(kind() != Code::KEYED_STORE_IC || | |
49 map_reg.is(StoreTransitionDescriptor::MapRegister())); | |
50 | |
51 int receiver_count = maps->length(); | |
52 int number_of_handled_maps = 0; | |
53 __ lw(map_reg, FieldMemOperand(receiver(), HeapObject::kMapOffset)); | |
54 for (int current = 0; current < receiver_count; ++current) { | |
55 Handle<Map> map = maps->at(current); | |
56 if (!map->is_deprecated()) { | |
57 number_of_handled_maps++; | |
58 // Check map and tail call if there's a match. | |
59 // Separate compare from branch, to provide path for above JumpIfSmi(). | |
60 Handle<WeakCell> cell = Map::WeakCellForMap(map); | |
61 __ GetWeakValue(match, cell); | |
62 __ Subu(match, match, Operand(map_reg)); | |
63 if (map->instance_type() == HEAP_NUMBER_TYPE) { | |
64 DCHECK(!number_case.is_unused()); | |
65 __ bind(&number_case); | |
66 } | |
67 __ Jump(handlers->at(current), RelocInfo::CODE_TARGET, eq, match, | |
68 Operand(zero_reg)); | |
69 } | |
70 } | |
71 DCHECK(number_of_handled_maps != 0); | |
72 | |
73 __ bind(&miss); | |
74 TailCallBuiltin(masm(), MissBuiltin(kind())); | |
75 | |
76 // Return the generated code. | |
77 InlineCacheState state = | |
78 number_of_handled_maps > 1 ? POLYMORPHIC : MONOMORPHIC; | |
79 return GetCode(kind(), type, name, state); | |
80 } | |
81 | |
82 | |
83 Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic( | |
84 MapHandleList* receiver_maps, CodeHandleList* handler_stubs, | |
85 MapHandleList* transitioned_maps) { | |
86 Label miss; | |
87 __ JumpIfSmi(receiver(), &miss); | |
88 | |
89 int receiver_count = receiver_maps->length(); | |
90 Register map_reg = scratch1(); | |
91 Register match = scratch2(); | |
92 __ lw(map_reg, FieldMemOperand(receiver(), HeapObject::kMapOffset)); | |
93 for (int i = 0; i < receiver_count; ++i) { | |
94 Handle<WeakCell> cell = Map::WeakCellForMap(receiver_maps->at(i)); | |
95 __ GetWeakValue(match, cell); | |
96 if (transitioned_maps->at(i).is_null()) { | |
97 __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET, eq, match, | |
98 Operand(map_reg)); | |
99 } else { | |
100 Label next_map; | |
101 __ Branch(&next_map, ne, match, Operand(map_reg)); | |
102 Handle<WeakCell> cell = Map::WeakCellForMap(transitioned_maps->at(i)); | |
103 Register transition_map = scratch1(); | |
104 DCHECK(!FLAG_vector_stores && | |
105 transition_map.is(StoreTransitionDescriptor::MapRegister())); | |
106 __ LoadWeakValue(transition_map, cell, &miss); | |
107 __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET); | |
108 __ bind(&next_map); | |
109 } | |
110 } | |
111 | |
112 __ bind(&miss); | |
113 TailCallBuiltin(masm(), MissBuiltin(kind())); | |
114 | |
115 // Return the generated code. | |
116 return GetCode(kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); | |
117 } | |
118 | |
119 | |
120 #undef __ | |
121 #define __ ACCESS_MASM(masm) | 13 #define __ ACCESS_MASM(masm) |
122 | 14 |
123 | 15 |
124 void PropertyICCompiler::GenerateRuntimeSetProperty( | 16 void PropertyICCompiler::GenerateRuntimeSetProperty( |
125 MacroAssembler* masm, LanguageMode language_mode) { | 17 MacroAssembler* masm, LanguageMode language_mode) { |
126 __ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(), | 18 __ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(), |
127 StoreDescriptor::ValueRegister()); | 19 StoreDescriptor::ValueRegister()); |
128 | 20 |
129 __ li(a0, Operand(Smi::FromInt(language_mode))); | 21 __ li(a0, Operand(Smi::FromInt(language_mode))); |
130 __ Push(a0); | 22 __ Push(a0); |
131 | 23 |
132 // Do tail-call to runtime routine. | 24 // Do tail-call to runtime routine. |
133 __ TailCallRuntime(Runtime::kSetProperty, 4, 1); | 25 __ TailCallRuntime(Runtime::kSetProperty, 4, 1); |
134 } | 26 } |
135 | 27 |
136 | 28 |
137 #undef __ | 29 #undef __ |
138 } // namespace internal | 30 } // namespace internal |
139 } // namespace v8 | 31 } // namespace v8 |
140 | 32 |
141 #endif // V8_TARGET_ARCH_MIPS | 33 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |