| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_MIPS | 7 #if V8_TARGET_ARCH_MIPS |
| 8 | 8 |
| 9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
| 10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
| (...skipping 3480 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3491 __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase); | 3491 __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase); |
| 3492 } | 3492 } |
| 3493 | 3493 |
| 3494 | 3494 |
| 3495 enum CopyCharactersFlags { | 3495 enum CopyCharactersFlags { |
| 3496 COPY_ASCII = 1, | 3496 COPY_ASCII = 1, |
| 3497 DEST_ALWAYS_ALIGNED = 2 | 3497 DEST_ALWAYS_ALIGNED = 2 |
| 3498 }; | 3498 }; |
| 3499 | 3499 |
| 3500 | 3500 |
| 3501 void StringHelper::GenerateCopyCharactersLong(MacroAssembler* masm, | 3501 void StringHelper::GenerateCopyCharacters(MacroAssembler* masm, |
| 3502 Register dest, | 3502 Register dest, |
| 3503 Register src, | 3503 Register src, |
| 3504 Register count, | 3504 Register count, |
| 3505 Register scratch1, | 3505 Register scratch, |
| 3506 Register scratch2, | 3506 String::Encoding encoding) { |
| 3507 Register scratch3, | 3507 if (FLAG_debug_code) { |
| 3508 Register scratch4, | 3508 // Check that destination is word aligned. |
| 3509 Register scratch5, | 3509 __ And(scratch, dest, Operand(kPointerAlignmentMask)); |
| 3510 int flags) { | |
| 3511 bool ascii = (flags & COPY_ASCII) != 0; | |
| 3512 bool dest_always_aligned = (flags & DEST_ALWAYS_ALIGNED) != 0; | |
| 3513 | |
| 3514 if (dest_always_aligned && FLAG_debug_code) { | |
| 3515 // Check that destination is actually word aligned if the flag says | |
| 3516 // that it is. | |
| 3517 __ And(scratch4, dest, Operand(kPointerAlignmentMask)); | |
| 3518 __ Check(eq, | 3510 __ Check(eq, |
| 3519 kDestinationOfCopyNotAligned, | 3511 kDestinationOfCopyNotAligned, |
| 3520 scratch4, | 3512 scratch, |
| 3521 Operand(zero_reg)); | 3513 Operand(zero_reg)); |
| 3522 } | 3514 } |
| 3523 | 3515 |
| 3524 const int kReadAlignment = 4; | |
| 3525 const int kReadAlignmentMask = kReadAlignment - 1; | |
| 3526 // Ensure that reading an entire aligned word containing the last character | |
| 3527 // of a string will not read outside the allocated area (because we pad up | |
| 3528 // to kObjectAlignment). | |
| 3529 STATIC_ASSERT(kObjectAlignment >= kReadAlignment); | |
| 3530 // Assumes word reads and writes are little endian. | 3516 // Assumes word reads and writes are little endian. |
| 3531 // Nothing to do for zero characters. | 3517 // Nothing to do for zero characters. |
| 3532 Label done; | 3518 Label done; |
| 3533 | 3519 |
| 3534 if (!ascii) { | 3520 if (encoding == String::TWO_BYTE_ENCODING) { |
| 3535 __ addu(count, count, count); | 3521 __ Addu(count, count, count); |
| 3536 } | |
| 3537 __ Branch(&done, eq, count, Operand(zero_reg)); | |
| 3538 | |
| 3539 Label byte_loop; | |
| 3540 // Must copy at least eight bytes, otherwise just do it one byte at a time. | |
| 3541 __ Subu(scratch1, count, Operand(8)); | |
| 3542 __ Addu(count, dest, Operand(count)); | |
| 3543 Register limit = count; // Read until src equals this. | |
| 3544 __ Branch(&byte_loop, lt, scratch1, Operand(zero_reg)); | |
| 3545 | |
| 3546 if (!dest_always_aligned) { | |
| 3547 // Align dest by byte copying. Copies between zero and three bytes. | |
| 3548 __ And(scratch4, dest, Operand(kReadAlignmentMask)); | |
| 3549 Label dest_aligned; | |
| 3550 __ Branch(&dest_aligned, eq, scratch4, Operand(zero_reg)); | |
| 3551 Label aligned_loop; | |
| 3552 __ bind(&aligned_loop); | |
| 3553 __ lbu(scratch1, MemOperand(src)); | |
| 3554 __ addiu(src, src, 1); | |
| 3555 __ sb(scratch1, MemOperand(dest)); | |
| 3556 __ addiu(dest, dest, 1); | |
| 3557 __ addiu(scratch4, scratch4, 1); | |
| 3558 __ Branch(&aligned_loop, le, scratch4, Operand(kReadAlignmentMask)); | |
| 3559 __ bind(&dest_aligned); | |
| 3560 } | 3522 } |
| 3561 | 3523 |
| 3562 Label simple_loop; | 3524 Register limit = count; // Read until dest equals this. |
| 3525 __ Addu(limit, dest, Operand(count)); |
| 3563 | 3526 |
| 3564 __ And(scratch4, src, Operand(kReadAlignmentMask)); | 3527 Label loop_entry, loop; |
| 3565 __ Branch(&simple_loop, eq, scratch4, Operand(zero_reg)); | |
| 3566 | |
| 3567 // Loop for src/dst that are not aligned the same way. | |
| 3568 // This loop uses lwl and lwr instructions. These instructions | |
| 3569 // depend on the endianness, and the implementation assumes little-endian. | |
| 3570 { | |
| 3571 Label loop; | |
| 3572 __ bind(&loop); | |
| 3573 if (kArchEndian == kBig) { | |
| 3574 __ lwl(scratch1, MemOperand(src)); | |
| 3575 __ Addu(src, src, Operand(kReadAlignment)); | |
| 3576 __ lwr(scratch1, MemOperand(src, -1)); | |
| 3577 } else { | |
| 3578 __ lwr(scratch1, MemOperand(src)); | |
| 3579 __ Addu(src, src, Operand(kReadAlignment)); | |
| 3580 __ lwl(scratch1, MemOperand(src, -1)); | |
| 3581 } | |
| 3582 __ sw(scratch1, MemOperand(dest)); | |
| 3583 __ Addu(dest, dest, Operand(kReadAlignment)); | |
| 3584 __ Subu(scratch2, limit, dest); | |
| 3585 __ Branch(&loop, ge, scratch2, Operand(kReadAlignment)); | |
| 3586 } | |
| 3587 | |
| 3588 __ Branch(&byte_loop); | |
| 3589 | |
| 3590 // Simple loop. | |
| 3591 // Copy words from src to dest, until less than four bytes left. | |
| 3592 // Both src and dest are word aligned. | |
| 3593 __ bind(&simple_loop); | |
| 3594 { | |
| 3595 Label loop; | |
| 3596 __ bind(&loop); | |
| 3597 __ lw(scratch1, MemOperand(src)); | |
| 3598 __ Addu(src, src, Operand(kReadAlignment)); | |
| 3599 __ sw(scratch1, MemOperand(dest)); | |
| 3600 __ Addu(dest, dest, Operand(kReadAlignment)); | |
| 3601 __ Subu(scratch2, limit, dest); | |
| 3602 __ Branch(&loop, ge, scratch2, Operand(kReadAlignment)); | |
| 3603 } | |
| 3604 | |
| 3605 // Copy bytes from src to dest until dest hits limit. | 3528 // Copy bytes from src to dest until dest hits limit. |
| 3606 __ bind(&byte_loop); | 3529 __ Branch(&loop_entry); |
| 3607 // Test if dest has already reached the limit. | 3530 __ bind(&loop); |
| 3608 __ Branch(&done, ge, dest, Operand(limit)); | 3531 __ lbu(scratch, MemOperand(src)); |
| 3609 __ lbu(scratch1, MemOperand(src)); | 3532 __ Addu(src, src, Operand(1)); |
| 3610 __ addiu(src, src, 1); | 3533 __ sb(scratch, MemOperand(dest)); |
| 3611 __ sb(scratch1, MemOperand(dest)); | 3534 __ Addu(dest, dest, Operand(1)); |
| 3612 __ addiu(dest, dest, 1); | 3535 __ bind(&loop_entry); |
| 3613 __ Branch(&byte_loop); | 3536 __ Branch(&loop, lt, dest, Operand(limit)); |
| 3614 | 3537 |
| 3615 __ bind(&done); | 3538 __ bind(&done); |
| 3616 } | 3539 } |
| 3617 | 3540 |
| 3618 | 3541 |
| 3619 void StringHelper::GenerateHashInit(MacroAssembler* masm, | 3542 void StringHelper::GenerateHashInit(MacroAssembler* masm, |
| 3620 Register hash, | 3543 Register hash, |
| 3621 Register character) { | 3544 Register character) { |
| 3622 // hash = seed + character + ((seed + character) << 10); | 3545 // hash = seed + character + ((seed + character) << 10); |
| 3623 __ LoadRoot(hash, Heap::kHashSeedRootIndex); | 3546 __ LoadRoot(hash, Heap::kHashSeedRootIndex); |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3837 __ Addu(t1, t1, a3); | 3760 __ Addu(t1, t1, a3); |
| 3838 | 3761 |
| 3839 // Locate first character of result. | 3762 // Locate first character of result. |
| 3840 __ Addu(a1, v0, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); | 3763 __ Addu(a1, v0, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
| 3841 | 3764 |
| 3842 // v0: result string | 3765 // v0: result string |
| 3843 // a1: first character of result string | 3766 // a1: first character of result string |
| 3844 // a2: result string length | 3767 // a2: result string length |
| 3845 // t1: first character of substring to copy | 3768 // t1: first character of substring to copy |
| 3846 STATIC_ASSERT((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0); | 3769 STATIC_ASSERT((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0); |
| 3847 StringHelper::GenerateCopyCharactersLong( | 3770 StringHelper::GenerateCopyCharacters( |
| 3848 masm, a1, t1, a2, a3, t0, t2, t3, t4, COPY_ASCII | DEST_ALWAYS_ALIGNED); | 3771 masm, a1, t1, a2, a3, String::ONE_BYTE_ENCODING); |
| 3849 __ jmp(&return_v0); | 3772 __ jmp(&return_v0); |
| 3850 | 3773 |
| 3851 // Allocate and copy the resulting two-byte string. | 3774 // Allocate and copy the resulting two-byte string. |
| 3852 __ bind(&two_byte_sequential); | 3775 __ bind(&two_byte_sequential); |
| 3853 __ AllocateTwoByteString(v0, a2, t0, t2, t3, &runtime); | 3776 __ AllocateTwoByteString(v0, a2, t0, t2, t3, &runtime); |
| 3854 | 3777 |
| 3855 // Locate first character of substring to copy. | 3778 // Locate first character of substring to copy. |
| 3856 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); | 3779 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); |
| 3857 __ sll(t0, a3, 1); | 3780 __ sll(t0, a3, 1); |
| 3858 __ Addu(t1, t1, t0); | 3781 __ Addu(t1, t1, t0); |
| 3859 // Locate first character of result. | 3782 // Locate first character of result. |
| 3860 __ Addu(a1, v0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); | 3783 __ Addu(a1, v0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); |
| 3861 | 3784 |
| 3862 // v0: result string. | 3785 // v0: result string. |
| 3863 // a1: first character of result. | 3786 // a1: first character of result. |
| 3864 // a2: result length. | 3787 // a2: result length. |
| 3865 // t1: first character of substring to copy. | 3788 // t1: first character of substring to copy. |
| 3866 STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0); | 3789 STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0); |
| 3867 StringHelper::GenerateCopyCharactersLong( | 3790 StringHelper::GenerateCopyCharacters( |
| 3868 masm, a1, t1, a2, a3, t0, t2, t3, t4, DEST_ALWAYS_ALIGNED); | 3791 masm, a1, t1, a2, a3, String::TWO_BYTE_ENCODING); |
| 3869 | 3792 |
| 3870 __ bind(&return_v0); | 3793 __ bind(&return_v0); |
| 3871 Counters* counters = isolate()->counters(); | 3794 Counters* counters = isolate()->counters(); |
| 3872 __ IncrementCounter(counters->sub_string_native(), 1, a3, t0); | 3795 __ IncrementCounter(counters->sub_string_native(), 1, a3, t0); |
| 3873 __ DropAndRet(3); | 3796 __ DropAndRet(3); |
| 3874 | 3797 |
| 3875 // Just jump to runtime to create the sub string. | 3798 // Just jump to runtime to create the sub string. |
| 3876 __ bind(&runtime); | 3799 __ bind(&runtime); |
| 3877 __ TailCallRuntime(Runtime::kHiddenSubString, 3, 1); | 3800 __ TailCallRuntime(Runtime::kHiddenSubString, 3, 1); |
| 3878 | 3801 |
| (...skipping 1595 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5474 MemOperand(fp, 6 * kPointerSize), | 5397 MemOperand(fp, 6 * kPointerSize), |
| 5475 NULL); | 5398 NULL); |
| 5476 } | 5399 } |
| 5477 | 5400 |
| 5478 | 5401 |
| 5479 #undef __ | 5402 #undef __ |
| 5480 | 5403 |
| 5481 } } // namespace v8::internal | 5404 } } // namespace v8::internal |
| 5482 | 5405 |
| 5483 #endif // V8_TARGET_ARCH_MIPS | 5406 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |