__ JumpIfNonSmisNotBothSequentialAsciiStrings(lhs_, rhs_, r2, r3, &slow);
__ IncrementCounter(isolate->counters()->string_compare_native(), 1, r2, r3);
- StringCompareStub::GenerateCompareFlatAsciiStrings(masm,
+ if (cc_ == eq) {
+ StringCompareStub::GenerateFlatAsciiStringEquals(masm,
lhs_,
rhs_,
r2,
r3,
- r4,
- r5);
+ r4);
+ } else {
+ StringCompareStub::GenerateCompareFlatAsciiStrings(masm,
+ lhs_,
+ rhs_,
+ r2,
+ r3,
+ r4,
+ r5);
+ }
// Never falls through to here.
__ bind(&slow);
}
+void StringCompareStub::GenerateFlatAsciiStringEquals(MacroAssembler* masm,
+ Register left,
+ Register right,
+ Register scratch1,
+ Register scratch2,
+ Register scratch3) {
+ Register length = scratch1;
+
+ // Compare lengths.
+ Label strings_not_equal, check_zero_length;
+ __ ldr(length, FieldMemOperand(left, String::kLengthOffset));
+ __ ldr(scratch2, FieldMemOperand(right, String::kLengthOffset));
+ __ cmp(length, scratch2);
+ __ b(eq, &check_zero_length);
+ __ bind(&strings_not_equal);
+ __ mov(r0, Operand(Smi::FromInt(NOT_EQUAL)));
+ __ Ret();
+
+ // Check if the length is zero.
+ Label compare_chars;
+ __ bind(&check_zero_length);
+ STATIC_ASSERT(kSmiTag == 0);
+ __ tst(length, Operand(length));
+ __ b(ne, &compare_chars);
+ __ mov(r0, Operand(Smi::FromInt(EQUAL)));
+ __ Ret();
+
+ // Compare characters.
+ __ bind(&compare_chars);
+
+ // Change index to run from -length to -1 by adding length to string
+ // start. This means that loop ends when index reaches zero, which
+ // doesn't need an additional compare.
+ __ SmiUntag(length);
+ __ add(scratch2, length,
+ Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
+ __ add(left, left, Operand(scratch2));
+ __ add(right, right, Operand(scratch2));
+ __ rsb(length, length, Operand(0));
+ Register index = length; // index = -length;
+
+ // Compare loop.
+ Label loop;
+ __ bind(&loop);
+ __ ldrb(scratch2, MemOperand(left, index));
+ __ ldrb(scratch3, MemOperand(right, index));
+ __ cmp(scratch2, scratch3);
+ __ b(ne, &strings_not_equal);
+ __ add(index, index, Operand(1), SetCC);
+ __ b(ne, &loop);
+
+ // Characters are equal.
+ __ mov(r0, Operand(Smi::FromInt(EQUAL)));
+ __ Ret();
+}
+
+
void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
Register left,
Register right,
&runtime);
// Compare flat ASCII strings. Returns when done.
- StringCompareStub::GenerateCompareFlatAsciiStrings(
- masm, left, right, tmp1, tmp2, tmp3, tmp4);
+ StringCompareStub::GenerateFlatAsciiStringEquals(
+ masm, left, right, tmp1, tmp2, tmp3);
// Handle more complex cases in runtime.
__ bind(&runtime);
__ Push(left, right);
- __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
+ __ TailCallRuntime(Runtime::kStringEquals, 2, 1);
__ bind(&miss);
GenerateMiss(masm);
public:
StringCompareStub() { }
- // Compare two flat ASCII strings and returns result in r0.
- // Does not use the stack.
+ // Compares two flat ASCII strings and returns result in r0.
static void GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
Register left,
Register right,
Register scratch3,
Register scratch4);
+ // Compares two flat ASCII strings for equality and returns result
+ // in r0.
+ static void GenerateFlatAsciiStringEquals(MacroAssembler* masm,
+ Register left,
+ Register right,
+ Register scratch1,
+ Register scratch2,
+ Register scratch3);
+
private:
Major MajorKey() { return StringCompare; }
int MinorKey() { return 0; }
&check_unequal_objects);
// Inline comparison of ascii strings.
- StringCompareStub::GenerateCompareFlatAsciiStrings(masm,
+ if (cc_ == equal) {
+ StringCompareStub::GenerateFlatAsciiStringEquals(masm,
edx,
eax,
ecx,
- ebx,
- edi);
+ ebx);
+ } else {
+ StringCompareStub::GenerateCompareFlatAsciiStrings(masm,
+ edx,
+ eax,
+ ecx,
+ ebx,
+ edi);
+ }
#ifdef DEBUG
__ Abort("Unexpected fall-through from string comparison");
#endif
}
+void StringCompareStub::GenerateFlatAsciiStringEquals(MacroAssembler* masm,
+ Register left,
+ Register right,
+ Register scratch1,
+ Register scratch2) {
+ Register length = scratch1;
+
+ // Compare lengths.
+ NearLabel strings_not_equal, check_zero_length;
+ __ mov(length, FieldOperand(left, String::kLengthOffset));
+ __ cmp(length, FieldOperand(right, String::kLengthOffset));
+ __ j(equal, &check_zero_length);
+ __ bind(&strings_not_equal);
+ __ Set(eax, Immediate(Smi::FromInt(NOT_EQUAL)));
+ __ ret(0);
+
+ // Check if the length is zero.
+ NearLabel compare_chars;
+ __ bind(&check_zero_length);
+ STATIC_ASSERT(kSmiTag == 0);
+ __ test(length, Operand(length));
+ __ j(not_zero, &compare_chars);
+ __ Set(eax, Immediate(Smi::FromInt(EQUAL)));
+ __ ret(0);
+
+ // Compare characters.
+ __ bind(&compare_chars);
+
+ // Change index to run from -length to -1 by adding length to string
+ // start. This means that loop ends when index reaches zero, which
+ // doesn't need an additional compare.
+ __ SmiUntag(length);
+ __ lea(left,
+ FieldOperand(left, length, times_1, SeqAsciiString::kHeaderSize));
+ __ lea(right,
+ FieldOperand(right, length, times_1, SeqAsciiString::kHeaderSize));
+ __ neg(length);
+ Register index = length; // index = -length;
+
+ // Compare loop.
+ NearLabel loop;
+ __ bind(&loop);
+ __ mov_b(scratch2, Operand(left, index, times_1, 0));
+ __ cmpb(scratch2, Operand(right, index, times_1, 0));
+ __ j(not_equal, &strings_not_equal);
+ __ add(Operand(index), Immediate(1));
+ __ j(not_zero, &loop);
+
+ // Characters are equal.
+ __ Set(eax, Immediate(Smi::FromInt(EQUAL)));
+ __ ret(0);
+}
+
+
void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
Register left,
Register right,
void ICCompareStub::GenerateStrings(MacroAssembler* masm) {
ASSERT(state_ == CompareIC::STRINGS);
+ ASSERT(GetCondition() == equal);
Label miss;
// Registers containing left and right operands respectively.
// Check that both strings are symbols. If they are, we're done
// because we already know they are not identical.
NearLabel do_compare;
- ASSERT(GetCondition() == equal);
STATIC_ASSERT(kSymbolTag != 0);
__ and_(tmp1, Operand(tmp2));
__ test(tmp1, Immediate(kIsSymbolMask));
__ JumpIfNotBothSequentialAsciiStrings(left, right, tmp1, tmp2, &runtime);
// Compare flat ASCII strings. Returns when done.
- StringCompareStub::GenerateCompareFlatAsciiStrings(
- masm, left, right, tmp1, tmp2, tmp3);
+ StringCompareStub::GenerateFlatAsciiStringEquals(
+ masm, left, right, tmp1, tmp2);
// Handle more complex cases in runtime.
__ bind(&runtime);
__ push(left);
__ push(right);
__ push(tmp1);
- __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
+ __ TailCallRuntime(Runtime::kStringEquals, 2, 1);
__ bind(&miss);
GenerateMiss(masm);
class StringCompareStub: public CodeStub {
public:
- explicit StringCompareStub() {
- }
+ StringCompareStub() { }
- // Compare two flat ascii strings and returns result in eax after popping two
- // arguments from the stack.
+ // Compares two flat ASCII strings and returns result in eax.
static void GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
Register left,
Register right,
Register scratch2,
Register scratch3);
+ // Compares two flat ASCII strings for equality and returns result
+ // in eax.
+ static void GenerateFlatAsciiStringEquals(MacroAssembler* masm,
+ Register left,
+ Register right,
+ Register scratch1,
+ Register scratch2);
+
private:
Major MajorKey() { return StringCompare; }
int MinorKey() { return 0; }
rdx, rax, rcx, rbx, &check_unequal_objects);
// Inline comparison of ascii strings.
- StringCompareStub::GenerateCompareFlatAsciiStrings(masm,
+ if (cc_ == equal) {
+ StringCompareStub::GenerateFlatAsciiStringEquals(masm,
rdx,
rax,
rcx,
- rbx,
- rdi,
- r8);
+ rbx);
+ } else {
+ StringCompareStub::GenerateCompareFlatAsciiStrings(masm,
+ rdx,
+ rax,
+ rcx,
+ rbx,
+ rdi,
+ r8);
+ }
#ifdef DEBUG
__ Abort("Unexpected fall-through from string comparison");
}
+void StringCompareStub::GenerateFlatAsciiStringEquals(MacroAssembler* masm,
+ Register left,
+ Register right,
+ Register scratch1,
+ Register scratch2) {
+ Register length = scratch1;
+
+ // Compare lengths.
+ NearLabel check_zero_length;
+ __ movq(length, FieldOperand(left, String::kLengthOffset));
+ __ SmiCompare(length, FieldOperand(right, String::kLengthOffset));
+ __ j(equal, &check_zero_length);
+ __ Move(rax, Smi::FromInt(NOT_EQUAL));
+ __ ret(0);
+
+ // Check if the length is zero.
+ NearLabel compare_chars;
+ __ bind(&check_zero_length);
+ STATIC_ASSERT(kSmiTag == 0);
+ __ SmiTest(length);
+ __ j(not_zero, &compare_chars);
+ __ Move(rax, Smi::FromInt(EQUAL));
+ __ ret(0);
+
+ // Compare characters.
+ __ bind(&compare_chars);
+
+ // Change index to run from -length to -1 by adding length to string
+ // start. This means that loop ends when index reaches zero, which
+ // doesn't need an additional compare.
+ __ SmiToInteger32(length, length);
+ __ lea(left,
+ FieldOperand(left, length, times_1, SeqAsciiString::kHeaderSize));
+ __ lea(right,
+ FieldOperand(right, length, times_1, SeqAsciiString::kHeaderSize));
+ __ neg(length);
+ Register index = length; // index = -length;
+
+ // Compare loop.
+ NearLabel strings_not_equal, loop;
+ __ bind(&loop);
+ __ movb(scratch2, Operand(left, index, times_1, 0));
+ __ cmpb(scratch2, Operand(right, index, times_1, 0));
+ __ j(not_equal, &strings_not_equal);
+ __ addq(index, Immediate(1));
+ __ j(not_zero, &loop);
+
+ // Characters are equal.
+ __ Move(rax, Smi::FromInt(EQUAL));
+ __ ret(0);
+
+ // Characters are not equal.
+ __ bind(&strings_not_equal);
+ __ Move(rax, Smi::FromInt(NOT_EQUAL));
+ __ ret(0);
+}
+
+
void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
Register left,
Register right,
void ICCompareStub::GenerateStrings(MacroAssembler* masm) {
ASSERT(state_ == CompareIC::STRINGS);
+ ASSERT(GetCondition() == equal);
Label miss;
// Registers containing left and right operands respectively.
Register tmp1 = rcx;
Register tmp2 = rbx;
Register tmp3 = rdi;
- Register tmp4 = r8;
// Check that both operands are heap objects.
Condition cond = masm->CheckEitherSmi(left, right, tmp1);
// Check that both strings are symbols. If they are, we're done
// because we already know they are not identical.
NearLabel do_compare;
- ASSERT(GetCondition() == equal);
STATIC_ASSERT(kSymbolTag != 0);
__ and_(tmp1, tmp2);
__ testl(tmp1, Immediate(kIsSymbolMask));
__ JumpIfNotBothSequentialAsciiStrings(left, right, tmp1, tmp2, &runtime);
// Compare flat ASCII strings. Returns when done.
- StringCompareStub::GenerateCompareFlatAsciiStrings(
- masm, left, right, tmp1, tmp2, tmp3, tmp4);
+ StringCompareStub::GenerateFlatAsciiStringEquals(
+ masm, left, right, tmp1, tmp2);
// Handle more complex cases in runtime.
__ bind(&runtime);
__ push(left);
__ push(right);
__ push(tmp1);
- __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
+ __ TailCallRuntime(Runtime::kStringEquals, 2, 1);
__ bind(&miss);
GenerateMiss(masm);
class StringCompareStub: public CodeStub {
public:
- explicit StringCompareStub() {}
+ StringCompareStub() {}
- // Compare two flat ascii strings and returns result in rax after popping two
- // arguments from the stack.
+ // Compares two flat ASCII strings and returns result in rax.
static void GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
Register left,
Register right,
Register scratch3,
Register scratch4);
+ // Compares two flat ASCII strings for equality and returns result
+ // in rax.
+ static void GenerateFlatAsciiStringEquals(MacroAssembler* masm,
+ Register left,
+ Register right,
+ Register scratch1,
+ Register scratch2);
+
private:
Major MajorKey() { return StringCompare; }
int MinorKey() { return 0; }