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 5625 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5636 // 0 <= from <= to <= string.length. | 5636 // 0 <= from <= to <= string.length. |
5637 // If any of these assumptions fail, we call the runtime system. | 5637 // If any of these assumptions fail, we call the runtime system. |
5638 | 5638 |
5639 static const int kToOffset = 0 * kPointerSize; | 5639 static const int kToOffset = 0 * kPointerSize; |
5640 static const int kFromOffset = 1 * kPointerSize; | 5640 static const int kFromOffset = 1 * kPointerSize; |
5641 static const int kStringOffset = 2 * kPointerSize; | 5641 static const int kStringOffset = 2 * kPointerSize; |
5642 | 5642 |
5643 Register to = t2; | 5643 Register to = t2; |
5644 Register from = t3; | 5644 Register from = t3; |
5645 | 5645 |
5646 if (FLAG_string_slices) { | |
5647 __ nop(); // Jumping as first instruction would crash the code generation. | |
5648 __ jmp(&sub_string_runtime); | |
5649 } | |
5650 | |
5651 // Check bounds and smi-ness. | 5646 // Check bounds and smi-ness. |
5652 __ lw(to, MemOperand(sp, kToOffset)); | 5647 __ lw(to, MemOperand(sp, kToOffset)); |
5653 __ lw(from, MemOperand(sp, kFromOffset)); | 5648 __ lw(from, MemOperand(sp, kFromOffset)); |
5654 STATIC_ASSERT(kFromOffset == kToOffset + 4); | 5649 STATIC_ASSERT(kFromOffset == kToOffset + 4); |
5655 STATIC_ASSERT(kSmiTag == 0); | 5650 STATIC_ASSERT(kSmiTag == 0); |
5656 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); | 5651 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); |
5657 | 5652 |
5658 __ JumpIfNotSmi(from, &sub_string_runtime); | 5653 __ JumpIfNotSmi(from, &sub_string_runtime); |
5659 __ JumpIfNotSmi(to, &sub_string_runtime); | 5654 __ JumpIfNotSmi(to, &sub_string_runtime); |
5660 | 5655 |
5661 __ sra(a3, from, kSmiTagSize); // Remove smi tag. | 5656 __ sra(a3, from, kSmiTagSize); // Remove smi tag. |
5662 __ sra(t5, to, kSmiTagSize); // Remove smi tag. | 5657 __ sra(t5, to, kSmiTagSize); // Remove smi tag. |
5663 | 5658 |
5664 // a3: from index (untagged smi) | 5659 // a3: from index (untagged smi) |
5665 // t5: to index (untagged smi) | 5660 // t5: to index (untagged smi) |
5666 | 5661 |
5667 __ Branch(&sub_string_runtime, lt, a3, Operand(zero_reg)); // From < 0. | 5662 __ Branch(&sub_string_runtime, lt, a3, Operand(zero_reg)); // From < 0. |
5668 | 5663 |
5669 __ subu(a2, t5, a3); | 5664 __ subu(a2, t5, a3); |
5670 __ Branch(&sub_string_runtime, gt, a3, Operand(t5)); // Fail if from > to. | 5665 __ Branch(&sub_string_runtime, gt, a3, Operand(t5)); // Fail if from > to. |
5671 | 5666 |
5672 // Special handling of sub-strings of length 1 and 2. One character strings | 5667 // Special handling of sub-strings of length 1 and 2. One character strings |
5673 // are handled in the runtime system (looked up in the single character | 5668 // are handled in the runtime system (looked up in the single character |
5674 // cache). Two character strings are looked for in the symbol cache. | 5669 // cache). Two character strings are looked for in the symbol cache in |
| 5670 // generated code. |
5675 __ Branch(&sub_string_runtime, lt, a2, Operand(2)); | 5671 __ Branch(&sub_string_runtime, lt, a2, Operand(2)); |
5676 | 5672 |
5677 // Both to and from are smis. | 5673 // Both to and from are smis. |
5678 | 5674 |
5679 // a2: result string length | 5675 // a2: result string length |
5680 // a3: from index (untagged smi) | 5676 // a3: from index (untagged smi) |
5681 // t2: (a.k.a. to): to (smi) | 5677 // t2: (a.k.a. to): to (smi) |
5682 // t3: (a.k.a. from): from offset (smi) | 5678 // t3: (a.k.a. from): from offset (smi) |
5683 // t5: to index (untagged smi) | 5679 // t5: to index (untagged smi) |
5684 | 5680 |
5685 // Make sure first argument is a sequential (or flat) string. | 5681 // Make sure first argument is a sequential (or flat) string. |
5686 __ lw(t1, MemOperand(sp, kStringOffset)); | 5682 __ lw(v0, MemOperand(sp, kStringOffset)); |
5687 __ Branch(&sub_string_runtime, eq, t1, Operand(kSmiTagMask)); | 5683 __ Branch(&sub_string_runtime, eq, v0, Operand(kSmiTagMask)); |
5688 | 5684 |
5689 __ lw(a1, FieldMemOperand(t1, HeapObject::kMapOffset)); | 5685 __ lw(a1, FieldMemOperand(v0, HeapObject::kMapOffset)); |
5690 __ lbu(a1, FieldMemOperand(a1, Map::kInstanceTypeOffset)); | 5686 __ lbu(a1, FieldMemOperand(a1, Map::kInstanceTypeOffset)); |
5691 __ And(t4, a1, Operand(kIsNotStringMask)); | 5687 __ And(t4, v0, Operand(kIsNotStringMask)); |
5692 | 5688 |
5693 __ Branch(&sub_string_runtime, ne, t4, Operand(zero_reg)); | 5689 __ Branch(&sub_string_runtime, ne, t4, Operand(zero_reg)); |
5694 | 5690 |
| 5691 // Short-cut for the case of trivial substring. |
| 5692 Label return_v0; |
| 5693 // v0: original string |
| 5694 // a2: result string length |
| 5695 __ lw(t0, FieldMemOperand(v0, String::kLengthOffset)); |
| 5696 __ sra(t0, t0, 1); |
| 5697 __ Branch(&return_v0, eq, a2, Operand(t0)); |
| 5698 |
| 5699 Label create_slice; |
| 5700 if (FLAG_string_slices) { |
| 5701 __ Branch(&create_slice, ge, a2, Operand(SlicedString::kMinLength)); |
| 5702 } |
| 5703 |
| 5704 // v0: original string |
5695 // a1: instance type | 5705 // a1: instance type |
5696 // a2: result string length | 5706 // a2: result string length |
5697 // a3: from index (untagged smi) | 5707 // a3: from index (untagged smi) |
5698 // t1: string | |
5699 // t2: (a.k.a. to): to (smi) | 5708 // t2: (a.k.a. to): to (smi) |
5700 // t3: (a.k.a. from): from offset (smi) | 5709 // t3: (a.k.a. from): from offset (smi) |
5701 // t5: to index (untagged smi) | 5710 // t5: to index (untagged smi) |
5702 | 5711 |
5703 Label seq_string; | 5712 Label seq_string; |
5704 __ And(t0, a1, Operand(kStringRepresentationMask)); | 5713 __ And(t0, a1, Operand(kStringRepresentationMask)); |
5705 STATIC_ASSERT(kSeqStringTag < kConsStringTag); | 5714 STATIC_ASSERT(kSeqStringTag < kConsStringTag); |
5706 STATIC_ASSERT(kConsStringTag < kExternalStringTag); | 5715 STATIC_ASSERT(kConsStringTag < kExternalStringTag); |
| 5716 STATIC_ASSERT(kConsStringTag < kSlicedStringTag); |
5707 | 5717 |
5708 // External strings go to runtime. | 5718 // Slices and external strings go to runtime. |
5709 __ Branch(&sub_string_runtime, gt, t0, Operand(kConsStringTag)); | 5719 __ Branch(&sub_string_runtime, gt, t0, Operand(kConsStringTag)); |
5710 | 5720 |
5711 // Sequential strings are handled directly. | 5721 // Sequential strings are handled directly. |
5712 __ Branch(&seq_string, lt, t0, Operand(kConsStringTag)); | 5722 __ Branch(&seq_string, lt, t0, Operand(kConsStringTag)); |
5713 | 5723 |
5714 // Cons string. Try to recurse (once) on the first substring. | 5724 // Cons string. Try to recurse (once) on the first substring. |
5715 // (This adds a little more generality than necessary to handle flattened | 5725 // (This adds a little more generality than necessary to handle flattened |
5716 // cons strings, but not much). | 5726 // cons strings, but not much). |
5717 __ lw(t1, FieldMemOperand(t1, ConsString::kFirstOffset)); | 5727 __ lw(v0, FieldMemOperand(v0, ConsString::kFirstOffset)); |
5718 __ lw(t0, FieldMemOperand(t1, HeapObject::kMapOffset)); | 5728 __ lw(t0, FieldMemOperand(v0, HeapObject::kMapOffset)); |
5719 __ lbu(a1, FieldMemOperand(t0, Map::kInstanceTypeOffset)); | 5729 __ lbu(a1, FieldMemOperand(t0, Map::kInstanceTypeOffset)); |
5720 STATIC_ASSERT(kSeqStringTag == 0); | 5730 STATIC_ASSERT(kSeqStringTag == 0); |
5721 // Cons and External strings go to runtime. | 5731 // Cons, slices and external strings go to runtime. |
5722 __ Branch(&sub_string_runtime, ne, a1, Operand(kStringRepresentationMask)); | 5732 __ Branch(&sub_string_runtime, ne, a1, Operand(kStringRepresentationMask)); |
5723 | 5733 |
5724 // Definitly a sequential string. | 5734 // Definitly a sequential string. |
5725 __ bind(&seq_string); | 5735 __ bind(&seq_string); |
5726 | 5736 |
| 5737 // v0: original string |
5727 // a1: instance type | 5738 // a1: instance type |
5728 // a2: result string length | 5739 // a2: result string length |
5729 // a3: from index (untagged smi) | 5740 // a3: from index (untagged smi) |
5730 // t1: string | |
5731 // t2: (a.k.a. to): to (smi) | 5741 // t2: (a.k.a. to): to (smi) |
5732 // t3: (a.k.a. from): from offset (smi) | 5742 // t3: (a.k.a. from): from offset (smi) |
5733 // t5: to index (untagged smi) | 5743 // t5: to index (untagged smi) |
5734 | 5744 |
5735 __ lw(t0, FieldMemOperand(t1, String::kLengthOffset)); | 5745 __ lw(t0, FieldMemOperand(v0, String::kLengthOffset)); |
5736 __ Branch(&sub_string_runtime, lt, t0, Operand(to)); // Fail if to > length. | 5746 __ Branch(&sub_string_runtime, lt, t0, Operand(to)); // Fail if to > length. |
5737 to = no_reg; | 5747 to = no_reg; |
5738 | 5748 |
| 5749 // v0: original string or left hand side of the original cons string. |
5739 // a1: instance type | 5750 // a1: instance type |
5740 // a2: result string length | 5751 // a2: result string length |
5741 // a3: from index (untagged smi) | 5752 // a3: from index (untagged smi) |
5742 // t1: string | |
5743 // t3: (a.k.a. from): from offset (smi) | 5753 // t3: (a.k.a. from): from offset (smi) |
5744 // t5: to index (untagged smi) | 5754 // t5: to index (untagged smi) |
5745 | 5755 |
5746 // Check for flat ASCII string. | 5756 // Check for flat ASCII string. |
5747 Label non_ascii_flat; | 5757 Label non_ascii_flat; |
5748 STATIC_ASSERT(kTwoByteStringTag == 0); | 5758 STATIC_ASSERT(kTwoByteStringTag == 0); |
5749 | 5759 |
5750 __ And(t4, a1, Operand(kStringEncodingMask)); | 5760 __ And(t4, a1, Operand(kStringEncodingMask)); |
5751 __ Branch(&non_ascii_flat, eq, t4, Operand(zero_reg)); | 5761 __ Branch(&non_ascii_flat, eq, t4, Operand(zero_reg)); |
5752 | 5762 |
5753 Label result_longer_than_two; | 5763 Label result_longer_than_two; |
5754 __ Branch(&result_longer_than_two, gt, a2, Operand(2)); | 5764 __ Branch(&result_longer_than_two, gt, a2, Operand(2)); |
5755 | 5765 |
5756 // Sub string of length 2 requested. | 5766 // Sub string of length 2 requested. |
5757 // Get the two characters forming the sub string. | 5767 // Get the two characters forming the sub string. |
5758 __ Addu(t1, t1, Operand(a3)); | 5768 __ Addu(v0, v0, Operand(a3)); |
5759 __ lbu(a3, FieldMemOperand(t1, SeqAsciiString::kHeaderSize)); | 5769 __ lbu(a3, FieldMemOperand(v0, SeqAsciiString::kHeaderSize)); |
5760 __ lbu(t0, FieldMemOperand(t1, SeqAsciiString::kHeaderSize + 1)); | 5770 __ lbu(t0, FieldMemOperand(v0, SeqAsciiString::kHeaderSize + 1)); |
5761 | 5771 |
5762 // Try to lookup two character string in symbol table. | 5772 // Try to lookup two character string in symbol table. |
5763 Label make_two_character_string; | 5773 Label make_two_character_string; |
5764 StringHelper::GenerateTwoCharacterSymbolTableProbe( | 5774 StringHelper::GenerateTwoCharacterSymbolTableProbe( |
5765 masm, a3, t0, a1, t1, t2, t3, t4, &make_two_character_string); | 5775 masm, a3, t0, a1, t1, t2, t3, t4, &make_two_character_string); |
5766 Counters* counters = masm->isolate()->counters(); | 5776 Counters* counters = masm->isolate()->counters(); |
5767 __ IncrementCounter(counters->sub_string_native(), 1, a3, t0); | 5777 __ jmp(&return_v0); |
5768 __ Addu(sp, sp, Operand(3 * kPointerSize)); | |
5769 __ Ret(); | |
5770 | |
5771 | 5778 |
5772 // a2: result string length. | 5779 // a2: result string length. |
5773 // a3: two characters combined into halfword in little endian byte order. | 5780 // a3: two characters combined into halfword in little endian byte order. |
5774 __ bind(&make_two_character_string); | 5781 __ bind(&make_two_character_string); |
5775 __ AllocateAsciiString(v0, a2, t0, t1, t4, &sub_string_runtime); | 5782 __ AllocateAsciiString(v0, a2, t0, t1, t4, &sub_string_runtime); |
5776 __ sh(a3, FieldMemOperand(v0, SeqAsciiString::kHeaderSize)); | 5783 __ sh(a3, FieldMemOperand(v0, SeqAsciiString::kHeaderSize)); |
5777 __ IncrementCounter(counters->sub_string_native(), 1, a3, t0); | 5784 __ jmp(&return_v0); |
5778 __ Addu(sp, sp, Operand(3 * kPointerSize)); | |
5779 __ Ret(); | |
5780 | 5785 |
5781 __ bind(&result_longer_than_two); | 5786 __ bind(&result_longer_than_two); |
5782 | 5787 |
| 5788 // Locate 'from' character of string. |
| 5789 __ Addu(t1, v0, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); |
| 5790 __ sra(t4, from, 1); |
| 5791 __ Addu(t1, t1, t4); |
| 5792 |
5783 // Allocate the result. | 5793 // Allocate the result. |
5784 __ AllocateAsciiString(v0, a2, t4, t0, a1, &sub_string_runtime); | 5794 __ AllocateAsciiString(v0, a2, t4, t0, a1, &sub_string_runtime); |
5785 | 5795 |
5786 // v0: result string. | 5796 // v0: result string |
5787 // a2: result string length. | 5797 // a2: result string length |
5788 // a3: from index (untagged smi) | 5798 // a3: from index (untagged smi) |
5789 // t1: string. | 5799 // t1: first character of substring to copy |
5790 // t3: (a.k.a. from): from offset (smi) | 5800 // t3: (a.k.a. from): from offset (smi) |
5791 // Locate first character of result. | 5801 // Locate first character of result. |
5792 __ Addu(a1, v0, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); | 5802 __ Addu(a1, v0, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); |
5793 // Locate 'from' character of string. | |
5794 __ Addu(t1, t1, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); | |
5795 __ Addu(t1, t1, Operand(a3)); | |
5796 | 5803 |
5797 // v0: result string. | 5804 // v0: result string |
5798 // a1: first character of result string. | 5805 // a1: first character of result string |
5799 // a2: result string length. | 5806 // a2: result string length |
5800 // t1: first character of sub string to copy. | 5807 // t1: first character of substring to copy |
5801 STATIC_ASSERT((SeqAsciiString::kHeaderSize & kObjectAlignmentMask) == 0); | 5808 STATIC_ASSERT((SeqAsciiString::kHeaderSize & kObjectAlignmentMask) == 0); |
5802 StringHelper::GenerateCopyCharactersLong( | 5809 StringHelper::GenerateCopyCharactersLong( |
5803 masm, a1, t1, a2, a3, t0, t2, t3, t4, COPY_ASCII | DEST_ALWAYS_ALIGNED); | 5810 masm, a1, t1, a2, a3, t0, t2, t3, t4, COPY_ASCII | DEST_ALWAYS_ALIGNED); |
5804 __ IncrementCounter(counters->sub_string_native(), 1, a3, t0); | 5811 __ jmp(&return_v0); |
5805 __ Addu(sp, sp, Operand(3 * kPointerSize)); | |
5806 __ Ret(); | |
5807 | 5812 |
5808 __ bind(&non_ascii_flat); | 5813 __ bind(&non_ascii_flat); |
5809 // a2: result string length. | 5814 // a2: result string length |
5810 // t1: string. | 5815 // t1: string |
5811 // t3: (a.k.a. from): from offset (smi) | 5816 // t3: (a.k.a. from): from offset (smi) |
5812 // Check for flat two byte string. | 5817 // Check for flat two byte string. |
5813 | 5818 |
| 5819 // Locate 'from' character of string. |
| 5820 __ Addu(t1, v0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); |
| 5821 // As "from" is a smi it is 2 times the value which matches the size of a two |
| 5822 // byte character. |
| 5823 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); |
| 5824 __ Addu(t1, t1, Operand(from)); |
| 5825 |
5814 // Allocate the result. | 5826 // Allocate the result. |
5815 __ AllocateTwoByteString(v0, a2, a1, a3, t0, &sub_string_runtime); | 5827 __ AllocateTwoByteString(v0, a2, a1, a3, t0, &sub_string_runtime); |
5816 | 5828 |
5817 // v0: result string. | 5829 // v0: result string |
5818 // a2: result string length. | 5830 // a2: result string length |
5819 // t1: string. | 5831 // t1: first character of substring to copy |
5820 // Locate first character of result. | 5832 // Locate first character of result. |
5821 __ Addu(a1, v0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); | 5833 __ Addu(a1, v0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); |
5822 // Locate 'from' character of string. | 5834 |
5823 __ Addu(t1, t1, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); | |
5824 // As "from" is a smi it is 2 times the value which matches the size of a two | |
5825 // byte character. | |
5826 __ Addu(t1, t1, Operand(from)); | |
5827 from = no_reg; | 5835 from = no_reg; |
5828 | 5836 |
5829 // v0: result string. | 5837 // v0: result string. |
5830 // a1: first character of result. | 5838 // a1: first character of result. |
5831 // a2: result length. | 5839 // a2: result length. |
5832 // t1: first character of string to copy. | 5840 // t1: first character of substring to copy. |
5833 STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0); | 5841 STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0); |
5834 StringHelper::GenerateCopyCharactersLong( | 5842 StringHelper::GenerateCopyCharactersLong( |
5835 masm, a1, t1, a2, a3, t0, t2, t3, t4, DEST_ALWAYS_ALIGNED); | 5843 masm, a1, t1, a2, a3, t0, t2, t3, t4, DEST_ALWAYS_ALIGNED); |
| 5844 __ jmp(&return_v0); |
| 5845 |
| 5846 if (FLAG_string_slices) { |
| 5847 __ bind(&create_slice); |
| 5848 // v0: original string |
| 5849 // a1: instance type |
| 5850 // a2: length |
| 5851 // a3: from index (untagged smi) |
| 5852 // t2 (a.k.a. to): to (smi) |
| 5853 // t3 (a.k.a. from): from offset (smi) |
| 5854 Label allocate_slice, sliced_string, seq_string; |
| 5855 STATIC_ASSERT(kSeqStringTag == 0); |
| 5856 __ And(t4, a1, Operand(kStringRepresentationMask)); |
| 5857 __ Branch(&seq_string, eq, t4, Operand(zero_reg)); |
| 5858 STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag)); |
| 5859 STATIC_ASSERT(kIsIndirectStringMask != 0); |
| 5860 __ And(t4, a1, Operand(kIsIndirectStringMask)); |
| 5861 // External string. Jump to runtime. |
| 5862 __ Branch(&sub_string_runtime, eq, t4, Operand(zero_reg)); |
| 5863 |
| 5864 __ And(t4, a1, Operand(kSlicedNotConsMask)); |
| 5865 __ Branch(&sliced_string, ne, t4, Operand(zero_reg)); |
| 5866 // Cons string. Check whether it is flat, then fetch first part. |
| 5867 __ lw(t1, FieldMemOperand(v0, ConsString::kSecondOffset)); |
| 5868 __ LoadRoot(t5, Heap::kEmptyStringRootIndex); |
| 5869 __ Branch(&sub_string_runtime, ne, t1, Operand(t5)); |
| 5870 __ lw(t1, FieldMemOperand(v0, ConsString::kFirstOffset)); |
| 5871 __ jmp(&allocate_slice); |
| 5872 |
| 5873 __ bind(&sliced_string); |
| 5874 // Sliced string. Fetch parent and correct start index by offset. |
| 5875 __ lw(t1, FieldMemOperand(v0, SlicedString::kOffsetOffset)); |
| 5876 __ addu(t3, t3, t1); |
| 5877 __ lw(t1, FieldMemOperand(v0, SlicedString::kParentOffset)); |
| 5878 __ jmp(&allocate_slice); |
| 5879 |
| 5880 __ bind(&seq_string); |
| 5881 // Sequential string. Just move string to the right register. |
| 5882 __ mov(t1, v0); |
| 5883 |
| 5884 __ bind(&allocate_slice); |
| 5885 // a1: instance type of original string |
| 5886 // a2: length |
| 5887 // t1: underlying subject string |
| 5888 // t3 (a.k.a. from): from offset (smi) |
| 5889 // Allocate new sliced string. At this point we do not reload the instance |
| 5890 // type including the string encoding because we simply rely on the info |
| 5891 // provided by the original string. It does not matter if the original |
| 5892 // string's encoding is wrong because we always have to recheck encoding of |
| 5893 // the newly created string's parent anyways due to externalized strings. |
| 5894 Label two_byte_slice, set_slice_header; |
| 5895 STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0); |
| 5896 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0); |
| 5897 __ And(t4, a1, Operand(kStringEncodingMask)); |
| 5898 __ Branch(&two_byte_slice, eq, t4, Operand(zero_reg)); |
| 5899 __ AllocateAsciiSlicedString(v0, a2, a3, t0, &sub_string_runtime); |
| 5900 __ jmp(&set_slice_header); |
| 5901 __ bind(&two_byte_slice); |
| 5902 __ AllocateTwoByteSlicedString(v0, a2, a3, t0, &sub_string_runtime); |
| 5903 __ bind(&set_slice_header); |
| 5904 __ sw(t3, FieldMemOperand(v0, SlicedString::kOffsetOffset)); |
| 5905 __ sw(t1, FieldMemOperand(v0, SlicedString::kParentOffset)); |
| 5906 } |
| 5907 |
| 5908 __ bind(&return_v0); |
5836 __ IncrementCounter(counters->sub_string_native(), 1, a3, t0); | 5909 __ IncrementCounter(counters->sub_string_native(), 1, a3, t0); |
5837 __ Addu(sp, sp, Operand(3 * kPointerSize)); | 5910 __ Addu(sp, sp, Operand(3 * kPointerSize)); |
5838 __ Ret(); | 5911 __ Ret(); |
5839 | 5912 |
5840 // Just jump to runtime to create the sub string. | 5913 // Just jump to runtime to create the sub string. |
5841 __ bind(&sub_string_runtime); | 5914 __ bind(&sub_string_runtime); |
5842 __ TailCallRuntime(Runtime::kSubString, 3, 1); | 5915 __ TailCallRuntime(Runtime::kSubString, 3, 1); |
5843 } | 5916 } |
5844 | 5917 |
5845 | 5918 |
(...skipping 1040 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6886 __ mov(result, zero_reg); | 6959 __ mov(result, zero_reg); |
6887 __ Ret(); | 6960 __ Ret(); |
6888 } | 6961 } |
6889 | 6962 |
6890 | 6963 |
6891 #undef __ | 6964 #undef __ |
6892 | 6965 |
6893 } } // namespace v8::internal | 6966 } } // namespace v8::internal |
6894 | 6967 |
6895 #endif // V8_TARGET_ARCH_MIPS | 6968 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |