| Index: src/ia32/codegen-ia32.cc
|
| ===================================================================
|
| --- src/ia32/codegen-ia32.cc (revision 3551)
|
| +++ src/ia32/codegen-ia32.cc (working copy)
|
| @@ -5282,6 +5282,19 @@
|
| }
|
|
|
|
|
| +void CodeGenerator::GenerateSubString(ZoneList<Expression*>* args) {
|
| + ASSERT_EQ(3, args->length());
|
| +
|
| + Load(args->at(0));
|
| + Load(args->at(1));
|
| + Load(args->at(2));
|
| +
|
| + SubStringStub stub;
|
| + Result answer = frame_->CallStub(&stub, 3);
|
| + frame_->Push(&answer);
|
| +}
|
| +
|
| +
|
| void CodeGenerator::GenerateRegExpExec(ZoneList<Expression*>* args) {
|
| ASSERT_EQ(args->length(), 4);
|
|
|
| @@ -9168,12 +9181,12 @@
|
| }
|
|
|
|
|
| -void StringAddStub::GenerateCopyCharacters(MacroAssembler* masm,
|
| - Register dest,
|
| - Register src,
|
| - Register count,
|
| - Register scratch,
|
| - bool ascii) {
|
| +void StringStubBase::GenerateCopyCharacters(MacroAssembler* masm,
|
| + Register dest,
|
| + Register src,
|
| + Register count,
|
| + Register scratch,
|
| + bool ascii) {
|
| Label loop;
|
| __ bind(&loop);
|
| // This loop just copies one character at a time, as it is only used for very
|
| @@ -9194,6 +9207,175 @@
|
| }
|
|
|
|
|
| +void StringStubBase::GenerateCopyCharactersREP(MacroAssembler* masm,
|
| + Register dest,
|
| + Register src,
|
| + Register count,
|
| + Register scratch,
|
| + 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.
|
| + ASSERT(dest.is(edi)); // rep movs destination
|
| + ASSERT(src.is(esi)); // rep movs source
|
| + ASSERT(count.is(ecx)); // rep movs count
|
| + ASSERT(!scratch.is(dest));
|
| + ASSERT(!scratch.is(src));
|
| + ASSERT(!scratch.is(count));
|
| +
|
| + // Nothing to do for zero characters.
|
| + Label done;
|
| + __ test(count, Operand(count));
|
| + __ j(zero, &done);
|
| +
|
| + // Make count the number of bytes to copy.
|
| + if (!ascii) {
|
| + __ 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);
|
| +
|
| + // Copy from edi to esi using rep movs instruction.
|
| + __ mov(scratch, count);
|
| + __ sar(count, 2); // Number of doublewords to copy.
|
| + __ 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, Operand(count));
|
| + __ j(zero, &done);
|
| +
|
| + // Copy remaining characters.
|
| + Label loop;
|
| + __ bind(&loop);
|
| + __ mov_b(scratch, Operand(src, 0));
|
| + __ mov_b(Operand(dest, 0), scratch);
|
| + __ add(Operand(src), Immediate(1));
|
| + __ add(Operand(dest), Immediate(1));
|
| + __ sub(Operand(count), Immediate(1));
|
| + __ j(not_zero, &loop);
|
| +
|
| + __ bind(&done);
|
| +}
|
| +
|
| +
|
| +void SubStringStub::Generate(MacroAssembler* masm) {
|
| + Label runtime;
|
| +
|
| + // Stack frame on entry.
|
| + // esp[0]: return address
|
| + // esp[4]: to
|
| + // esp[8]: from
|
| + // esp[12]: string
|
| +
|
| + // Make sure first argument is a string.
|
| + __ mov(eax, Operand(esp, 3 * kPointerSize));
|
| + ASSERT_EQ(0, kSmiTag);
|
| + __ test(eax, Immediate(kSmiTagMask));
|
| + __ j(zero, &runtime);
|
| + Condition is_string = masm->IsObjectStringType(eax, ebx, ebx);
|
| + __ j(NegateCondition(is_string), &runtime);
|
| +
|
| + // eax: string
|
| + // ebx: instance type
|
| + // Calculate length of sub string using the smi values.
|
| + __ mov(ecx, Operand(esp, 1 * kPointerSize)); // to
|
| + __ test(ecx, Immediate(kSmiTagMask));
|
| + __ j(not_zero, &runtime);
|
| + __ mov(edx, Operand(esp, 2 * kPointerSize)); // from
|
| + __ test(edx, Immediate(kSmiTagMask));
|
| + __ j(not_zero, &runtime);
|
| + __ sub(ecx, Operand(edx));
|
| + // Handle sub-strings of length 2 and less in the runtime system.
|
| + __ SmiUntag(ecx); // Result length is no longer smi.
|
| + __ cmp(ecx, 2);
|
| + __ j(below_equal, &runtime);
|
| +
|
| + // eax: string
|
| + // ebx: instance type
|
| + // ecx: result string length
|
| + // Check for flat ascii string
|
| + Label non_ascii_flat;
|
| + __ and_(ebx, kStringRepresentationMask | kStringEncodingMask);
|
| + __ cmp(ebx, kSeqStringTag | kAsciiStringTag);
|
| + __ j(not_equal, &non_ascii_flat);
|
| +
|
| + // Allocate the result.
|
| + __ AllocateAsciiString(eax, ecx, ebx, edx, edi, &runtime);
|
| +
|
| + // eax: result string
|
| + // ecx: result string length
|
| + __ mov(edx, esi); // esi used by following code.
|
| + // Locate first character of result.
|
| + __ mov(edi, eax);
|
| + __ add(Operand(edi), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
|
| + // Load string argument and locate character of sub string start.
|
| + __ mov(esi, Operand(esp, 3 * kPointerSize));
|
| + __ add(Operand(esi), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
|
| + __ mov(ebx, Operand(esp, 2 * kPointerSize)); // from
|
| + __ SmiUntag(ebx);
|
| + __ add(esi, Operand(ebx));
|
| +
|
| + // eax: result string
|
| + // ecx: result length
|
| + // edx: original value of esi
|
| + // edi: first character of result
|
| + // esi: character of sub string start
|
| + GenerateCopyCharactersREP(masm, edi, esi, ecx, ebx, true);
|
| + __ mov(esi, edx); // Restore esi.
|
| + __ IncrementCounter(&Counters::sub_string_native, 1);
|
| + __ ret(3 * kPointerSize);
|
| +
|
| + __ bind(&non_ascii_flat);
|
| + // eax: string
|
| + // ebx: instance type & kStringRepresentationMask | kStringEncodingMask
|
| + // ecx: result string length
|
| + // Check for flat two byte string
|
| + __ cmp(ebx, kSeqStringTag | kTwoByteStringTag);
|
| + __ j(not_equal, &runtime);
|
| +
|
| + // Allocate the result.
|
| + __ AllocateTwoByteString(eax, ecx, ebx, edx, edi, &runtime);
|
| +
|
| + // eax: result string
|
| + // ecx: result string length
|
| + __ mov(edx, esi); // esi used by following code.
|
| + // Locate first character of result.
|
| + __ mov(edi, eax);
|
| + __ add(Operand(edi),
|
| + Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
|
| + // Load string argument and locate character of sub string start.
|
| + __ mov(esi, Operand(esp, 3 * kPointerSize));
|
| + __ add(Operand(esi), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
|
| + __ mov(ebx, Operand(esp, 2 * kPointerSize)); // from
|
| + // As from is a smi it is 2 times the value which matches the size of a two
|
| + // byte character.
|
| + ASSERT_EQ(0, kSmiTag);
|
| + ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize);
|
| + __ add(esi, Operand(ebx));
|
| +
|
| + // eax: result string
|
| + // ecx: result length
|
| + // edx: original value of esi
|
| + // edi: first character of result
|
| + // esi: character of sub string start
|
| + GenerateCopyCharactersREP(masm, edi, esi, ecx, ebx, false);
|
| + __ mov(esi, edx); // Restore esi.
|
| + __ IncrementCounter(&Counters::sub_string_native, 1);
|
| + __ ret(3 * kPointerSize);
|
| +
|
| + // Just jump to runtime to create the sub string.
|
| + __ bind(&runtime);
|
| + __ TailCallRuntime(ExternalReference(Runtime::kSubString), 3, 1);
|
| +}
|
| +
|
| #undef __
|
|
|
| } } // namespace v8::internal
|
|
|