OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 5767 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5778 // nothing can be assumed about the arguments. It is tested that: | 5778 // nothing can be assumed about the arguments. It is tested that: |
5779 // "string" is a sequential string, | 5779 // "string" is a sequential string, |
5780 // both "from" and "to" are smis, and | 5780 // both "from" and "to" are smis, and |
5781 // 0 <= from <= to <= string.length. | 5781 // 0 <= from <= to <= string.length. |
5782 // If any of these assumptions fail, we call the runtime system. | 5782 // If any of these assumptions fail, we call the runtime system. |
5783 | 5783 |
5784 static const int kToOffset = 0 * kPointerSize; | 5784 static const int kToOffset = 0 * kPointerSize; |
5785 static const int kFromOffset = 1 * kPointerSize; | 5785 static const int kFromOffset = 1 * kPointerSize; |
5786 static const int kStringOffset = 2 * kPointerSize; | 5786 static const int kStringOffset = 2 * kPointerSize; |
5787 | 5787 |
5788 // Check bounds and smi-ness. | 5788 __ Ldrd(r2, r3, MemOperand(sp, kToOffset)); |
5789 Register to = r6; | |
5790 Register from = r7; | |
5791 | |
5792 __ Ldrd(to, from, MemOperand(sp, kToOffset)); | |
5793 STATIC_ASSERT(kFromOffset == kToOffset + 4); | 5789 STATIC_ASSERT(kFromOffset == kToOffset + 4); |
5794 STATIC_ASSERT(kSmiTag == 0); | 5790 STATIC_ASSERT(kSmiTag == 0); |
5795 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); | 5791 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); |
5796 | 5792 |
5797 // I.e., arithmetic shift right by one un-smi-tags. | 5793 // I.e., arithmetic shift right by one un-smi-tags. |
5798 __ mov(r2, Operand(to, ASR, 1), SetCC); | 5794 __ mov(r2, Operand(r2, ASR, 1), SetCC); |
5799 __ mov(r3, Operand(from, ASR, 1), SetCC, cc); | 5795 __ mov(r3, Operand(r3, ASR, 1), SetCC, cc); |
5800 // If either to or from had the smi tag bit set, then carry is set now. | 5796 // If either to or from had the smi tag bit set, then carry is set now. |
5801 __ b(cs, &runtime); // Either "from" or "to" is not a smi. | 5797 __ b(cs, &runtime); // Either "from" or "to" is not a smi. |
5802 __ b(mi, &runtime); // From is negative. | 5798 __ b(mi, &runtime); // From is negative. |
5803 | 5799 |
5804 // Both to and from are smis. | 5800 // Both r2 and r3 are untagged integers. |
5805 __ sub(r2, r2, Operand(r3), SetCC); | 5801 __ sub(r2, r2, Operand(r3), SetCC); |
5806 __ b(mi, &runtime); // Fail if from > to. | 5802 __ b(mi, &runtime); // Fail if from > to. |
5807 // Special handling of sub-strings of length 1 and 2. One character strings | |
5808 // are handled in the runtime system (looked up in the single character | |
5809 // cache). Two character strings are looked for in the symbol cache in | |
5810 // generated code. | |
5811 __ cmp(r2, Operand(2)); | |
5812 __ b(lt, &runtime); | |
5813 | 5803 |
5814 // r2: result string length | 5804 // Make sure first argument is a string. |
5815 // r3: from index (untagged smi) | |
5816 // r6 (a.k.a. to): to (smi) | |
5817 // r7 (a.k.a. from): from offset (smi) | |
5818 // Make sure first argument is a sequential (or flat) string. | |
5819 __ ldr(r0, MemOperand(sp, kStringOffset)); | 5805 __ ldr(r0, MemOperand(sp, kStringOffset)); |
5820 STATIC_ASSERT(kSmiTag == 0); | 5806 STATIC_ASSERT(kSmiTag == 0); |
5821 __ JumpIfSmi(r0, &runtime); | 5807 __ JumpIfSmi(r0, &runtime); |
5822 Condition is_string = masm->IsObjectStringType(r0, r1); | 5808 Condition is_string = masm->IsObjectStringType(r0, r1); |
5823 __ b(NegateCondition(is_string), &runtime); | 5809 __ b(NegateCondition(is_string), &runtime); |
5824 | 5810 |
5825 // Short-cut for the case of trivial substring. | 5811 // Short-cut for the case of trivial substring. |
5826 Label return_r0; | 5812 Label return_r0; |
5827 // r0: original string | 5813 // r0: original string |
5828 // r2: result string length | 5814 // r2: result string length |
5829 __ ldr(r4, FieldMemOperand(r0, String::kLengthOffset)); | 5815 __ ldr(r4, FieldMemOperand(r0, String::kLengthOffset)); |
5830 __ cmp(r2, Operand(r4, ASR, 1)); | 5816 __ cmp(r2, Operand(r4, ASR, 1)); |
5831 __ b(eq, &return_r0); | 5817 __ b(eq, &return_r0); |
5832 | 5818 |
5833 Label create_slice; | |
5834 if (FLAG_string_slices) { | |
5835 __ cmp(r2, Operand(SlicedString::kMinLength)); | |
5836 __ b(ge, &create_slice); | |
5837 } | |
5838 | |
5839 // r0: original string | |
5840 // r1: instance type | |
5841 // r2: result string length | |
5842 // r3: from index (untagged smi) | |
5843 // r6 (a.k.a. to): to (smi) | |
5844 // r7 (a.k.a. from): from offset (smi) | |
5845 Label seq_string; | |
5846 __ and_(r4, r1, Operand(kStringRepresentationMask)); | |
5847 STATIC_ASSERT(kSeqStringTag < kConsStringTag); | |
5848 STATIC_ASSERT(kConsStringTag < kExternalStringTag); | |
5849 STATIC_ASSERT(kConsStringTag < kSlicedStringTag); | |
5850 __ cmp(r4, Operand(kConsStringTag)); | |
5851 __ b(gt, &runtime); // Slices and external strings go to runtime. | |
5852 __ b(lt, &seq_string); // Sequential strings are handled directly. | |
5853 | |
5854 // Cons string. Try to recurse (once) on the first substring. | |
5855 // (This adds a little more generality than necessary to handle flattened | |
5856 // cons strings, but not much). | |
5857 __ ldr(r0, FieldMemOperand(r0, ConsString::kFirstOffset)); | |
5858 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); | |
5859 __ ldrb(r1, FieldMemOperand(r4, Map::kInstanceTypeOffset)); | |
5860 __ tst(r1, Operand(kStringRepresentationMask)); | |
5861 STATIC_ASSERT(kSeqStringTag == 0); | |
5862 __ b(ne, &runtime); // Cons, slices and external strings go to runtime. | |
5863 | |
5864 // Definitly a sequential string. | |
5865 __ bind(&seq_string); | |
5866 | |
5867 // r0: original string | |
5868 // r1: instance type | |
5869 // r2: result string length | |
5870 // r3: from index (untagged smi) | |
5871 // r6 (a.k.a. to): to (smi) | |
5872 // r7 (a.k.a. from): from offset (smi) | |
5873 __ ldr(r4, FieldMemOperand(r0, String::kLengthOffset)); | |
5874 __ cmp(r4, Operand(to)); | |
5875 __ b(lt, &runtime); // Fail if to > length. | |
5876 to = no_reg; | |
5877 | |
5878 // r0: original string or left hand side of the original cons string. | |
5879 // r1: instance type | |
5880 // r2: result string length | |
5881 // r3: from index (untagged smi) | |
5882 // r7 (a.k.a. from): from offset (smi) | |
5883 // Check for flat ASCII string. | |
5884 Label non_ascii_flat; | |
5885 __ tst(r1, Operand(kStringEncodingMask)); | |
5886 STATIC_ASSERT(kTwoByteStringTag == 0); | |
5887 __ b(eq, &non_ascii_flat); | |
5888 | |
5889 Label result_longer_than_two; | 5819 Label result_longer_than_two; |
| 5820 // Check for special case of two character ascii string, in which case |
| 5821 // we do a lookup in the symbol table first. |
5890 __ cmp(r2, Operand(2)); | 5822 __ cmp(r2, Operand(2)); |
5891 __ b(gt, &result_longer_than_two); | 5823 __ b(gt, &result_longer_than_two); |
| 5824 __ b(lt, &runtime); |
5892 | 5825 |
5893 // Sub string of length 2 requested. | 5826 __ JumpIfInstanceTypeIsNotSequentialAscii(r1, r1, &runtime); |
| 5827 |
5894 // Get the two characters forming the sub string. | 5828 // Get the two characters forming the sub string. |
5895 __ add(r0, r0, Operand(r3)); | 5829 __ add(r0, r0, Operand(r3)); |
5896 __ ldrb(r3, FieldMemOperand(r0, SeqAsciiString::kHeaderSize)); | 5830 __ ldrb(r3, FieldMemOperand(r0, SeqAsciiString::kHeaderSize)); |
5897 __ ldrb(r4, FieldMemOperand(r0, SeqAsciiString::kHeaderSize + 1)); | 5831 __ ldrb(r4, FieldMemOperand(r0, SeqAsciiString::kHeaderSize + 1)); |
5898 | 5832 |
5899 // Try to lookup two character string in symbol table. | 5833 // Try to lookup two character string in symbol table. |
5900 Label make_two_character_string; | 5834 Label make_two_character_string; |
5901 StringHelper::GenerateTwoCharacterSymbolTableProbe( | 5835 StringHelper::GenerateTwoCharacterSymbolTableProbe( |
5902 masm, r3, r4, r1, r5, r6, r7, r9, &make_two_character_string); | 5836 masm, r3, r4, r1, r5, r6, r7, r9, &make_two_character_string); |
5903 Counters* counters = masm->isolate()->counters(); | |
5904 __ jmp(&return_r0); | 5837 __ jmp(&return_r0); |
5905 | 5838 |
5906 // r2: result string length. | 5839 // r2: result string length. |
5907 // r3: two characters combined into halfword in little endian byte order. | 5840 // r3: two characters combined into halfword in little endian byte order. |
5908 __ bind(&make_two_character_string); | 5841 __ bind(&make_two_character_string); |
5909 __ AllocateAsciiString(r0, r2, r4, r5, r9, &runtime); | 5842 __ AllocateAsciiString(r0, r2, r4, r5, r9, &runtime); |
5910 __ strh(r3, FieldMemOperand(r0, SeqAsciiString::kHeaderSize)); | 5843 __ strh(r3, FieldMemOperand(r0, SeqAsciiString::kHeaderSize)); |
5911 __ jmp(&return_r0); | 5844 __ jmp(&return_r0); |
5912 | 5845 |
5913 __ bind(&result_longer_than_two); | 5846 __ bind(&result_longer_than_two); |
| 5847 // Deal with different string types: update the index if necessary |
| 5848 // and put the underlying string into r5. |
| 5849 // r0: original string |
| 5850 // r1: instance type |
| 5851 // r2: length |
| 5852 // r3: from index (untagged) |
| 5853 Label underlying_unpacked, sliced_string, seq_or_external_string; |
| 5854 // If the string is not indirect, it can only be sequential or external. |
| 5855 STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag)); |
| 5856 STATIC_ASSERT(kIsIndirectStringMask != 0); |
| 5857 __ tst(r1, Operand(kIsIndirectStringMask)); |
| 5858 __ b(eq, &seq_or_external_string); |
5914 | 5859 |
5915 // Locate 'from' character of string. | 5860 __ tst(r1, Operand(kSlicedNotConsMask)); |
5916 __ add(r5, r0, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); | 5861 __ b(ne, &sliced_string); |
5917 __ add(r5, r5, Operand(from, ASR, 1)); | 5862 // Cons string. Check whether it is flat, then fetch first part. |
| 5863 __ ldr(r5, FieldMemOperand(r0, ConsString::kSecondOffset)); |
| 5864 __ CompareRoot(r5, Heap::kEmptyStringRootIndex); |
| 5865 __ b(ne, &runtime); |
| 5866 __ ldr(r5, FieldMemOperand(r0, ConsString::kFirstOffset)); |
| 5867 // Update instance type. |
| 5868 __ ldr(r1, FieldMemOperand(r5, HeapObject::kMapOffset)); |
| 5869 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset)); |
| 5870 __ jmp(&underlying_unpacked); |
5918 | 5871 |
5919 // Allocate the result. | 5872 __ bind(&sliced_string); |
5920 __ AllocateAsciiString(r0, r2, r3, r4, r1, &runtime); | 5873 // Sliced string. Fetch parent and correct start index by offset. |
| 5874 __ ldr(r5, FieldMemOperand(r0, SlicedString::kOffsetOffset)); |
| 5875 __ add(r3, r3, Operand(r5, ASR, 1)); |
| 5876 __ ldr(r5, FieldMemOperand(r0, SlicedString::kParentOffset)); |
| 5877 // Update instance type. |
| 5878 __ ldr(r1, FieldMemOperand(r5, HeapObject::kMapOffset)); |
| 5879 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset)); |
| 5880 __ jmp(&underlying_unpacked); |
5921 | 5881 |
5922 // r0: result string | 5882 __ bind(&seq_or_external_string); |
5923 // r2: result string length | 5883 // Sequential or external string. Just move string to the expected register. |
5924 // r5: first character of substring to copy | 5884 __ mov(r5, r0); |
5925 // r7 (a.k.a. from): from offset (smi) | 5885 |
| 5886 __ bind(&underlying_unpacked); |
| 5887 |
| 5888 if (FLAG_string_slices) { |
| 5889 Label copy_routine; |
| 5890 // r5: underlying subject string |
| 5891 // r1: instance type of underlying subject string |
| 5892 // r2: length |
| 5893 // r3: adjusted start index (untagged) |
| 5894 __ cmp(r2, Operand(SlicedString::kMinLength)); |
| 5895 // Short slice. Copy instead of slicing. |
| 5896 __ b(lt, ©_routine); |
| 5897 // Allocate new sliced string. At this point we do not reload the instance |
| 5898 // type including the string encoding because we simply rely on the info |
| 5899 // provided by the original string. It does not matter if the original |
| 5900 // string's encoding is wrong because we always have to recheck encoding of |
| 5901 // the newly created string's parent anyways due to externalized strings. |
| 5902 Label two_byte_slice, set_slice_header; |
| 5903 STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0); |
| 5904 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); |
| 5905 __ tst(r1, Operand(kStringEncodingMask)); |
| 5906 __ b(eq, &two_byte_slice); |
| 5907 __ AllocateAsciiSlicedString(r0, r2, r6, r7, &runtime); |
| 5908 __ jmp(&set_slice_header); |
| 5909 __ bind(&two_byte_slice); |
| 5910 __ AllocateTwoByteSlicedString(r0, r2, r6, r7, &runtime); |
| 5911 __ bind(&set_slice_header); |
| 5912 __ mov(r3, Operand(r3, LSL, 1)); |
| 5913 __ str(r3, FieldMemOperand(r0, SlicedString::kOffsetOffset)); |
| 5914 __ str(r5, FieldMemOperand(r0, SlicedString::kParentOffset)); |
| 5915 __ jmp(&return_r0); |
| 5916 |
| 5917 __ bind(©_routine); |
| 5918 } |
| 5919 |
| 5920 // r5: underlying subject string |
| 5921 // r1: instance type of underlying subject string |
| 5922 // r2: length |
| 5923 // r3: adjusted start index (untagged) |
| 5924 Label two_byte_sequential, sequential_string, allocate_result; |
| 5925 STATIC_ASSERT(kExternalStringTag != 0); |
| 5926 STATIC_ASSERT(kSeqStringTag == 0); |
| 5927 __ tst(r1, Operand(kExternalStringTag)); |
| 5928 __ b(eq, &sequential_string); |
| 5929 |
| 5930 // Handle external string. |
| 5931 // Rule out short external strings. |
| 5932 STATIC_CHECK(kShortExternalStringTag != 0); |
| 5933 __ tst(r1, Operand(kShortExternalStringTag)); |
| 5934 __ b(ne, &runtime); |
| 5935 __ ldr(r5, FieldMemOperand(r5, ExternalString::kResourceDataOffset)); |
| 5936 // r5 already points to the first character of underlying string. |
| 5937 __ jmp(&allocate_result); |
| 5938 |
| 5939 __ bind(&sequential_string); |
| 5940 // Locate first character of underlying subject string. |
| 5941 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqAsciiString::kHeaderSize); |
| 5942 __ add(r5, r5, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); |
| 5943 |
| 5944 __ bind(&allocate_result); |
| 5945 // Sequential acii string. Allocate the result. |
| 5946 STATIC_ASSERT((kAsciiStringTag & kStringEncodingMask) != 0); |
| 5947 __ tst(r1, Operand(kStringEncodingMask)); |
| 5948 __ b(eq, &two_byte_sequential); |
| 5949 |
| 5950 // Allocate and copy the resulting ascii string. |
| 5951 __ AllocateAsciiString(r0, r2, r4, r6, r7, &runtime); |
| 5952 |
| 5953 // Locate first character of substring to copy. |
| 5954 __ add(r5, r5, r3); |
5926 // Locate first character of result. | 5955 // Locate first character of result. |
5927 __ add(r1, r0, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); | 5956 __ add(r1, r0, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); |
5928 | 5957 |
5929 // r0: result string | 5958 // r0: result string |
5930 // r1: first character of result string | 5959 // r1: first character of result string |
5931 // r2: result string length | 5960 // r2: result string length |
5932 // r5: first character of substring to copy | 5961 // r5: first character of substring to copy |
5933 STATIC_ASSERT((SeqAsciiString::kHeaderSize & kObjectAlignmentMask) == 0); | 5962 STATIC_ASSERT((SeqAsciiString::kHeaderSize & kObjectAlignmentMask) == 0); |
5934 StringHelper::GenerateCopyCharactersLong(masm, r1, r5, r2, r3, r4, r6, r7, r9, | 5963 StringHelper::GenerateCopyCharactersLong(masm, r1, r5, r2, r3, r4, r6, r7, r9, |
5935 COPY_ASCII | DEST_ALWAYS_ALIGNED); | 5964 COPY_ASCII | DEST_ALWAYS_ALIGNED); |
5936 __ jmp(&return_r0); | 5965 __ jmp(&return_r0); |
5937 | 5966 |
5938 __ bind(&non_ascii_flat); | 5967 // Allocate and copy the resulting two-byte string. |
5939 // r0: original string | 5968 __ bind(&two_byte_sequential); |
5940 // r2: result string length | 5969 __ AllocateTwoByteString(r0, r2, r4, r6, r7, &runtime); |
5941 // r7 (a.k.a. from): from offset (smi) | |
5942 // Check for flat two byte string. | |
5943 | 5970 |
5944 // Locate 'from' character of string. | 5971 // Locate first character of substring to copy. |
5945 __ add(r5, r0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); | |
5946 // As "from" is a smi it is 2 times the value which matches the size of a two | |
5947 // byte character. | |
5948 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); | 5972 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); |
5949 __ add(r5, r5, Operand(from)); | 5973 __ add(r5, r5, Operand(r3, LSL, 1)); |
5950 | |
5951 // Allocate the result. | |
5952 __ AllocateTwoByteString(r0, r2, r1, r3, r4, &runtime); | |
5953 | |
5954 // r0: result string | |
5955 // r2: result string length | |
5956 // r5: first character of substring to copy | |
5957 // Locate first character of result. | 5974 // Locate first character of result. |
5958 __ add(r1, r0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); | 5975 __ add(r1, r0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); |
5959 | 5976 |
5960 from = no_reg; | |
5961 | |
5962 // r0: result string. | 5977 // r0: result string. |
5963 // r1: first character of result. | 5978 // r1: first character of result. |
5964 // r2: result length. | 5979 // r2: result length. |
5965 // r5: first character of substring to copy. | 5980 // r5: first character of substring to copy. |
5966 STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0); | 5981 STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0); |
5967 StringHelper::GenerateCopyCharactersLong( | 5982 StringHelper::GenerateCopyCharactersLong( |
5968 masm, r1, r5, r2, r3, r4, r6, r7, r9, DEST_ALWAYS_ALIGNED); | 5983 masm, r1, r5, r2, r3, r4, r6, r7, r9, DEST_ALWAYS_ALIGNED); |
5969 __ jmp(&return_r0); | |
5970 | |
5971 if (FLAG_string_slices) { | |
5972 __ bind(&create_slice); | |
5973 // r0: original string | |
5974 // r1: instance type | |
5975 // r2: length | |
5976 // r3: from index (untagged smi) | |
5977 // r6 (a.k.a. to): to (smi) | |
5978 // r7 (a.k.a. from): from offset (smi) | |
5979 Label allocate_slice, sliced_string, seq_or_external_string; | |
5980 // If the string is not indirect, it can only be sequential or external. | |
5981 STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag)); | |
5982 STATIC_ASSERT(kIsIndirectStringMask != 0); | |
5983 __ tst(r1, Operand(kIsIndirectStringMask)); | |
5984 __ b(eq, &seq_or_external_string); | |
5985 | |
5986 __ tst(r1, Operand(kSlicedNotConsMask)); | |
5987 __ b(ne, &sliced_string); | |
5988 // Cons string. Check whether it is flat, then fetch first part. | |
5989 __ ldr(r5, FieldMemOperand(r0, ConsString::kSecondOffset)); | |
5990 __ LoadRoot(r9, Heap::kEmptyStringRootIndex); | |
5991 __ cmp(r5, r9); | |
5992 __ b(ne, &runtime); | |
5993 __ ldr(r5, FieldMemOperand(r0, ConsString::kFirstOffset)); | |
5994 __ jmp(&allocate_slice); | |
5995 | |
5996 __ bind(&sliced_string); | |
5997 // Sliced string. Fetch parent and correct start index by offset. | |
5998 __ ldr(r5, FieldMemOperand(r0, SlicedString::kOffsetOffset)); | |
5999 __ add(r7, r7, r5); | |
6000 __ ldr(r5, FieldMemOperand(r0, SlicedString::kParentOffset)); | |
6001 __ jmp(&allocate_slice); | |
6002 | |
6003 __ bind(&seq_or_external_string); | |
6004 // Sequential or external string. Just move string to the correct register. | |
6005 __ mov(r5, r0); | |
6006 | |
6007 __ bind(&allocate_slice); | |
6008 // r1: instance type of original string | |
6009 // r2: length | |
6010 // r5: underlying subject string | |
6011 // r7 (a.k.a. from): from offset (smi) | |
6012 // Allocate new sliced string. At this point we do not reload the instance | |
6013 // type including the string encoding because we simply rely on the info | |
6014 // provided by the original string. It does not matter if the original | |
6015 // string's encoding is wrong because we always have to recheck encoding of | |
6016 // the newly created string's parent anyways due to externalized strings. | |
6017 Label two_byte_slice, set_slice_header; | |
6018 STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0); | |
6019 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); | |
6020 __ tst(r1, Operand(kStringEncodingMask)); | |
6021 __ b(eq, &two_byte_slice); | |
6022 __ AllocateAsciiSlicedString(r0, r2, r3, r4, &runtime); | |
6023 __ jmp(&set_slice_header); | |
6024 __ bind(&two_byte_slice); | |
6025 __ AllocateTwoByteSlicedString(r0, r2, r3, r4, &runtime); | |
6026 __ bind(&set_slice_header); | |
6027 __ str(r7, FieldMemOperand(r0, SlicedString::kOffsetOffset)); | |
6028 __ str(r5, FieldMemOperand(r0, SlicedString::kParentOffset)); | |
6029 } | |
6030 | 5984 |
6031 __ bind(&return_r0); | 5985 __ bind(&return_r0); |
| 5986 Counters* counters = masm->isolate()->counters(); |
6032 __ IncrementCounter(counters->sub_string_native(), 1, r3, r4); | 5987 __ IncrementCounter(counters->sub_string_native(), 1, r3, r4); |
6033 __ add(sp, sp, Operand(3 * kPointerSize)); | 5988 __ add(sp, sp, Operand(3 * kPointerSize)); |
6034 __ Ret(); | 5989 __ Ret(); |
6035 | 5990 |
6036 // Just jump to runtime to create the sub string. | 5991 // Just jump to runtime to create the sub string. |
6037 __ bind(&runtime); | 5992 __ bind(&runtime); |
6038 __ TailCallRuntime(Runtime::kSubString, 3, 1); | 5993 __ TailCallRuntime(Runtime::kSubString, 3, 1); |
6039 } | 5994 } |
6040 | 5995 |
6041 | 5996 |
(...skipping 1319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7361 __ StoreNumberToDoubleElements(r0, r3, r1, r5, r6, r7, r9, r10, | 7316 __ StoreNumberToDoubleElements(r0, r3, r1, r5, r6, r7, r9, r10, |
7362 &slow_elements); | 7317 &slow_elements); |
7363 __ Ret(); | 7318 __ Ret(); |
7364 } | 7319 } |
7365 | 7320 |
7366 #undef __ | 7321 #undef __ |
7367 | 7322 |
7368 } } // namespace v8::internal | 7323 } } // namespace v8::internal |
7369 | 7324 |
7370 #endif // V8_TARGET_ARCH_ARM | 7325 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |