OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_ARM64 | 7 #if V8_TARGET_ARCH_ARM64 |
8 | 8 |
9 #include "src/arm64/assembler-arm64.h" | 9 #include "src/arm64/assembler-arm64.h" |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
45 // The scratch registers need to be different from elements, name and result. | 45 // The scratch registers need to be different from elements, name and result. |
46 // The generated code assumes that the receiver has slow properties, | 46 // The generated code assumes that the receiver has slow properties, |
47 // is not a global object and does not have interceptors. | 47 // is not a global object and does not have interceptors. |
48 static void GenerateDictionaryLoad(MacroAssembler* masm, | 48 static void GenerateDictionaryLoad(MacroAssembler* masm, |
49 Label* miss, | 49 Label* miss, |
50 Register elements, | 50 Register elements, |
51 Register name, | 51 Register name, |
52 Register result, | 52 Register result, |
53 Register scratch1, | 53 Register scratch1, |
54 Register scratch2) { | 54 Register scratch2) { |
55 ASSERT(!AreAliased(elements, name, scratch1, scratch2)); | 55 DCHECK(!AreAliased(elements, name, scratch1, scratch2)); |
56 ASSERT(!AreAliased(result, scratch1, scratch2)); | 56 DCHECK(!AreAliased(result, scratch1, scratch2)); |
57 | 57 |
58 Label done; | 58 Label done; |
59 | 59 |
60 // Probe the dictionary. | 60 // Probe the dictionary. |
61 NameDictionaryLookupStub::GeneratePositiveLookup(masm, | 61 NameDictionaryLookupStub::GeneratePositiveLookup(masm, |
62 miss, | 62 miss, |
63 &done, | 63 &done, |
64 elements, | 64 elements, |
65 name, | 65 name, |
66 scratch1, | 66 scratch1, |
(...skipping 25 matching lines...) Expand all Loading... |
92 // | 92 // |
93 // The generated code assumes that the receiver has slow properties, | 93 // The generated code assumes that the receiver has slow properties, |
94 // is not a global object and does not have interceptors. | 94 // is not a global object and does not have interceptors. |
95 static void GenerateDictionaryStore(MacroAssembler* masm, | 95 static void GenerateDictionaryStore(MacroAssembler* masm, |
96 Label* miss, | 96 Label* miss, |
97 Register elements, | 97 Register elements, |
98 Register name, | 98 Register name, |
99 Register value, | 99 Register value, |
100 Register scratch1, | 100 Register scratch1, |
101 Register scratch2) { | 101 Register scratch2) { |
102 ASSERT(!AreAliased(elements, name, value, scratch1, scratch2)); | 102 DCHECK(!AreAliased(elements, name, value, scratch1, scratch2)); |
103 | 103 |
104 Label done; | 104 Label done; |
105 | 105 |
106 // Probe the dictionary. | 106 // Probe the dictionary. |
107 NameDictionaryLookupStub::GeneratePositiveLookup(masm, | 107 NameDictionaryLookupStub::GeneratePositiveLookup(masm, |
108 miss, | 108 miss, |
109 &done, | 109 &done, |
110 elements, | 110 elements, |
111 name, | 111 name, |
112 scratch1, | 112 scratch1, |
(...skipping 27 matching lines...) Expand all Loading... |
140 | 140 |
141 // Checks the receiver for special cases (value type, slow case bits). | 141 // Checks the receiver for special cases (value type, slow case bits). |
142 // Falls through for regular JS object and return the map of the | 142 // Falls through for regular JS object and return the map of the |
143 // receiver in 'map_scratch' if the receiver is not a SMI. | 143 // receiver in 'map_scratch' if the receiver is not a SMI. |
144 static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm, | 144 static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm, |
145 Register receiver, | 145 Register receiver, |
146 Register map_scratch, | 146 Register map_scratch, |
147 Register scratch, | 147 Register scratch, |
148 int interceptor_bit, | 148 int interceptor_bit, |
149 Label* slow) { | 149 Label* slow) { |
150 ASSERT(!AreAliased(map_scratch, scratch)); | 150 DCHECK(!AreAliased(map_scratch, scratch)); |
151 | 151 |
152 // Check that the object isn't a smi. | 152 // Check that the object isn't a smi. |
153 __ JumpIfSmi(receiver, slow); | 153 __ JumpIfSmi(receiver, slow); |
154 // Get the map of the receiver. | 154 // Get the map of the receiver. |
155 __ Ldr(map_scratch, FieldMemOperand(receiver, HeapObject::kMapOffset)); | 155 __ Ldr(map_scratch, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
156 // Check bit field. | 156 // Check bit field. |
157 __ Ldrb(scratch, FieldMemOperand(map_scratch, Map::kBitFieldOffset)); | 157 __ Ldrb(scratch, FieldMemOperand(map_scratch, Map::kBitFieldOffset)); |
158 __ Tbnz(scratch, Map::kIsAccessCheckNeeded, slow); | 158 __ Tbnz(scratch, Map::kIsAccessCheckNeeded, slow); |
159 __ Tbnz(scratch, interceptor_bit, slow); | 159 __ Tbnz(scratch, interceptor_bit, slow); |
160 | 160 |
(...skipping 28 matching lines...) Expand all Loading... |
189 // used by further computation. | 189 // used by further computation. |
190 static void GenerateFastArrayLoad(MacroAssembler* masm, | 190 static void GenerateFastArrayLoad(MacroAssembler* masm, |
191 Register receiver, | 191 Register receiver, |
192 Register key, | 192 Register key, |
193 Register elements, | 193 Register elements, |
194 Register elements_map, | 194 Register elements_map, |
195 Register scratch2, | 195 Register scratch2, |
196 Register result, | 196 Register result, |
197 Label* not_fast_array, | 197 Label* not_fast_array, |
198 Label* slow) { | 198 Label* slow) { |
199 ASSERT(!AreAliased(receiver, key, elements, elements_map, scratch2)); | 199 DCHECK(!AreAliased(receiver, key, elements, elements_map, scratch2)); |
200 | 200 |
201 // Check for fast array. | 201 // Check for fast array. |
202 __ Ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); | 202 __ Ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
203 if (not_fast_array != NULL) { | 203 if (not_fast_array != NULL) { |
204 // Check that the object is in fast mode and writable. | 204 // Check that the object is in fast mode and writable. |
205 __ Ldr(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset)); | 205 __ Ldr(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset)); |
206 __ JumpIfNotRoot(elements_map, Heap::kFixedArrayMapRootIndex, | 206 __ JumpIfNotRoot(elements_map, Heap::kFixedArrayMapRootIndex, |
207 not_fast_array); | 207 not_fast_array); |
208 } else { | 208 } else { |
209 __ AssertFastElements(elements); | 209 __ AssertFastElements(elements); |
(...skipping 28 matching lines...) Expand all Loading... |
238 // Falls through if a key is a unique name. | 238 // Falls through if a key is a unique name. |
239 // The map of the key is returned in 'map_scratch'. | 239 // The map of the key is returned in 'map_scratch'. |
240 // If the jump to 'index_string' is done the hash of the key is left | 240 // If the jump to 'index_string' is done the hash of the key is left |
241 // in 'hash_scratch'. | 241 // in 'hash_scratch'. |
242 static void GenerateKeyNameCheck(MacroAssembler* masm, | 242 static void GenerateKeyNameCheck(MacroAssembler* masm, |
243 Register key, | 243 Register key, |
244 Register map_scratch, | 244 Register map_scratch, |
245 Register hash_scratch, | 245 Register hash_scratch, |
246 Label* index_string, | 246 Label* index_string, |
247 Label* not_unique) { | 247 Label* not_unique) { |
248 ASSERT(!AreAliased(key, map_scratch, hash_scratch)); | 248 DCHECK(!AreAliased(key, map_scratch, hash_scratch)); |
249 | 249 |
250 // Is the key a name? | 250 // Is the key a name? |
251 Label unique; | 251 Label unique; |
252 __ JumpIfObjectType(key, map_scratch, hash_scratch, LAST_UNIQUE_NAME_TYPE, | 252 __ JumpIfObjectType(key, map_scratch, hash_scratch, LAST_UNIQUE_NAME_TYPE, |
253 not_unique, hi); | 253 not_unique, hi); |
254 STATIC_ASSERT(LAST_UNIQUE_NAME_TYPE == FIRST_NONSTRING_TYPE); | 254 STATIC_ASSERT(LAST_UNIQUE_NAME_TYPE == FIRST_NONSTRING_TYPE); |
255 __ B(eq, &unique); | 255 __ B(eq, &unique); |
256 | 256 |
257 // Is the string an array index with cached numeric value? | 257 // Is the string an array index with cached numeric value? |
258 __ Ldr(hash_scratch.W(), FieldMemOperand(key, Name::kHashFieldOffset)); | 258 __ Ldr(hash_scratch.W(), FieldMemOperand(key, Name::kHashFieldOffset)); |
(...skipping 18 matching lines...) Expand all Loading... |
277 // left with the object's elements map. Otherwise, it is used as a scratch | 277 // left with the object's elements map. Otherwise, it is used as a scratch |
278 // register. | 278 // register. |
279 static MemOperand GenerateMappedArgumentsLookup(MacroAssembler* masm, | 279 static MemOperand GenerateMappedArgumentsLookup(MacroAssembler* masm, |
280 Register object, | 280 Register object, |
281 Register key, | 281 Register key, |
282 Register map, | 282 Register map, |
283 Register scratch1, | 283 Register scratch1, |
284 Register scratch2, | 284 Register scratch2, |
285 Label* unmapped_case, | 285 Label* unmapped_case, |
286 Label* slow_case) { | 286 Label* slow_case) { |
287 ASSERT(!AreAliased(object, key, map, scratch1, scratch2)); | 287 DCHECK(!AreAliased(object, key, map, scratch1, scratch2)); |
288 | 288 |
289 Heap* heap = masm->isolate()->heap(); | 289 Heap* heap = masm->isolate()->heap(); |
290 | 290 |
291 // Check that the receiver is a JSObject. Because of the elements | 291 // Check that the receiver is a JSObject. Because of the elements |
292 // map check later, we do not need to check for interceptors or | 292 // map check later, we do not need to check for interceptors or |
293 // whether it requires access checks. | 293 // whether it requires access checks. |
294 __ JumpIfSmi(object, slow_case); | 294 __ JumpIfSmi(object, slow_case); |
295 // Check that the object is some kind of JSObject. | 295 // Check that the object is some kind of JSObject. |
296 __ JumpIfObjectType(object, map, scratch1, FIRST_JS_RECEIVER_TYPE, | 296 __ JumpIfObjectType(object, map, scratch1, FIRST_JS_RECEIVER_TYPE, |
297 slow_case, lt); | 297 slow_case, lt); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
332 } | 332 } |
333 | 333 |
334 | 334 |
335 // The 'parameter_map' register must be loaded with the parameter map of the | 335 // The 'parameter_map' register must be loaded with the parameter map of the |
336 // arguments object and is overwritten. | 336 // arguments object and is overwritten. |
337 static MemOperand GenerateUnmappedArgumentsLookup(MacroAssembler* masm, | 337 static MemOperand GenerateUnmappedArgumentsLookup(MacroAssembler* masm, |
338 Register key, | 338 Register key, |
339 Register parameter_map, | 339 Register parameter_map, |
340 Register scratch, | 340 Register scratch, |
341 Label* slow_case) { | 341 Label* slow_case) { |
342 ASSERT(!AreAliased(key, parameter_map, scratch)); | 342 DCHECK(!AreAliased(key, parameter_map, scratch)); |
343 | 343 |
344 // Element is in arguments backing store, which is referenced by the | 344 // Element is in arguments backing store, which is referenced by the |
345 // second element of the parameter_map. | 345 // second element of the parameter_map. |
346 const int kBackingStoreOffset = FixedArray::kHeaderSize + kPointerSize; | 346 const int kBackingStoreOffset = FixedArray::kHeaderSize + kPointerSize; |
347 Register backing_store = parameter_map; | 347 Register backing_store = parameter_map; |
348 __ Ldr(backing_store, FieldMemOperand(parameter_map, kBackingStoreOffset)); | 348 __ Ldr(backing_store, FieldMemOperand(parameter_map, kBackingStoreOffset)); |
349 Handle<Map> fixed_array_map(masm->isolate()->heap()->fixed_array_map()); | 349 Handle<Map> fixed_array_map(masm->isolate()->heap()->fixed_array_map()); |
350 __ CheckMap( | 350 __ CheckMap( |
351 backing_store, scratch, fixed_array_map, slow_case, DONT_DO_SMI_CHECK); | 351 backing_store, scratch, fixed_array_map, slow_case, DONT_DO_SMI_CHECK); |
352 __ Ldr(scratch, FieldMemOperand(backing_store, FixedArray::kLengthOffset)); | 352 __ Ldr(scratch, FieldMemOperand(backing_store, FixedArray::kLengthOffset)); |
353 __ Cmp(key, scratch); | 353 __ Cmp(key, scratch); |
354 __ B(hs, slow_case); | 354 __ B(hs, slow_case); |
355 | 355 |
356 __ Add(backing_store, | 356 __ Add(backing_store, |
357 backing_store, | 357 backing_store, |
358 FixedArray::kHeaderSize - kHeapObjectTag); | 358 FixedArray::kHeaderSize - kHeapObjectTag); |
359 __ SmiUntag(scratch, key); | 359 __ SmiUntag(scratch, key); |
360 return MemOperand(backing_store, scratch, LSL, kPointerSizeLog2); | 360 return MemOperand(backing_store, scratch, LSL, kPointerSizeLog2); |
361 } | 361 } |
362 | 362 |
363 | 363 |
364 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { | 364 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { |
365 // The return address is in lr. | 365 // The return address is in lr. |
366 Register receiver = ReceiverRegister(); | 366 Register receiver = ReceiverRegister(); |
367 Register name = NameRegister(); | 367 Register name = NameRegister(); |
368 ASSERT(receiver.is(x1)); | 368 DCHECK(receiver.is(x1)); |
369 ASSERT(name.is(x2)); | 369 DCHECK(name.is(x2)); |
370 | 370 |
371 // Probe the stub cache. | 371 // Probe the stub cache. |
372 Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( | 372 Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( |
373 Code::ComputeHandlerFlags(Code::LOAD_IC)); | 373 Code::ComputeHandlerFlags(Code::LOAD_IC)); |
374 masm->isolate()->stub_cache()->GenerateProbe( | 374 masm->isolate()->stub_cache()->GenerateProbe( |
375 masm, flags, receiver, name, x3, x4, x5, x6); | 375 masm, flags, receiver, name, x3, x4, x5, x6); |
376 | 376 |
377 // Cache miss: Jump to runtime. | 377 // Cache miss: Jump to runtime. |
378 GenerateMiss(masm); | 378 GenerateMiss(masm); |
379 } | 379 } |
380 | 380 |
381 | 381 |
382 void LoadIC::GenerateNormal(MacroAssembler* masm) { | 382 void LoadIC::GenerateNormal(MacroAssembler* masm) { |
383 Register dictionary = x0; | 383 Register dictionary = x0; |
384 ASSERT(!dictionary.is(ReceiverRegister())); | 384 DCHECK(!dictionary.is(ReceiverRegister())); |
385 ASSERT(!dictionary.is(NameRegister())); | 385 DCHECK(!dictionary.is(NameRegister())); |
386 Label slow; | 386 Label slow; |
387 | 387 |
388 __ Ldr(dictionary, | 388 __ Ldr(dictionary, |
389 FieldMemOperand(ReceiverRegister(), JSObject::kPropertiesOffset)); | 389 FieldMemOperand(ReceiverRegister(), JSObject::kPropertiesOffset)); |
390 GenerateDictionaryLoad(masm, &slow, dictionary, NameRegister(), x0, x3, x4); | 390 GenerateDictionaryLoad(masm, &slow, dictionary, NameRegister(), x0, x3, x4); |
391 __ Ret(); | 391 __ Ret(); |
392 | 392 |
393 // Dictionary load failed, go slow (but don't miss). | 393 // Dictionary load failed, go slow (but don't miss). |
394 __ Bind(&slow); | 394 __ Bind(&slow); |
395 GenerateRuntimeGetProperty(masm); | 395 GenerateRuntimeGetProperty(masm); |
(...skipping 20 matching lines...) Expand all Loading... |
416 __ Push(ReceiverRegister(), NameRegister()); | 416 __ Push(ReceiverRegister(), NameRegister()); |
417 __ TailCallRuntime(Runtime::kGetProperty, 2, 1); | 417 __ TailCallRuntime(Runtime::kGetProperty, 2, 1); |
418 } | 418 } |
419 | 419 |
420 | 420 |
421 void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) { | 421 void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) { |
422 // The return address is in lr. | 422 // The return address is in lr. |
423 Register result = x0; | 423 Register result = x0; |
424 Register receiver = ReceiverRegister(); | 424 Register receiver = ReceiverRegister(); |
425 Register key = NameRegister(); | 425 Register key = NameRegister(); |
426 ASSERT(receiver.is(x1)); | 426 DCHECK(receiver.is(x1)); |
427 ASSERT(key.is(x2)); | 427 DCHECK(key.is(x2)); |
428 | 428 |
429 Label miss, unmapped; | 429 Label miss, unmapped; |
430 | 430 |
431 Register map_scratch = x0; | 431 Register map_scratch = x0; |
432 MemOperand mapped_location = GenerateMappedArgumentsLookup( | 432 MemOperand mapped_location = GenerateMappedArgumentsLookup( |
433 masm, receiver, key, map_scratch, x3, x4, &unmapped, &miss); | 433 masm, receiver, key, map_scratch, x3, x4, &unmapped, &miss); |
434 __ Ldr(result, mapped_location); | 434 __ Ldr(result, mapped_location); |
435 __ Ret(); | 435 __ Ret(); |
436 | 436 |
437 __ Bind(&unmapped); | 437 __ Bind(&unmapped); |
438 // Parameter map is left in map_scratch when a jump on unmapped is done. | 438 // Parameter map is left in map_scratch when a jump on unmapped is done. |
439 MemOperand unmapped_location = | 439 MemOperand unmapped_location = |
440 GenerateUnmappedArgumentsLookup(masm, key, map_scratch, x3, &miss); | 440 GenerateUnmappedArgumentsLookup(masm, key, map_scratch, x3, &miss); |
441 __ Ldr(result, unmapped_location); | 441 __ Ldr(result, unmapped_location); |
442 __ JumpIfRoot(result, Heap::kTheHoleValueRootIndex, &miss); | 442 __ JumpIfRoot(result, Heap::kTheHoleValueRootIndex, &miss); |
443 __ Ret(); | 443 __ Ret(); |
444 | 444 |
445 __ Bind(&miss); | 445 __ Bind(&miss); |
446 GenerateMiss(masm); | 446 GenerateMiss(masm); |
447 } | 447 } |
448 | 448 |
449 | 449 |
450 void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) { | 450 void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) { |
451 ASM_LOCATION("KeyedStoreIC::GenerateSloppyArguments"); | 451 ASM_LOCATION("KeyedStoreIC::GenerateSloppyArguments"); |
452 Label slow, notin; | 452 Label slow, notin; |
453 Register value = ValueRegister(); | 453 Register value = ValueRegister(); |
454 Register key = NameRegister(); | 454 Register key = NameRegister(); |
455 Register receiver = ReceiverRegister(); | 455 Register receiver = ReceiverRegister(); |
456 ASSERT(receiver.is(x1)); | 456 DCHECK(receiver.is(x1)); |
457 ASSERT(key.is(x2)); | 457 DCHECK(key.is(x2)); |
458 ASSERT(value.is(x0)); | 458 DCHECK(value.is(x0)); |
459 | 459 |
460 Register map = x3; | 460 Register map = x3; |
461 | 461 |
462 // These registers are used by GenerateMappedArgumentsLookup to build a | 462 // These registers are used by GenerateMappedArgumentsLookup to build a |
463 // MemOperand. They are live for as long as the MemOperand is live. | 463 // MemOperand. They are live for as long as the MemOperand is live. |
464 Register mapped1 = x4; | 464 Register mapped1 = x4; |
465 Register mapped2 = x5; | 465 Register mapped2 = x5; |
466 | 466 |
467 MemOperand mapped = | 467 MemOperand mapped = |
468 GenerateMappedArgumentsLookup(masm, receiver, key, map, | 468 GenerateMappedArgumentsLookup(masm, receiver, key, map, |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
509 | 509 |
510 __ TailCallExternalReference(ref, 2, 1); | 510 __ TailCallExternalReference(ref, 2, 1); |
511 } | 511 } |
512 | 512 |
513 | 513 |
514 // IC register specifications | 514 // IC register specifications |
515 const Register LoadIC::ReceiverRegister() { return x1; } | 515 const Register LoadIC::ReceiverRegister() { return x1; } |
516 const Register LoadIC::NameRegister() { return x2; } | 516 const Register LoadIC::NameRegister() { return x2; } |
517 | 517 |
518 const Register LoadIC::SlotRegister() { | 518 const Register LoadIC::SlotRegister() { |
519 ASSERT(FLAG_vector_ics); | 519 DCHECK(FLAG_vector_ics); |
520 return x0; | 520 return x0; |
521 } | 521 } |
522 | 522 |
523 | 523 |
524 const Register LoadIC::VectorRegister() { | 524 const Register LoadIC::VectorRegister() { |
525 ASSERT(FLAG_vector_ics); | 525 DCHECK(FLAG_vector_ics); |
526 return x3; | 526 return x3; |
527 } | 527 } |
528 | 528 |
529 | 529 |
530 const Register StoreIC::ReceiverRegister() { return x1; } | 530 const Register StoreIC::ReceiverRegister() { return x1; } |
531 const Register StoreIC::NameRegister() { return x2; } | 531 const Register StoreIC::NameRegister() { return x2; } |
532 const Register StoreIC::ValueRegister() { return x0; } | 532 const Register StoreIC::ValueRegister() { return x0; } |
533 | 533 |
534 | 534 |
535 const Register KeyedStoreIC::MapRegister() { | 535 const Register KeyedStoreIC::MapRegister() { |
(...skipping 10 matching lines...) Expand all Loading... |
546 | 546 |
547 static void GenerateKeyedLoadWithSmiKey(MacroAssembler* masm, | 547 static void GenerateKeyedLoadWithSmiKey(MacroAssembler* masm, |
548 Register key, | 548 Register key, |
549 Register receiver, | 549 Register receiver, |
550 Register scratch1, | 550 Register scratch1, |
551 Register scratch2, | 551 Register scratch2, |
552 Register scratch3, | 552 Register scratch3, |
553 Register scratch4, | 553 Register scratch4, |
554 Register scratch5, | 554 Register scratch5, |
555 Label *slow) { | 555 Label *slow) { |
556 ASSERT(!AreAliased( | 556 DCHECK(!AreAliased( |
557 key, receiver, scratch1, scratch2, scratch3, scratch4, scratch5)); | 557 key, receiver, scratch1, scratch2, scratch3, scratch4, scratch5)); |
558 | 558 |
559 Isolate* isolate = masm->isolate(); | 559 Isolate* isolate = masm->isolate(); |
560 Label check_number_dictionary; | 560 Label check_number_dictionary; |
561 // If we can load the value, it should be returned in x0. | 561 // If we can load the value, it should be returned in x0. |
562 Register result = x0; | 562 Register result = x0; |
563 | 563 |
564 GenerateKeyedLoadReceiverCheck( | 564 GenerateKeyedLoadReceiverCheck( |
565 masm, receiver, scratch1, scratch2, Map::kHasIndexedInterceptor, slow); | 565 masm, receiver, scratch1, scratch2, Map::kHasIndexedInterceptor, slow); |
566 | 566 |
(...skipping 20 matching lines...) Expand all Loading... |
587 | 587 |
588 static void GenerateKeyedLoadWithNameKey(MacroAssembler* masm, | 588 static void GenerateKeyedLoadWithNameKey(MacroAssembler* masm, |
589 Register key, | 589 Register key, |
590 Register receiver, | 590 Register receiver, |
591 Register scratch1, | 591 Register scratch1, |
592 Register scratch2, | 592 Register scratch2, |
593 Register scratch3, | 593 Register scratch3, |
594 Register scratch4, | 594 Register scratch4, |
595 Register scratch5, | 595 Register scratch5, |
596 Label *slow) { | 596 Label *slow) { |
597 ASSERT(!AreAliased( | 597 DCHECK(!AreAliased( |
598 key, receiver, scratch1, scratch2, scratch3, scratch4, scratch5)); | 598 key, receiver, scratch1, scratch2, scratch3, scratch4, scratch5)); |
599 | 599 |
600 Isolate* isolate = masm->isolate(); | 600 Isolate* isolate = masm->isolate(); |
601 Label probe_dictionary, property_array_property; | 601 Label probe_dictionary, property_array_property; |
602 // If we can load the value, it should be returned in x0. | 602 // If we can load the value, it should be returned in x0. |
603 Register result = x0; | 603 Register result = x0; |
604 | 604 |
605 GenerateKeyedLoadReceiverCheck( | 605 GenerateKeyedLoadReceiverCheck( |
606 masm, receiver, scratch1, scratch2, Map::kHasNamedInterceptor, slow); | 606 masm, receiver, scratch1, scratch2, Map::kHasNamedInterceptor, slow); |
607 | 607 |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
706 __ Ret(); | 706 __ Ret(); |
707 } | 707 } |
708 | 708 |
709 | 709 |
710 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { | 710 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { |
711 // The return address is in lr. | 711 // The return address is in lr. |
712 Label slow, check_name, index_smi, index_name; | 712 Label slow, check_name, index_smi, index_name; |
713 | 713 |
714 Register key = NameRegister(); | 714 Register key = NameRegister(); |
715 Register receiver = ReceiverRegister(); | 715 Register receiver = ReceiverRegister(); |
716 ASSERT(key.is(x2)); | 716 DCHECK(key.is(x2)); |
717 ASSERT(receiver.is(x1)); | 717 DCHECK(receiver.is(x1)); |
718 | 718 |
719 __ JumpIfNotSmi(key, &check_name); | 719 __ JumpIfNotSmi(key, &check_name); |
720 __ Bind(&index_smi); | 720 __ Bind(&index_smi); |
721 // Now the key is known to be a smi. This place is also jumped to from below | 721 // Now the key is known to be a smi. This place is also jumped to from below |
722 // where a numeric string is converted to a smi. | 722 // where a numeric string is converted to a smi. |
723 GenerateKeyedLoadWithSmiKey(masm, key, receiver, x7, x3, x4, x5, x6, &slow); | 723 GenerateKeyedLoadWithSmiKey(masm, key, receiver, x7, x3, x4, x5, x6, &slow); |
724 | 724 |
725 // Slow case. | 725 // Slow case. |
726 __ Bind(&slow); | 726 __ Bind(&slow); |
727 __ IncrementCounter( | 727 __ IncrementCounter( |
(...skipping 13 matching lines...) Expand all Loading... |
741 | 741 |
742 | 742 |
743 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { | 743 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { |
744 // Return address is in lr. | 744 // Return address is in lr. |
745 Label miss; | 745 Label miss; |
746 | 746 |
747 Register receiver = ReceiverRegister(); | 747 Register receiver = ReceiverRegister(); |
748 Register index = NameRegister(); | 748 Register index = NameRegister(); |
749 Register result = x0; | 749 Register result = x0; |
750 Register scratch = x3; | 750 Register scratch = x3; |
751 ASSERT(!scratch.is(receiver) && !scratch.is(index)); | 751 DCHECK(!scratch.is(receiver) && !scratch.is(index)); |
752 | 752 |
753 StringCharAtGenerator char_at_generator(receiver, | 753 StringCharAtGenerator char_at_generator(receiver, |
754 index, | 754 index, |
755 scratch, | 755 scratch, |
756 result, | 756 result, |
757 &miss, // When not a string. | 757 &miss, // When not a string. |
758 &miss, // When not a number. | 758 &miss, // When not a number. |
759 &miss, // When index out of range. | 759 &miss, // When index out of range. |
760 STRING_INDEX_IS_ARRAY_INDEX); | 760 STRING_INDEX_IS_ARRAY_INDEX); |
761 char_at_generator.GenerateFast(masm); | 761 char_at_generator.GenerateFast(masm); |
762 __ Ret(); | 762 __ Ret(); |
763 | 763 |
764 StubRuntimeCallHelper call_helper; | 764 StubRuntimeCallHelper call_helper; |
765 char_at_generator.GenerateSlow(masm, call_helper); | 765 char_at_generator.GenerateSlow(masm, call_helper); |
766 | 766 |
767 __ Bind(&miss); | 767 __ Bind(&miss); |
768 GenerateMiss(masm); | 768 GenerateMiss(masm); |
769 } | 769 } |
770 | 770 |
771 | 771 |
772 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { | 772 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { |
773 // Return address is in lr. | 773 // Return address is in lr. |
774 Label slow; | 774 Label slow; |
775 | 775 |
776 Register receiver = ReceiverRegister(); | 776 Register receiver = ReceiverRegister(); |
777 Register key = NameRegister(); | 777 Register key = NameRegister(); |
778 Register scratch1 = x3; | 778 Register scratch1 = x3; |
779 Register scratch2 = x4; | 779 Register scratch2 = x4; |
780 ASSERT(!AreAliased(scratch1, scratch2, receiver, key)); | 780 DCHECK(!AreAliased(scratch1, scratch2, receiver, key)); |
781 | 781 |
782 // Check that the receiver isn't a smi. | 782 // Check that the receiver isn't a smi. |
783 __ JumpIfSmi(receiver, &slow); | 783 __ JumpIfSmi(receiver, &slow); |
784 | 784 |
785 // Check that the key is an array index, that is Uint32. | 785 // Check that the key is an array index, that is Uint32. |
786 __ TestAndBranchIfAnySet(key, kSmiTagMask | kSmiSignMask, &slow); | 786 __ TestAndBranchIfAnySet(key, kSmiTagMask | kSmiSignMask, &slow); |
787 | 787 |
788 // Get the map of the receiver. | 788 // Get the map of the receiver. |
789 Register map = scratch1; | 789 Register map = scratch1; |
790 __ Ldr(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); | 790 __ Ldr(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
791 | 791 |
792 // Check that it has indexed interceptor and access checks | 792 // Check that it has indexed interceptor and access checks |
793 // are not enabled for this object. | 793 // are not enabled for this object. |
794 __ Ldrb(scratch2, FieldMemOperand(map, Map::kBitFieldOffset)); | 794 __ Ldrb(scratch2, FieldMemOperand(map, Map::kBitFieldOffset)); |
795 ASSERT(kSlowCaseBitFieldMask == | 795 DCHECK(kSlowCaseBitFieldMask == |
796 ((1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor))); | 796 ((1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor))); |
797 __ Tbnz(scratch2, Map::kIsAccessCheckNeeded, &slow); | 797 __ Tbnz(scratch2, Map::kIsAccessCheckNeeded, &slow); |
798 __ Tbz(scratch2, Map::kHasIndexedInterceptor, &slow); | 798 __ Tbz(scratch2, Map::kHasIndexedInterceptor, &slow); |
799 | 799 |
800 // Everything is fine, call runtime. | 800 // Everything is fine, call runtime. |
801 __ Push(receiver, key); | 801 __ Push(receiver, key); |
802 __ TailCallExternalReference( | 802 __ TailCallExternalReference( |
803 ExternalReference(IC_Utility(kLoadElementWithInterceptor), | 803 ExternalReference(IC_Utility(kLoadElementWithInterceptor), |
804 masm->isolate()), | 804 masm->isolate()), |
805 2, 1); | 805 2, 1); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
856 Label* fast_double, | 856 Label* fast_double, |
857 Label* slow, | 857 Label* slow, |
858 KeyedStoreCheckMap check_map, | 858 KeyedStoreCheckMap check_map, |
859 KeyedStoreIncrementLength increment_length, | 859 KeyedStoreIncrementLength increment_length, |
860 Register value, | 860 Register value, |
861 Register key, | 861 Register key, |
862 Register receiver, | 862 Register receiver, |
863 Register receiver_map, | 863 Register receiver_map, |
864 Register elements_map, | 864 Register elements_map, |
865 Register elements) { | 865 Register elements) { |
866 ASSERT(!AreAliased( | 866 DCHECK(!AreAliased( |
867 value, key, receiver, receiver_map, elements_map, elements, x10, x11)); | 867 value, key, receiver, receiver_map, elements_map, elements, x10, x11)); |
868 | 868 |
869 Label transition_smi_elements; | 869 Label transition_smi_elements; |
870 Label transition_double_elements; | 870 Label transition_double_elements; |
871 Label fast_double_without_map_check; | 871 Label fast_double_without_map_check; |
872 Label non_double_value; | 872 Label non_double_value; |
873 Label finish_store; | 873 Label finish_store; |
874 | 874 |
875 __ Bind(fast_object); | 875 __ Bind(fast_object); |
876 if (check_map == kCheckMap) { | 876 if (check_map == kCheckMap) { |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1018 Label array; | 1018 Label array; |
1019 Label fast_object; | 1019 Label fast_object; |
1020 Label extra; | 1020 Label extra; |
1021 Label fast_object_grow; | 1021 Label fast_object_grow; |
1022 Label fast_double_grow; | 1022 Label fast_double_grow; |
1023 Label fast_double; | 1023 Label fast_double; |
1024 | 1024 |
1025 Register value = ValueRegister(); | 1025 Register value = ValueRegister(); |
1026 Register key = NameRegister(); | 1026 Register key = NameRegister(); |
1027 Register receiver = ReceiverRegister(); | 1027 Register receiver = ReceiverRegister(); |
1028 ASSERT(receiver.is(x1)); | 1028 DCHECK(receiver.is(x1)); |
1029 ASSERT(key.is(x2)); | 1029 DCHECK(key.is(x2)); |
1030 ASSERT(value.is(x0)); | 1030 DCHECK(value.is(x0)); |
1031 | 1031 |
1032 Register receiver_map = x3; | 1032 Register receiver_map = x3; |
1033 Register elements = x4; | 1033 Register elements = x4; |
1034 Register elements_map = x5; | 1034 Register elements_map = x5; |
1035 | 1035 |
1036 __ JumpIfNotSmi(key, &slow); | 1036 __ JumpIfNotSmi(key, &slow); |
1037 __ JumpIfSmi(receiver, &slow); | 1037 __ JumpIfSmi(receiver, &slow); |
1038 __ Ldr(receiver_map, FieldMemOperand(receiver, HeapObject::kMapOffset)); | 1038 __ Ldr(receiver_map, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
1039 | 1039 |
1040 // Check that the receiver does not require access checks and is not observed. | 1040 // Check that the receiver does not require access checks and is not observed. |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1108 KeyedStoreGenerateGenericHelper(masm, &fast_object_grow, &fast_double_grow, | 1108 KeyedStoreGenerateGenericHelper(masm, &fast_object_grow, &fast_double_grow, |
1109 &slow, kDontCheckMap, kIncrementLength, | 1109 &slow, kDontCheckMap, kIncrementLength, |
1110 value, key, receiver, receiver_map, | 1110 value, key, receiver, receiver_map, |
1111 elements_map, elements); | 1111 elements_map, elements); |
1112 } | 1112 } |
1113 | 1113 |
1114 | 1114 |
1115 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { | 1115 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { |
1116 Register receiver = ReceiverRegister(); | 1116 Register receiver = ReceiverRegister(); |
1117 Register name = NameRegister(); | 1117 Register name = NameRegister(); |
1118 ASSERT(!AreAliased(receiver, name, ValueRegister(), x3, x4, x5, x6)); | 1118 DCHECK(!AreAliased(receiver, name, ValueRegister(), x3, x4, x5, x6)); |
1119 | 1119 |
1120 // Probe the stub cache. | 1120 // Probe the stub cache. |
1121 Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( | 1121 Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( |
1122 Code::ComputeHandlerFlags(Code::STORE_IC)); | 1122 Code::ComputeHandlerFlags(Code::STORE_IC)); |
1123 masm->isolate()->stub_cache()->GenerateProbe( | 1123 masm->isolate()->stub_cache()->GenerateProbe( |
1124 masm, flags, receiver, name, x3, x4, x5, x6); | 1124 masm, flags, receiver, name, x3, x4, x5, x6); |
1125 | 1125 |
1126 // Cache miss: Jump to runtime. | 1126 // Cache miss: Jump to runtime. |
1127 GenerateMiss(masm); | 1127 GenerateMiss(masm); |
1128 } | 1128 } |
1129 | 1129 |
1130 | 1130 |
1131 void StoreIC::GenerateMiss(MacroAssembler* masm) { | 1131 void StoreIC::GenerateMiss(MacroAssembler* masm) { |
1132 __ Push(ReceiverRegister(), NameRegister(), ValueRegister()); | 1132 __ Push(ReceiverRegister(), NameRegister(), ValueRegister()); |
1133 | 1133 |
1134 // Tail call to the entry. | 1134 // Tail call to the entry. |
1135 ExternalReference ref = | 1135 ExternalReference ref = |
1136 ExternalReference(IC_Utility(kStoreIC_Miss), masm->isolate()); | 1136 ExternalReference(IC_Utility(kStoreIC_Miss), masm->isolate()); |
1137 __ TailCallExternalReference(ref, 3, 1); | 1137 __ TailCallExternalReference(ref, 3, 1); |
1138 } | 1138 } |
1139 | 1139 |
1140 | 1140 |
1141 void StoreIC::GenerateNormal(MacroAssembler* masm) { | 1141 void StoreIC::GenerateNormal(MacroAssembler* masm) { |
1142 Label miss; | 1142 Label miss; |
1143 Register value = ValueRegister(); | 1143 Register value = ValueRegister(); |
1144 Register receiver = ReceiverRegister(); | 1144 Register receiver = ReceiverRegister(); |
1145 Register name = NameRegister(); | 1145 Register name = NameRegister(); |
1146 Register dictionary = x3; | 1146 Register dictionary = x3; |
1147 ASSERT(!AreAliased(value, receiver, name, x3, x4, x5)); | 1147 DCHECK(!AreAliased(value, receiver, name, x3, x4, x5)); |
1148 | 1148 |
1149 __ Ldr(dictionary, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); | 1149 __ Ldr(dictionary, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); |
1150 | 1150 |
1151 GenerateDictionaryStore(masm, &miss, dictionary, name, value, x4, x5); | 1151 GenerateDictionaryStore(masm, &miss, dictionary, name, value, x4, x5); |
1152 Counters* counters = masm->isolate()->counters(); | 1152 Counters* counters = masm->isolate()->counters(); |
1153 __ IncrementCounter(counters->store_normal_hit(), 1, x4, x5); | 1153 __ IncrementCounter(counters->store_normal_hit(), 1, x4, x5); |
1154 __ Ret(); | 1154 __ Ret(); |
1155 | 1155 |
1156 // Cache miss: Jump to runtime. | 1156 // Cache miss: Jump to runtime. |
1157 __ Bind(&miss); | 1157 __ Bind(&miss); |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1246 } | 1246 } |
1247 | 1247 |
1248 // Patch and activate code generated by JumpPatchSite::EmitJumpIfNotSmi() | 1248 // Patch and activate code generated by JumpPatchSite::EmitJumpIfNotSmi() |
1249 // and JumpPatchSite::EmitJumpIfSmi(). | 1249 // and JumpPatchSite::EmitJumpIfSmi(). |
1250 // Changing | 1250 // Changing |
1251 // tb(n)z xzr, #0, <target> | 1251 // tb(n)z xzr, #0, <target> |
1252 // to | 1252 // to |
1253 // tb(!n)z test_reg, #0, <target> | 1253 // tb(!n)z test_reg, #0, <target> |
1254 Instruction* to_patch = info.SmiCheck(); | 1254 Instruction* to_patch = info.SmiCheck(); |
1255 PatchingAssembler patcher(to_patch, 1); | 1255 PatchingAssembler patcher(to_patch, 1); |
1256 ASSERT(to_patch->IsTestBranch()); | 1256 DCHECK(to_patch->IsTestBranch()); |
1257 ASSERT(to_patch->ImmTestBranchBit5() == 0); | 1257 DCHECK(to_patch->ImmTestBranchBit5() == 0); |
1258 ASSERT(to_patch->ImmTestBranchBit40() == 0); | 1258 DCHECK(to_patch->ImmTestBranchBit40() == 0); |
1259 | 1259 |
1260 STATIC_ASSERT(kSmiTag == 0); | 1260 STATIC_ASSERT(kSmiTag == 0); |
1261 STATIC_ASSERT(kSmiTagMask == 1); | 1261 STATIC_ASSERT(kSmiTagMask == 1); |
1262 | 1262 |
1263 int branch_imm = to_patch->ImmTestBranch(); | 1263 int branch_imm = to_patch->ImmTestBranch(); |
1264 Register smi_reg; | 1264 Register smi_reg; |
1265 if (check == ENABLE_INLINED_SMI_CHECK) { | 1265 if (check == ENABLE_INLINED_SMI_CHECK) { |
1266 ASSERT(to_patch->Rt() == xzr.code()); | 1266 DCHECK(to_patch->Rt() == xzr.code()); |
1267 smi_reg = info.SmiRegister(); | 1267 smi_reg = info.SmiRegister(); |
1268 } else { | 1268 } else { |
1269 ASSERT(check == DISABLE_INLINED_SMI_CHECK); | 1269 DCHECK(check == DISABLE_INLINED_SMI_CHECK); |
1270 ASSERT(to_patch->Rt() != xzr.code()); | 1270 DCHECK(to_patch->Rt() != xzr.code()); |
1271 smi_reg = xzr; | 1271 smi_reg = xzr; |
1272 } | 1272 } |
1273 | 1273 |
1274 if (to_patch->Mask(TestBranchMask) == TBZ) { | 1274 if (to_patch->Mask(TestBranchMask) == TBZ) { |
1275 // This is JumpIfNotSmi(smi_reg, branch_imm). | 1275 // This is JumpIfNotSmi(smi_reg, branch_imm). |
1276 patcher.tbnz(smi_reg, 0, branch_imm); | 1276 patcher.tbnz(smi_reg, 0, branch_imm); |
1277 } else { | 1277 } else { |
1278 ASSERT(to_patch->Mask(TestBranchMask) == TBNZ); | 1278 DCHECK(to_patch->Mask(TestBranchMask) == TBNZ); |
1279 // This is JumpIfSmi(smi_reg, branch_imm). | 1279 // This is JumpIfSmi(smi_reg, branch_imm). |
1280 patcher.tbz(smi_reg, 0, branch_imm); | 1280 patcher.tbz(smi_reg, 0, branch_imm); |
1281 } | 1281 } |
1282 } | 1282 } |
1283 | 1283 |
1284 | 1284 |
1285 } } // namespace v8::internal | 1285 } } // namespace v8::internal |
1286 | 1286 |
1287 #endif // V8_TARGET_ARCH_ARM64 | 1287 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |