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, |