Commit 9c633592 authored by lrn@chromium.org's avatar lrn@chromium.org

Implement inline string compare on ARM.

Backport optimizations from x64 version to ia32.

Review URL: http://codereview.chromium.org/546087

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3670 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 399be5ee
......@@ -3576,7 +3576,8 @@ void CodeGenerator::GenerateStringCompare(ZoneList<Expression*>* args) {
Load(args->at(0));
Load(args->at(1));
frame_->CallRuntime(Runtime::kStringCompare, 2);
StringCompareStub stub;
frame_->CallStub(&stub, 2);
frame_->EmitPush(r0);
}
......@@ -5089,8 +5090,9 @@ static void EmitCheckForSymbols(MacroAssembler* masm, Label* slow) {
}
// On entry r0 and r1 are the things to be compared. On exit r0 is 0,
// positive or negative to indicate the result of the comparison.
// On entry r0 (rhs) and r1 (lhs) are the values to be compared.
// On exit r0 is 0, positive or negative to indicate the result of
// the comparison.
void CompareStub::Generate(MacroAssembler* masm) {
Label slow; // Call builtin.
Label not_smis, both_loaded_as_doubles, lhs_not_nan;
......@@ -5168,6 +5170,7 @@ void CompareStub::Generate(MacroAssembler* masm) {
}
Label check_for_symbols;
Label flat_string_check;
// Check for heap-number-heap-number comparison. Can jump to slow case,
// or load both doubles into r0, r1, r2, r3 and jump to the code that handles
// that case. If the inputs are not doubles then jumps to check_for_symbols.
......@@ -5175,7 +5178,7 @@ void CompareStub::Generate(MacroAssembler* masm) {
EmitCheckForTwoHeapNumbers(masm,
&both_loaded_as_doubles,
&check_for_symbols,
&slow);
&flat_string_check);
__ bind(&check_for_symbols);
// In the strict case the EmitStrictTwoHeapObjectCompare already took care of
......@@ -5183,10 +5186,27 @@ void CompareStub::Generate(MacroAssembler* masm) {
if (cc_ == eq && !strict_) {
// Either jumps to slow or returns the answer. Assumes that r2 is the type
// of r0 on entry.
EmitCheckForSymbols(masm, &slow);
EmitCheckForSymbols(masm, &flat_string_check);
}
// Check for both being sequential ASCII strings, and inline if that is the
// case.
__ bind(&flat_string_check);
__ JumpIfNonSmisNotBothSequentialAsciiStrings(r0, r1, r2, r3, &slow);
__ IncrementCounter(&Counters::string_compare_native, 1, r2, r3);
StringCompareStub::GenerateCompareFlatAsciiStrings(masm,
r1,
r0,
r2,
r3,
r4,
r5);
// Never falls through to here.
__ bind(&slow);
__ push(r1);
__ push(r0);
// Figure out which native to call and setup the arguments.
......@@ -6737,6 +6757,101 @@ int CompareStub::MinorKey() {
}
void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
Register left,
Register right,
Register scratch1,
Register scratch2,
Register scratch3,
Register scratch4) {
Label compare_lengths;
// Find minimum length and length difference.
__ ldr(scratch1, FieldMemOperand(left, String::kLengthOffset));
__ ldr(scratch2, FieldMemOperand(right, String::kLengthOffset));
__ sub(scratch3, scratch1, Operand(scratch2), SetCC);
Register length_delta = scratch3;
__ mov(scratch1, scratch2, LeaveCC, gt);
Register min_length = scratch1;
__ tst(min_length, Operand(min_length));
__ b(eq, &compare_lengths);
// Setup registers so that we only need to increment one register
// in the loop.
__ add(scratch2, min_length,
Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
__ add(left, left, Operand(scratch2));
__ add(right, right, Operand(scratch2));
// Registers left and right points to the min_length character of strings.
__ rsb(min_length, min_length, Operand(-1));
Register index = min_length;
// Index starts at -min_length.
{
// Compare loop.
Label loop;
__ bind(&loop);
// Compare characters.
__ add(index, index, Operand(1), SetCC);
__ ldrb(scratch2, MemOperand(left, index), ne);
__ ldrb(scratch4, MemOperand(right, index), ne);
// Skip to compare lengths with eq condition true.
__ b(eq, &compare_lengths);
__ cmp(scratch2, scratch4);
__ b(eq, &loop);
// Fallthrough with eq condition false.
}
// Compare lengths - strings up to min-length are equal.
__ bind(&compare_lengths);
ASSERT(Smi::FromInt(EQUAL) == static_cast<Smi*>(0));
// Use zero length_delta as result.
__ mov(r0, Operand(length_delta), SetCC, eq);
// Fall through to here if characters compare not-equal.
__ mov(r0, Operand(Smi::FromInt(GREATER)), LeaveCC, gt);
__ mov(r0, Operand(Smi::FromInt(LESS)), LeaveCC, lt);
__ Ret();
}
void StringCompareStub::Generate(MacroAssembler* masm) {
Label runtime;
// Stack frame on entry.
// sp[0]: return address
// sp[4]: right string
// sp[8]: left string
__ ldr(r0, MemOperand(sp, 2 * kPointerSize)); // left
__ ldr(r1, MemOperand(sp, 1 * kPointerSize)); // right
Label not_same;
__ cmp(r0, r1);
__ b(ne, &not_same);
ASSERT_EQ(0, EQUAL);
ASSERT_EQ(0, kSmiTag);
__ mov(r0, Operand(Smi::FromInt(EQUAL)));
__ IncrementCounter(&Counters::string_compare_native, 1, r1, r2);
__ add(sp, sp, Operand(2 * kPointerSize));
__ Ret();
__ bind(&not_same);
// Check that both objects are sequential ascii strings.
__ JumpIfNotBothSequentialAsciiStrings(r0, r1, r2, r3, &runtime);
// Compare flat ascii strings natively. Remove arguments from stack first.
__ IncrementCounter(&Counters::string_compare_native, 1, r2, r3);
__ add(sp, sp, Operand(2 * kPointerSize));
GenerateCompareFlatAsciiStrings(masm, r0, r1, r2, r3, r4, r5);
// Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
// tagged as a small integer.
__ bind(&runtime);
__ TailCallRuntime(ExternalReference(Runtime::kStringCompare), 2, 1);
}
#undef __
} } // namespace v8::internal
......@@ -512,6 +512,28 @@ class GenericBinaryOpStub : public CodeStub {
};
class StringCompareStub: public CodeStub {
public:
StringCompareStub() { }
// Compare two flat ASCII strings and returns result in r0.
// Does not use the stack.
static void GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
Register left,
Register right,
Register scratch1,
Register scratch2,
Register scratch3,
Register scratch4);
private:
Major MajorKey() { return StringCompare; }
int MinorKey() { return 0; }
void Generate(MacroAssembler* masm);
};
} } // namespace v8::internal
#endif // V8_ARM_CODEGEN_ARM_H_
......@@ -1221,6 +1221,46 @@ void MacroAssembler::LoadContext(Register dst, int context_chain_length) {
}
void MacroAssembler::JumpIfNonSmisNotBothSequentialAsciiStrings(
Register first,
Register second,
Register scratch1,
Register scratch2,
Label* failure) {
// Test that both first and second are sequential ASCII strings.
// Assume that they are non-smis.
ldr(scratch1, FieldMemOperand(first, HeapObject::kMapOffset));
ldr(scratch2, FieldMemOperand(second, HeapObject::kMapOffset));
ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
ldrb(scratch2, FieldMemOperand(scratch2, Map::kInstanceTypeOffset));
int kFlatAsciiStringMask =
kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask;
int kFlatAsciiStringTag = ASCII_STRING_TYPE;
and_(scratch1, scratch1, Operand(kFlatAsciiStringMask));
and_(scratch2, scratch2, Operand(kFlatAsciiStringMask));
cmp(scratch1, Operand(kFlatAsciiStringTag));
// Ignore second test if first test failed.
cmp(scratch2, Operand(kFlatAsciiStringTag), eq);
b(ne, failure);
}
void MacroAssembler::JumpIfNotBothSequentialAsciiStrings(Register first,
Register second,
Register scratch1,
Register scratch2,
Label* failure) {
// Check that neither is a smi.
ASSERT_EQ(0, kSmiTag);
and_(scratch1, first, Operand(second));
tst(scratch1, Operand(kSmiTagMask));
b(eq, failure);
JumpIfNonSmisNotBothSequentialAsciiStrings(first,
second,
scratch1,
scratch2,
failure);
}
#ifdef ENABLE_DEBUGGER_SUPPORT
CodePatcher::CodePatcher(byte* address, int instructions)
......
......@@ -337,6 +337,25 @@ class MacroAssembler: public Assembler {
void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; }
bool allow_stub_calls() { return allow_stub_calls_; }
// ---------------------------------------------------------------------------
// String utilities
// Checks if both objects are sequential ASCII strings and jumps to label
// if either is not. Assumes that neither object is a smi.
void JumpIfNonSmisNotBothSequentialAsciiStrings(Register object1,
Register object2,
Register scratch1,
Register scratch2,
Label *failure);
// Checks if both objects are sequential ASCII strings and jumps to label
// if either is not.
void JumpIfNotBothSequentialAsciiStrings(Register first,
Register second,
Register scratch1,
Register scratch2,
Label* not_flat_ascii_strings);
private:
List<Unresolved> unresolved_;
bool generating_stub_;
......
......@@ -860,6 +860,24 @@ void Assembler::cmpb(const Operand& op, int8_t imm8) {
}
void Assembler::cmpb(const Operand& dst, Register src) {
ASSERT(src.is_byte_register());
EnsureSpace ensure_space(this);
last_pc_ = pc_;
EMIT(0x38);
emit_operand(src, dst);
}
void Assembler::cmpb(Register dst, const Operand& src) {
ASSERT(dst.is_byte_register());
EnsureSpace ensure_space(this);
last_pc_ = pc_;
EMIT(0x3A);
emit_operand(dst, src);
}
void Assembler::cmpw(const Operand& op, Immediate imm16) {
ASSERT(imm16.is_int16());
EnsureSpace ensure_space(this);
......
......@@ -559,6 +559,8 @@ class Assembler : public Malloced {
void and_(const Operand& dst, const Immediate& x);
void cmpb(const Operand& op, int8_t imm8);
void cmpb(Register src, const Operand& dst);
void cmpb(const Operand& dst, Register src);
void cmpb_al(const Operand& op);
void cmpw_ax(const Operand& op);
void cmpw(const Operand& op, Immediate imm16);
......
......@@ -8575,30 +8575,7 @@ void CompareStub::Generate(MacroAssembler* masm) {
__ bind(&check_for_strings);
// Check that both objects are not smis.
ASSERT_EQ(0, kSmiTag);
__ mov(ebx, Operand(edx));
__ and_(ebx, Operand(eax));
__ test(ebx, Immediate(kSmiTagMask));
__ j(zero, &call_builtin);
// Load instance type for both objects.
__ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
__ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
__ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
__ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
// Check that both are flat ascii strings.
Label non_ascii_flat;
ASSERT(kNotStringTag != 0);
const int kFlatAsciiString =
kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
__ and_(ecx, kFlatAsciiString);
__ cmp(ecx, kStringTag | kSeqStringTag | kAsciiStringTag);
__ j(not_equal, &call_builtin);
__ and_(ebx, kFlatAsciiString);
__ cmp(ebx, kStringTag | kSeqStringTag | kAsciiStringTag);
__ j(not_equal, &call_builtin);
__ JumpIfNotBothSequentialAsciiStrings(edx, eax, ecx, ebx, &call_builtin);
// Inline comparison of ascii strings.
StringCompareStub::GenerateCompareFlatAsciiStrings(masm,
......@@ -9652,79 +9629,76 @@ void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
Register scratch1,
Register scratch2,
Register scratch3) {
Label compare_lengths, compare_lengths_1;
// Find minimum length. If either length is zero just compare lengths.
Label result_not_equal;
Label result_greater;
Label compare_lengths;
// Find minimum length.
Label left_shorter;
__ mov(scratch1, FieldOperand(left, String::kLengthOffset));
__ test(scratch1, Operand(scratch1));
__ j(zero, &compare_lengths_1);
__ mov(scratch2, FieldOperand(right, String::kLengthOffset));
__ test(scratch2, Operand(scratch2));
__ j(zero, &compare_lengths_1);
__ cmp(scratch1, Operand(scratch2));
if (CpuFeatures::IsSupported(CMOV)) {
CpuFeatures::Scope use_cmov(CMOV);
__ cmov(greater, scratch1, Operand(scratch2));
} else {
Label l;
__ j(less, &l);
__ mov(scratch1, scratch2);
__ bind(&l);
__ mov(scratch3, scratch1);
__ sub(scratch3, FieldOperand(right, String::kLengthOffset));
Register length_delta = scratch3;
__ j(less_equal, &left_shorter);
// Right string is shorter. Change scratch1 to be length of right string.
__ sub(scratch1, Operand(length_delta));
__ bind(&left_shorter);
Register min_length = scratch1;
// If either length is zero, just compare lengths.
__ test(min_length, Operand(min_length));
__ j(zero, &compare_lengths);
// Change index to run from -min_length to -1 by adding min_length
// to string start. This means that loop ends when index reaches zero,
// which doesn't need an additional compare.
__ lea(left,
FieldOperand(left,
min_length, times_1,
SeqAsciiString::kHeaderSize));
__ lea(right,
FieldOperand(right,
min_length, times_1,
SeqAsciiString::kHeaderSize));
__ neg(min_length);
Register index = min_length; // index = -min_length;
{
// Compare loop.
Label loop;
__ bind(&loop);
// Compare characters.
__ mov_b(scratch2, Operand(left, index, times_1, 0));
__ cmpb(scratch2, Operand(right, index, times_1, 0));
__ j(not_equal, &result_not_equal);
__ add(Operand(index), Immediate(1));
__ j(not_zero, &loop);
}
Label result_greater, result_less;
Label loop;
// Compare next character.
__ mov(scratch3, Immediate(-1)); // Index into strings.
__ bind(&loop);
// Compare characters.
Label character_compare_done;
__ add(Operand(scratch3), Immediate(1));
__ mov_b(scratch2, Operand(left,
scratch3,
times_1,
SeqAsciiString::kHeaderSize - kHeapObjectTag));
__ subb(scratch2, Operand(right,
scratch3,
times_1,
SeqAsciiString::kHeaderSize - kHeapObjectTag));
__ j(not_equal, &character_compare_done);
__ sub(Operand(scratch1), Immediate(1));
__ j(not_zero, &loop);
// If min length characters match compare lengths otherwise last character
// compare is the result.
__ bind(&character_compare_done);
__ j(equal, &compare_lengths);
__ j(less, &result_less);
__ jmp(&result_greater);
// Compare lengths.
Label result_not_equal;
// Compare lengths - strings up to min-length are equal.
__ bind(&compare_lengths);
__ mov(scratch1, FieldOperand(left, String::kLengthOffset));
__ bind(&compare_lengths_1);
__ sub(scratch1, FieldOperand(right, String::kLengthOffset));
__ test(length_delta, Operand(length_delta));
__ j(not_zero, &result_not_equal);
// Result is EQUAL.
ASSERT_EQ(0, EQUAL);
ASSERT_EQ(0, kSmiTag);
__ xor_(eax, Operand(eax));
__ IncrementCounter(&Counters::string_compare_native, 1);
__ Set(eax, Immediate(Smi::FromInt(EQUAL)));
__ ret(2 * kPointerSize);
__ bind(&result_not_equal);
__ j(greater, &result_greater);
// Result is LESS.
__ bind(&result_less);
__ mov(eax, Immediate(Smi::FromInt(LESS)->value()));
__ IncrementCounter(&Counters::string_compare_native, 1);
__ Set(eax, Immediate(Smi::FromInt(LESS)));
__ ret(2 * kPointerSize);
// Result is GREATER.
__ bind(&result_greater);
__ mov(eax, Immediate(Smi::FromInt(GREATER)->value()));
__ IncrementCounter(&Counters::string_compare_native, 1);
__ Set(eax, Immediate(Smi::FromInt(GREATER)));
__ ret(2 * kPointerSize);
}
......@@ -9745,41 +9719,19 @@ void StringCompareStub::Generate(MacroAssembler* masm) {
__ j(not_equal, &not_same);
ASSERT_EQ(0, EQUAL);
ASSERT_EQ(0, kSmiTag);
__ xor_(eax, Operand(eax));
__ Set(eax, Immediate(Smi::FromInt(EQUAL)));
__ IncrementCounter(&Counters::string_compare_native, 1);
__ ret(2 * kPointerSize);
__ bind(&not_same);
// Check that both objects are not smis.
ASSERT_EQ(0, kSmiTag);
__ mov(ebx, Operand(edx));
__ and_(ebx, Operand(eax));
__ test(ebx, Immediate(kSmiTagMask));
__ j(zero, &runtime);
// Load instance type for both strings.
__ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
__ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
__ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
__ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
// Check that both are flat ascii strings.
Label non_ascii_flat;
__ and_(ecx, kStringRepresentationMask | kStringEncodingMask);
__ cmp(ecx, kSeqStringTag | kAsciiStringTag);
__ j(not_equal, &non_ascii_flat);
const int kFlatAsciiString =
kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
__ and_(ebx, kFlatAsciiString);
__ cmp(ebx, kStringTag | kSeqStringTag | kAsciiStringTag);
__ j(not_equal, &non_ascii_flat);
// Check that both objects are sequential ascii strings.
__ JumpIfNotBothSequentialAsciiStrings(edx, eax, ecx, ebx, &runtime);
// Compare flat ascii strings.
__ IncrementCounter(&Counters::string_compare_native, 1);
GenerateCompareFlatAsciiStrings(masm, edx, eax, ecx, ebx, edi);
__ bind(&non_ascii_flat);
// Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
// tagged as a small integer.
__ bind(&runtime);
......
......@@ -53,23 +53,25 @@ struct ByteMnemonic {
static ByteMnemonic two_operands_instr[] = {
{0x03, "add", REG_OPER_OP_ORDER},
{0x21, "and", OPER_REG_OP_ORDER},
{0x23, "and", REG_OPER_OP_ORDER},
{0x3B, "cmp", REG_OPER_OP_ORDER},
{0x8D, "lea", REG_OPER_OP_ORDER},
{0x09, "or", OPER_REG_OP_ORDER},
{0x0B, "or", REG_OPER_OP_ORDER},
{0x1B, "sbb", REG_OPER_OP_ORDER},
{0x21, "and", OPER_REG_OP_ORDER},
{0x23, "and", REG_OPER_OP_ORDER},
{0x29, "sub", OPER_REG_OP_ORDER},
{0x2A, "subb", REG_OPER_OP_ORDER},
{0x2B, "sub", REG_OPER_OP_ORDER},
{0x84, "test_b", REG_OPER_OP_ORDER},
{0x85, "test", REG_OPER_OP_ORDER},
{0x31, "xor", OPER_REG_OP_ORDER},
{0x33, "xor", REG_OPER_OP_ORDER},
{0x38, "cmpb", OPER_REG_OP_ORDER},
{0x3A, "cmpb", REG_OPER_OP_ORDER},
{0x3B, "cmp", REG_OPER_OP_ORDER},
{0x84, "test_b", REG_OPER_OP_ORDER},
{0x85, "test", REG_OPER_OP_ORDER},
{0x87, "xchg", REG_OPER_OP_ORDER},
{0x8A, "mov_b", REG_OPER_OP_ORDER},
{0x8B, "mov", REG_OPER_OP_ORDER},
{0x8D, "lea", REG_OPER_OP_ORDER},
{-1, "", UNSET_OP_ORDER}
};
......
......@@ -1525,6 +1525,38 @@ void MacroAssembler::Abort(const char* msg) {
}
void MacroAssembler::JumpIfNotBothSequentialAsciiStrings(Register object1,
Register object2,
Register scratch1,
Register scratch2,
Label* failure) {
// Check that both objects are not smis.
ASSERT_EQ(0, kSmiTag);
mov(scratch1, Operand(object1));
and_(scratch1, Operand(object2));
test(scratch1, Immediate(kSmiTagMask));
j(zero, failure);
// Load instance type for both strings.
mov(scratch1, FieldOperand(object1, HeapObject::kMapOffset));
mov(scratch2, FieldOperand(object2, HeapObject::kMapOffset));
movzx_b(scratch1, FieldOperand(scratch1, Map::kInstanceTypeOffset));
movzx_b(scratch2, FieldOperand(scratch2, Map::kInstanceTypeOffset));
// Check that both are flat ascii strings.
const int kFlatAsciiStringMask =
kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
const int kFlatAsciiStringTag = ASCII_STRING_TYPE;
// Interleave bits from both instance types and compare them in one check.
ASSERT_EQ(0, kFlatAsciiStringMask & (kFlatAsciiStringMask << 3));
and_(scratch1, kFlatAsciiStringMask);
and_(scratch2, kFlatAsciiStringMask);
lea(scratch1, Operand(scratch1, scratch2, times_8, 0));
cmp(scratch1, kFlatAsciiStringTag | (kFlatAsciiStringTag << 3));
j(not_equal, failure);
}
CodePatcher::CodePatcher(byte* address, int size)
: address_(address), size_(size), masm_(address, size + Assembler::kGap) {
// Create a new macro assembler pointing to the address of the code to patch.
......
......@@ -415,6 +415,17 @@ class MacroAssembler: public Assembler {
void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; }
bool allow_stub_calls() { return allow_stub_calls_; }
// ---------------------------------------------------------------------------
// String utilities.
// Checks if both objects are sequential ASCII strings, and jumps to label
// if either is not.
void JumpIfNotBothSequentialAsciiStrings(Register object1,
Register object2,
Register scratch1,
Register scratch2,
Label *on_not_flat_ascii_strings);
private:
List<Unresolved> unresolved_;
bool generating_stub_;
......
......@@ -68,7 +68,8 @@ class List {
// not safe to use after operations that can change the list's
// backing store (eg, Add).
inline T& operator[](int i) const {
ASSERT(0 <= i && i < length_);
ASSERT(0 <= i);
ASSERT(i < length_);
return data_[i];
}
inline T& at(int i) const { return operator[](i); }
......
......@@ -8231,7 +8231,6 @@ void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
// Result is EQUAL.
__ Move(rax, Smi::FromInt(EQUAL));
__ IncrementCounter(&Counters::string_compare_native, 1);
__ ret(2 * kPointerSize);
Label result_greater;
......@@ -8241,13 +8240,11 @@ void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
// Result is LESS.
__ Move(rax, Smi::FromInt(LESS));
__ IncrementCounter(&Counters::string_compare_native, 1);
__ ret(2 * kPointerSize);
// Result is GREATER.
__ bind(&result_greater);
__ Move(rax, Smi::FromInt(GREATER));
__ IncrementCounter(&Counters::string_compare_native, 1);
__ ret(2 * kPointerSize);
}
......@@ -8277,6 +8274,7 @@ void StringCompareStub::Generate(MacroAssembler* masm) {
__ JumpIfNotBothSequentialAsciiStrings(rdx, rax, rcx, rbx, &runtime);
// Inline comparison of ascii strings.
__ IncrementCounter(&Counters::string_compare_native, 1);
GenerateCompareFlatAsciiStrings(masm, rdx, rax, rcx, rbx, rdi, r8);
// Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
......
......@@ -1311,8 +1311,7 @@ void MacroAssembler::JumpIfNotBothSequentialAsciiStrings(Register first_object,
ASSERT(kNotStringTag != 0);
const int kFlatAsciiStringMask =
kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
const int kFlatAsciiStringBits =
kNotStringTag | kSeqStringTag | kAsciiStringTag;
const int kFlatAsciiStringTag = ASCII_STRING_TYPE;
andl(scratch1, Immediate(kFlatAsciiStringMask));
andl(scratch2, Immediate(kFlatAsciiStringMask));
......@@ -1320,7 +1319,7 @@ void MacroAssembler::JumpIfNotBothSequentialAsciiStrings(Register first_object,
ASSERT_EQ(0, kFlatAsciiStringMask & (kFlatAsciiStringMask << 3));
lea(scratch1, Operand(scratch1, scratch2, times_8, 0));
cmpl(scratch1,
Immediate(kFlatAsciiStringBits + (kFlatAsciiStringBits << 3)));
Immediate(kFlatAsciiStringTag + (kFlatAsciiStringTag << 3)));
j(not_equal, on_fail);
}
......
......@@ -101,6 +101,8 @@ TEST(DisasmIa320) {
__ cmp(Operand(ebp, ecx, times_4, 0), Immediate(1000));
Handle<FixedArray> foo2 = Factory::NewFixedArray(10, TENURED);
__ cmp(ebx, foo2);
__ cmpb(ebx, Operand(ebp, ecx, times_2, 0));
__ cmpb(Operand(ebp, ecx, times_2, 0), ebx);
__ or_(edx, 3);
__ xor_(edx, 3);
__ nop();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment