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/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/base/division-by-constant.h" | 10 #include "src/base/division-by-constant.h" |
(...skipping 2683 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2694 Bind(&loop); | 2694 Bind(&loop); |
2695 Stp(filler, filler, MemOperand(field_ptr, 2 * kPointerSize, PostIndex)); | 2695 Stp(filler, filler, MemOperand(field_ptr, 2 * kPointerSize, PostIndex)); |
2696 Subs(counter, counter, 2); | 2696 Subs(counter, counter, 2); |
2697 Bind(&entry); | 2697 Bind(&entry); |
2698 B(gt, &loop); | 2698 B(gt, &loop); |
2699 | 2699 |
2700 Bind(&done); | 2700 Bind(&done); |
2701 } | 2701 } |
2702 | 2702 |
2703 | 2703 |
2704 void MacroAssembler::JumpIfEitherIsNotSequentialAsciiStrings( | 2704 void MacroAssembler::JumpIfEitherIsNotSequentialOneByteStrings( |
2705 Register first, | 2705 Register first, Register second, Register scratch1, Register scratch2, |
2706 Register second, | 2706 Label* failure, SmiCheckType smi_check) { |
2707 Register scratch1, | |
2708 Register scratch2, | |
2709 Label* failure, | |
2710 SmiCheckType smi_check) { | |
2711 | |
2712 if (smi_check == DO_SMI_CHECK) { | 2707 if (smi_check == DO_SMI_CHECK) { |
2713 JumpIfEitherSmi(first, second, failure); | 2708 JumpIfEitherSmi(first, second, failure); |
2714 } else if (emit_debug_code()) { | 2709 } else if (emit_debug_code()) { |
2715 DCHECK(smi_check == DONT_DO_SMI_CHECK); | 2710 DCHECK(smi_check == DONT_DO_SMI_CHECK); |
2716 Label not_smi; | 2711 Label not_smi; |
2717 JumpIfEitherSmi(first, second, NULL, ¬_smi); | 2712 JumpIfEitherSmi(first, second, NULL, ¬_smi); |
2718 | 2713 |
2719 // At least one input is a smi, but the flags indicated a smi check wasn't | 2714 // At least one input is a smi, but the flags indicated a smi check wasn't |
2720 // needed. | 2715 // needed. |
2721 Abort(kUnexpectedSmi); | 2716 Abort(kUnexpectedSmi); |
2722 | 2717 |
2723 Bind(¬_smi); | 2718 Bind(¬_smi); |
2724 } | 2719 } |
2725 | 2720 |
2726 // Test that both first and second are sequential ASCII strings. | 2721 // Test that both first and second are sequential one-byte strings. |
2727 Ldr(scratch1, FieldMemOperand(first, HeapObject::kMapOffset)); | 2722 Ldr(scratch1, FieldMemOperand(first, HeapObject::kMapOffset)); |
2728 Ldr(scratch2, FieldMemOperand(second, HeapObject::kMapOffset)); | 2723 Ldr(scratch2, FieldMemOperand(second, HeapObject::kMapOffset)); |
2729 Ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); | 2724 Ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); |
2730 Ldrb(scratch2, FieldMemOperand(scratch2, Map::kInstanceTypeOffset)); | 2725 Ldrb(scratch2, FieldMemOperand(scratch2, Map::kInstanceTypeOffset)); |
2731 | 2726 |
2732 JumpIfEitherInstanceTypeIsNotSequentialAscii(scratch1, | 2727 JumpIfEitherInstanceTypeIsNotSequentialOneByte(scratch1, scratch2, scratch1, |
2733 scratch2, | 2728 scratch2, failure); |
2734 scratch1, | |
2735 scratch2, | |
2736 failure); | |
2737 } | 2729 } |
2738 | 2730 |
2739 | 2731 |
2740 void MacroAssembler::JumpIfEitherInstanceTypeIsNotSequentialAscii( | 2732 void MacroAssembler::JumpIfEitherInstanceTypeIsNotSequentialOneByte( |
2741 Register first, | 2733 Register first, Register second, Register scratch1, Register scratch2, |
2742 Register second, | |
2743 Register scratch1, | |
2744 Register scratch2, | |
2745 Label* failure) { | 2734 Label* failure) { |
2746 DCHECK(!AreAliased(scratch1, second)); | 2735 DCHECK(!AreAliased(scratch1, second)); |
2747 DCHECK(!AreAliased(scratch1, scratch2)); | 2736 DCHECK(!AreAliased(scratch1, scratch2)); |
2748 static const int kFlatAsciiStringMask = | 2737 static const int kFlatOneByteStringMask = |
2749 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask; | 2738 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask; |
2750 static const int kFlatAsciiStringTag = ASCII_STRING_TYPE; | 2739 static const int kFlatOneByteStringTag = ONE_BYTE_STRING_TYPE; |
2751 And(scratch1, first, kFlatAsciiStringMask); | 2740 And(scratch1, first, kFlatOneByteStringMask); |
2752 And(scratch2, second, kFlatAsciiStringMask); | 2741 And(scratch2, second, kFlatOneByteStringMask); |
2753 Cmp(scratch1, kFlatAsciiStringTag); | 2742 Cmp(scratch1, kFlatOneByteStringTag); |
2754 Ccmp(scratch2, kFlatAsciiStringTag, NoFlag, eq); | 2743 Ccmp(scratch2, kFlatOneByteStringTag, NoFlag, eq); |
2755 B(ne, failure); | 2744 B(ne, failure); |
2756 } | 2745 } |
2757 | 2746 |
2758 | 2747 |
2759 void MacroAssembler::JumpIfInstanceTypeIsNotSequentialAscii(Register type, | 2748 void MacroAssembler::JumpIfInstanceTypeIsNotSequentialOneByte(Register type, |
2760 Register scratch, | 2749 Register scratch, |
2761 Label* failure) { | 2750 Label* failure) { |
2762 const int kFlatAsciiStringMask = | 2751 const int kFlatOneByteStringMask = |
2763 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask; | 2752 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask; |
2764 const int kFlatAsciiStringTag = | 2753 const int kFlatOneByteStringTag = |
2765 kStringTag | kOneByteStringTag | kSeqStringTag; | 2754 kStringTag | kOneByteStringTag | kSeqStringTag; |
2766 And(scratch, type, kFlatAsciiStringMask); | 2755 And(scratch, type, kFlatOneByteStringMask); |
2767 Cmp(scratch, kFlatAsciiStringTag); | 2756 Cmp(scratch, kFlatOneByteStringTag); |
2768 B(ne, failure); | 2757 B(ne, failure); |
2769 } | 2758 } |
2770 | 2759 |
2771 | 2760 |
2772 void MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialAscii( | 2761 void MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialOneByte( |
2773 Register first, | 2762 Register first, Register second, Register scratch1, Register scratch2, |
2774 Register second, | |
2775 Register scratch1, | |
2776 Register scratch2, | |
2777 Label* failure) { | 2763 Label* failure) { |
2778 DCHECK(!AreAliased(first, second, scratch1, scratch2)); | 2764 DCHECK(!AreAliased(first, second, scratch1, scratch2)); |
2779 const int kFlatAsciiStringMask = | 2765 const int kFlatOneByteStringMask = |
2780 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask; | 2766 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask; |
2781 const int kFlatAsciiStringTag = | 2767 const int kFlatOneByteStringTag = |
2782 kStringTag | kOneByteStringTag | kSeqStringTag; | 2768 kStringTag | kOneByteStringTag | kSeqStringTag; |
2783 And(scratch1, first, kFlatAsciiStringMask); | 2769 And(scratch1, first, kFlatOneByteStringMask); |
2784 And(scratch2, second, kFlatAsciiStringMask); | 2770 And(scratch2, second, kFlatOneByteStringMask); |
2785 Cmp(scratch1, kFlatAsciiStringTag); | 2771 Cmp(scratch1, kFlatOneByteStringTag); |
2786 Ccmp(scratch2, kFlatAsciiStringTag, NoFlag, eq); | 2772 Ccmp(scratch2, kFlatOneByteStringTag, NoFlag, eq); |
2787 B(ne, failure); | 2773 B(ne, failure); |
2788 } | 2774 } |
2789 | 2775 |
2790 | 2776 |
2791 void MacroAssembler::JumpIfNotUniqueName(Register type, | 2777 void MacroAssembler::JumpIfNotUniqueName(Register type, |
2792 Label* not_unique_name) { | 2778 Label* not_unique_name) { |
2793 STATIC_ASSERT((kInternalizedTag == 0) && (kStringTag == 0)); | 2779 STATIC_ASSERT((kInternalizedTag == 0) && (kStringTag == 0)); |
2794 // if ((type is string && type is internalized) || type == SYMBOL_TYPE) { | 2780 // if ((type is string && type is internalized) || type == SYMBOL_TYPE) { |
2795 // continue | 2781 // continue |
2796 // } else { | 2782 // } else { |
(...skipping 771 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3568 | 3554 |
3569 // Set the map, length and hash field. | 3555 // Set the map, length and hash field. |
3570 InitializeNewString(result, | 3556 InitializeNewString(result, |
3571 length, | 3557 length, |
3572 Heap::kStringMapRootIndex, | 3558 Heap::kStringMapRootIndex, |
3573 scratch1, | 3559 scratch1, |
3574 scratch2); | 3560 scratch2); |
3575 } | 3561 } |
3576 | 3562 |
3577 | 3563 |
3578 void MacroAssembler::AllocateAsciiString(Register result, | 3564 void MacroAssembler::AllocateOneByteString(Register result, Register length, |
3579 Register length, | 3565 Register scratch1, Register scratch2, |
3580 Register scratch1, | 3566 Register scratch3, |
3581 Register scratch2, | 3567 Label* gc_required) { |
3582 Register scratch3, | |
3583 Label* gc_required) { | |
3584 DCHECK(!AreAliased(result, length, scratch1, scratch2, scratch3)); | 3568 DCHECK(!AreAliased(result, length, scratch1, scratch2, scratch3)); |
3585 // Calculate the number of bytes needed for the characters in the string while | 3569 // Calculate the number of bytes needed for the characters in the string while |
3586 // observing object alignment. | 3570 // observing object alignment. |
3587 STATIC_ASSERT((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0); | 3571 STATIC_ASSERT((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0); |
3588 STATIC_ASSERT(kCharSize == 1); | 3572 STATIC_ASSERT(kCharSize == 1); |
3589 Add(scratch1, length, kObjectAlignmentMask + SeqOneByteString::kHeaderSize); | 3573 Add(scratch1, length, kObjectAlignmentMask + SeqOneByteString::kHeaderSize); |
3590 Bic(scratch1, scratch1, kObjectAlignmentMask); | 3574 Bic(scratch1, scratch1, kObjectAlignmentMask); |
3591 | 3575 |
3592 // Allocate ASCII string in new space. | 3576 // Allocate one-byte string in new space. |
3593 Allocate(scratch1, | 3577 Allocate(scratch1, |
3594 result, | 3578 result, |
3595 scratch2, | 3579 scratch2, |
3596 scratch3, | 3580 scratch3, |
3597 gc_required, | 3581 gc_required, |
3598 TAG_OBJECT); | 3582 TAG_OBJECT); |
3599 | 3583 |
3600 // Set the map, length and hash field. | 3584 // Set the map, length and hash field. |
3601 InitializeNewString(result, | 3585 InitializeNewString(result, length, Heap::kOneByteStringMapRootIndex, |
3602 length, | 3586 scratch1, scratch2); |
3603 Heap::kAsciiStringMapRootIndex, | |
3604 scratch1, | |
3605 scratch2); | |
3606 } | 3587 } |
3607 | 3588 |
3608 | 3589 |
3609 void MacroAssembler::AllocateTwoByteConsString(Register result, | 3590 void MacroAssembler::AllocateTwoByteConsString(Register result, |
3610 Register length, | 3591 Register length, |
3611 Register scratch1, | 3592 Register scratch1, |
3612 Register scratch2, | 3593 Register scratch2, |
3613 Label* gc_required) { | 3594 Label* gc_required) { |
3614 Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required, | 3595 Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required, |
3615 TAG_OBJECT); | 3596 TAG_OBJECT); |
3616 | 3597 |
3617 InitializeNewString(result, | 3598 InitializeNewString(result, |
3618 length, | 3599 length, |
3619 Heap::kConsStringMapRootIndex, | 3600 Heap::kConsStringMapRootIndex, |
3620 scratch1, | 3601 scratch1, |
3621 scratch2); | 3602 scratch2); |
3622 } | 3603 } |
3623 | 3604 |
3624 | 3605 |
3625 void MacroAssembler::AllocateAsciiConsString(Register result, | 3606 void MacroAssembler::AllocateOneByteConsString(Register result, Register length, |
3626 Register length, | 3607 Register scratch1, |
3627 Register scratch1, | 3608 Register scratch2, |
3628 Register scratch2, | 3609 Label* gc_required) { |
3629 Label* gc_required) { | |
3630 Allocate(ConsString::kSize, | 3610 Allocate(ConsString::kSize, |
3631 result, | 3611 result, |
3632 scratch1, | 3612 scratch1, |
3633 scratch2, | 3613 scratch2, |
3634 gc_required, | 3614 gc_required, |
3635 TAG_OBJECT); | 3615 TAG_OBJECT); |
3636 | 3616 |
3637 InitializeNewString(result, | 3617 InitializeNewString(result, length, Heap::kConsOneByteStringMapRootIndex, |
3638 length, | 3618 scratch1, scratch2); |
3639 Heap::kConsAsciiStringMapRootIndex, | |
3640 scratch1, | |
3641 scratch2); | |
3642 } | 3619 } |
3643 | 3620 |
3644 | 3621 |
3645 void MacroAssembler::AllocateTwoByteSlicedString(Register result, | 3622 void MacroAssembler::AllocateTwoByteSlicedString(Register result, |
3646 Register length, | 3623 Register length, |
3647 Register scratch1, | 3624 Register scratch1, |
3648 Register scratch2, | 3625 Register scratch2, |
3649 Label* gc_required) { | 3626 Label* gc_required) { |
3650 DCHECK(!AreAliased(result, length, scratch1, scratch2)); | 3627 DCHECK(!AreAliased(result, length, scratch1, scratch2)); |
3651 Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required, | 3628 Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required, |
3652 TAG_OBJECT); | 3629 TAG_OBJECT); |
3653 | 3630 |
3654 InitializeNewString(result, | 3631 InitializeNewString(result, |
3655 length, | 3632 length, |
3656 Heap::kSlicedStringMapRootIndex, | 3633 Heap::kSlicedStringMapRootIndex, |
3657 scratch1, | 3634 scratch1, |
3658 scratch2); | 3635 scratch2); |
3659 } | 3636 } |
3660 | 3637 |
3661 | 3638 |
3662 void MacroAssembler::AllocateAsciiSlicedString(Register result, | 3639 void MacroAssembler::AllocateOneByteSlicedString(Register result, |
3663 Register length, | 3640 Register length, |
3664 Register scratch1, | 3641 Register scratch1, |
3665 Register scratch2, | 3642 Register scratch2, |
3666 Label* gc_required) { | 3643 Label* gc_required) { |
3667 DCHECK(!AreAliased(result, length, scratch1, scratch2)); | 3644 DCHECK(!AreAliased(result, length, scratch1, scratch2)); |
3668 Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required, | 3645 Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required, |
3669 TAG_OBJECT); | 3646 TAG_OBJECT); |
3670 | 3647 |
3671 InitializeNewString(result, | 3648 InitializeNewString(result, length, Heap::kSlicedOneByteStringMapRootIndex, |
3672 length, | 3649 scratch1, scratch2); |
3673 Heap::kSlicedAsciiStringMapRootIndex, | |
3674 scratch1, | |
3675 scratch2); | |
3676 } | 3650 } |
3677 | 3651 |
3678 | 3652 |
3679 // Allocates a heap number or jumps to the need_gc label if the young space | 3653 // Allocates a heap number or jumps to the need_gc label if the young space |
3680 // is full and a scavenge is needed. | 3654 // is full and a scavenge is needed. |
3681 void MacroAssembler::AllocateHeapNumber(Register result, | 3655 void MacroAssembler::AllocateHeapNumber(Register result, |
3682 Label* gc_required, | 3656 Label* gc_required, |
3683 Register scratch1, | 3657 Register scratch1, |
3684 Register scratch2, | 3658 Register scratch2, |
3685 CPURegister value, | 3659 CPURegister value, |
(...skipping 1100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4786 // It's a non-indirect (non-cons and non-slice) string. | 4760 // It's a non-indirect (non-cons and non-slice) string. |
4787 // If it's external, the length is just ExternalString::kSize. | 4761 // If it's external, the length is just ExternalString::kSize. |
4788 // Otherwise it's String::kHeaderSize + string->length() * (1 or 2). | 4762 // Otherwise it's String::kHeaderSize + string->length() * (1 or 2). |
4789 // External strings are the only ones with the kExternalStringTag bit | 4763 // External strings are the only ones with the kExternalStringTag bit |
4790 // set. | 4764 // set. |
4791 DCHECK_EQ(0, kSeqStringTag & kExternalStringTag); | 4765 DCHECK_EQ(0, kSeqStringTag & kExternalStringTag); |
4792 DCHECK_EQ(0, kConsStringTag & kExternalStringTag); | 4766 DCHECK_EQ(0, kConsStringTag & kExternalStringTag); |
4793 Mov(length_scratch, ExternalString::kSize); | 4767 Mov(length_scratch, ExternalString::kSize); |
4794 TestAndBranchIfAnySet(instance_type, kExternalStringTag, &is_data_object); | 4768 TestAndBranchIfAnySet(instance_type, kExternalStringTag, &is_data_object); |
4795 | 4769 |
4796 // Sequential string, either ASCII or UC16. | 4770 // Sequential string, either Latin1 or UC16. |
4797 // For ASCII (char-size of 1) we shift the smi tag away to get the length. | 4771 // For Latin1 (char-size of 1) we shift the smi tag away to get the length. |
4798 // For UC16 (char-size of 2) we just leave the smi tag in place, thereby | 4772 // For UC16 (char-size of 2) we just leave the smi tag in place, thereby |
4799 // getting the length multiplied by 2. | 4773 // getting the length multiplied by 2. |
4800 DCHECK(kOneByteStringTag == 4 && kStringEncodingMask == 4); | 4774 DCHECK(kOneByteStringTag == 4 && kStringEncodingMask == 4); |
4801 Ldrsw(length_scratch, UntagSmiFieldMemOperand(value, | 4775 Ldrsw(length_scratch, UntagSmiFieldMemOperand(value, |
4802 String::kLengthOffset)); | 4776 String::kLengthOffset)); |
4803 Tst(instance_type, kStringEncodingMask); | 4777 Tst(instance_type, kStringEncodingMask); |
4804 Cset(load_scratch, eq); | 4778 Cset(load_scratch, eq); |
4805 Lsl(length_scratch, length_scratch, load_scratch); | 4779 Lsl(length_scratch, length_scratch, load_scratch); |
4806 Add(length_scratch, | 4780 Add(length_scratch, |
4807 length_scratch, | 4781 length_scratch, |
(...skipping 620 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5428 } | 5402 } |
5429 } | 5403 } |
5430 | 5404 |
5431 | 5405 |
5432 #undef __ | 5406 #undef __ |
5433 | 5407 |
5434 | 5408 |
5435 } } // namespace v8::internal | 5409 } } // namespace v8::internal |
5436 | 5410 |
5437 #endif // V8_TARGET_ARCH_ARM64 | 5411 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |