Index: src/x64/macro-assembler-x64.cc |
diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc |
index 9e8568c2de5b260edfd23c53c33f599a2792b857..99ffcead460349bda8e31482db034838eb01817f 100644 |
--- a/src/x64/macro-assembler-x64.cc |
+++ b/src/x64/macro-assembler-x64.cc |
@@ -4417,18 +4417,27 @@ void MacroAssembler::CopyBytes(Register destination, |
cmpl(length, Immediate(min_length)); |
Assert(greater_equal, kInvalidMinLength); |
} |
- Label loop, done, short_string, short_loop; |
+ Label short_loop, len8, len16, len24, done, short_string; |
- const int kLongStringLimit = 20; |
+ const int kLongStringLimit = 4 * kPointerSize; |
if (min_length <= kLongStringLimit) { |
- cmpl(length, Immediate(kLongStringLimit)); |
- j(less_equal, &short_string); |
+ cmpl(length, Immediate(kPointerSize)); |
+ j(below, &short_string, Label::kNear); |
} |
ASSERT(source.is(rsi)); |
ASSERT(destination.is(rdi)); |
ASSERT(length.is(rcx)); |
+ if (min_length <= kLongStringLimit) { |
+ cmpl(length, Immediate(2 * kPointerSize)); |
+ j(below_equal, &len8, Label::kNear); |
+ cmpl(length, Immediate(3 * kPointerSize)); |
+ j(below_equal, &len16, Label::kNear); |
+ cmpl(length, Immediate(4 * kPointerSize)); |
+ j(below_equal, &len24, Label::kNear); |
+ } |
+ |
// Because source is 8-byte aligned in our uses of this function, |
// we keep source aligned for the rep movs operation by copying the odd bytes |
// at the end of the ranges. |
@@ -4442,25 +4451,38 @@ void MacroAssembler::CopyBytes(Register destination, |
addq(destination, scratch); |
if (min_length <= kLongStringLimit) { |
- jmp(&done); |
+ jmp(&done, Label::kNear); |
+ bind(&len24); |
+ movq(scratch, Operand(source, 2 * kPointerSize)); |
+ movq(Operand(destination, 2 * kPointerSize), scratch); |
+ bind(&len16); |
+ movq(scratch, Operand(source, kPointerSize)); |
+ movq(Operand(destination, kPointerSize), scratch); |
+ bind(&len8); |
+ movq(scratch, Operand(source, 0)); |
+ movq(Operand(destination, 0), scratch); |
+ // Move remaining bytes of length. |
+ movq(scratch, Operand(source, length, times_1, -kPointerSize)); |
+ movq(Operand(destination, length, times_1, -kPointerSize), scratch); |
+ addq(destination, length); |
+ jmp(&done, Label::kNear); |
bind(&short_string); |
if (min_length == 0) { |
testl(length, length); |
- j(zero, &done); |
+ j(zero, &done, Label::kNear); |
} |
- lea(scratch, Operand(destination, length, times_1, 0)); |
bind(&short_loop); |
- movb(length, Operand(source, 0)); |
- movb(Operand(destination, 0), length); |
+ movb(scratch, Operand(source, 0)); |
+ movb(Operand(destination, 0), scratch); |
incq(source); |
incq(destination); |
- cmpq(destination, scratch); |
- j(not_equal, &short_loop); |
- |
- bind(&done); |
+ decl(length); |
+ j(not_zero, &short_loop); |
} |
+ |
+ bind(&done); |
} |