Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/ic/mips64/ic-mips64.cc

Issue 496393002: MIPS: Move IC code into a subdir and move ic-compilation related code from stub-cache into ic-compi… (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Fix formatting Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ic/mips64/ic-compiler-mips64.cc ('k') | src/ic/mips64/stub-cache-mips64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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, &notin, &slow);
442 masm, receiver, key, a0, a3, a4, &notin, &slow);
443 __ Ret(USE_DELAY_SLOT); 401 __ Ret(USE_DELAY_SLOT);
444 __ ld(v0, mapped_location); 402 __ ld(v0, mapped_location);
445 __ bind(&notin); 403 __ bind(&notin);
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, &notin, &slow); 426 masm, receiver, key, a3, a4, a5, &notin, &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(&notin); 434 __ bind(&notin);
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/ic/mips64/ic-compiler-mips64.cc ('k') | src/ic/mips64/stub-cache-mips64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698