| 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 |