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 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
405 return MemOperand(backing_store, scratch, LSL, kPointerSizeLog2); | 405 return MemOperand(backing_store, scratch, LSL, kPointerSizeLog2); |
406 } | 406 } |
407 | 407 |
408 | 408 |
409 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { | 409 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { |
410 // ----------- S t a t e ------------- | 410 // ----------- S t a t e ------------- |
411 // -- x2 : name | 411 // -- x2 : name |
412 // -- lr : return address | 412 // -- lr : return address |
413 // -- x0 : receiver | 413 // -- x0 : receiver |
414 // ----------------------------------- | 414 // ----------------------------------- |
| 415 ASSERT(x0.is(ReceiverRegister())); |
| 416 ASSERT(x2.is(NameRegister())); |
415 | 417 |
416 // Probe the stub cache. | 418 // Probe the stub cache. |
417 Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC); | 419 Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC); |
418 masm->isolate()->stub_cache()->GenerateProbe( | 420 masm->isolate()->stub_cache()->GenerateProbe( |
419 masm, flags, x0, x2, x3, x4, x5, x6); | 421 masm, flags, x0, x2, x3, x4, x5, x6); |
420 | 422 |
421 // Cache miss: Jump to runtime. | 423 // Cache miss: Jump to runtime. |
422 GenerateMiss(masm); | 424 GenerateMiss(masm); |
423 } | 425 } |
424 | 426 |
425 | 427 |
426 void LoadIC::GenerateNormal(MacroAssembler* masm) { | 428 void LoadIC::GenerateNormal(MacroAssembler* masm) { |
427 // ----------- S t a t e ------------- | 429 // ----------- S t a t e ------------- |
428 // -- x2 : name | 430 // -- x2 : name |
429 // -- lr : return address | 431 // -- lr : return address |
430 // -- x0 : receiver | 432 // -- x0 : receiver |
431 // ----------------------------------- | 433 // ----------------------------------- |
| 434 ASSERT(x0.is(ReceiverRegister())); |
| 435 ASSERT(x2.is(NameRegister())); |
432 Label miss, slow; | 436 Label miss, slow; |
433 | 437 |
434 GenerateNameDictionaryReceiverCheck(masm, x0, x1, x3, x4, &miss); | 438 GenerateNameDictionaryReceiverCheck(masm, x0, x1, x3, x4, &miss); |
435 | 439 |
436 // x1 now holds the property dictionary. | 440 // x1 now holds the property dictionary. |
437 GenerateDictionaryLoad(masm, &slow, x1, x2, x0, x3, x4); | 441 GenerateDictionaryLoad(masm, &slow, x1, x2, x0, x3, x4); |
438 __ Ret(); | 442 __ Ret(); |
439 | 443 |
440 // Dictionary load failed, go slow (but don't miss). | 444 // Dictionary load failed, go slow (but don't miss). |
441 __ Bind(&slow); | 445 __ Bind(&slow); |
442 GenerateRuntimeGetProperty(masm); | 446 GenerateRuntimeGetProperty(masm); |
443 | 447 |
444 // Cache miss: Jump to runtime. | 448 // Cache miss: Jump to runtime. |
445 __ Bind(&miss); | 449 __ Bind(&miss); |
446 GenerateMiss(masm); | 450 GenerateMiss(masm); |
447 } | 451 } |
448 | 452 |
449 | 453 |
450 void LoadIC::GenerateMiss(MacroAssembler* masm) { | 454 void LoadIC::GenerateMiss(MacroAssembler* masm) { |
451 // ----------- S t a t e ------------- | 455 // The return address is on the stack. |
452 // -- x2 : name | |
453 // -- lr : return address | |
454 // -- x0 : receiver | |
455 // ----------------------------------- | |
456 Isolate* isolate = masm->isolate(); | 456 Isolate* isolate = masm->isolate(); |
457 ASM_LOCATION("LoadIC::GenerateMiss"); | 457 ASM_LOCATION("LoadIC::GenerateMiss"); |
458 | 458 |
459 __ IncrementCounter(isolate->counters()->load_miss(), 1, x3, x4); | 459 __ IncrementCounter(isolate->counters()->load_miss(), 1, x3, x4); |
460 | 460 |
461 // Perform tail call to the entry. | 461 // Perform tail call to the entry. |
462 __ Push(x0, x2); | 462 __ Push(ReceiverRegister(), NameRegister()); |
463 ExternalReference ref = | 463 ExternalReference ref = |
464 ExternalReference(IC_Utility(kLoadIC_Miss), isolate); | 464 ExternalReference(IC_Utility(kLoadIC_Miss), isolate); |
465 __ TailCallExternalReference(ref, 2, 1); | 465 __ TailCallExternalReference(ref, 2, 1); |
466 } | 466 } |
467 | 467 |
468 | 468 |
469 void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { | 469 void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { |
470 // ---------- S t a t e -------------- | 470 // The return address is on the stack. |
471 // -- x2 : name | 471 __ Push(ReceiverRegister(), NameRegister()); |
472 // -- lr : return address | |
473 // -- x0 : receiver | |
474 // ----------------------------------- | |
475 | |
476 __ Push(x0, x2); | |
477 __ TailCallRuntime(Runtime::kGetProperty, 2, 1); | 472 __ TailCallRuntime(Runtime::kGetProperty, 2, 1); |
478 } | 473 } |
479 | 474 |
480 | 475 |
481 void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) { | 476 void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) { |
482 // ---------- S t a t e -------------- | 477 // ---------- S t a t e -------------- |
483 // -- lr : return address | 478 // -- lr : return address |
484 // -- x0 : key | 479 // -- x0 : key |
485 // -- x1 : receiver | 480 // -- x1 : receiver |
486 // ----------------------------------- | 481 // ----------------------------------- |
487 Register result = x0; | 482 Register result = x0; |
488 Register key = x0; | 483 Register receiver = ReceiverRegister(); |
489 Register receiver = x1; | 484 Register key = NameRegister(); |
| 485 ASSERT(receiver.is(x1)); |
| 486 ASSERT(key.is(x0)); |
| 487 |
490 Label miss, unmapped; | 488 Label miss, unmapped; |
491 | 489 |
492 Register map_scratch = x2; | 490 Register map_scratch = x2; |
493 MemOperand mapped_location = GenerateMappedArgumentsLookup( | 491 MemOperand mapped_location = GenerateMappedArgumentsLookup( |
494 masm, receiver, key, map_scratch, x3, x4, &unmapped, &miss); | 492 masm, receiver, key, map_scratch, x3, x4, &unmapped, &miss); |
495 __ Ldr(result, mapped_location); | 493 __ Ldr(result, mapped_location); |
496 __ Ret(); | 494 __ Ret(); |
497 | 495 |
498 __ Bind(&unmapped); | 496 __ Bind(&unmapped); |
499 // Parameter map is left in map_scratch when a jump on unmapped is done. | 497 // Parameter map is left in map_scratch when a jump on unmapped is done. |
(...skipping 11 matching lines...) Expand all Loading... |
511 | 509 |
512 | 510 |
513 void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) { | 511 void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) { |
514 ASM_LOCATION("KeyedStoreIC::GenerateSloppyArguments"); | 512 ASM_LOCATION("KeyedStoreIC::GenerateSloppyArguments"); |
515 // ---------- S t a t e -------------- | 513 // ---------- S t a t e -------------- |
516 // -- lr : return address | 514 // -- lr : return address |
517 // -- x0 : value | 515 // -- x0 : value |
518 // -- x1 : key | 516 // -- x1 : key |
519 // -- x2 : receiver | 517 // -- x2 : receiver |
520 // ----------------------------------- | 518 // ----------------------------------- |
521 | |
522 Label slow, notin; | 519 Label slow, notin; |
523 | 520 |
524 Register value = x0; | 521 Register value = x0; |
525 Register key = x1; | 522 Register key = x1; |
526 Register receiver = x2; | 523 Register receiver = x2; |
527 Register map = x3; | 524 Register map = x3; |
528 | 525 |
529 // These registers are used by GenerateMappedArgumentsLookup to build a | 526 // These registers are used by GenerateMappedArgumentsLookup to build a |
530 // MemOperand. They are live for as long as the MemOperand is live. | 527 // MemOperand. They are live for as long as the MemOperand is live. |
531 Register mapped1 = x4; | 528 Register mapped1 = x4; |
(...skipping 24 matching lines...) Expand all Loading... |
556 __ Mov(x11, value); | 553 __ Mov(x11, value); |
557 __ RecordWrite(unmapped.base(), x10, x11, | 554 __ RecordWrite(unmapped.base(), x10, x11, |
558 kLRHasNotBeenSaved, kDontSaveFPRegs); | 555 kLRHasNotBeenSaved, kDontSaveFPRegs); |
559 __ Ret(); | 556 __ Ret(); |
560 __ Bind(&slow); | 557 __ Bind(&slow); |
561 GenerateMiss(masm); | 558 GenerateMiss(masm); |
562 } | 559 } |
563 | 560 |
564 | 561 |
565 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { | 562 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { |
566 // ---------- S t a t e -------------- | 563 // The return address is on the stack. |
567 // -- lr : return address | |
568 // -- x0 : key | |
569 // -- x1 : receiver | |
570 // ----------------------------------- | |
571 Isolate* isolate = masm->isolate(); | 564 Isolate* isolate = masm->isolate(); |
572 | 565 |
573 __ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, x10, x11); | 566 __ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, x10, x11); |
574 | 567 |
575 __ Push(x1, x0); | 568 __ Push(ReceiverRegister(), NameRegister()); |
576 | 569 |
577 // Perform tail call to the entry. | 570 // Perform tail call to the entry. |
578 ExternalReference ref = | 571 ExternalReference ref = |
579 ExternalReference(IC_Utility(kKeyedLoadIC_Miss), isolate); | 572 ExternalReference(IC_Utility(kKeyedLoadIC_Miss), isolate); |
580 | 573 |
581 __ TailCallExternalReference(ref, 2, 1); | 574 __ TailCallExternalReference(ref, 2, 1); |
582 } | 575 } |
583 | 576 |
584 | 577 |
585 // IC register specifications | 578 // IC register specifications |
586 const Register LoadIC::ReceiverRegister() { return x0; } | 579 const Register LoadIC::ReceiverRegister() { return x0; } |
587 const Register LoadIC::NameRegister() { return x2; } | 580 const Register LoadIC::NameRegister() { return x2; } |
588 const Register KeyedLoadIC::ReceiverRegister() { return x1; } | 581 const Register KeyedLoadIC::ReceiverRegister() { return x1; } |
589 const Register KeyedLoadIC::NameRegister() { return x0; } | 582 const Register KeyedLoadIC::NameRegister() { return x0; } |
590 | 583 |
591 | 584 |
592 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { | 585 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { |
593 // ---------- S t a t e -------------- | 586 // The return address is on the stack. |
594 // -- lr : return address | 587 __ Push(ReceiverRegister(), NameRegister()); |
595 // -- x0 : key | |
596 // -- x1 : receiver | |
597 // ----------------------------------- | |
598 Register key = x0; | |
599 Register receiver = x1; | |
600 | |
601 __ Push(receiver, key); | |
602 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); | 588 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); |
603 } | 589 } |
604 | 590 |
605 | 591 |
606 static void GenerateKeyedLoadWithSmiKey(MacroAssembler* masm, | 592 static void GenerateKeyedLoadWithSmiKey(MacroAssembler* masm, |
607 Register key, | 593 Register key, |
608 Register receiver, | 594 Register receiver, |
609 Register scratch1, | 595 Register scratch1, |
610 Register scratch2, | 596 Register scratch2, |
611 Register scratch3, | 597 Register scratch3, |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
767 | 753 |
768 | 754 |
769 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { | 755 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { |
770 // ---------- S t a t e -------------- | 756 // ---------- S t a t e -------------- |
771 // -- lr : return address | 757 // -- lr : return address |
772 // -- x0 : key | 758 // -- x0 : key |
773 // -- x1 : receiver | 759 // -- x1 : receiver |
774 // ----------------------------------- | 760 // ----------------------------------- |
775 Label slow, check_name, index_smi, index_name; | 761 Label slow, check_name, index_smi, index_name; |
776 | 762 |
777 Register key = x0; | 763 Register key = NameRegister(); |
778 Register receiver = x1; | 764 Register receiver = ReceiverRegister(); |
| 765 ASSERT(key.is(x0)); |
| 766 ASSERT(receiver.is(x1)); |
779 | 767 |
780 __ JumpIfNotSmi(key, &check_name); | 768 __ JumpIfNotSmi(key, &check_name); |
781 __ Bind(&index_smi); | 769 __ Bind(&index_smi); |
782 // Now the key is known to be a smi. This place is also jumped to from below | 770 // Now the key is known to be a smi. This place is also jumped to from below |
783 // where a numeric string is converted to a smi. | 771 // where a numeric string is converted to a smi. |
784 GenerateKeyedLoadWithSmiKey(masm, key, receiver, x2, x3, x4, x5, x6, &slow); | 772 GenerateKeyedLoadWithSmiKey(masm, key, receiver, x2, x3, x4, x5, x6, &slow); |
785 | 773 |
786 // Slow case, key and receiver still in x0 and x1. | 774 // Slow case, key and receiver still in x0 and x1. |
787 __ Bind(&slow); | 775 __ Bind(&slow); |
788 __ IncrementCounter( | 776 __ IncrementCounter( |
789 masm->isolate()->counters()->keyed_load_generic_slow(), 1, x2, x3); | 777 masm->isolate()->counters()->keyed_load_generic_slow(), 1, x2, x3); |
790 GenerateRuntimeGetProperty(masm); | 778 GenerateRuntimeGetProperty(masm); |
791 | 779 |
792 __ Bind(&check_name); | 780 __ Bind(&check_name); |
793 GenerateKeyNameCheck(masm, key, x2, x3, &index_name, &slow); | 781 GenerateKeyNameCheck(masm, key, x2, x3, &index_name, &slow); |
794 | 782 |
795 GenerateKeyedLoadWithNameKey(masm, key, receiver, x2, x3, x4, x5, x6, &slow); | 783 GenerateKeyedLoadWithNameKey(masm, key, receiver, x2, x3, x4, x5, x6, &slow); |
796 | 784 |
797 __ Bind(&index_name); | 785 __ Bind(&index_name); |
798 __ IndexFromHash(x3, key); | 786 __ IndexFromHash(x3, key); |
799 // Now jump to the place where smi keys are handled. | 787 // Now jump to the place where smi keys are handled. |
800 __ B(&index_smi); | 788 __ B(&index_smi); |
801 } | 789 } |
802 | 790 |
803 | 791 |
804 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { | 792 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { |
805 // ---------- S t a t e -------------- | 793 // Return address is on the stack. |
806 // -- lr : return address | |
807 // -- x0 : key (index) | |
808 // -- x1 : receiver | |
809 // ----------------------------------- | |
810 Label miss; | 794 Label miss; |
811 | 795 |
812 Register index = x0; | 796 Register receiver = ReceiverRegister(); |
813 Register receiver = x1; | 797 Register index = NameRegister(); |
814 Register result = x0; | 798 Register result = x0; |
815 Register scratch = x3; | 799 Register scratch = x3; |
| 800 ASSERT(!scratch.is(receiver) && !scratch.is(index)); |
816 | 801 |
817 StringCharAtGenerator char_at_generator(receiver, | 802 StringCharAtGenerator char_at_generator(receiver, |
818 index, | 803 index, |
819 scratch, | 804 scratch, |
820 result, | 805 result, |
821 &miss, // When not a string. | 806 &miss, // When not a string. |
822 &miss, // When not a number. | 807 &miss, // When not a number. |
823 &miss, // When index out of range. | 808 &miss, // When index out of range. |
824 STRING_INDEX_IS_ARRAY_INDEX); | 809 STRING_INDEX_IS_ARRAY_INDEX); |
825 char_at_generator.GenerateFast(masm); | 810 char_at_generator.GenerateFast(masm); |
826 __ Ret(); | 811 __ Ret(); |
827 | 812 |
828 StubRuntimeCallHelper call_helper; | 813 StubRuntimeCallHelper call_helper; |
829 char_at_generator.GenerateSlow(masm, call_helper); | 814 char_at_generator.GenerateSlow(masm, call_helper); |
830 | 815 |
831 __ Bind(&miss); | 816 __ Bind(&miss); |
832 GenerateMiss(masm); | 817 GenerateMiss(masm); |
833 } | 818 } |
834 | 819 |
835 | 820 |
836 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { | 821 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { |
837 // ---------- S t a t e -------------- | 822 // Return address is on the stack. |
838 // -- lr : return address | |
839 // -- x0 : key | |
840 // -- x1 : receiver | |
841 // ----------------------------------- | |
842 Label slow; | 823 Label slow; |
843 Register key = x0; | 824 |
844 Register receiver = x1; | 825 Register receiver = ReceiverRegister(); |
| 826 Register key = NameRegister(); |
| 827 Register scratch1 = x2; |
| 828 Register scratch2 = x3; |
| 829 ASSERT(!scratch1.is(receiver) && !scratch1.is(key)); |
| 830 ASSERT(!scratch2.is(receiver) && !scratch2.is(key)); |
845 | 831 |
846 // Check that the receiver isn't a smi. | 832 // Check that the receiver isn't a smi. |
847 __ JumpIfSmi(receiver, &slow); | 833 __ JumpIfSmi(receiver, &slow); |
848 | 834 |
849 // Check that the key is an array index, that is Uint32. | 835 // Check that the key is an array index, that is Uint32. |
850 __ TestAndBranchIfAnySet(key, kSmiTagMask | kSmiSignMask, &slow); | 836 __ TestAndBranchIfAnySet(key, kSmiTagMask | kSmiSignMask, &slow); |
851 | 837 |
852 // Get the map of the receiver. | 838 // Get the map of the receiver. |
853 Register map = x2; | 839 Register map = scratch1; |
854 __ Ldr(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); | 840 __ Ldr(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
855 | 841 |
856 // Check that it has indexed interceptor and access checks | 842 // Check that it has indexed interceptor and access checks |
857 // are not enabled for this object. | 843 // are not enabled for this object. |
858 __ Ldrb(x3, FieldMemOperand(map, Map::kBitFieldOffset)); | 844 __ Ldrb(scratch2, FieldMemOperand(map, Map::kBitFieldOffset)); |
859 ASSERT(kSlowCaseBitFieldMask == | 845 ASSERT(kSlowCaseBitFieldMask == |
860 ((1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor))); | 846 ((1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor))); |
861 __ Tbnz(x3, Map::kIsAccessCheckNeeded, &slow); | 847 __ Tbnz(scratch2, Map::kIsAccessCheckNeeded, &slow); |
862 __ Tbz(x3, Map::kHasIndexedInterceptor, &slow); | 848 __ Tbz(scratch2, Map::kHasIndexedInterceptor, &slow); |
863 | 849 |
864 // Everything is fine, call runtime. | 850 // Everything is fine, call runtime. |
865 __ Push(receiver, key); | 851 __ Push(receiver, key); |
866 __ TailCallExternalReference( | 852 __ TailCallExternalReference( |
867 ExternalReference(IC_Utility(kKeyedLoadPropertyWithInterceptor), | 853 ExternalReference(IC_Utility(kKeyedLoadPropertyWithInterceptor), |
868 masm->isolate()), | 854 masm->isolate()), |
869 2, | 855 2, |
870 1); | 856 1); |
871 | 857 |
872 __ Bind(&slow); | 858 __ Bind(&slow); |
(...skipping 512 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1385 ASSERT(to_patch->Mask(TestBranchMask) == TBNZ); | 1371 ASSERT(to_patch->Mask(TestBranchMask) == TBNZ); |
1386 // This is JumpIfSmi(smi_reg, branch_imm). | 1372 // This is JumpIfSmi(smi_reg, branch_imm). |
1387 patcher.tbz(smi_reg, 0, branch_imm); | 1373 patcher.tbz(smi_reg, 0, branch_imm); |
1388 } | 1374 } |
1389 } | 1375 } |
1390 | 1376 |
1391 | 1377 |
1392 } } // namespace v8::internal | 1378 } } // namespace v8::internal |
1393 | 1379 |
1394 #endif // V8_TARGET_ARCH_ARM64 | 1380 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |