Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(793)

Side by Side Diff: src/arm64/code-stubs-arm64.cc

Issue 2355793003: [stubs] Port SubStringStub to TurboFan (Closed)
Patch Set: Address comments Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 #if V8_TARGET_ARCH_ARM64 5 #if V8_TARGET_ARCH_ARM64
6 6
7 #include "src/code-stubs.h" 7 #include "src/code-stubs.h"
8 #include "src/api-arguments.h" 8 #include "src/api-arguments.h"
9 #include "src/bootstrapper.h" 9 #include "src/bootstrapper.h"
10 #include "src/codegen.h" 10 #include "src/codegen.h"
(...skipping 2655 matching lines...) Expand 10 before | Expand all | Expand 10 after
2666 // Compute the entry point of the rewritten stub. 2666 // Compute the entry point of the rewritten stub.
2667 __ Add(stub_entry, x0, Code::kHeaderSize - kHeapObjectTag); 2667 __ Add(stub_entry, x0, Code::kHeaderSize - kHeapObjectTag);
2668 // Restore caller-saved registers. 2668 // Restore caller-saved registers.
2669 __ Pop(lr, x0, x1); 2669 __ Pop(lr, x0, x1);
2670 } 2670 }
2671 2671
2672 // Tail-call to the new stub. 2672 // Tail-call to the new stub.
2673 __ Jump(stub_entry); 2673 __ Jump(stub_entry);
2674 } 2674 }
2675 2675
2676
2677 void SubStringStub::Generate(MacroAssembler* masm) {
2678 ASM_LOCATION("SubStringStub::Generate");
2679 Label runtime;
2680
2681 // Stack frame on entry.
2682 // lr: return address
2683 // jssp[0]: substring "to" offset
2684 // jssp[8]: substring "from" offset
2685 // jssp[16]: pointer to string object
2686
2687 // This stub is called from the native-call %_SubString(...), so
2688 // nothing can be assumed about the arguments. It is tested that:
2689 // "string" is a sequential string,
2690 // both "from" and "to" are smis, and
2691 // 0 <= from <= to <= string.length (in debug mode.)
2692 // If any of these assumptions fail, we call the runtime system.
2693
2694 static const int kToOffset = 0 * kPointerSize;
2695 static const int kFromOffset = 1 * kPointerSize;
2696 static const int kStringOffset = 2 * kPointerSize;
2697
2698 Register to = x0;
2699 Register from = x15;
2700 Register input_string = x10;
2701 Register input_length = x11;
2702 Register input_type = x12;
2703 Register result_string = x0;
2704 Register result_length = x1;
2705 Register temp = x3;
2706
2707 __ Peek(to, kToOffset);
2708 __ Peek(from, kFromOffset);
2709
2710 // Check that both from and to are smis. If not, jump to runtime.
2711 __ JumpIfEitherNotSmi(from, to, &runtime);
2712 __ SmiUntag(from);
2713 __ SmiUntag(to);
2714
2715 // Calculate difference between from and to. If to < from, branch to runtime.
2716 __ Subs(result_length, to, from);
2717 __ B(mi, &runtime);
2718
2719 // Check from is positive.
2720 __ Tbnz(from, kWSignBit, &runtime);
2721
2722 // Make sure first argument is a string.
2723 __ Peek(input_string, kStringOffset);
2724 __ JumpIfSmi(input_string, &runtime);
2725 __ IsObjectJSStringType(input_string, input_type, &runtime);
2726
2727 Label single_char;
2728 __ Cmp(result_length, 1);
2729 __ B(eq, &single_char);
2730
2731 // Short-cut for the case of trivial substring.
2732 Label return_x0;
2733 __ Ldrsw(input_length,
2734 UntagSmiFieldMemOperand(input_string, String::kLengthOffset));
2735
2736 __ Cmp(result_length, input_length);
2737 __ CmovX(x0, input_string, eq);
2738 // Return original string.
2739 __ B(eq, &return_x0);
2740
2741 // Longer than original string's length or negative: unsafe arguments.
2742 __ B(hi, &runtime);
2743
2744 // Shorter than original string's length: an actual substring.
2745
2746 // x0 to substring end character offset
2747 // x1 result_length length of substring result
2748 // x10 input_string pointer to input string object
2749 // x10 unpacked_string pointer to unpacked string object
2750 // x11 input_length length of input string
2751 // x12 input_type instance type of input string
2752 // x15 from substring start character offset
2753
2754 // Deal with different string types: update the index if necessary and put
2755 // the underlying string into register unpacked_string.
2756 Label underlying_unpacked, sliced_string, seq_or_external_string;
2757 Label update_instance_type;
2758 // If the string is not indirect, it can only be sequential or external.
2759 STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag));
2760 STATIC_ASSERT(kIsIndirectStringMask != 0);
2761
2762 // Test for string types, and branch/fall through to appropriate unpacking
2763 // code.
2764 __ Tst(input_type, kIsIndirectStringMask);
2765 __ B(eq, &seq_or_external_string);
2766 __ Tst(input_type, kSlicedNotConsMask);
2767 __ B(ne, &sliced_string);
2768
2769 Register unpacked_string = input_string;
2770
2771 // Cons string. Check whether it is flat, then fetch first part.
2772 __ Ldr(temp, FieldMemOperand(input_string, ConsString::kSecondOffset));
2773 __ JumpIfNotRoot(temp, Heap::kempty_stringRootIndex, &runtime);
2774 __ Ldr(unpacked_string,
2775 FieldMemOperand(input_string, ConsString::kFirstOffset));
2776 __ B(&update_instance_type);
2777
2778 __ Bind(&sliced_string);
2779 // Sliced string. Fetch parent and correct start index by offset.
2780 __ Ldrsw(temp,
2781 UntagSmiFieldMemOperand(input_string, SlicedString::kOffsetOffset));
2782 __ Add(from, from, temp);
2783 __ Ldr(unpacked_string,
2784 FieldMemOperand(input_string, SlicedString::kParentOffset));
2785
2786 __ Bind(&update_instance_type);
2787 __ Ldr(temp, FieldMemOperand(unpacked_string, HeapObject::kMapOffset));
2788 __ Ldrb(input_type, FieldMemOperand(temp, Map::kInstanceTypeOffset));
2789 // Now control must go to &underlying_unpacked. Since the no code is generated
2790 // before then we fall through instead of generating a useless branch.
2791
2792 __ Bind(&seq_or_external_string);
2793 // Sequential or external string. Registers unpacked_string and input_string
2794 // alias, so there's nothing to do here.
2795 // Note that if code is added here, the above code must be updated.
2796
2797 // x0 result_string pointer to result string object (uninit)
2798 // x1 result_length length of substring result
2799 // x10 unpacked_string pointer to unpacked string object
2800 // x11 input_length length of input string
2801 // x12 input_type instance type of input string
2802 // x15 from substring start character offset
2803 __ Bind(&underlying_unpacked);
2804
2805 if (FLAG_string_slices) {
2806 Label copy_routine;
2807 __ Cmp(result_length, SlicedString::kMinLength);
2808 // Short slice. Copy instead of slicing.
2809 __ B(lt, &copy_routine);
2810 // Allocate new sliced string. At this point we do not reload the instance
2811 // type including the string encoding because we simply rely on the info
2812 // provided by the original string. It does not matter if the original
2813 // string's encoding is wrong because we always have to recheck encoding of
2814 // the newly created string's parent anyway due to externalized strings.
2815 Label two_byte_slice, set_slice_header;
2816 STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0);
2817 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
2818 __ Tbz(input_type, MaskToBit(kStringEncodingMask), &two_byte_slice);
2819 __ AllocateOneByteSlicedString(result_string, result_length, x3, x4,
2820 &runtime);
2821 __ B(&set_slice_header);
2822
2823 __ Bind(&two_byte_slice);
2824 __ AllocateTwoByteSlicedString(result_string, result_length, x3, x4,
2825 &runtime);
2826
2827 __ Bind(&set_slice_header);
2828 __ SmiTag(from);
2829 __ Str(from, FieldMemOperand(result_string, SlicedString::kOffsetOffset));
2830 __ Str(unpacked_string,
2831 FieldMemOperand(result_string, SlicedString::kParentOffset));
2832 __ B(&return_x0);
2833
2834 __ Bind(&copy_routine);
2835 }
2836
2837 // x0 result_string pointer to result string object (uninit)
2838 // x1 result_length length of substring result
2839 // x10 unpacked_string pointer to unpacked string object
2840 // x11 input_length length of input string
2841 // x12 input_type instance type of input string
2842 // x13 unpacked_char0 pointer to first char of unpacked string (uninit)
2843 // x13 substring_char0 pointer to first char of substring (uninit)
2844 // x14 result_char0 pointer to first char of result (uninit)
2845 // x15 from substring start character offset
2846 Register unpacked_char0 = x13;
2847 Register substring_char0 = x13;
2848 Register result_char0 = x14;
2849 Label two_byte_sequential, sequential_string, allocate_result;
2850 STATIC_ASSERT(kExternalStringTag != 0);
2851 STATIC_ASSERT(kSeqStringTag == 0);
2852
2853 __ Tst(input_type, kExternalStringTag);
2854 __ B(eq, &sequential_string);
2855
2856 __ Tst(input_type, kShortExternalStringTag);
2857 __ B(ne, &runtime);
2858 __ Ldr(unpacked_char0,
2859 FieldMemOperand(unpacked_string, ExternalString::kResourceDataOffset));
2860 // unpacked_char0 points to the first character of the underlying string.
2861 __ B(&allocate_result);
2862
2863 __ Bind(&sequential_string);
2864 // Locate first character of underlying subject string.
2865 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
2866 __ Add(unpacked_char0, unpacked_string,
2867 SeqOneByteString::kHeaderSize - kHeapObjectTag);
2868
2869 __ Bind(&allocate_result);
2870 // Sequential one-byte string. Allocate the result.
2871 STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0);
2872 __ Tbz(input_type, MaskToBit(kStringEncodingMask), &two_byte_sequential);
2873
2874 // Allocate and copy the resulting one-byte string.
2875 __ AllocateOneByteString(result_string, result_length, x3, x4, x5, &runtime);
2876
2877 // Locate first character of substring to copy.
2878 __ Add(substring_char0, unpacked_char0, from);
2879
2880 // Locate first character of result.
2881 __ Add(result_char0, result_string,
2882 SeqOneByteString::kHeaderSize - kHeapObjectTag);
2883
2884 STATIC_ASSERT((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0);
2885 __ CopyBytes(result_char0, substring_char0, result_length, x3, kCopyLong);
2886 __ B(&return_x0);
2887
2888 // Allocate and copy the resulting two-byte string.
2889 __ Bind(&two_byte_sequential);
2890 __ AllocateTwoByteString(result_string, result_length, x3, x4, x5, &runtime);
2891
2892 // Locate first character of substring to copy.
2893 __ Add(substring_char0, unpacked_char0, Operand(from, LSL, 1));
2894
2895 // Locate first character of result.
2896 __ Add(result_char0, result_string,
2897 SeqTwoByteString::kHeaderSize - kHeapObjectTag);
2898
2899 STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0);
2900 __ Add(result_length, result_length, result_length);
2901 __ CopyBytes(result_char0, substring_char0, result_length, x3, kCopyLong);
2902
2903 __ Bind(&return_x0);
2904 Counters* counters = isolate()->counters();
2905 __ IncrementCounter(counters->sub_string_native(), 1, x3, x4);
2906 __ Drop(3);
2907 __ Ret();
2908
2909 __ Bind(&runtime);
2910 __ TailCallRuntime(Runtime::kSubString);
2911
2912 __ bind(&single_char);
2913 // x1: result_length
2914 // x10: input_string
2915 // x12: input_type
2916 // x15: from (untagged)
2917 __ SmiTag(from);
2918 StringCharAtGenerator generator(input_string, from, result_length, x0,
2919 &runtime, &runtime, &runtime,
2920 RECEIVER_IS_STRING);
2921 generator.GenerateFast(masm);
2922 __ Drop(3);
2923 __ Ret();
2924 generator.SkipSlow(masm, &runtime);
2925 }
2926
2927 void ToStringStub::Generate(MacroAssembler* masm) { 2676 void ToStringStub::Generate(MacroAssembler* masm) {
2928 // The ToString stub takes one argument in x0. 2677 // The ToString stub takes one argument in x0.
2929 Label is_number; 2678 Label is_number;
2930 __ JumpIfSmi(x0, &is_number); 2679 __ JumpIfSmi(x0, &is_number);
2931 2680
2932 Label not_string; 2681 Label not_string;
2933 __ JumpIfObjectType(x0, x1, x1, FIRST_NONSTRING_TYPE, &not_string, hs); 2682 __ JumpIfObjectType(x0, x1, x1, FIRST_NONSTRING_TYPE, &not_string, hs);
2934 // x0: receiver 2683 // x0: receiver
2935 // x1: receiver instance type 2684 // x1: receiver instance type
2936 __ Ret(); 2685 __ Ret();
(...skipping 2598 matching lines...) Expand 10 before | Expand all | Expand 10 after
5535 kStackUnwindSpace, NULL, spill_offset, 5284 kStackUnwindSpace, NULL, spill_offset,
5536 return_value_operand, NULL); 5285 return_value_operand, NULL);
5537 } 5286 }
5538 5287
5539 #undef __ 5288 #undef __
5540 5289
5541 } // namespace internal 5290 } // namespace internal
5542 } // namespace v8 5291 } // namespace v8
5543 5292
5544 #endif // V8_TARGET_ARCH_ARM64 5293 #endif // V8_TARGET_ARCH_ARM64
OLDNEW
« no previous file with comments | « src/arm/code-stubs-arm.cc ('k') | src/code-stub-assembler.h » ('j') | src/code-stub-assembler.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698