From: yangguo@chromium.org Date: Wed, 11 Jun 2014 06:59:25 +0000 (+0000) Subject: Simplify string copy in SubStringStub. X-Git-Tag: upstream/4.7.83~8747 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=d5c6e4a9f689f4cd6dea043d622e501487d76e68;p=platform%2Fupstream%2Fv8.git Simplify string copy in SubStringStub. The optimizations are unnecessary since the maximum string length they operate on is currently 12. R=bmeurer@chromium.org BUG=352155 LOG=N Review URL: https://codereview.chromium.org/326943002 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@21756 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc index d2f95e6..9f54ff3 100644 --- a/src/arm/code-stubs-arm.cc +++ b/src/arm/code-stubs-arm.cc @@ -3322,142 +3322,37 @@ enum CopyCharactersFlags { }; -void StringHelper::GenerateCopyCharactersLong(MacroAssembler* masm, - Register dest, - Register src, - Register count, - Register scratch1, - Register scratch2, - Register scratch3, - Register scratch4, - int flags) { - bool ascii = (flags & COPY_ASCII) != 0; - bool dest_always_aligned = (flags & DEST_ALWAYS_ALIGNED) != 0; - - if (dest_always_aligned && FLAG_debug_code) { - // Check that destination is actually word aligned if the flag says - // that it is. +void StringHelper::GenerateCopyCharacters(MacroAssembler* masm, + Register dest, + Register src, + Register count, + Register scratch, + String::Encoding encoding) { + if (FLAG_debug_code) { + // Check that destination is word aligned. __ tst(dest, Operand(kPointerAlignmentMask)); __ Check(eq, kDestinationOfCopyNotAligned); } - const int kReadAlignment = 4; - const int kReadAlignmentMask = kReadAlignment - 1; - // Ensure that reading an entire aligned word containing the last character - // of a string will not read outside the allocated area (because we pad up - // to kObjectAlignment). - STATIC_ASSERT(kObjectAlignment >= kReadAlignment); // Assumes word reads and writes are little endian. // Nothing to do for zero characters. Label done; - if (!ascii) { + if (encoding == String::TWO_BYTE_ENCODING) { __ add(count, count, Operand(count), SetCC); - } else { - __ cmp(count, Operand::Zero()); } - __ b(eq, &done); - - // Assume that you cannot read (or write) unaligned. - Label byte_loop; - // Must copy at least eight bytes, otherwise just do it one byte at a time. - __ cmp(count, Operand(8)); - __ add(count, dest, Operand(count)); - Register limit = count; // Read until src equals this. - __ b(lt, &byte_loop); - - if (!dest_always_aligned) { - // Align dest by byte copying. Copies between zero and three bytes. - __ and_(scratch4, dest, Operand(kReadAlignmentMask), SetCC); - Label dest_aligned; - __ b(eq, &dest_aligned); - __ cmp(scratch4, Operand(2)); - __ ldrb(scratch1, MemOperand(src, 1, PostIndex)); - __ ldrb(scratch2, MemOperand(src, 1, PostIndex), le); - __ ldrb(scratch3, MemOperand(src, 1, PostIndex), lt); - __ strb(scratch1, MemOperand(dest, 1, PostIndex)); - __ strb(scratch2, MemOperand(dest, 1, PostIndex), le); - __ strb(scratch3, MemOperand(dest, 1, PostIndex), lt); - __ bind(&dest_aligned); - } - - Label simple_loop; - - __ sub(scratch4, dest, Operand(src)); - __ and_(scratch4, scratch4, Operand(0x03), SetCC); - __ b(eq, &simple_loop); - // Shift register is number of bits in a source word that - // must be combined with bits in the next source word in order - // to create a destination word. - // Complex loop for src/dst that are not aligned the same way. - { - Label loop; - __ mov(scratch4, Operand(scratch4, LSL, 3)); - Register left_shift = scratch4; - __ and_(src, src, Operand(~3)); // Round down to load previous word. - __ ldr(scratch1, MemOperand(src, 4, PostIndex)); - // Store the "shift" most significant bits of scratch in the least - // signficant bits (i.e., shift down by (32-shift)). - __ rsb(scratch2, left_shift, Operand(32)); - Register right_shift = scratch2; - __ mov(scratch1, Operand(scratch1, LSR, right_shift)); - - __ bind(&loop); - __ ldr(scratch3, MemOperand(src, 4, PostIndex)); - __ orr(scratch1, scratch1, Operand(scratch3, LSL, left_shift)); - __ str(scratch1, MemOperand(dest, 4, PostIndex)); - __ mov(scratch1, Operand(scratch3, LSR, right_shift)); - // Loop if four or more bytes left to copy. - __ sub(scratch3, limit, Operand(dest)); - __ sub(scratch3, scratch3, Operand(4), SetCC); - __ b(ge, &loop); - } - // There is now between zero and three bytes left to copy (negative that - // number is in scratch3), and between one and three bytes already read into - // scratch1 (eight times that number in scratch4). We may have read past - // the end of the string, but because objects are aligned, we have not read - // past the end of the object. - // Find the minimum of remaining characters to move and preloaded characters - // and write those as bytes. - __ add(scratch3, scratch3, Operand(4), SetCC); - __ b(eq, &done); - __ cmp(scratch4, Operand(scratch3, LSL, 3), ne); - // Move minimum of bytes read and bytes left to copy to scratch4. - __ mov(scratch3, Operand(scratch4, LSR, 3), LeaveCC, lt); - // Between one and three (value in scratch3) characters already read into - // scratch ready to write. - __ cmp(scratch3, Operand(2)); - __ strb(scratch1, MemOperand(dest, 1, PostIndex)); - __ mov(scratch1, Operand(scratch1, LSR, 8), LeaveCC, ge); - __ strb(scratch1, MemOperand(dest, 1, PostIndex), ge); - __ mov(scratch1, Operand(scratch1, LSR, 8), LeaveCC, gt); - __ strb(scratch1, MemOperand(dest, 1, PostIndex), gt); - // Copy any remaining bytes. - __ b(&byte_loop); - - // Simple loop. - // Copy words from src to dst, until less than four bytes left. - // Both src and dest are word aligned. - __ bind(&simple_loop); - { - Label loop; - __ bind(&loop); - __ ldr(scratch1, MemOperand(src, 4, PostIndex)); - __ sub(scratch3, limit, Operand(dest)); - __ str(scratch1, MemOperand(dest, 4, PostIndex)); - // Compare to 8, not 4, because we do the substraction before increasing - // dest. - __ cmp(scratch3, Operand(8)); - __ b(ge, &loop); - } + Register limit = count; // Read until dest equals this. + __ add(limit, dest, Operand(count)); - // Copy bytes from src to dst until dst hits limit. - __ bind(&byte_loop); + Label loop_entry, loop; + // Copy bytes from src to dest until dest hits limit. + __ b(&loop_entry); + __ bind(&loop); + __ ldrb(scratch, MemOperand(src, 1, PostIndex), lt); + __ strb(scratch, MemOperand(dest, 1, PostIndex)); + __ bind(&loop_entry); __ cmp(dest, Operand(limit)); - __ ldrb(scratch1, MemOperand(src, 1, PostIndex), lt); - __ b(ge, &done); - __ strb(scratch1, MemOperand(dest, 1, PostIndex)); - __ b(&byte_loop); + __ b(lt, &loop); __ bind(&done); } @@ -3683,8 +3578,8 @@ void SubStringStub::Generate(MacroAssembler* masm) { // r2: result string length // r5: first character of substring to copy STATIC_ASSERT((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0); - StringHelper::GenerateCopyCharactersLong(masm, r1, r5, r2, r3, r4, r6, r9, - COPY_ASCII | DEST_ALWAYS_ALIGNED); + StringHelper::GenerateCopyCharacters( + masm, r1, r5, r2, r3, String::ONE_BYTE_ENCODING); __ jmp(&return_r0); // Allocate and copy the resulting two-byte string. @@ -3702,8 +3597,8 @@ void SubStringStub::Generate(MacroAssembler* masm) { // r2: result length. // r5: first character of substring to copy. STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0); - StringHelper::GenerateCopyCharactersLong( - masm, r1, r5, r2, r3, r4, r6, r9, DEST_ALWAYS_ALIGNED); + StringHelper::GenerateCopyCharacters( + masm, r1, r5, r2, r3, String::TWO_BYTE_ENCODING); __ bind(&return_r0); Counters* counters = isolate()->counters(); diff --git a/src/arm/code-stubs-arm.h b/src/arm/code-stubs-arm.h index 2a90d27..5dde337 100644 --- a/src/arm/code-stubs-arm.h +++ b/src/arm/code-stubs-arm.h @@ -38,15 +38,12 @@ class StringHelper : public AllStatic { // is allowed to spend extra time setting up conditions to make copying // faster. Copying of overlapping regions is not supported. // Dest register ends at the position after the last character written. - static void GenerateCopyCharactersLong(MacroAssembler* masm, - Register dest, - Register src, - Register count, - Register scratch1, - Register scratch2, - Register scratch3, - Register scratch4, - int flags); + static void GenerateCopyCharacters(MacroAssembler* masm, + Register dest, + Register src, + Register count, + Register scratch, + String::Encoding encoding); // Generate string hash. diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc index 68aa844..efc714b 100644 --- a/src/ia32/code-stubs-ia32.cc +++ b/src/ia32/code-stubs-ia32.cc @@ -3180,18 +3180,12 @@ void StringCharFromCodeGenerator::GenerateSlow( } -void StringHelper::GenerateCopyCharactersREP(MacroAssembler* masm, - Register dest, - Register src, - Register count, - Register scratch, - bool ascii) { - // Copy characters using rep movs of doublewords. - // The destination is aligned on a 4 byte boundary because we are - // copying to the beginning of a newly allocated string. - ASSERT(dest.is(edi)); // rep movs destination - ASSERT(src.is(esi)); // rep movs source - ASSERT(count.is(ecx)); // rep movs count +void StringHelper::GenerateCopyCharacters(MacroAssembler* masm, + Register dest, + Register src, + Register count, + Register scratch, + String::Encoding encoding) { ASSERT(!scratch.is(dest)); ASSERT(!scratch.is(src)); ASSERT(!scratch.is(count)); @@ -3202,38 +3196,17 @@ void StringHelper::GenerateCopyCharactersREP(MacroAssembler* masm, __ j(zero, &done); // Make count the number of bytes to copy. - if (!ascii) { + if (encoding == String::TWO_BYTE_ENCODING) { __ shl(count, 1); } - // Don't enter the rep movs if there are less than 4 bytes to copy. - Label last_bytes; - __ test(count, Immediate(~3)); - __ j(zero, &last_bytes, Label::kNear); - - // Copy from edi to esi using rep movs instruction. - __ mov(scratch, count); - __ sar(count, 2); // Number of doublewords to copy. - __ cld(); - __ rep_movs(); - - // Find number of bytes left. - __ mov(count, scratch); - __ and_(count, 3); - - // Check if there are more bytes to copy. - __ bind(&last_bytes); - __ test(count, count); - __ j(zero, &done); - - // Copy remaining characters. Label loop; __ bind(&loop); __ mov_b(scratch, Operand(src, 0)); __ mov_b(Operand(dest, 0), scratch); - __ add(src, Immediate(1)); - __ add(dest, Immediate(1)); - __ sub(count, Immediate(1)); + __ inc(src); + __ inc(dest); + __ dec(count); __ j(not_zero, &loop); __ bind(&done); @@ -3462,23 +3435,21 @@ void SubStringStub::Generate(MacroAssembler* masm) { // eax: result string // ecx: result string length - __ mov(edx, esi); // esi used by following code. // Locate first character of result. __ mov(edi, eax); __ add(edi, Immediate(SeqOneByteString::kHeaderSize - kHeapObjectTag)); // Load string argument and locate character of sub string start. - __ pop(esi); + __ pop(edx); __ pop(ebx); __ SmiUntag(ebx); - __ lea(esi, FieldOperand(esi, ebx, times_1, SeqOneByteString::kHeaderSize)); + __ lea(edx, FieldOperand(edx, ebx, times_1, SeqOneByteString::kHeaderSize)); // eax: result string // ecx: result length - // edx: original value of esi // edi: first character of result - // esi: character of sub string start - StringHelper::GenerateCopyCharactersREP(masm, edi, esi, ecx, ebx, true); - __ mov(esi, edx); // Restore esi. + // edx: character of sub string start + StringHelper::GenerateCopyCharacters( + masm, edi, edx, ecx, ebx, String::ONE_BYTE_ENCODING); __ IncrementCounter(counters->sub_string_native(), 1); __ ret(3 * kPointerSize); @@ -3488,27 +3459,25 @@ void SubStringStub::Generate(MacroAssembler* masm) { // eax: result string // ecx: result string length - __ mov(edx, esi); // esi used by following code. // Locate first character of result. __ mov(edi, eax); __ add(edi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); // Load string argument and locate character of sub string start. - __ pop(esi); + __ pop(edx); __ pop(ebx); // As from is a smi it is 2 times the value which matches the size of a two // byte character. STATIC_ASSERT(kSmiTag == 0); STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); - __ lea(esi, FieldOperand(esi, ebx, times_1, SeqTwoByteString::kHeaderSize)); + __ lea(edx, FieldOperand(edx, ebx, times_1, SeqTwoByteString::kHeaderSize)); // eax: result string // ecx: result length - // edx: original value of esi // edi: first character of result - // esi: character of sub string start - StringHelper::GenerateCopyCharactersREP(masm, edi, esi, ecx, ebx, false); - __ mov(esi, edx); // Restore esi. + // edx: character of sub string start + StringHelper::GenerateCopyCharacters( + masm, edi, edx, ecx, ebx, String::TWO_BYTE_ENCODING); __ IncrementCounter(counters->sub_string_native(), 1); __ ret(3 * kPointerSize); diff --git a/src/ia32/code-stubs-ia32.h b/src/ia32/code-stubs-ia32.h index ab60bc0..8700181 100644 --- a/src/ia32/code-stubs-ia32.h +++ b/src/ia32/code-stubs-ia32.h @@ -40,12 +40,12 @@ class StringHelper : public AllStatic { // Generate code for copying characters using the rep movs instruction. // Copies ecx characters from esi to edi. Copying of overlapping regions is // not supported. - static void GenerateCopyCharactersREP(MacroAssembler* masm, - Register dest, // Must be edi. - Register src, // Must be esi. - Register count, // Must be ecx. - Register scratch, // Neither of above. - bool ascii); + static void GenerateCopyCharacters(MacroAssembler* masm, + Register dest, + Register src, + Register count, + Register scratch, + String::Encoding encoding); // Generate string hash. static void GenerateHashInit(MacroAssembler* masm, diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc index 0a12952..1ae91c2 100644 --- a/src/x64/code-stubs-x64.cc +++ b/src/x64/code-stubs-x64.cc @@ -3134,50 +3134,22 @@ void StringCharFromCodeGenerator::GenerateSlow( } -void StringHelper::GenerateCopyCharactersREP(MacroAssembler* masm, - Register dest, - Register src, - Register count, - bool ascii) { - // Copy characters using rep movs of doublewords. Align destination on 4 byte - // boundary before starting rep movs. Copy remaining characters after running - // rep movs. - // Count is positive int32, dest and src are character pointers. - ASSERT(dest.is(rdi)); // rep movs destination - ASSERT(src.is(rsi)); // rep movs source - ASSERT(count.is(rcx)); // rep movs count - +void StringHelper::GenerateCopyCharacters(MacroAssembler* masm, + Register dest, + Register src, + Register count, + String::Encoding encoding) { // Nothing to do for zero characters. Label done; __ testl(count, count); __ j(zero, &done, Label::kNear); // Make count the number of bytes to copy. - if (!ascii) { + if (encoding == String::TWO_BYTE_ENCODING) { STATIC_ASSERT(2 == sizeof(uc16)); __ addl(count, count); } - // Don't enter the rep movs if there are less than 4 bytes to copy. - Label last_bytes; - __ testl(count, Immediate(~(kPointerSize - 1))); - __ j(zero, &last_bytes, Label::kNear); - - // Copy from edi to esi using rep movs instruction. - __ movl(kScratchRegister, count); - // Number of doublewords to copy. - __ shrl(count, Immediate(kPointerSizeLog2)); - __ repmovsp(); - - // Find number of bytes left. - __ movl(count, kScratchRegister); - __ andp(count, Immediate(kPointerSize - 1)); - - // Check if there are more bytes to copy. - __ bind(&last_bytes); - __ testl(count, count); - __ j(zero, &done, Label::kNear); - // Copy remaining characters. Label loop; __ bind(&loop); @@ -3415,10 +3387,9 @@ void SubStringStub::Generate(MacroAssembler* masm) { // rax: result string // rcx: result string length - __ movp(r14, rsi); // esi used by following code. { // Locate character of sub string start. SmiIndex smi_as_index = masm->SmiToIndex(rdx, rdx, times_1); - __ leap(rsi, Operand(rdi, smi_as_index.reg, smi_as_index.scale, + __ leap(r14, Operand(rdi, smi_as_index.reg, smi_as_index.scale, SeqOneByteString::kHeaderSize - kHeapObjectTag)); } // Locate first character of result. @@ -3426,11 +3397,10 @@ void SubStringStub::Generate(MacroAssembler* masm) { // rax: result string // rcx: result length - // rdi: first character of result + // r14: first character of result // rsi: character of sub string start - // r14: original value of rsi - StringHelper::GenerateCopyCharactersREP(masm, rdi, rsi, rcx, true); - __ movp(rsi, r14); // Restore rsi. + StringHelper::GenerateCopyCharacters( + masm, rdi, r14, rcx, String::ONE_BYTE_ENCODING); __ IncrementCounter(counters->sub_string_native(), 1); __ ret(SUB_STRING_ARGUMENT_COUNT * kPointerSize); @@ -3440,10 +3410,9 @@ void SubStringStub::Generate(MacroAssembler* masm) { // rax: result string // rcx: result string length - __ movp(r14, rsi); // esi used by following code. { // Locate character of sub string start. SmiIndex smi_as_index = masm->SmiToIndex(rdx, rdx, times_2); - __ leap(rsi, Operand(rdi, smi_as_index.reg, smi_as_index.scale, + __ leap(r14, Operand(rdi, smi_as_index.reg, smi_as_index.scale, SeqOneByteString::kHeaderSize - kHeapObjectTag)); } // Locate first character of result. @@ -3452,10 +3421,9 @@ void SubStringStub::Generate(MacroAssembler* masm) { // rax: result string // rcx: result length // rdi: first character of result - // rsi: character of sub string start - // r14: original value of rsi - StringHelper::GenerateCopyCharactersREP(masm, rdi, rsi, rcx, false); - __ movp(rsi, r14); // Restore esi. + // r14: character of sub string start + StringHelper::GenerateCopyCharacters( + masm, rdi, r14, rcx, String::TWO_BYTE_ENCODING); __ IncrementCounter(counters->sub_string_native(), 1); __ ret(SUB_STRING_ARGUMENT_COUNT * kPointerSize); diff --git a/src/x64/code-stubs-x64.h b/src/x64/code-stubs-x64.h index cb141fe..7f9420c 100644 --- a/src/x64/code-stubs-x64.h +++ b/src/x64/code-stubs-x64.h @@ -36,11 +36,11 @@ class StringHelper : public AllStatic { // Generate code for copying characters using the rep movs instruction. // Copies rcx characters from rsi to rdi. Copying of overlapping regions is // not supported. - static void GenerateCopyCharactersREP(MacroAssembler* masm, - Register dest, // Must be rdi. - Register src, // Must be rsi. - Register count, // Must be rcx. - bool ascii); + static void GenerateCopyCharacters(MacroAssembler* masm, + Register dest, + Register src, + Register count, + String::Encoding encoding); // Generate string hash.