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

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

Issue 7830036: Optimize isFinite and isNaN. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Made the change general by moving putting it in the NUMBER_IS_FINITE macro. Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/messages.js ('k') | src/mips/constants-mips.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/messages.js ('k') | src/mips/constants-mips.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698