Chromium Code Reviews| Index: src/x64/codegen-x64.cc |
| diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc |
| index 9a9cc3fb81008d8f1557f2488f8a6920616008d0..31328ef46c3af79bc348e650fcb9c9ef1c7ac83e 100644 |
| --- a/src/x64/codegen-x64.cc |
| +++ b/src/x64/codegen-x64.cc |
| @@ -3942,7 +3942,8 @@ void CodeGenerator::GenerateSubString(ZoneList<Expression*>* args) { |
| Load(args->at(1)); |
| Load(args->at(2)); |
| - Result answer = frame_->CallRuntime(Runtime::kSubString, 3); |
| + SubStringStub stub; |
| + Result answer = frame_->CallStub(&stub, 3); |
| frame_->Push(&answer); |
| } |
| @@ -8138,11 +8139,11 @@ void StringAddStub::Generate(MacroAssembler* masm) { |
| } |
| -void StringAddStub::GenerateCopyCharacters(MacroAssembler* masm, |
| - Register dest, |
| - Register src, |
| - Register count, |
| - bool ascii) { |
| +void StringStubBase::GenerateCopyCharacters(MacroAssembler* masm, |
| + Register dest, |
| + Register src, |
| + Register count, |
| + bool ascii) { |
| Label loop; |
| __ bind(&loop); |
| // This loop just copies one character at a time, as it is only used for very |
| @@ -8163,6 +8164,172 @@ void StringAddStub::GenerateCopyCharacters(MacroAssembler* masm, |
| } |
| +void StringStubBase::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. |
| + ASSERT(dest.is(rdi)); // rep movs destination |
| + ASSERT(src.is(rsi)); // rep movs source |
| + ASSERT(count.is(rcx)); // rep movs count |
| + |
| + // Nothing to do for zero characters. |
| + Label done; |
| + __ testq(count, count); |
| + __ j(zero, &done); |
| + |
| + // Make count the number of bytes to copy. |
| + if (!ascii) { |
|
Søren Thygesen Gjesse
2010/01/25 08:31:33
ASSERT(kShortSize == 2);
Lasse Reichstein
2010/01/25 08:47:20
It's not really the size of short ints that matter
|
| + __ addq(count, count); |
| + } |
| + |
| + // Don't enter the rep movs if there are less than 4 bytes to copy. |
| + Label last_bytes; |
| + __ testq(count, Immediate(~3)); |
| + __ j(zero, &last_bytes); |
| + |
| + // Copy from edi to esi using rep movs instruction. |
| + __ movq(kScratchRegister, count); |
| + __ sar(count, Immediate(2)); // Number of doublewords to copy. |
| + __ repmovsl(); |
|
Søren Thygesen Gjesse
2010/01/25 08:31:33
It is not better to use repmovsq?
Lasse Reichstein
2010/01/25 08:47:20
Probably, since we expect long strings, the tine s
|
| + |
| + // Find number of bytes left. |
| + __ movq(count, kScratchRegister); |
| + __ and_(count, Immediate(3)); |
| + |
| + // Check if there are more bytes to copy. |
| + __ bind(&last_bytes); |
| + __ testq(count, count); |
| + __ j(zero, &done); |
| + |
| + // Copy remaining characters. |
| + Label loop; |
| + __ bind(&loop); |
| + __ movb(kScratchRegister, Operand(src, 0)); |
| + __ movb(Operand(dest, 0), kScratchRegister); |
| + __ addq(src, Immediate(1)); |
| + __ addq(dest, Immediate(1)); |
| + __ subq(count, Immediate(1)); |
| + __ j(not_zero, &loop); |
| + |
| + __ bind(&done); |
| +} |
| + |
| + |
| +void SubStringStub::Generate(MacroAssembler* masm) { |
| + Label runtime; |
| + |
| + // Stack frame on entry. |
| + // rsp[0]: return address |
| + // rsp[8]: to |
| + // rsp[16]: from |
| + // rsp[24]: string |
| + |
| + const int kToOffset = 1 * kPointerSize; |
| + const int kFromOffset = 2 * kPointerSize; |
| + const int kStringOffset = 3 * kPointerSize; |
|
Søren Thygesen Gjesse
2010/01/25 08:31:33
Now that you have these constants, why not add
Lasse Reichstein
2010/01/25 08:47:20
Done.
|
| + |
| + // Make sure first argument is a string. |
| + __ movq(rax, Operand(rsp, kStringOffset)); |
| + ASSERT_EQ(0, kSmiTag); |
| + __ testl(rax, Immediate(kSmiTagMask)); |
| + __ j(zero, &runtime); |
| + Condition is_string = masm->IsObjectStringType(rax, rbx, rbx); |
| + __ j(NegateCondition(is_string), &runtime); |
| + |
| + // rax: string |
| + // rbx: instance type |
| + // Calculate length of sub string using the smi values. |
| + __ movq(rcx, Operand(rsp, kToOffset)); |
| + __ movq(rdx, Operand(rsp, kFromOffset)); |
| + __ JumpIfNotBothPositiveSmi(rcx, rdx, &runtime); |
| + |
| + __ SmiSub(rcx, rcx, rdx, NULL); // Overflow doesn't happen. |
| + __ j(negative, &runtime); |
| + // Handle sub-strings of length 2 and less in the runtime system. |
| + __ SmiToInteger32(rcx, rcx); |
| + __ cmpl(rcx, Immediate(2)); |
| + __ j(below_equal, &runtime); |
| + |
| + // rax: string |
| + // rbx: instance type |
| + // rcx: result string length |
| + // Check for flat ascii string |
| + Label non_ascii_flat; |
| + __ and_(rbx, Immediate(kStringRepresentationMask | kStringEncodingMask)); |
| + __ cmpb(rbx, Immediate(kSeqStringTag | kAsciiStringTag)); |
| + __ j(not_equal, &non_ascii_flat); |
| + |
| + // Allocate the result. |
| + __ AllocateAsciiString(rax, rcx, rbx, rdx, rdi, &runtime); |
| + |
| + // rax: result string |
| + // rcx: result string length |
| + __ movq(rdx, rsi); // esi used by following code. |
| + // Locate first character of result. |
| + __ lea(rdi, FieldOperand(rax, SeqAsciiString::kHeaderSize)); |
| + // Load string argument and locate character of sub string start. |
| + __ movq(rsi, Operand(rsp, kStringOffset)); |
| + __ movq(rbx, Operand(rsp, kFromOffset)); |
| + { |
| + SmiIndex smi_as_index = masm->SmiToIndex(rbx, rbx, times_1); |
| + __ lea(rsi, Operand(rsi, smi_as_index.reg, smi_as_index.scale, |
|
Søren Thygesen Gjesse
2010/01/25 08:31:33
Perhaps use FieldOperand, and remove " - kHeapObje
|
| + SeqAsciiString::kHeaderSize - kHeapObjectTag)); |
| + } |
| + |
| + // rax: result string |
| + // rcx: result length |
| + // rdx: original value of rsi |
| + // rdi: first character of result |
| + // rsi: character of sub string start |
| + GenerateCopyCharactersREP(masm, rdi, rsi, rcx, true); |
| + __ movq(rsi, rdx); // Restore rsi. |
| + __ IncrementCounter(&Counters::sub_string_native, 1); |
| + __ ret(3 * kPointerSize); |
| + |
| + __ bind(&non_ascii_flat); |
| + // rax: string |
| + // rbx: instance type & kStringRepresentationMask | kStringEncodingMask |
| + // rcx: result string length |
| + // Check for sequential two byte string |
| + __ cmpb(rbx, Immediate(kSeqStringTag | kTwoByteStringTag)); |
| + __ j(not_equal, &runtime); |
| + |
| + // Allocate the result. |
| + __ AllocateTwoByteString(rax, rcx, rbx, rdx, rdi, &runtime); |
| + |
| + // rax: result string |
| + // rcx: result string length |
| + __ movq(rdx, rsi); // esi used by following code. |
| + // Locate first character of result. |
| + __ lea(rdi, FieldOperand(rax, SeqTwoByteString::kHeaderSize)); |
| + // Load string argument and locate character of sub string start. |
| + __ movq(rsi, Operand(rsp, kStringOffset)); |
| + __ movq(rbx, Operand(rsp, kFromOffset)); |
| + { |
| + SmiIndex smi_as_index = masm->SmiToIndex(rbx, rbx, times_2); |
| + __ lea(rsi, Operand(rsi, smi_as_index.reg, smi_as_index.scale, |
|
Søren Thygesen Gjesse
2010/01/25 08:31:33
Operand -> FieldOperand?
|
| + SeqAsciiString::kHeaderSize - kHeapObjectTag)); |
| + } |
| + |
| + // rax: result string |
| + // rcx: result length |
| + // rdx: original value of rsi |
| + // rdi: first character of result |
| + // rsi: character of sub string start |
| + GenerateCopyCharactersREP(masm, rdi, rsi, rcx, false); |
| + __ movq(rsi, rdx); // 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); |
| +} |
| + |
| void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, |
| Register left, |