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