OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 | 5 |
6 | |
7 #include "src/v8.h" | 6 #include "src/v8.h" |
8 | 7 |
9 #if V8_TARGET_ARCH_MIPS64 | 8 #if V8_TARGET_ARCH_MIPS64 |
10 | 9 |
11 #include "src/code-stubs.h" | |
12 #include "src/codegen.h" | 10 #include "src/codegen.h" |
13 #include "src/ic-inl.h" | 11 #include "src/ic/ic.h" |
14 #include "src/runtime.h" | 12 #include "src/ic/stub-cache.h" |
15 #include "src/stub-cache.h" | |
16 | 13 |
17 namespace v8 { | 14 namespace v8 { |
18 namespace internal { | 15 namespace internal { |
19 | 16 |
20 | 17 |
21 // ---------------------------------------------------------------------------- | 18 // ---------------------------------------------------------------------------- |
22 // Static IC stub generators. | 19 // Static IC stub generators. |
23 // | 20 // |
24 | 21 |
25 #define __ ACCESS_MASM(masm) | 22 #define __ ACCESS_MASM(masm) |
26 | 23 |
27 | 24 |
28 static void GenerateGlobalInstanceTypeCheck(MacroAssembler* masm, | 25 static void GenerateGlobalInstanceTypeCheck(MacroAssembler* masm, Register type, |
29 Register type, | |
30 Label* global_object) { | 26 Label* global_object) { |
31 // Register usage: | 27 // Register usage: |
32 // type: holds the receiver instance type on entry. | 28 // type: holds the receiver instance type on entry. |
33 __ Branch(global_object, eq, type, Operand(JS_GLOBAL_OBJECT_TYPE)); | 29 __ Branch(global_object, eq, type, Operand(JS_GLOBAL_OBJECT_TYPE)); |
34 __ Branch(global_object, eq, type, Operand(JS_BUILTINS_OBJECT_TYPE)); | 30 __ Branch(global_object, eq, type, Operand(JS_BUILTINS_OBJECT_TYPE)); |
35 __ Branch(global_object, eq, type, Operand(JS_GLOBAL_PROXY_TYPE)); | 31 __ Branch(global_object, eq, type, Operand(JS_GLOBAL_PROXY_TYPE)); |
36 } | 32 } |
37 | 33 |
38 | 34 |
39 // Helper function used from LoadIC GenerateNormal. | 35 // Helper function used from LoadIC GenerateNormal. |
40 // | 36 // |
41 // elements: Property dictionary. It is not clobbered if a jump to the miss | 37 // elements: Property dictionary. It is not clobbered if a jump to the miss |
42 // label is done. | 38 // label is done. |
43 // name: Property name. It is not clobbered if a jump to the miss label is | 39 // name: Property name. It is not clobbered if a jump to the miss label is |
44 // done | 40 // done |
45 // result: Register for the result. It is only updated if a jump to the miss | 41 // result: Register for the result. It is only updated if a jump to the miss |
46 // label is not done. Can be the same as elements or name clobbering | 42 // label is not done. Can be the same as elements or name clobbering |
47 // one of these in the case of not jumping to the miss label. | 43 // one of these in the case of not jumping to the miss label. |
48 // The two scratch registers need to be different from elements, name and | 44 // The two scratch registers need to be different from elements, name and |
49 // result. | 45 // result. |
50 // The generated code assumes that the receiver has slow properties, | 46 // The generated code assumes that the receiver has slow properties, |
51 // is not a global object and does not have interceptors. | 47 // is not a global object and does not have interceptors. |
52 // The address returned from GenerateStringDictionaryProbes() in scratch2 | 48 // The address returned from GenerateStringDictionaryProbes() in scratch2 |
53 // is used. | 49 // is used. |
54 static void GenerateDictionaryLoad(MacroAssembler* masm, | 50 static void GenerateDictionaryLoad(MacroAssembler* masm, Label* miss, |
55 Label* miss, | 51 Register elements, Register name, |
56 Register elements, | 52 Register result, Register scratch1, |
57 Register name, | |
58 Register result, | |
59 Register scratch1, | |
60 Register scratch2) { | 53 Register scratch2) { |
61 // Main use of the scratch registers. | 54 // Main use of the scratch registers. |
62 // scratch1: Used as temporary and to hold the capacity of the property | 55 // scratch1: Used as temporary and to hold the capacity of the property |
63 // dictionary. | 56 // dictionary. |
64 // scratch2: Used as temporary. | 57 // scratch2: Used as temporary. |
65 Label done; | 58 Label done; |
66 | 59 |
67 // Probe the dictionary. | 60 // Probe the dictionary. |
68 NameDictionaryLookupStub::GeneratePositiveLookup(masm, | 61 NameDictionaryLookupStub::GeneratePositiveLookup(masm, miss, &done, elements, |
69 miss, | 62 name, scratch1, scratch2); |
70 &done, | |
71 elements, | |
72 name, | |
73 scratch1, | |
74 scratch2); | |
75 | 63 |
76 // If probing finds an entry check that the value is a normal | 64 // If probing finds an entry check that the value is a normal |
77 // property. | 65 // property. |
78 __ bind(&done); // scratch2 == elements + 4 * index. | 66 __ bind(&done); // scratch2 == elements + 4 * index. |
79 const int kElementsStartOffset = NameDictionary::kHeaderSize + | 67 const int kElementsStartOffset = |
| 68 NameDictionary::kHeaderSize + |
80 NameDictionary::kElementsStartIndex * kPointerSize; | 69 NameDictionary::kElementsStartIndex * kPointerSize; |
81 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; | 70 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; |
82 __ ld(scratch1, FieldMemOperand(scratch2, kDetailsOffset)); | 71 __ ld(scratch1, FieldMemOperand(scratch2, kDetailsOffset)); |
83 __ And(at, | 72 __ And(at, scratch1, |
84 scratch1, | |
85 Operand(Smi::FromInt(PropertyDetails::TypeField::kMask))); | 73 Operand(Smi::FromInt(PropertyDetails::TypeField::kMask))); |
86 __ Branch(miss, ne, at, Operand(zero_reg)); | 74 __ Branch(miss, ne, at, Operand(zero_reg)); |
87 | 75 |
88 // Get the value at the masked, scaled index and return. | 76 // Get the value at the masked, scaled index and return. |
89 __ ld(result, | 77 __ ld(result, |
90 FieldMemOperand(scratch2, kElementsStartOffset + 1 * kPointerSize)); | 78 FieldMemOperand(scratch2, kElementsStartOffset + 1 * kPointerSize)); |
91 } | 79 } |
92 | 80 |
93 | 81 |
94 // Helper function used from StoreIC::GenerateNormal. | 82 // Helper function used from StoreIC::GenerateNormal. |
95 // | 83 // |
96 // elements: Property dictionary. It is not clobbered if a jump to the miss | 84 // elements: Property dictionary. It is not clobbered if a jump to the miss |
97 // label is done. | 85 // label is done. |
98 // name: Property name. It is not clobbered if a jump to the miss label is | 86 // name: Property name. It is not clobbered if a jump to the miss label is |
99 // done | 87 // done |
100 // value: The value to store. | 88 // value: The value to store. |
101 // The two scratch registers need to be different from elements, name and | 89 // The two scratch registers need to be different from elements, name and |
102 // result. | 90 // result. |
103 // The generated code assumes that the receiver has slow properties, | 91 // The generated code assumes that the receiver has slow properties, |
104 // is not a global object and does not have interceptors. | 92 // is not a global object and does not have interceptors. |
105 // The address returned from GenerateStringDictionaryProbes() in scratch2 | 93 // The address returned from GenerateStringDictionaryProbes() in scratch2 |
106 // is used. | 94 // is used. |
107 static void GenerateDictionaryStore(MacroAssembler* masm, | 95 static void GenerateDictionaryStore(MacroAssembler* masm, Label* miss, |
108 Label* miss, | 96 Register elements, Register name, |
109 Register elements, | 97 Register value, Register scratch1, |
110 Register name, | |
111 Register value, | |
112 Register scratch1, | |
113 Register scratch2) { | 98 Register scratch2) { |
114 // Main use of the scratch registers. | 99 // Main use of the scratch registers. |
115 // scratch1: Used as temporary and to hold the capacity of the property | 100 // scratch1: Used as temporary and to hold the capacity of the property |
116 // dictionary. | 101 // dictionary. |
117 // scratch2: Used as temporary. | 102 // scratch2: Used as temporary. |
118 Label done; | 103 Label done; |
119 | 104 |
120 // Probe the dictionary. | 105 // Probe the dictionary. |
121 NameDictionaryLookupStub::GeneratePositiveLookup(masm, | 106 NameDictionaryLookupStub::GeneratePositiveLookup(masm, miss, &done, elements, |
122 miss, | 107 name, scratch1, scratch2); |
123 &done, | |
124 elements, | |
125 name, | |
126 scratch1, | |
127 scratch2); | |
128 | 108 |
129 // If probing finds an entry in the dictionary check that the value | 109 // If probing finds an entry in the dictionary check that the value |
130 // is a normal property that is not read only. | 110 // is a normal property that is not read only. |
131 __ bind(&done); // scratch2 == elements + 4 * index. | 111 __ bind(&done); // scratch2 == elements + 4 * index. |
132 const int kElementsStartOffset = NameDictionary::kHeaderSize + | 112 const int kElementsStartOffset = |
| 113 NameDictionary::kHeaderSize + |
133 NameDictionary::kElementsStartIndex * kPointerSize; | 114 NameDictionary::kElementsStartIndex * kPointerSize; |
134 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; | 115 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; |
135 const int kTypeAndReadOnlyMask = | 116 const int kTypeAndReadOnlyMask = |
136 (PropertyDetails::TypeField::kMask | | 117 (PropertyDetails::TypeField::kMask | |
137 PropertyDetails::AttributesField::encode(READ_ONLY)); | 118 PropertyDetails::AttributesField::encode(READ_ONLY)); |
138 __ ld(scratch1, FieldMemOperand(scratch2, kDetailsOffset)); | 119 __ ld(scratch1, FieldMemOperand(scratch2, kDetailsOffset)); |
139 __ And(at, scratch1, Operand(Smi::FromInt(kTypeAndReadOnlyMask))); | 120 __ And(at, scratch1, Operand(Smi::FromInt(kTypeAndReadOnlyMask))); |
140 __ Branch(miss, ne, at, Operand(zero_reg)); | 121 __ Branch(miss, ne, at, Operand(zero_reg)); |
141 | 122 |
142 // Store the value at the masked, scaled index and return. | 123 // Store the value at the masked, scaled index and return. |
143 const int kValueOffset = kElementsStartOffset + kPointerSize; | 124 const int kValueOffset = kElementsStartOffset + kPointerSize; |
144 __ Daddu(scratch2, scratch2, Operand(kValueOffset - kHeapObjectTag)); | 125 __ Daddu(scratch2, scratch2, Operand(kValueOffset - kHeapObjectTag)); |
145 __ sd(value, MemOperand(scratch2)); | 126 __ sd(value, MemOperand(scratch2)); |
146 | 127 |
147 // Update the write barrier. Make sure not to clobber the value. | 128 // Update the write barrier. Make sure not to clobber the value. |
148 __ mov(scratch1, value); | 129 __ mov(scratch1, value); |
149 __ RecordWrite( | 130 __ RecordWrite(elements, scratch2, scratch1, kRAHasNotBeenSaved, |
150 elements, scratch2, scratch1, kRAHasNotBeenSaved, kDontSaveFPRegs); | 131 kDontSaveFPRegs); |
151 } | 132 } |
152 | 133 |
153 | 134 |
154 // Checks the receiver for special cases (value type, slow case bits). | 135 // Checks the receiver for special cases (value type, slow case bits). |
155 // Falls through for regular JS object. | 136 // Falls through for regular JS object. |
156 static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm, | 137 static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm, |
157 Register receiver, | 138 Register receiver, Register map, |
158 Register map, | |
159 Register scratch, | 139 Register scratch, |
160 int interceptor_bit, | 140 int interceptor_bit, Label* slow) { |
161 Label* slow) { | |
162 // Check that the object isn't a smi. | 141 // Check that the object isn't a smi. |
163 __ JumpIfSmi(receiver, slow); | 142 __ JumpIfSmi(receiver, slow); |
164 // Get the map of the receiver. | 143 // Get the map of the receiver. |
165 __ ld(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); | 144 __ ld(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
166 // Check bit field. | 145 // Check bit field. |
167 __ lbu(scratch, FieldMemOperand(map, Map::kBitFieldOffset)); | 146 __ lbu(scratch, FieldMemOperand(map, Map::kBitFieldOffset)); |
168 __ And(at, scratch, | 147 __ And(at, scratch, |
169 Operand((1 << Map::kIsAccessCheckNeeded) | (1 << interceptor_bit))); | 148 Operand((1 << Map::kIsAccessCheckNeeded) | (1 << interceptor_bit))); |
170 __ Branch(slow, ne, at, Operand(zero_reg)); | 149 __ Branch(slow, ne, at, Operand(zero_reg)); |
171 // Check that the object is some kind of JS object EXCEPT JS Value type. | 150 // Check that the object is some kind of JS object EXCEPT JS Value type. |
172 // In the case that the object is a value-wrapper object, | 151 // In the case that the object is a value-wrapper object, |
173 // we enter the runtime system to make sure that indexing into string | 152 // we enter the runtime system to make sure that indexing into string |
174 // objects work as intended. | 153 // objects work as intended. |
175 DCHECK(JS_OBJECT_TYPE > JS_VALUE_TYPE); | 154 DCHECK(JS_OBJECT_TYPE > JS_VALUE_TYPE); |
176 __ lbu(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset)); | 155 __ lbu(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset)); |
177 __ Branch(slow, lt, scratch, Operand(JS_OBJECT_TYPE)); | 156 __ Branch(slow, lt, scratch, Operand(JS_OBJECT_TYPE)); |
178 } | 157 } |
179 | 158 |
180 | 159 |
181 // Loads an indexed element from a fast case array. | 160 // Loads an indexed element from a fast case array. |
182 // If not_fast_array is NULL, doesn't perform the elements map check. | 161 // If not_fast_array is NULL, doesn't perform the elements map check. |
183 static void GenerateFastArrayLoad(MacroAssembler* masm, | 162 static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, |
184 Register receiver, | 163 Register key, Register elements, |
185 Register key, | 164 Register scratch1, Register scratch2, |
186 Register elements, | 165 Register result, Label* not_fast_array, |
187 Register scratch1, | |
188 Register scratch2, | |
189 Register result, | |
190 Label* not_fast_array, | |
191 Label* out_of_range) { | 166 Label* out_of_range) { |
192 // Register use: | 167 // Register use: |
193 // | 168 // |
194 // receiver - holds the receiver on entry. | 169 // receiver - holds the receiver on entry. |
195 // Unchanged unless 'result' is the same register. | 170 // Unchanged unless 'result' is the same register. |
196 // | 171 // |
197 // key - holds the smi key on entry. | 172 // key - holds the smi key on entry. |
198 // Unchanged unless 'result' is the same register. | 173 // Unchanged unless 'result' is the same register. |
199 // | 174 // |
200 // elements - holds the elements of the receiver on exit. | 175 // elements - holds the elements of the receiver on exit. |
(...skipping 19 matching lines...) Expand all Loading... |
220 } else { | 195 } else { |
221 __ AssertFastElements(elements); | 196 __ AssertFastElements(elements); |
222 } | 197 } |
223 | 198 |
224 // Check that the key (index) is within bounds. | 199 // Check that the key (index) is within bounds. |
225 __ ld(scratch1, FieldMemOperand(elements, FixedArray::kLengthOffset)); | 200 __ ld(scratch1, FieldMemOperand(elements, FixedArray::kLengthOffset)); |
226 __ Branch(out_of_range, hs, key, Operand(scratch1)); | 201 __ Branch(out_of_range, hs, key, Operand(scratch1)); |
227 | 202 |
228 // Fast case: Do the load. | 203 // Fast case: Do the load. |
229 __ Daddu(scratch1, elements, | 204 __ Daddu(scratch1, elements, |
230 Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 205 Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
231 // The key is a smi. | 206 // The key is a smi. |
232 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); | 207 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); |
233 __ SmiScale(at, key, kPointerSizeLog2); | 208 __ SmiScale(at, key, kPointerSizeLog2); |
234 __ daddu(at, at, scratch1); | 209 __ daddu(at, at, scratch1); |
235 __ ld(scratch2, MemOperand(at)); | 210 __ ld(scratch2, MemOperand(at)); |
236 | 211 |
237 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 212 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
238 // In case the loaded value is the_hole we have to consult GetProperty | 213 // In case the loaded value is the_hole we have to consult GetProperty |
239 // to ensure the prototype chain is searched. | 214 // to ensure the prototype chain is searched. |
240 __ Branch(out_of_range, eq, scratch2, Operand(at)); | 215 __ Branch(out_of_range, eq, scratch2, Operand(at)); |
241 __ mov(result, scratch2); | 216 __ mov(result, scratch2); |
242 } | 217 } |
243 | 218 |
244 | 219 |
245 // Checks whether a key is an array index string or a unique name. | 220 // Checks whether a key is an array index string or a unique name. |
246 // Falls through if a key is a unique name. | 221 // Falls through if a key is a unique name. |
247 static void GenerateKeyNameCheck(MacroAssembler* masm, | 222 static void GenerateKeyNameCheck(MacroAssembler* masm, Register key, |
248 Register key, | 223 Register map, Register hash, |
249 Register map, | 224 Label* index_string, Label* not_unique) { |
250 Register hash, | |
251 Label* index_string, | |
252 Label* not_unique) { | |
253 // The key is not a smi. | 225 // The key is not a smi. |
254 Label unique; | 226 Label unique; |
255 // Is it a name? | 227 // Is it a name? |
256 __ GetObjectType(key, map, hash); | 228 __ GetObjectType(key, map, hash); |
257 __ Branch(not_unique, hi, hash, Operand(LAST_UNIQUE_NAME_TYPE)); | 229 __ Branch(not_unique, hi, hash, Operand(LAST_UNIQUE_NAME_TYPE)); |
258 STATIC_ASSERT(LAST_UNIQUE_NAME_TYPE == FIRST_NONSTRING_TYPE); | 230 STATIC_ASSERT(LAST_UNIQUE_NAME_TYPE == FIRST_NONSTRING_TYPE); |
259 __ Branch(&unique, eq, hash, Operand(LAST_UNIQUE_NAME_TYPE)); | 231 __ Branch(&unique, eq, hash, Operand(LAST_UNIQUE_NAME_TYPE)); |
260 | 232 |
261 // Is the string an array index, with cached numeric value? | 233 // Is the string an array index, with cached numeric value? |
262 __ lwu(hash, FieldMemOperand(key, Name::kHashFieldOffset)); | 234 __ lwu(hash, FieldMemOperand(key, Name::kHashFieldOffset)); |
(...skipping 15 matching lines...) Expand all Loading... |
278 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { | 250 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { |
279 // The return address is in lr. | 251 // The return address is in lr. |
280 Register receiver = ReceiverRegister(); | 252 Register receiver = ReceiverRegister(); |
281 Register name = NameRegister(); | 253 Register name = NameRegister(); |
282 DCHECK(receiver.is(a1)); | 254 DCHECK(receiver.is(a1)); |
283 DCHECK(name.is(a2)); | 255 DCHECK(name.is(a2)); |
284 | 256 |
285 // Probe the stub cache. | 257 // Probe the stub cache. |
286 Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( | 258 Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( |
287 Code::ComputeHandlerFlags(Code::LOAD_IC)); | 259 Code::ComputeHandlerFlags(Code::LOAD_IC)); |
288 masm->isolate()->stub_cache()->GenerateProbe( | 260 masm->isolate()->stub_cache()->GenerateProbe(masm, flags, receiver, name, a3, |
289 masm, flags, receiver, name, a3, a4, a5, a6); | 261 a4, a5, a6); |
290 | 262 |
291 // Cache miss: Jump to runtime. | 263 // Cache miss: Jump to runtime. |
292 GenerateMiss(masm); | 264 GenerateMiss(masm); |
293 } | 265 } |
294 | 266 |
295 | 267 |
296 void LoadIC::GenerateNormal(MacroAssembler* masm) { | 268 void LoadIC::GenerateNormal(MacroAssembler* masm) { |
297 Register dictionary = a0; | 269 Register dictionary = a0; |
298 DCHECK(!dictionary.is(ReceiverRegister())); | 270 DCHECK(!dictionary.is(ReceiverRegister())); |
299 DCHECK(!dictionary.is(NameRegister())); | 271 DCHECK(!dictionary.is(NameRegister())); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
332 void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { | 304 void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { |
333 // The return address is in ra. | 305 // The return address is in ra. |
334 | 306 |
335 __ mov(LoadIC_TempRegister(), ReceiverRegister()); | 307 __ mov(LoadIC_TempRegister(), ReceiverRegister()); |
336 __ Push(LoadIC_TempRegister(), NameRegister()); | 308 __ Push(LoadIC_TempRegister(), NameRegister()); |
337 | 309 |
338 __ TailCallRuntime(Runtime::kGetProperty, 2, 1); | 310 __ TailCallRuntime(Runtime::kGetProperty, 2, 1); |
339 } | 311 } |
340 | 312 |
341 | 313 |
342 static MemOperand GenerateMappedArgumentsLookup(MacroAssembler* masm, | 314 static MemOperand GenerateMappedArgumentsLookup( |
343 Register object, | 315 MacroAssembler* masm, Register object, Register key, Register scratch1, |
344 Register key, | 316 Register scratch2, Register scratch3, Label* unmapped_case, |
345 Register scratch1, | 317 Label* slow_case) { |
346 Register scratch2, | |
347 Register scratch3, | |
348 Label* unmapped_case, | |
349 Label* slow_case) { | |
350 Heap* heap = masm->isolate()->heap(); | 318 Heap* heap = masm->isolate()->heap(); |
351 | 319 |
352 // Check that the receiver is a JSObject. Because of the map check | 320 // Check that the receiver is a JSObject. Because of the map check |
353 // later, we do not need to check for interceptors or whether it | 321 // later, we do not need to check for interceptors or whether it |
354 // requires access checks. | 322 // requires access checks. |
355 __ JumpIfSmi(object, slow_case); | 323 __ JumpIfSmi(object, slow_case); |
356 // Check that the object is some kind of JSObject. | 324 // Check that the object is some kind of JSObject. |
357 __ GetObjectType(object, scratch1, scratch2); | 325 __ GetObjectType(object, scratch1, scratch2); |
358 __ Branch(slow_case, lt, scratch2, Operand(FIRST_JS_RECEIVER_TYPE)); | 326 __ Branch(slow_case, lt, scratch2, Operand(FIRST_JS_RECEIVER_TYPE)); |
359 | 327 |
360 // Check that the key is a positive smi. | 328 // Check that the key is a positive smi. |
361 __ NonNegativeSmiTst(key, scratch1); | 329 __ NonNegativeSmiTst(key, scratch1); |
362 __ Branch(slow_case, ne, scratch1, Operand(zero_reg)); | 330 __ Branch(slow_case, ne, scratch1, Operand(zero_reg)); |
363 | 331 |
364 // Load the elements into scratch1 and check its map. | 332 // Load the elements into scratch1 and check its map. |
365 Handle<Map> arguments_map(heap->sloppy_arguments_elements_map()); | 333 Handle<Map> arguments_map(heap->sloppy_arguments_elements_map()); |
366 __ ld(scratch1, FieldMemOperand(object, JSObject::kElementsOffset)); | 334 __ ld(scratch1, FieldMemOperand(object, JSObject::kElementsOffset)); |
367 __ CheckMap(scratch1, | 335 __ CheckMap(scratch1, scratch2, arguments_map, slow_case, DONT_DO_SMI_CHECK); |
368 scratch2, | |
369 arguments_map, | |
370 slow_case, | |
371 DONT_DO_SMI_CHECK); | |
372 // Check if element is in the range of mapped arguments. If not, jump | 336 // Check if element is in the range of mapped arguments. If not, jump |
373 // to the unmapped lookup with the parameter map in scratch1. | 337 // to the unmapped lookup with the parameter map in scratch1. |
374 __ ld(scratch2, FieldMemOperand(scratch1, FixedArray::kLengthOffset)); | 338 __ ld(scratch2, FieldMemOperand(scratch1, FixedArray::kLengthOffset)); |
375 __ Dsubu(scratch2, scratch2, Operand(Smi::FromInt(2))); | 339 __ Dsubu(scratch2, scratch2, Operand(Smi::FromInt(2))); |
376 __ Branch(unmapped_case, Ugreater_equal, key, Operand(scratch2)); | 340 __ Branch(unmapped_case, Ugreater_equal, key, Operand(scratch2)); |
377 | 341 |
378 // Load element index and check whether it is the hole. | 342 // Load element index and check whether it is the hole. |
379 const int kOffset = | 343 const int kOffset = |
380 FixedArray::kHeaderSize + 2 * kPointerSize - kHeapObjectTag; | 344 FixedArray::kHeaderSize + 2 * kPointerSize - kHeapObjectTag; |
381 | 345 |
(...skipping 23 matching lines...) Expand all Loading... |
405 Register parameter_map, | 369 Register parameter_map, |
406 Register scratch, | 370 Register scratch, |
407 Label* slow_case) { | 371 Label* slow_case) { |
408 // Element is in arguments backing store, which is referenced by the | 372 // Element is in arguments backing store, which is referenced by the |
409 // second element of the parameter_map. The parameter_map register | 373 // second element of the parameter_map. The parameter_map register |
410 // must be loaded with the parameter map of the arguments object and is | 374 // must be loaded with the parameter map of the arguments object and is |
411 // overwritten. | 375 // overwritten. |
412 const int kBackingStoreOffset = FixedArray::kHeaderSize + kPointerSize; | 376 const int kBackingStoreOffset = FixedArray::kHeaderSize + kPointerSize; |
413 Register backing_store = parameter_map; | 377 Register backing_store = parameter_map; |
414 __ ld(backing_store, FieldMemOperand(parameter_map, kBackingStoreOffset)); | 378 __ ld(backing_store, FieldMemOperand(parameter_map, kBackingStoreOffset)); |
415 __ CheckMap(backing_store, | 379 __ CheckMap(backing_store, scratch, Heap::kFixedArrayMapRootIndex, slow_case, |
416 scratch, | |
417 Heap::kFixedArrayMapRootIndex, | |
418 slow_case, | |
419 DONT_DO_SMI_CHECK); | 380 DONT_DO_SMI_CHECK); |
420 __ ld(scratch, FieldMemOperand(backing_store, FixedArray::kLengthOffset)); | 381 __ ld(scratch, FieldMemOperand(backing_store, FixedArray::kLengthOffset)); |
421 __ Branch(slow_case, Ugreater_equal, key, Operand(scratch)); | 382 __ Branch(slow_case, Ugreater_equal, key, Operand(scratch)); |
422 __ SmiUntag(scratch, key); | 383 __ SmiUntag(scratch, key); |
423 __ dsll(scratch, scratch, kPointerSizeLog2); | 384 __ dsll(scratch, scratch, kPointerSizeLog2); |
424 __ Daddu(scratch, | 385 __ Daddu(scratch, scratch, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
425 scratch, | |
426 Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | |
427 __ Daddu(scratch, backing_store, scratch); | 386 __ Daddu(scratch, backing_store, scratch); |
428 return MemOperand(scratch); | 387 return MemOperand(scratch); |
429 } | 388 } |
430 | 389 |
431 | 390 |
432 void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) { | 391 void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) { |
433 // The return address is in ra. | 392 // The return address is in ra. |
434 Register receiver = ReceiverRegister(); | 393 Register receiver = ReceiverRegister(); |
435 Register key = NameRegister(); | 394 Register key = NameRegister(); |
436 DCHECK(receiver.is(a1)); | 395 DCHECK(receiver.is(a1)); |
437 DCHECK(key.is(a2)); | 396 DCHECK(key.is(a2)); |
438 | 397 |
439 Label slow, notin; | 398 Label slow, notin; |
440 MemOperand mapped_location = | 399 MemOperand mapped_location = GenerateMappedArgumentsLookup( |
441 GenerateMappedArgumentsLookup( | 400 masm, receiver, key, a0, a3, a4, ¬in, &slow); |
442 masm, receiver, key, a0, a3, a4, ¬in, &slow); | |
443 __ Ret(USE_DELAY_SLOT); | 401 __ Ret(USE_DELAY_SLOT); |
444 __ ld(v0, mapped_location); | 402 __ ld(v0, mapped_location); |
445 __ bind(¬in); | 403 __ bind(¬in); |
446 // The unmapped lookup expects that the parameter map is in a2. | 404 // The unmapped lookup expects that the parameter map is in a2. |
447 MemOperand unmapped_location = | 405 MemOperand unmapped_location = |
448 GenerateUnmappedArgumentsLookup(masm, key, a0, a3, &slow); | 406 GenerateUnmappedArgumentsLookup(masm, key, a0, a3, &slow); |
449 __ ld(a0, unmapped_location); | 407 __ ld(a0, unmapped_location); |
450 __ LoadRoot(a3, Heap::kTheHoleValueRootIndex); | 408 __ LoadRoot(a3, Heap::kTheHoleValueRootIndex); |
451 __ Branch(&slow, eq, a0, Operand(a3)); | 409 __ Branch(&slow, eq, a0, Operand(a3)); |
452 __ Ret(USE_DELAY_SLOT); | 410 __ Ret(USE_DELAY_SLOT); |
453 __ mov(v0, a0); | 411 __ mov(v0, a0); |
454 __ bind(&slow); | 412 __ bind(&slow); |
455 GenerateMiss(masm); | 413 GenerateMiss(masm); |
456 } | 414 } |
457 | 415 |
458 | 416 |
459 void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) { | 417 void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) { |
460 Register receiver = ReceiverRegister(); | 418 Register receiver = ReceiverRegister(); |
461 Register key = NameRegister(); | 419 Register key = NameRegister(); |
462 Register value = ValueRegister(); | 420 Register value = ValueRegister(); |
463 DCHECK(value.is(a0)); | 421 DCHECK(value.is(a0)); |
464 | 422 |
465 Label slow, notin; | 423 Label slow, notin; |
466 // Store address is returned in register (of MemOperand) mapped_location. | 424 // Store address is returned in register (of MemOperand) mapped_location. |
467 MemOperand mapped_location = GenerateMappedArgumentsLookup( | 425 MemOperand mapped_location = GenerateMappedArgumentsLookup( |
468 masm, receiver, key, a3, a4, a5, ¬in, &slow); | 426 masm, receiver, key, a3, a4, a5, ¬in, &slow); |
469 __ sd(value, mapped_location); | 427 __ sd(value, mapped_location); |
470 __ mov(t1, value); | 428 __ mov(t1, value); |
471 DCHECK_EQ(mapped_location.offset(), 0); | 429 DCHECK_EQ(mapped_location.offset(), 0); |
472 __ RecordWrite(a3, mapped_location.rm(), t1, | 430 __ RecordWrite(a3, mapped_location.rm(), t1, kRAHasNotBeenSaved, |
473 kRAHasNotBeenSaved, kDontSaveFPRegs); | 431 kDontSaveFPRegs); |
474 __ Ret(USE_DELAY_SLOT); | 432 __ Ret(USE_DELAY_SLOT); |
475 __ mov(v0, value); // (In delay slot) return the value stored in v0. | 433 __ mov(v0, value); // (In delay slot) return the value stored in v0. |
476 __ bind(¬in); | 434 __ bind(¬in); |
477 // The unmapped lookup expects that the parameter map is in a3. | 435 // The unmapped lookup expects that the parameter map is in a3. |
478 // Store address is returned in register (of MemOperand) unmapped_location. | 436 // Store address is returned in register (of MemOperand) unmapped_location. |
479 MemOperand unmapped_location = | 437 MemOperand unmapped_location = |
480 GenerateUnmappedArgumentsLookup(masm, key, a3, a4, &slow); | 438 GenerateUnmappedArgumentsLookup(masm, key, a3, a4, &slow); |
481 __ sd(value, unmapped_location); | 439 __ sd(value, unmapped_location); |
482 __ mov(t1, value); | 440 __ mov(t1, value); |
483 DCHECK_EQ(unmapped_location.offset(), 0); | 441 DCHECK_EQ(unmapped_location.offset(), 0); |
484 __ RecordWrite(a3, unmapped_location.rm(), t1, | 442 __ RecordWrite(a3, unmapped_location.rm(), t1, kRAHasNotBeenSaved, |
485 kRAHasNotBeenSaved, kDontSaveFPRegs); | 443 kDontSaveFPRegs); |
486 __ Ret(USE_DELAY_SLOT); | 444 __ Ret(USE_DELAY_SLOT); |
487 __ mov(v0, a0); // (In delay slot) return the value stored in v0. | 445 __ mov(v0, a0); // (In delay slot) return the value stored in v0. |
488 __ bind(&slow); | 446 __ bind(&slow); |
489 GenerateMiss(masm); | 447 GenerateMiss(masm); |
490 } | 448 } |
491 | 449 |
492 | 450 |
493 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { | 451 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { |
494 // The return address is in ra. | 452 // The return address is in ra. |
495 Isolate* isolate = masm->isolate(); | 453 Isolate* isolate = masm->isolate(); |
(...skipping 25 matching lines...) Expand all Loading... |
521 DCHECK(FLAG_vector_ics); | 479 DCHECK(FLAG_vector_ics); |
522 return a3; | 480 return a3; |
523 } | 481 } |
524 | 482 |
525 | 483 |
526 const Register StoreIC::ReceiverRegister() { return a1; } | 484 const Register StoreIC::ReceiverRegister() { return a1; } |
527 const Register StoreIC::NameRegister() { return a2; } | 485 const Register StoreIC::NameRegister() { return a2; } |
528 const Register StoreIC::ValueRegister() { return a0; } | 486 const Register StoreIC::ValueRegister() { return a0; } |
529 | 487 |
530 | 488 |
531 const Register KeyedStoreIC::MapRegister() { | 489 const Register KeyedStoreIC::MapRegister() { return a3; } |
532 return a3; | |
533 } | |
534 | 490 |
535 | 491 |
536 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { | 492 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { |
537 // The return address is in ra. | 493 // The return address is in ra. |
538 | 494 |
539 __ Push(ReceiverRegister(), NameRegister()); | 495 __ Push(ReceiverRegister(), NameRegister()); |
540 | 496 |
541 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); | 497 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); |
542 } | 498 } |
543 | 499 |
544 | 500 |
545 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { | 501 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { |
546 // The return address is in ra. | 502 // The return address is in ra. |
547 Label slow, check_name, index_smi, index_name, property_array_property; | 503 Label slow, check_name, index_smi, index_name, property_array_property; |
548 Label probe_dictionary, check_number_dictionary; | 504 Label probe_dictionary, check_number_dictionary; |
549 | 505 |
550 Register key = NameRegister(); | 506 Register key = NameRegister(); |
551 Register receiver = ReceiverRegister(); | 507 Register receiver = ReceiverRegister(); |
552 DCHECK(key.is(a2)); | 508 DCHECK(key.is(a2)); |
553 DCHECK(receiver.is(a1)); | 509 DCHECK(receiver.is(a1)); |
554 | 510 |
555 Isolate* isolate = masm->isolate(); | 511 Isolate* isolate = masm->isolate(); |
556 | 512 |
557 // Check that the key is a smi. | 513 // Check that the key is a smi. |
558 __ JumpIfNotSmi(key, &check_name); | 514 __ JumpIfNotSmi(key, &check_name); |
559 __ bind(&index_smi); | 515 __ bind(&index_smi); |
560 // Now the key is known to be a smi. This place is also jumped to from below | 516 // Now the key is known to be a smi. This place is also jumped to from below |
561 // where a numeric string is converted to a smi. | 517 // where a numeric string is converted to a smi. |
562 | 518 |
563 GenerateKeyedLoadReceiverCheck( | 519 GenerateKeyedLoadReceiverCheck(masm, receiver, a0, a3, |
564 masm, receiver, a0, a3, Map::kHasIndexedInterceptor, &slow); | 520 Map::kHasIndexedInterceptor, &slow); |
565 | 521 |
566 // Check the receiver's map to see if it has fast elements. | 522 // Check the receiver's map to see if it has fast elements. |
567 __ CheckFastElements(a0, a3, &check_number_dictionary); | 523 __ CheckFastElements(a0, a3, &check_number_dictionary); |
568 | 524 |
569 GenerateFastArrayLoad( | 525 GenerateFastArrayLoad(masm, receiver, key, a0, a3, a4, v0, NULL, &slow); |
570 masm, receiver, key, a0, a3, a4, v0, NULL, &slow); | |
571 __ IncrementCounter(isolate->counters()->keyed_load_generic_smi(), 1, a4, a3); | 526 __ IncrementCounter(isolate->counters()->keyed_load_generic_smi(), 1, a4, a3); |
572 __ Ret(); | 527 __ Ret(); |
573 | 528 |
574 __ bind(&check_number_dictionary); | 529 __ bind(&check_number_dictionary); |
575 __ ld(a4, FieldMemOperand(receiver, JSObject::kElementsOffset)); | 530 __ ld(a4, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
576 __ ld(a3, FieldMemOperand(a4, JSObject::kMapOffset)); | 531 __ ld(a3, FieldMemOperand(a4, JSObject::kMapOffset)); |
577 | 532 |
578 // Check whether the elements is a number dictionary. | 533 // Check whether the elements is a number dictionary. |
579 // a3: elements map | 534 // a3: elements map |
580 // a4: elements | 535 // a4: elements |
581 __ LoadRoot(at, Heap::kHashTableMapRootIndex); | 536 __ LoadRoot(at, Heap::kHashTableMapRootIndex); |
582 __ Branch(&slow, ne, a3, Operand(at)); | 537 __ Branch(&slow, ne, a3, Operand(at)); |
583 __ dsra32(a0, key, 0); | 538 __ dsra32(a0, key, 0); |
584 __ LoadFromNumberDictionary(&slow, a4, key, v0, a0, a3, a5); | 539 __ LoadFromNumberDictionary(&slow, a4, key, v0, a0, a3, a5); |
585 __ Ret(); | 540 __ Ret(); |
586 | 541 |
587 // Slow case, key and receiver still in a2 and a1. | 542 // Slow case, key and receiver still in a2 and a1. |
588 __ bind(&slow); | 543 __ bind(&slow); |
589 __ IncrementCounter(isolate->counters()->keyed_load_generic_slow(), | 544 __ IncrementCounter(isolate->counters()->keyed_load_generic_slow(), 1, a4, |
590 1, | |
591 a4, | |
592 a3); | 545 a3); |
593 GenerateRuntimeGetProperty(masm); | 546 GenerateRuntimeGetProperty(masm); |
594 | 547 |
595 __ bind(&check_name); | 548 __ bind(&check_name); |
596 GenerateKeyNameCheck(masm, key, a0, a3, &index_name, &slow); | 549 GenerateKeyNameCheck(masm, key, a0, a3, &index_name, &slow); |
597 | 550 |
598 GenerateKeyedLoadReceiverCheck( | 551 GenerateKeyedLoadReceiverCheck(masm, receiver, a0, a3, |
599 masm, receiver, a0, a3, Map::kHasNamedInterceptor, &slow); | 552 Map::kHasNamedInterceptor, &slow); |
600 | 553 |
601 | 554 |
602 // If the receiver is a fast-case object, check the keyed lookup | 555 // If the receiver is a fast-case object, check the keyed lookup |
603 // cache. Otherwise probe the dictionary. | 556 // cache. Otherwise probe the dictionary. |
604 __ ld(a3, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); | 557 __ ld(a3, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); |
605 __ ld(a4, FieldMemOperand(a3, HeapObject::kMapOffset)); | 558 __ ld(a4, FieldMemOperand(a3, HeapObject::kMapOffset)); |
606 __ LoadRoot(at, Heap::kHashTableMapRootIndex); | 559 __ LoadRoot(at, Heap::kHashTableMapRootIndex); |
607 __ Branch(&probe_dictionary, eq, a4, Operand(at)); | 560 __ Branch(&probe_dictionary, eq, a4, Operand(at)); |
608 | 561 |
609 // Load the map of the receiver, compute the keyed lookup cache hash | 562 // Load the map of the receiver, compute the keyed lookup cache hash |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
670 // Load in-object property. | 623 // Load in-object property. |
671 __ bind(&load_in_object_property); | 624 __ bind(&load_in_object_property); |
672 __ lbu(a6, FieldMemOperand(a0, Map::kInstanceSizeOffset)); | 625 __ lbu(a6, FieldMemOperand(a0, Map::kInstanceSizeOffset)); |
673 // Index from start of object. | 626 // Index from start of object. |
674 __ daddu(a6, a6, a5); | 627 __ daddu(a6, a6, a5); |
675 // Remove the heap tag. | 628 // Remove the heap tag. |
676 __ Dsubu(receiver, receiver, Operand(kHeapObjectTag)); | 629 __ Dsubu(receiver, receiver, Operand(kHeapObjectTag)); |
677 __ dsll(at, a6, kPointerSizeLog2); | 630 __ dsll(at, a6, kPointerSizeLog2); |
678 __ daddu(at, receiver, at); | 631 __ daddu(at, receiver, at); |
679 __ ld(v0, MemOperand(at)); | 632 __ ld(v0, MemOperand(at)); |
680 __ IncrementCounter(isolate->counters()->keyed_load_generic_lookup_cache(), | 633 __ IncrementCounter(isolate->counters()->keyed_load_generic_lookup_cache(), 1, |
681 1, | 634 a4, a3); |
682 a4, | |
683 a3); | |
684 __ Ret(); | 635 __ Ret(); |
685 | 636 |
686 // Load property array property. | 637 // Load property array property. |
687 __ bind(&property_array_property); | 638 __ bind(&property_array_property); |
688 __ ld(receiver, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); | 639 __ ld(receiver, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); |
689 __ Daddu(receiver, receiver, FixedArray::kHeaderSize - kHeapObjectTag); | 640 __ Daddu(receiver, receiver, FixedArray::kHeaderSize - kHeapObjectTag); |
690 __ dsll(v0, a5, kPointerSizeLog2); | 641 __ dsll(v0, a5, kPointerSizeLog2); |
691 __ Daddu(v0, v0, a1); | 642 __ Daddu(v0, v0, a1); |
692 __ ld(v0, MemOperand(v0)); | 643 __ ld(v0, MemOperand(v0)); |
693 __ IncrementCounter(isolate->counters()->keyed_load_generic_lookup_cache(), | 644 __ IncrementCounter(isolate->counters()->keyed_load_generic_lookup_cache(), 1, |
694 1, | 645 a4, a3); |
695 a4, | |
696 a3); | |
697 __ Ret(); | 646 __ Ret(); |
698 | 647 |
699 | 648 |
700 // Do a quick inline probe of the receiver's dictionary, if it | 649 // Do a quick inline probe of the receiver's dictionary, if it |
701 // exists. | 650 // exists. |
702 __ bind(&probe_dictionary); | 651 __ bind(&probe_dictionary); |
703 // a3: elements | 652 // a3: elements |
704 __ ld(a0, FieldMemOperand(receiver, HeapObject::kMapOffset)); | 653 __ ld(a0, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
705 __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset)); | 654 __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset)); |
706 GenerateGlobalInstanceTypeCheck(masm, a0, &slow); | 655 GenerateGlobalInstanceTypeCheck(masm, a0, &slow); |
707 // Load the property to v0. | 656 // Load the property to v0. |
708 GenerateDictionaryLoad(masm, &slow, a3, key, v0, a5, a4); | 657 GenerateDictionaryLoad(masm, &slow, a3, key, v0, a5, a4); |
709 __ IncrementCounter(isolate->counters()->keyed_load_generic_symbol(), | 658 __ IncrementCounter(isolate->counters()->keyed_load_generic_symbol(), 1, a4, |
710 1, | |
711 a4, | |
712 a3); | 659 a3); |
713 __ Ret(); | 660 __ Ret(); |
714 | 661 |
715 __ bind(&index_name); | 662 __ bind(&index_name); |
716 __ IndexFromHash(a3, key); | 663 __ IndexFromHash(a3, key); |
717 // Now jump to the place where smi keys are handled. | 664 // Now jump to the place where smi keys are handled. |
718 __ Branch(&index_smi); | 665 __ Branch(&index_smi); |
719 } | 666 } |
720 | 667 |
721 | 668 |
722 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { | 669 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { |
723 // Return address is in ra. | 670 // Return address is in ra. |
724 Label miss; | 671 Label miss; |
725 | 672 |
726 Register receiver = ReceiverRegister(); | 673 Register receiver = ReceiverRegister(); |
727 Register index = NameRegister(); | 674 Register index = NameRegister(); |
728 Register scratch = a3; | 675 Register scratch = a3; |
729 Register result = v0; | 676 Register result = v0; |
730 DCHECK(!scratch.is(receiver) && !scratch.is(index)); | 677 DCHECK(!scratch.is(receiver) && !scratch.is(index)); |
731 | 678 |
732 StringCharAtGenerator char_at_generator(receiver, | 679 StringCharAtGenerator char_at_generator(receiver, index, scratch, result, |
733 index, | |
734 scratch, | |
735 result, | |
736 &miss, // When not a string. | 680 &miss, // When not a string. |
737 &miss, // When not a number. | 681 &miss, // When not a number. |
738 &miss, // When index out of range. | 682 &miss, // When index out of range. |
739 STRING_INDEX_IS_ARRAY_INDEX); | 683 STRING_INDEX_IS_ARRAY_INDEX); |
740 char_at_generator.GenerateFast(masm); | 684 char_at_generator.GenerateFast(masm); |
741 __ Ret(); | 685 __ Ret(); |
742 | 686 |
743 StubRuntimeCallHelper call_helper; | 687 StubRuntimeCallHelper call_helper; |
744 char_at_generator.GenerateSlow(masm, call_helper); | 688 char_at_generator.GenerateSlow(masm, call_helper); |
745 | 689 |
746 __ bind(&miss); | 690 __ bind(&miss); |
747 GenerateMiss(masm); | 691 GenerateMiss(masm); |
748 } | 692 } |
749 | 693 |
750 | 694 |
751 void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm, | 695 void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm, |
752 StrictMode strict_mode) { | 696 StrictMode strict_mode) { |
753 // Push receiver, key and value for runtime call. | 697 // Push receiver, key and value for runtime call. |
754 __ Push(ReceiverRegister(), NameRegister(), ValueRegister()); | 698 __ Push(ReceiverRegister(), NameRegister(), ValueRegister()); |
755 | 699 |
756 __ li(a0, Operand(Smi::FromInt(strict_mode))); // Strict mode. | 700 __ li(a0, Operand(Smi::FromInt(strict_mode))); // Strict mode. |
757 __ Push(a0); | 701 __ Push(a0); |
758 | 702 |
759 __ TailCallRuntime(Runtime::kSetProperty, 4, 1); | 703 __ TailCallRuntime(Runtime::kSetProperty, 4, 1); |
760 } | 704 } |
761 | 705 |
762 | 706 |
763 static void KeyedStoreGenerateGenericHelper( | 707 static void KeyedStoreGenerateGenericHelper( |
764 MacroAssembler* masm, | 708 MacroAssembler* masm, Label* fast_object, Label* fast_double, Label* slow, |
765 Label* fast_object, | 709 KeyedStoreCheckMap check_map, KeyedStoreIncrementLength increment_length, |
766 Label* fast_double, | 710 Register value, Register key, Register receiver, Register receiver_map, |
767 Label* slow, | 711 Register elements_map, Register elements) { |
768 KeyedStoreCheckMap check_map, | |
769 KeyedStoreIncrementLength increment_length, | |
770 Register value, | |
771 Register key, | |
772 Register receiver, | |
773 Register receiver_map, | |
774 Register elements_map, | |
775 Register elements) { | |
776 Label transition_smi_elements; | 712 Label transition_smi_elements; |
777 Label finish_object_store, non_double_value, transition_double_elements; | 713 Label finish_object_store, non_double_value, transition_double_elements; |
778 Label fast_double_without_map_check; | 714 Label fast_double_without_map_check; |
779 | 715 |
780 // Fast case: Do the store, could be either Object or double. | 716 // Fast case: Do the store, could be either Object or double. |
781 __ bind(fast_object); | 717 __ bind(fast_object); |
782 Register scratch_value = a4; | 718 Register scratch_value = a4; |
783 Register address = a5; | 719 Register address = a5; |
784 if (check_map == kCheckMap) { | 720 if (check_map == kCheckMap) { |
785 __ ld(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset)); | 721 __ ld(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset)); |
(...skipping 21 matching lines...) Expand all Loading... |
807 Label non_smi_value; | 743 Label non_smi_value; |
808 __ JumpIfNotSmi(value, &non_smi_value); | 744 __ JumpIfNotSmi(value, &non_smi_value); |
809 | 745 |
810 if (increment_length == kIncrementLength) { | 746 if (increment_length == kIncrementLength) { |
811 // Add 1 to receiver->length. | 747 // Add 1 to receiver->length. |
812 __ Daddu(scratch_value, key, Operand(Smi::FromInt(1))); | 748 __ Daddu(scratch_value, key, Operand(Smi::FromInt(1))); |
813 __ sd(scratch_value, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 749 __ sd(scratch_value, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
814 } | 750 } |
815 // It's irrelevant whether array is smi-only or not when writing a smi. | 751 // It's irrelevant whether array is smi-only or not when writing a smi. |
816 __ Daddu(address, elements, | 752 __ Daddu(address, elements, |
817 Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 753 Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
818 __ SmiScale(scratch_value, key, kPointerSizeLog2); | 754 __ SmiScale(scratch_value, key, kPointerSizeLog2); |
819 __ Daddu(address, address, scratch_value); | 755 __ Daddu(address, address, scratch_value); |
820 __ sd(value, MemOperand(address)); | 756 __ sd(value, MemOperand(address)); |
821 __ Ret(); | 757 __ Ret(); |
822 | 758 |
823 __ bind(&non_smi_value); | 759 __ bind(&non_smi_value); |
824 // Escape to elements kind transition case. | 760 // Escape to elements kind transition case. |
825 __ CheckFastObjectElements(receiver_map, scratch_value, | 761 __ CheckFastObjectElements(receiver_map, scratch_value, |
826 &transition_smi_elements); | 762 &transition_smi_elements); |
827 | 763 |
828 // Fast elements array, store the value to the elements backing store. | 764 // Fast elements array, store the value to the elements backing store. |
829 __ bind(&finish_object_store); | 765 __ bind(&finish_object_store); |
830 if (increment_length == kIncrementLength) { | 766 if (increment_length == kIncrementLength) { |
831 // Add 1 to receiver->length. | 767 // Add 1 to receiver->length. |
832 __ Daddu(scratch_value, key, Operand(Smi::FromInt(1))); | 768 __ Daddu(scratch_value, key, Operand(Smi::FromInt(1))); |
833 __ sd(scratch_value, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 769 __ sd(scratch_value, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
834 } | 770 } |
835 __ Daddu(address, elements, | 771 __ Daddu(address, elements, |
836 Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 772 Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
837 __ SmiScale(scratch_value, key, kPointerSizeLog2); | 773 __ SmiScale(scratch_value, key, kPointerSizeLog2); |
838 __ Daddu(address, address, scratch_value); | 774 __ Daddu(address, address, scratch_value); |
839 __ sd(value, MemOperand(address)); | 775 __ sd(value, MemOperand(address)); |
840 // Update write barrier for the elements array address. | 776 // Update write barrier for the elements array address. |
841 __ mov(scratch_value, value); // Preserve the value which is returned. | 777 __ mov(scratch_value, value); // Preserve the value which is returned. |
842 __ RecordWrite(elements, | 778 __ RecordWrite(elements, address, scratch_value, kRAHasNotBeenSaved, |
843 address, | 779 kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); |
844 scratch_value, | |
845 kRAHasNotBeenSaved, | |
846 kDontSaveFPRegs, | |
847 EMIT_REMEMBERED_SET, | |
848 OMIT_SMI_CHECK); | |
849 __ Ret(); | 780 __ Ret(); |
850 | 781 |
851 __ bind(fast_double); | 782 __ bind(fast_double); |
852 if (check_map == kCheckMap) { | 783 if (check_map == kCheckMap) { |
853 // Check for fast double array case. If this fails, call through to the | 784 // Check for fast double array case. If this fails, call through to the |
854 // runtime. | 785 // runtime. |
855 __ LoadRoot(at, Heap::kFixedDoubleArrayMapRootIndex); | 786 __ LoadRoot(at, Heap::kFixedDoubleArrayMapRootIndex); |
856 __ Branch(slow, ne, elements_map, Operand(at)); | 787 __ Branch(slow, ne, elements_map, Operand(at)); |
857 } | 788 } |
858 | 789 |
859 // HOLECHECK: guards "A[i] double hole?" | 790 // HOLECHECK: guards "A[i] double hole?" |
860 // We have to see if the double version of the hole is present. If so | 791 // We have to see if the double version of the hole is present. If so |
861 // go to the runtime. | 792 // go to the runtime. |
862 __ Daddu(address, elements, | 793 __ Daddu(address, elements, |
863 Operand(FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32) | 794 Operand(FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32) - |
864 - kHeapObjectTag)); | 795 kHeapObjectTag)); |
865 __ SmiScale(at, key, kPointerSizeLog2); | 796 __ SmiScale(at, key, kPointerSizeLog2); |
866 __ daddu(address, address, at); | 797 __ daddu(address, address, at); |
867 __ lw(scratch_value, MemOperand(address)); | 798 __ lw(scratch_value, MemOperand(address)); |
868 __ Branch(&fast_double_without_map_check, ne, scratch_value, | 799 __ Branch(&fast_double_without_map_check, ne, scratch_value, |
869 Operand(kHoleNanUpper32)); | 800 Operand(kHoleNanUpper32)); |
870 __ JumpIfDictionaryInPrototypeChain(receiver, elements_map, scratch_value, | 801 __ JumpIfDictionaryInPrototypeChain(receiver, elements_map, scratch_value, |
871 slow); | 802 slow); |
872 | 803 |
873 __ bind(&fast_double_without_map_check); | 804 __ bind(&fast_double_without_map_check); |
874 __ StoreNumberToDoubleElements(value, | 805 __ StoreNumberToDoubleElements(value, key, |
875 key, | |
876 elements, // Overwritten. | 806 elements, // Overwritten. |
877 a3, // Scratch regs... | 807 a3, // Scratch regs... |
878 a4, | 808 a4, a5, &transition_double_elements); |
879 a5, | |
880 &transition_double_elements); | |
881 if (increment_length == kIncrementLength) { | 809 if (increment_length == kIncrementLength) { |
882 // Add 1 to receiver->length. | 810 // Add 1 to receiver->length. |
883 __ Daddu(scratch_value, key, Operand(Smi::FromInt(1))); | 811 __ Daddu(scratch_value, key, Operand(Smi::FromInt(1))); |
884 __ sd(scratch_value, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 812 __ sd(scratch_value, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
885 } | 813 } |
886 __ Ret(); | 814 __ Ret(); |
887 | 815 |
888 __ bind(&transition_smi_elements); | 816 __ bind(&transition_smi_elements); |
889 // Transition the array appropriately depending on the value type. | 817 // Transition the array appropriately depending on the value type. |
890 __ ld(a4, FieldMemOperand(value, HeapObject::kMapOffset)); | 818 __ ld(a4, FieldMemOperand(value, HeapObject::kMapOffset)); |
891 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); | 819 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); |
892 __ Branch(&non_double_value, ne, a4, Operand(at)); | 820 __ Branch(&non_double_value, ne, a4, Operand(at)); |
893 | 821 |
894 // Value is a double. Transition FAST_SMI_ELEMENTS -> | 822 // Value is a double. Transition FAST_SMI_ELEMENTS -> |
895 // FAST_DOUBLE_ELEMENTS and complete the store. | 823 // FAST_DOUBLE_ELEMENTS and complete the store. |
896 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, | 824 __ LoadTransitionedArrayMapConditional( |
897 FAST_DOUBLE_ELEMENTS, | 825 FAST_SMI_ELEMENTS, FAST_DOUBLE_ELEMENTS, receiver_map, a4, slow); |
898 receiver_map, | 826 AllocationSiteMode mode = |
899 a4, | 827 AllocationSite::GetMode(FAST_SMI_ELEMENTS, FAST_DOUBLE_ELEMENTS); |
900 slow); | 828 ElementsTransitionGenerator::GenerateSmiToDouble(masm, receiver, key, value, |
901 AllocationSiteMode mode = AllocationSite::GetMode(FAST_SMI_ELEMENTS, | 829 receiver_map, mode, slow); |
902 FAST_DOUBLE_ELEMENTS); | |
903 ElementsTransitionGenerator::GenerateSmiToDouble( | |
904 masm, receiver, key, value, receiver_map, mode, slow); | |
905 __ ld(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); | 830 __ ld(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
906 __ jmp(&fast_double_without_map_check); | 831 __ jmp(&fast_double_without_map_check); |
907 | 832 |
908 __ bind(&non_double_value); | 833 __ bind(&non_double_value); |
909 // Value is not a double, FAST_SMI_ELEMENTS -> FAST_ELEMENTS | 834 // Value is not a double, FAST_SMI_ELEMENTS -> FAST_ELEMENTS |
910 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, | 835 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, FAST_ELEMENTS, |
911 FAST_ELEMENTS, | 836 receiver_map, a4, slow); |
912 receiver_map, | |
913 a4, | |
914 slow); | |
915 mode = AllocationSite::GetMode(FAST_SMI_ELEMENTS, FAST_ELEMENTS); | 837 mode = AllocationSite::GetMode(FAST_SMI_ELEMENTS, FAST_ELEMENTS); |
916 ElementsTransitionGenerator::GenerateMapChangeElementsTransition( | 838 ElementsTransitionGenerator::GenerateMapChangeElementsTransition( |
917 masm, receiver, key, value, receiver_map, mode, slow); | 839 masm, receiver, key, value, receiver_map, mode, slow); |
918 __ ld(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); | 840 __ ld(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
919 __ jmp(&finish_object_store); | 841 __ jmp(&finish_object_store); |
920 | 842 |
921 __ bind(&transition_double_elements); | 843 __ bind(&transition_double_elements); |
922 // Elements are FAST_DOUBLE_ELEMENTS, but value is an Object that's not a | 844 // Elements are FAST_DOUBLE_ELEMENTS, but value is an Object that's not a |
923 // HeapNumber. Make sure that the receiver is a Array with FAST_ELEMENTS and | 845 // HeapNumber. Make sure that the receiver is a Array with FAST_ELEMENTS and |
924 // transition array from FAST_DOUBLE_ELEMENTS to FAST_ELEMENTS | 846 // transition array from FAST_DOUBLE_ELEMENTS to FAST_ELEMENTS |
925 __ LoadTransitionedArrayMapConditional(FAST_DOUBLE_ELEMENTS, | 847 __ LoadTransitionedArrayMapConditional(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS, |
926 FAST_ELEMENTS, | 848 receiver_map, a4, slow); |
927 receiver_map, | |
928 a4, | |
929 slow); | |
930 mode = AllocationSite::GetMode(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS); | 849 mode = AllocationSite::GetMode(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS); |
931 ElementsTransitionGenerator::GenerateDoubleToObject( | 850 ElementsTransitionGenerator::GenerateDoubleToObject( |
932 masm, receiver, key, value, receiver_map, mode, slow); | 851 masm, receiver, key, value, receiver_map, mode, slow); |
933 __ ld(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); | 852 __ ld(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
934 __ jmp(&finish_object_store); | 853 __ jmp(&finish_object_store); |
935 } | 854 } |
936 | 855 |
937 | 856 |
938 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, | 857 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, |
939 StrictMode strict_mode) { | 858 StrictMode strict_mode) { |
(...skipping 19 matching lines...) Expand all Loading... |
959 | 878 |
960 // Check that the key is a smi. | 879 // Check that the key is a smi. |
961 __ JumpIfNotSmi(key, &slow); | 880 __ JumpIfNotSmi(key, &slow); |
962 // Check that the object isn't a smi. | 881 // Check that the object isn't a smi. |
963 __ JumpIfSmi(receiver, &slow); | 882 __ JumpIfSmi(receiver, &slow); |
964 // Get the map of the object. | 883 // Get the map of the object. |
965 __ ld(receiver_map, FieldMemOperand(receiver, HeapObject::kMapOffset)); | 884 __ ld(receiver_map, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
966 // Check that the receiver does not require access checks and is not observed. | 885 // Check that the receiver does not require access checks and is not observed. |
967 // The generic stub does not perform map checks or handle observed objects. | 886 // The generic stub does not perform map checks or handle observed objects. |
968 __ lbu(a4, FieldMemOperand(receiver_map, Map::kBitFieldOffset)); | 887 __ lbu(a4, FieldMemOperand(receiver_map, Map::kBitFieldOffset)); |
969 __ And(a4, a4, Operand(1 << Map::kIsAccessCheckNeeded | | 888 __ And(a4, a4, |
970 1 << Map::kIsObserved)); | 889 Operand(1 << Map::kIsAccessCheckNeeded | 1 << Map::kIsObserved)); |
971 __ Branch(&slow, ne, a4, Operand(zero_reg)); | 890 __ Branch(&slow, ne, a4, Operand(zero_reg)); |
972 // Check if the object is a JS array or not. | 891 // Check if the object is a JS array or not. |
973 __ lbu(a4, FieldMemOperand(receiver_map, Map::kInstanceTypeOffset)); | 892 __ lbu(a4, FieldMemOperand(receiver_map, Map::kInstanceTypeOffset)); |
974 __ Branch(&array, eq, a4, Operand(JS_ARRAY_TYPE)); | 893 __ Branch(&array, eq, a4, Operand(JS_ARRAY_TYPE)); |
975 // Check that the object is some kind of JSObject. | 894 // Check that the object is some kind of JSObject. |
976 __ Branch(&slow, lt, a4, Operand(FIRST_JS_OBJECT_TYPE)); | 895 __ Branch(&slow, lt, a4, Operand(FIRST_JS_OBJECT_TYPE)); |
977 | 896 |
978 // Object case: Check key against length in the elements array. | 897 // Object case: Check key against length in the elements array. |
979 __ ld(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); | 898 __ ld(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
980 // Check array bounds. Both the key and the length of FixedArray are smis. | 899 // Check array bounds. Both the key and the length of FixedArray are smis. |
(...skipping 13 matching lines...) Expand all Loading... |
994 // element to the array by writing to array[array.length]. | 913 // element to the array by writing to array[array.length]. |
995 __ bind(&extra); | 914 __ bind(&extra); |
996 // Condition code from comparing key and array length is still available. | 915 // Condition code from comparing key and array length is still available. |
997 // Only support writing to array[array.length]. | 916 // Only support writing to array[array.length]. |
998 __ Branch(&slow, ne, key, Operand(a4)); | 917 __ Branch(&slow, ne, key, Operand(a4)); |
999 // Check for room in the elements backing store. | 918 // Check for room in the elements backing store. |
1000 // Both the key and the length of FixedArray are smis. | 919 // Both the key and the length of FixedArray are smis. |
1001 __ ld(a4, FieldMemOperand(elements, FixedArray::kLengthOffset)); | 920 __ ld(a4, FieldMemOperand(elements, FixedArray::kLengthOffset)); |
1002 __ Branch(&slow, hs, key, Operand(a4)); | 921 __ Branch(&slow, hs, key, Operand(a4)); |
1003 __ ld(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset)); | 922 __ ld(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset)); |
1004 __ Branch( | 923 __ Branch(&check_if_double_array, ne, elements_map, |
1005 &check_if_double_array, ne, elements_map, Heap::kFixedArrayMapRootIndex); | 924 Heap::kFixedArrayMapRootIndex); |
1006 | 925 |
1007 __ jmp(&fast_object_grow); | 926 __ jmp(&fast_object_grow); |
1008 | 927 |
1009 __ bind(&check_if_double_array); | 928 __ bind(&check_if_double_array); |
1010 __ Branch(&slow, ne, elements_map, Heap::kFixedDoubleArrayMapRootIndex); | 929 __ Branch(&slow, ne, elements_map, Heap::kFixedDoubleArrayMapRootIndex); |
1011 __ jmp(&fast_double_grow); | 930 __ jmp(&fast_double_grow); |
1012 | 931 |
1013 // Array case: Get the length and the elements array from the JS | 932 // Array case: Get the length and the elements array from the JS |
1014 // array. Check that the array is in fast mode (and writable); if it | 933 // array. Check that the array is in fast mode (and writable); if it |
1015 // is the length is always a smi. | 934 // is the length is always a smi. |
1016 __ bind(&array); | 935 __ bind(&array); |
1017 __ ld(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); | 936 __ ld(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
1018 | 937 |
1019 // Check the key against the length in the array. | 938 // Check the key against the length in the array. |
1020 __ ld(a4, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 939 __ ld(a4, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
1021 __ Branch(&extra, hs, key, Operand(a4)); | 940 __ Branch(&extra, hs, key, Operand(a4)); |
1022 | 941 |
1023 KeyedStoreGenerateGenericHelper(masm, &fast_object, &fast_double, | 942 KeyedStoreGenerateGenericHelper( |
1024 &slow, kCheckMap, kDontIncrementLength, | 943 masm, &fast_object, &fast_double, &slow, kCheckMap, kDontIncrementLength, |
1025 value, key, receiver, receiver_map, | 944 value, key, receiver, receiver_map, elements_map, elements); |
1026 elements_map, elements); | |
1027 KeyedStoreGenerateGenericHelper(masm, &fast_object_grow, &fast_double_grow, | 945 KeyedStoreGenerateGenericHelper(masm, &fast_object_grow, &fast_double_grow, |
1028 &slow, kDontCheckMap, kIncrementLength, | 946 &slow, kDontCheckMap, kIncrementLength, value, |
1029 value, key, receiver, receiver_map, | 947 key, receiver, receiver_map, elements_map, |
1030 elements_map, elements); | 948 elements); |
1031 } | 949 } |
1032 | 950 |
1033 | 951 |
1034 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { | 952 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { |
1035 // Return address is in ra. | 953 // Return address is in ra. |
1036 Label slow; | 954 Label slow; |
1037 | 955 |
1038 Register receiver = ReceiverRegister(); | 956 Register receiver = ReceiverRegister(); |
1039 Register key = NameRegister(); | 957 Register key = NameRegister(); |
1040 Register scratch1 = a3; | 958 Register scratch1 = a3; |
(...skipping 13 matching lines...) Expand all Loading... |
1054 | 972 |
1055 // Check that it has indexed interceptor and access checks | 973 // Check that it has indexed interceptor and access checks |
1056 // are not enabled for this object. | 974 // are not enabled for this object. |
1057 __ lbu(scratch2, FieldMemOperand(scratch1, Map::kBitFieldOffset)); | 975 __ lbu(scratch2, FieldMemOperand(scratch1, Map::kBitFieldOffset)); |
1058 __ And(scratch2, scratch2, Operand(kSlowCaseBitFieldMask)); | 976 __ And(scratch2, scratch2, Operand(kSlowCaseBitFieldMask)); |
1059 __ Branch(&slow, ne, scratch2, Operand(1 << Map::kHasIndexedInterceptor)); | 977 __ Branch(&slow, ne, scratch2, Operand(1 << Map::kHasIndexedInterceptor)); |
1060 // Everything is fine, call runtime. | 978 // Everything is fine, call runtime. |
1061 __ Push(receiver, key); // Receiver, key. | 979 __ Push(receiver, key); // Receiver, key. |
1062 | 980 |
1063 // Perform tail call to the entry. | 981 // Perform tail call to the entry. |
1064 __ TailCallExternalReference(ExternalReference( | 982 __ TailCallExternalReference( |
1065 IC_Utility(kLoadElementWithInterceptor), masm->isolate()), 2, 1); | 983 ExternalReference(IC_Utility(kLoadElementWithInterceptor), |
| 984 masm->isolate()), |
| 985 2, 1); |
1066 | 986 |
1067 __ bind(&slow); | 987 __ bind(&slow); |
1068 GenerateMiss(masm); | 988 GenerateMiss(masm); |
1069 } | 989 } |
1070 | 990 |
1071 | 991 |
1072 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { | 992 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { |
1073 // Push receiver, key and value for runtime call. | 993 // Push receiver, key and value for runtime call. |
1074 __ Push(ReceiverRegister(), NameRegister(), ValueRegister()); | 994 __ Push(ReceiverRegister(), NameRegister(), ValueRegister()); |
1075 | 995 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1107 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { | 1027 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { |
1108 Register receiver = ReceiverRegister(); | 1028 Register receiver = ReceiverRegister(); |
1109 Register name = NameRegister(); | 1029 Register name = NameRegister(); |
1110 DCHECK(receiver.is(a1)); | 1030 DCHECK(receiver.is(a1)); |
1111 DCHECK(name.is(a2)); | 1031 DCHECK(name.is(a2)); |
1112 DCHECK(ValueRegister().is(a0)); | 1032 DCHECK(ValueRegister().is(a0)); |
1113 | 1033 |
1114 // Get the receiver from the stack and probe the stub cache. | 1034 // Get the receiver from the stack and probe the stub cache. |
1115 Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( | 1035 Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( |
1116 Code::ComputeHandlerFlags(Code::STORE_IC)); | 1036 Code::ComputeHandlerFlags(Code::STORE_IC)); |
1117 masm->isolate()->stub_cache()->GenerateProbe( | 1037 masm->isolate()->stub_cache()->GenerateProbe(masm, flags, receiver, name, a3, |
1118 masm, flags, receiver, name, a3, a4, a5, a6); | 1038 a4, a5, a6); |
1119 | 1039 |
1120 // Cache miss: Jump to runtime. | 1040 // Cache miss: Jump to runtime. |
1121 GenerateMiss(masm); | 1041 GenerateMiss(masm); |
1122 } | 1042 } |
1123 | 1043 |
1124 | 1044 |
1125 void StoreIC::GenerateMiss(MacroAssembler* masm) { | 1045 void StoreIC::GenerateMiss(MacroAssembler* masm) { |
1126 __ Push(ReceiverRegister(), NameRegister(), ValueRegister()); | 1046 __ Push(ReceiverRegister(), NameRegister(), ValueRegister()); |
1127 // Perform tail call to the entry. | 1047 // Perform tail call to the entry. |
1128 ExternalReference ref = ExternalReference(IC_Utility(kStoreIC_Miss), | 1048 ExternalReference ref = |
1129 masm->isolate()); | 1049 ExternalReference(IC_Utility(kStoreIC_Miss), masm->isolate()); |
1130 __ TailCallExternalReference(ref, 3, 1); | 1050 __ TailCallExternalReference(ref, 3, 1); |
1131 } | 1051 } |
1132 | 1052 |
1133 | 1053 |
1134 void StoreIC::GenerateNormal(MacroAssembler* masm) { | 1054 void StoreIC::GenerateNormal(MacroAssembler* masm) { |
1135 Label miss; | 1055 Label miss; |
1136 Register receiver = ReceiverRegister(); | 1056 Register receiver = ReceiverRegister(); |
1137 Register name = NameRegister(); | 1057 Register name = NameRegister(); |
1138 Register value = ValueRegister(); | 1058 Register value = ValueRegister(); |
1139 Register dictionary = a3; | 1059 Register dictionary = a3; |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1189 | 1109 |
1190 bool CompareIC::HasInlinedSmiCode(Address address) { | 1110 bool CompareIC::HasInlinedSmiCode(Address address) { |
1191 // The address of the instruction following the call. | 1111 // The address of the instruction following the call. |
1192 Address andi_instruction_address = | 1112 Address andi_instruction_address = |
1193 address + Assembler::kCallTargetAddressOffset; | 1113 address + Assembler::kCallTargetAddressOffset; |
1194 | 1114 |
1195 // If the instruction following the call is not a andi at, rx, #yyy, nothing | 1115 // If the instruction following the call is not a andi at, rx, #yyy, nothing |
1196 // was inlined. | 1116 // was inlined. |
1197 Instr instr = Assembler::instr_at(andi_instruction_address); | 1117 Instr instr = Assembler::instr_at(andi_instruction_address); |
1198 return Assembler::IsAndImmediate(instr) && | 1118 return Assembler::IsAndImmediate(instr) && |
1199 Assembler::GetRt(instr) == static_cast<uint32_t>(zero_reg.code()); | 1119 Assembler::GetRt(instr) == static_cast<uint32_t>(zero_reg.code()); |
1200 } | 1120 } |
1201 | 1121 |
1202 | 1122 |
1203 void PatchInlinedSmiCode(Address address, InlinedSmiCheck check) { | 1123 void PatchInlinedSmiCode(Address address, InlinedSmiCheck check) { |
1204 Address andi_instruction_address = | 1124 Address andi_instruction_address = |
1205 address + Assembler::kCallTargetAddressOffset; | 1125 address + Assembler::kCallTargetAddressOffset; |
1206 | 1126 |
1207 // If the instruction following the call is not a andi at, rx, #yyy, nothing | 1127 // If the instruction following the call is not a andi at, rx, #yyy, nothing |
1208 // was inlined. | 1128 // was inlined. |
1209 Instr instr = Assembler::instr_at(andi_instruction_address); | 1129 Instr instr = Assembler::instr_at(andi_instruction_address); |
1210 if (!(Assembler::IsAndImmediate(instr) && | 1130 if (!(Assembler::IsAndImmediate(instr) && |
1211 Assembler::GetRt(instr) == static_cast<uint32_t>(zero_reg.code()))) { | 1131 Assembler::GetRt(instr) == static_cast<uint32_t>(zero_reg.code()))) { |
1212 return; | 1132 return; |
1213 } | 1133 } |
1214 | 1134 |
1215 // The delta to the start of the map check instruction and the | 1135 // The delta to the start of the map check instruction and the |
1216 // condition code uses at the patched jump. | 1136 // condition code uses at the patched jump. |
1217 int delta = Assembler::GetImmediate16(instr); | 1137 int delta = Assembler::GetImmediate16(instr); |
1218 delta += Assembler::GetRs(instr) * kImm16Mask; | 1138 delta += Assembler::GetRs(instr) * kImm16Mask; |
1219 // If the delta is 0 the instruction is andi at, zero_reg, #0 which also | 1139 // If the delta is 0 the instruction is andi at, zero_reg, #0 which also |
1220 // signals that nothing was inlined. | 1140 // signals that nothing was inlined. |
1221 if (delta == 0) { | 1141 if (delta == 0) { |
1222 return; | 1142 return; |
1223 } | 1143 } |
1224 | 1144 |
1225 if (FLAG_trace_ic) { | 1145 if (FLAG_trace_ic) { |
1226 PrintF("[ patching ic at %p, andi=%p, delta=%d\n", | 1146 PrintF("[ patching ic at %p, andi=%p, delta=%d\n", address, |
1227 address, andi_instruction_address, delta); | 1147 andi_instruction_address, delta); |
1228 } | 1148 } |
1229 | 1149 |
1230 Address patch_address = | 1150 Address patch_address = |
1231 andi_instruction_address - delta * Instruction::kInstrSize; | 1151 andi_instruction_address - delta * Instruction::kInstrSize; |
1232 Instr instr_at_patch = Assembler::instr_at(patch_address); | 1152 Instr instr_at_patch = Assembler::instr_at(patch_address); |
1233 Instr branch_instr = | 1153 Instr branch_instr = |
1234 Assembler::instr_at(patch_address + Instruction::kInstrSize); | 1154 Assembler::instr_at(patch_address + Instruction::kInstrSize); |
1235 // This is patching a conditional "jump if not smi/jump if smi" site. | 1155 // This is patching a conditional "jump if not smi/jump if smi" site. |
1236 // Enabling by changing from | 1156 // Enabling by changing from |
1237 // andi at, rx, 0 | 1157 // andi at, rx, 0 |
(...skipping 14 matching lines...) Expand all Loading... |
1252 patcher.masm()->andi(at, reg, 0); | 1172 patcher.masm()->andi(at, reg, 0); |
1253 } | 1173 } |
1254 DCHECK(Assembler::IsBranch(branch_instr)); | 1174 DCHECK(Assembler::IsBranch(branch_instr)); |
1255 if (Assembler::IsBeq(branch_instr)) { | 1175 if (Assembler::IsBeq(branch_instr)) { |
1256 patcher.ChangeBranchCondition(ne); | 1176 patcher.ChangeBranchCondition(ne); |
1257 } else { | 1177 } else { |
1258 DCHECK(Assembler::IsBne(branch_instr)); | 1178 DCHECK(Assembler::IsBne(branch_instr)); |
1259 patcher.ChangeBranchCondition(eq); | 1179 patcher.ChangeBranchCondition(eq); |
1260 } | 1180 } |
1261 } | 1181 } |
1262 | 1182 } |
1263 | 1183 } // namespace v8::internal |
1264 } } // namespace v8::internal | |
1265 | 1184 |
1266 #endif // V8_TARGET_ARCH_MIPS64 | 1185 #endif // V8_TARGET_ARCH_MIPS64 |
OLD | NEW |