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