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 389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
400 | 400 |
401 __ Add(backing_store, | 401 __ Add(backing_store, |
402 backing_store, | 402 backing_store, |
403 FixedArray::kHeaderSize - kHeapObjectTag); | 403 FixedArray::kHeaderSize - kHeapObjectTag); |
404 __ SmiUntag(scratch, key); | 404 __ SmiUntag(scratch, key); |
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 // The return address is in lr. |
411 // -- x2 : name | 411 Register receiver = ReceiverRegister(); |
412 // -- lr : return address | 412 Register name = NameRegister(); |
413 // -- x0 : receiver | 413 ASSERT(receiver.is(x1)); |
414 // ----------------------------------- | 414 ASSERT(name.is(x2)); |
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, receiver, name, 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 // -- x1 : receiver |
433 // ----------------------------------- | 431 // ----------------------------------- |
434 ASSERT(x0.is(ReceiverRegister())); | 432 ASSERT(x1.is(ReceiverRegister())); |
435 ASSERT(x2.is(NameRegister())); | 433 ASSERT(x2.is(NameRegister())); |
436 Label miss, slow; | 434 Label miss, slow; |
437 | 435 |
438 GenerateNameDictionaryReceiverCheck(masm, x0, x1, x3, x4, &miss); | 436 GenerateNameDictionaryReceiverCheck(masm, x1, x0, x3, x4, &miss); |
439 | 437 |
440 // x1 now holds the property dictionary. | 438 // x0 now holds the property dictionary. |
441 GenerateDictionaryLoad(masm, &slow, x1, x2, x0, x3, x4); | 439 GenerateDictionaryLoad(masm, &slow, x0, x2, x0, x3, x4); |
442 __ Ret(); | 440 __ Ret(); |
443 | 441 |
444 // Dictionary load failed, go slow (but don't miss). | 442 // Dictionary load failed, go slow (but don't miss). |
445 __ Bind(&slow); | 443 __ Bind(&slow); |
446 GenerateRuntimeGetProperty(masm); | 444 GenerateRuntimeGetProperty(masm); |
447 | 445 |
448 // Cache miss: Jump to runtime. | 446 // Cache miss: Jump to runtime. |
449 __ Bind(&miss); | 447 __ Bind(&miss); |
450 GenerateMiss(masm); | 448 GenerateMiss(masm); |
451 } | 449 } |
452 | 450 |
453 | 451 |
454 void LoadIC::GenerateMiss(MacroAssembler* masm) { | 452 void LoadIC::GenerateMiss(MacroAssembler* masm) { |
455 // The return address is on the stack. | 453 // The return address is in lr. |
456 Isolate* isolate = masm->isolate(); | 454 Isolate* isolate = masm->isolate(); |
457 ASM_LOCATION("LoadIC::GenerateMiss"); | 455 ASM_LOCATION("LoadIC::GenerateMiss"); |
458 | 456 |
459 __ IncrementCounter(isolate->counters()->load_miss(), 1, x3, x4); | 457 __ IncrementCounter(isolate->counters()->load_miss(), 1, x3, x4); |
460 | 458 |
461 // Perform tail call to the entry. | 459 // Perform tail call to the entry. |
462 __ Push(ReceiverRegister(), NameRegister()); | 460 __ Push(ReceiverRegister(), NameRegister()); |
463 ExternalReference ref = | 461 ExternalReference ref = |
464 ExternalReference(IC_Utility(kLoadIC_Miss), isolate); | 462 ExternalReference(IC_Utility(kLoadIC_Miss), isolate); |
465 __ TailCallExternalReference(ref, 2, 1); | 463 __ TailCallExternalReference(ref, 2, 1); |
466 } | 464 } |
467 | 465 |
468 | 466 |
469 void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { | 467 void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { |
470 // The return address is on the stack. | 468 // The return address is in lr. |
471 __ Push(ReceiverRegister(), NameRegister()); | 469 __ Push(ReceiverRegister(), NameRegister()); |
472 __ TailCallRuntime(Runtime::kGetProperty, 2, 1); | 470 __ TailCallRuntime(Runtime::kGetProperty, 2, 1); |
473 } | 471 } |
474 | 472 |
475 | 473 |
476 void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) { | 474 void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) { |
477 // ---------- S t a t e -------------- | 475 // The return address is in lr. |
478 // -- lr : return address | |
479 // -- x0 : key | |
480 // -- x1 : receiver | |
481 // ----------------------------------- | |
482 Register result = x0; | 476 Register result = x0; |
483 Register receiver = ReceiverRegister(); | 477 Register receiver = ReceiverRegister(); |
484 Register key = NameRegister(); | 478 Register key = NameRegister(); |
485 ASSERT(receiver.is(x1)); | 479 ASSERT(receiver.is(x1)); |
486 ASSERT(key.is(x0)); | 480 ASSERT(key.is(x2)); |
487 | 481 |
488 Label miss, unmapped; | 482 Label miss, unmapped; |
489 | 483 |
490 Register map_scratch = x2; | 484 Register map_scratch = x0; |
491 MemOperand mapped_location = GenerateMappedArgumentsLookup( | 485 MemOperand mapped_location = GenerateMappedArgumentsLookup( |
492 masm, receiver, key, map_scratch, x3, x4, &unmapped, &miss); | 486 masm, receiver, key, map_scratch, x3, x4, &unmapped, &miss); |
493 __ Ldr(result, mapped_location); | 487 __ Ldr(result, mapped_location); |
494 __ Ret(); | 488 __ Ret(); |
495 | 489 |
496 __ Bind(&unmapped); | 490 __ Bind(&unmapped); |
497 // Parameter map is left in map_scratch when a jump on unmapped is done. | 491 // Parameter map is left in map_scratch when a jump on unmapped is done. |
498 MemOperand unmapped_location = | 492 MemOperand unmapped_location = |
499 GenerateUnmappedArgumentsLookup(masm, key, map_scratch, x3, &miss); | 493 GenerateUnmappedArgumentsLookup(masm, key, map_scratch, x3, &miss); |
500 __ Ldr(x2, unmapped_location); | 494 __ Ldr(result, unmapped_location); |
501 __ JumpIfRoot(x2, Heap::kTheHoleValueRootIndex, &miss); | 495 __ JumpIfRoot(result, Heap::kTheHoleValueRootIndex, &miss); |
502 // Move the result in x0. x0 must be preserved on miss. | |
503 __ Mov(result, x2); | |
504 __ Ret(); | 496 __ Ret(); |
505 | 497 |
506 __ Bind(&miss); | 498 __ Bind(&miss); |
507 GenerateMiss(masm); | 499 GenerateMiss(masm); |
508 } | 500 } |
509 | 501 |
510 | 502 |
511 void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) { | 503 void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) { |
512 ASM_LOCATION("KeyedStoreIC::GenerateSloppyArguments"); | 504 ASM_LOCATION("KeyedStoreIC::GenerateSloppyArguments"); |
513 // ---------- S t a t e -------------- | 505 // ---------- S t a t e -------------- |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
553 __ Mov(x11, value); | 545 __ Mov(x11, value); |
554 __ RecordWrite(unmapped.base(), x10, x11, | 546 __ RecordWrite(unmapped.base(), x10, x11, |
555 kLRHasNotBeenSaved, kDontSaveFPRegs); | 547 kLRHasNotBeenSaved, kDontSaveFPRegs); |
556 __ Ret(); | 548 __ Ret(); |
557 __ Bind(&slow); | 549 __ Bind(&slow); |
558 GenerateMiss(masm); | 550 GenerateMiss(masm); |
559 } | 551 } |
560 | 552 |
561 | 553 |
562 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { | 554 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { |
563 // The return address is on the stack. | 555 // The return address is in lr. |
564 Isolate* isolate = masm->isolate(); | 556 Isolate* isolate = masm->isolate(); |
565 | 557 |
566 __ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, x10, x11); | 558 __ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, x10, x11); |
567 | 559 |
568 __ Push(ReceiverRegister(), NameRegister()); | 560 __ Push(ReceiverRegister(), NameRegister()); |
569 | 561 |
570 // Perform tail call to the entry. | 562 // Perform tail call to the entry. |
571 ExternalReference ref = | 563 ExternalReference ref = |
572 ExternalReference(IC_Utility(kKeyedLoadIC_Miss), isolate); | 564 ExternalReference(IC_Utility(kKeyedLoadIC_Miss), isolate); |
573 | 565 |
574 __ TailCallExternalReference(ref, 2, 1); | 566 __ TailCallExternalReference(ref, 2, 1); |
575 } | 567 } |
576 | 568 |
577 | 569 |
578 // IC register specifications | 570 // IC register specifications |
579 const Register LoadIC::ReceiverRegister() { return x0; } | 571 const Register LoadIC::ReceiverRegister() { return x1; } |
580 const Register LoadIC::NameRegister() { return x2; } | 572 const Register LoadIC::NameRegister() { return x2; } |
581 const Register KeyedLoadIC::ReceiverRegister() { return x1; } | |
582 const Register KeyedLoadIC::NameRegister() { return x0; } | |
583 | 573 |
584 | 574 |
585 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { | 575 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { |
586 // The return address is on the stack. | 576 // The return address is in lr. |
587 __ Push(ReceiverRegister(), NameRegister()); | 577 __ Push(ReceiverRegister(), NameRegister()); |
588 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); | 578 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); |
589 } | 579 } |
590 | 580 |
591 | 581 |
592 static void GenerateKeyedLoadWithSmiKey(MacroAssembler* masm, | 582 static void GenerateKeyedLoadWithSmiKey(MacroAssembler* masm, |
593 Register key, | 583 Register key, |
594 Register receiver, | 584 Register receiver, |
595 Register scratch1, | 585 Register scratch1, |
596 Register scratch2, | 586 Register scratch2, |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
746 GenerateGlobalInstanceTypeCheck(masm, scratch1, slow); | 736 GenerateGlobalInstanceTypeCheck(masm, scratch1, slow); |
747 // Load the property. | 737 // Load the property. |
748 GenerateDictionaryLoad(masm, slow, scratch2, key, result, scratch1, scratch3); | 738 GenerateDictionaryLoad(masm, slow, scratch2, key, result, scratch1, scratch3); |
749 __ IncrementCounter(isolate->counters()->keyed_load_generic_symbol(), | 739 __ IncrementCounter(isolate->counters()->keyed_load_generic_symbol(), |
750 1, scratch1, scratch2); | 740 1, scratch1, scratch2); |
751 __ Ret(); | 741 __ Ret(); |
752 } | 742 } |
753 | 743 |
754 | 744 |
755 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { | 745 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { |
756 // ---------- S t a t e -------------- | 746 // The return address is in lr. |
757 // -- lr : return address | |
758 // -- x0 : key | |
759 // -- x1 : receiver | |
760 // ----------------------------------- | |
761 Label slow, check_name, index_smi, index_name; | 747 Label slow, check_name, index_smi, index_name; |
762 | 748 |
763 Register key = NameRegister(); | 749 Register key = NameRegister(); |
764 Register receiver = ReceiverRegister(); | 750 Register receiver = ReceiverRegister(); |
765 ASSERT(key.is(x0)); | 751 ASSERT(key.is(x2)); |
766 ASSERT(receiver.is(x1)); | 752 ASSERT(receiver.is(x1)); |
767 | 753 |
768 __ JumpIfNotSmi(key, &check_name); | 754 __ JumpIfNotSmi(key, &check_name); |
769 __ Bind(&index_smi); | 755 __ Bind(&index_smi); |
770 // Now the key is known to be a smi. This place is also jumped to from below | 756 // 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. | 757 // where a numeric string is converted to a smi. |
772 GenerateKeyedLoadWithSmiKey(masm, key, receiver, x2, x3, x4, x5, x6, &slow); | 758 GenerateKeyedLoadWithSmiKey(masm, key, receiver, x7, x3, x4, x5, x6, &slow); |
773 | 759 |
774 // Slow case, key and receiver still in x0 and x1. | 760 // Slow case. |
775 __ Bind(&slow); | 761 __ Bind(&slow); |
776 __ IncrementCounter( | 762 __ IncrementCounter( |
777 masm->isolate()->counters()->keyed_load_generic_slow(), 1, x2, x3); | 763 masm->isolate()->counters()->keyed_load_generic_slow(), 1, x4, x3); |
778 GenerateRuntimeGetProperty(masm); | 764 GenerateRuntimeGetProperty(masm); |
779 | 765 |
780 __ Bind(&check_name); | 766 __ Bind(&check_name); |
781 GenerateKeyNameCheck(masm, key, x2, x3, &index_name, &slow); | 767 GenerateKeyNameCheck(masm, key, x0, x3, &index_name, &slow); |
782 | 768 |
783 GenerateKeyedLoadWithNameKey(masm, key, receiver, x2, x3, x4, x5, x6, &slow); | 769 GenerateKeyedLoadWithNameKey(masm, key, receiver, x7, x3, x4, x5, x6, &slow); |
784 | 770 |
785 __ Bind(&index_name); | 771 __ Bind(&index_name); |
786 __ IndexFromHash(x3, key); | 772 __ IndexFromHash(x3, key); |
787 // Now jump to the place where smi keys are handled. | 773 // Now jump to the place where smi keys are handled. |
788 __ B(&index_smi); | 774 __ B(&index_smi); |
789 } | 775 } |
790 | 776 |
791 | 777 |
792 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { | 778 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { |
793 // Return address is on the stack. | 779 // Return address is in lr. |
794 Label miss; | 780 Label miss; |
795 | 781 |
796 Register receiver = ReceiverRegister(); | 782 Register receiver = ReceiverRegister(); |
797 Register index = NameRegister(); | 783 Register index = NameRegister(); |
798 Register result = x0; | 784 Register result = x0; |
799 Register scratch = x3; | 785 Register scratch = x3; |
800 ASSERT(!scratch.is(receiver) && !scratch.is(index)); | 786 ASSERT(!scratch.is(receiver) && !scratch.is(index)); |
801 | 787 |
802 StringCharAtGenerator char_at_generator(receiver, | 788 StringCharAtGenerator char_at_generator(receiver, |
803 index, | 789 index, |
804 scratch, | 790 scratch, |
805 result, | 791 result, |
806 &miss, // When not a string. | 792 &miss, // When not a string. |
807 &miss, // When not a number. | 793 &miss, // When not a number. |
808 &miss, // When index out of range. | 794 &miss, // When index out of range. |
809 STRING_INDEX_IS_ARRAY_INDEX); | 795 STRING_INDEX_IS_ARRAY_INDEX); |
810 char_at_generator.GenerateFast(masm); | 796 char_at_generator.GenerateFast(masm); |
811 __ Ret(); | 797 __ Ret(); |
812 | 798 |
813 StubRuntimeCallHelper call_helper; | 799 StubRuntimeCallHelper call_helper; |
814 char_at_generator.GenerateSlow(masm, call_helper); | 800 char_at_generator.GenerateSlow(masm, call_helper); |
815 | 801 |
816 __ Bind(&miss); | 802 __ Bind(&miss); |
817 GenerateMiss(masm); | 803 GenerateMiss(masm); |
818 } | 804 } |
819 | 805 |
820 | 806 |
821 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { | 807 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { |
822 // Return address is on the stack. | 808 // Return address is in lr. |
823 Label slow; | 809 Label slow; |
824 | 810 |
825 Register receiver = ReceiverRegister(); | 811 Register receiver = ReceiverRegister(); |
826 Register key = NameRegister(); | 812 Register key = NameRegister(); |
827 Register scratch1 = x2; | 813 Register scratch1 = x3; |
828 Register scratch2 = x3; | 814 Register scratch2 = x4; |
829 ASSERT(!scratch1.is(receiver) && !scratch1.is(key)); | 815 ASSERT(!AreAliased(scratch1, scratch2, receiver, key)); |
830 ASSERT(!scratch2.is(receiver) && !scratch2.is(key)); | |
831 | 816 |
832 // Check that the receiver isn't a smi. | 817 // Check that the receiver isn't a smi. |
833 __ JumpIfSmi(receiver, &slow); | 818 __ JumpIfSmi(receiver, &slow); |
834 | 819 |
835 // Check that the key is an array index, that is Uint32. | 820 // Check that the key is an array index, that is Uint32. |
836 __ TestAndBranchIfAnySet(key, kSmiTagMask | kSmiSignMask, &slow); | 821 __ TestAndBranchIfAnySet(key, kSmiTagMask | kSmiSignMask, &slow); |
837 | 822 |
838 // Get the map of the receiver. | 823 // Get the map of the receiver. |
839 Register map = scratch1; | 824 Register map = scratch1; |
840 __ Ldr(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); | 825 __ Ldr(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
(...skipping 530 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1371 ASSERT(to_patch->Mask(TestBranchMask) == TBNZ); | 1356 ASSERT(to_patch->Mask(TestBranchMask) == TBNZ); |
1372 // This is JumpIfSmi(smi_reg, branch_imm). | 1357 // This is JumpIfSmi(smi_reg, branch_imm). |
1373 patcher.tbz(smi_reg, 0, branch_imm); | 1358 patcher.tbz(smi_reg, 0, branch_imm); |
1374 } | 1359 } |
1375 } | 1360 } |
1376 | 1361 |
1377 | 1362 |
1378 } } // namespace v8::internal | 1363 } } // namespace v8::internal |
1379 | 1364 |
1380 #endif // V8_TARGET_ARCH_ARM64 | 1365 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |