Commit 028e3414 authored by lrn@chromium.org's avatar lrn@chromium.org

Removed rep-cmps{w,b} from CheckCharacters to improve performance.


git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@984 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent c35f6aea
......@@ -866,21 +866,20 @@ void Assembler::cmp(const Operand& op, const Immediate& imm) {
}
void Assembler::rep_cmpsb() {
void Assembler::cmpb_al(const Operand& op) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
EMIT(0xFC); // CLD to ensure forward operation
EMIT(0xF3); // REP
EMIT(0xA6); // CMPSB
EMIT(0x38); // CMP r/m8, r8
emit_operand(eax, op); // eax has same code as register al.
}
void Assembler::rep_cmpsw() {
void Assembler::cmpw_ax(const Operand& op) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
EMIT(0xFC); // CLD to ensure forward operation
EMIT(0xF3); // REP
EMIT(0x66); // Operand size overide.
EMIT(0xA7); // CMPS
EMIT(0x66);
EMIT(0x39); // CMP r/m16, r16
emit_operand(eax, op); // eax has same code as register ax.
}
......
......@@ -503,15 +503,14 @@ class Assembler : public Malloced {
void and_(const Operand& dst, const Immediate& x);
void cmpb(const Operand& op, int8_t imm8);
void cmpb_al(const Operand& op);
void cmpw_ax(const Operand& op);
void cmpw(const Operand& op, Immediate imm16);
void cmp(Register reg, int32_t imm32);
void cmp(Register reg, Handle<Object> handle);
void cmp(Register reg, const Operand& op);
void cmp(const Operand& op, const Immediate& imm);
void rep_cmpsb();
void rep_cmpsw();
void dec_b(Register dst);
void dec(Register dst);
......
......@@ -193,7 +193,17 @@ void RegExpMacroAssemblerIA32::CheckCharacters(Vector<const uc16> str,
BranchOrBacktrack(greater, on_failure);
}
if (str.length() <= kMaxInlineStringTests) {
Label backtrack;
if (on_failure == NULL) {
// Avoid inlining the Backtrack macro for each test.
Label skip_backtrack;
__ jmp(&skip_backtrack);
__ bind(&backtrack);
Backtrack();
__ bind(&skip_backtrack);
on_failure = &backtrack;
}
for (int i = 0; i < str.length(); i++) {
if (mode_ == ASCII) {
__ cmpb(Operand(esi, edi, times_1, byte_offset + i),
......@@ -205,35 +215,6 @@ void RegExpMacroAssemblerIA32::CheckCharacters(Vector<const uc16> str,
}
BranchOrBacktrack(not_equal, on_failure);
}
return;
}
ArraySlice constant_buffer = constants_.GetBuffer(str.length(), char_size());
if (mode_ == ASCII) {
for (int i = 0; i < str.length(); i++) {
constant_buffer.at<char>(i) = static_cast<char>(str[i]);
}
} else {
ASSERT(mode_ == UC16);
memcpy(constant_buffer.location(),
str.start(),
str.length() * sizeof(uc16));
}
__ mov(eax, edi);
__ mov(ebx, esi);
__ lea(edi, Operand(esi, edi, times_1, byte_offset));
LoadConstantBufferAddress(esi, &constant_buffer);
__ mov(ecx, str.length());
if (char_size() == 1) {
__ rep_cmpsb();
} else {
ASSERT(char_size() == 2);
__ rep_cmpsw();
}
__ mov(esi, ebx);
__ mov(edi, eax);
BranchOrBacktrack(not_equal, on_failure);
}
......@@ -251,45 +232,50 @@ void RegExpMacroAssemblerIA32::CheckNotBackReferenceIgnoreCase(
int start_reg,
Label* on_no_match) {
Label fallthrough;
__ mov(eax, register_location(start_reg));
__ mov(edx, register_location(start_reg));
__ mov(ecx, register_location(start_reg + 1));
__ sub(ecx, Operand(eax)); // Length to check.
__ sub(ecx, Operand(edx)); // Length to check.
BranchOrBacktrack(less, on_no_match);
__ j(equal, &fallthrough);
if (mode_ == ASCII) {
Label success;
Label fail;
__ push(esi);
Label loop_increment;
__ push(edi);
__ add(edx, Operand(esi));
__ add(edi, Operand(esi));
__ add(esi, Operand(eax));
__ add(ecx, Operand(edi));
Label loop;
__ bind(&loop);
__ rep_cmpsb();
__ j(equal, &success);
__ movzx_b(eax, Operand(edi, 0));
__ cmpb_al(Operand(edx, 0));
__ j(equal, &loop_increment);
// Compare lower-case if letters.
__ movzx_b(eax, Operand(edi, -1));
__ or_(eax, 0x20); // To-lower-case
__ or_(eax, 0x20); // To lower-case.
__ lea(ebx, Operand(eax, -'a'));
__ cmp(ebx, static_cast<int32_t>('z' - 'a'));
__ j(above, &fail);
__ movzx_b(ebx, Operand(esi, -1));
__ movzx_b(ebx, Operand(edx, 0));
__ or_(ebx, 0x20); // To-lower-case
__ cmp(eax, Operand(ebx));
__ j(not_equal, &fail);
__ or_(ecx, Operand(ecx));
__ j(not_equal, &loop);
__ bind(&loop_increment);
__ add(Operand(edx), Immediate(1));
__ add(Operand(edi), Immediate(1));
__ cmp(edi, Operand(ecx));
__ j(below, &loop, taken);
__ jmp(&success);
__ bind(&fail);
__ pop(edi);
__ pop(esi);
BranchOrBacktrack(no_condition, on_no_match);
__ bind(&success);
__ pop(eax); // discard original value of edi
__ pop(esi);
__ sub(edi, Operand(esi));
} else {
ASSERT(mode_ == UC16);
......@@ -325,30 +311,47 @@ void RegExpMacroAssemblerIA32::CheckNotBackReference(
int start_reg,
Label* on_no_match) {
Label fallthrough;
__ mov(eax, register_location(start_reg));
Label success;
Label fail;
__ mov(edx, register_location(start_reg));
__ mov(ecx, register_location(start_reg + 1));
__ sub(ecx, Operand(eax)); // Length to check.
__ sub(ecx, Operand(edx)); // Length to check.
BranchOrBacktrack(less, on_no_match);
__ j(equal, &fallthrough);
// Check that there are sufficient characters left in the input.
__ mov(ebx, edi);
__ add(ebx, Operand(ecx));
BranchOrBacktrack(greater, on_no_match);
__ mov(ebx, edi);
__ mov(edx, esi);
__ add(edi, Operand(esi));
__ add(esi, Operand(eax));
__ rep_cmpsb();
__ mov(esi, edx);
Label success;
__ j(equal, &success);
__ add(edx, Operand(esi));
__ add(ecx, Operand(edi));
Label loop;
__ bind(&loop);
if (mode_ == ASCII) {
__ movzx_b(eax, Operand(edx, 0));
__ cmpb_al(Operand(edi, 0));
} else {
ASSERT(mode_ == UC16);
__ movzx_w(eax, Operand(edx, 0));
__ cmpw_ax(Operand(edi, 0));
}
__ j(not_equal, &fail);
__ add(Operand(edx), Immediate(char_size()));
__ add(Operand(edi), Immediate(char_size()));
__ cmp(edi, Operand(ecx));
__ j(below, &loop);
__ jmp(&success);
__ bind(&fail);
__ mov(edi, ebx);
BranchOrBacktrack(no_condition, on_no_match);
__ bind(&success);
__ sub(edi, Operand(esi));
__ bind(&fallthrough);
}
......
......@@ -126,10 +126,10 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler {
static const size_t kRegExpCodeSize = 1024;
// Initial size of constant buffers allocated during compilation.
static const int kRegExpConstantsSize = 256;
// Only unroll loops up to this length.
static const int kMaxInlineStringTests = 8;
// Only unroll loops up to this length. TODO(lrn): Actually use this.
static const int kMaxInlineStringTests = 32;
// Compares two-byte strings case insenstively.
// Compares two-byte strings case insensitively.
static int CaseInsensitiveCompareUC16(uc16** buffer,
int byte_offset1,
int byte_offset2,
......
......@@ -788,7 +788,7 @@ TEST(MacroAssemblerIA32Backtrack) {
}
TEST(MacroAssemblerIA32BackReference) {
TEST(MacroAssemblerIA32BackReferenceASCII) {
v8::V8::Initialize();
ContextInitializer initializer;
......@@ -835,6 +835,57 @@ TEST(MacroAssemblerIA32BackReference) {
}
TEST(MacroAssemblerIA32BackReferenceUC16) {
v8::V8::Initialize();
ContextInitializer initializer;
RegExpMacroAssemblerIA32 m(RegExpMacroAssemblerIA32::UC16, 3);
m.WriteCurrentPositionToRegister(0, 0);
m.AdvanceCurrentPosition(2);
m.WriteCurrentPositionToRegister(1, 0);
Label nomatch;
m.CheckNotBackReference(0, &nomatch);
m.Fail();
m.Bind(&nomatch);
m.AdvanceCurrentPosition(2);
Label missing_match;
m.CheckNotBackReference(0, &missing_match);
m.WriteCurrentPositionToRegister(2, 0);
m.Succeed();
m.Bind(&missing_match);
m.Fail();
Handle<String> source = Factory::NewStringFromAscii(CStrVector("^(..)..\1"));
Handle<Object> code_object = m.GetCode(source);
Handle<Code> code = Handle<Code>::cast(code_object);
const uc16 input_data[6] = {'f', 0x2028, 'o', 'o', 'f', 0x2028};
Handle<String> input =
Factory::NewStringFromTwoByte(Vector<const uc16>(input_data, 6));
Handle<SeqTwoByteString> seq_input = Handle<SeqTwoByteString>::cast(input);
Address start_adr = seq_input->GetCharsAddress();
int start_offset = start_adr - reinterpret_cast<Address>(*seq_input);
int end_offset = start_offset + seq_input->length() * sizeof(input_data[0]);
int output[3];
RegExpMacroAssemblerIA32::Result result =
RegExpMacroAssemblerIA32::Execute(*code,
seq_input.location(),
start_offset,
end_offset,
output,
true);
CHECK_EQ(RegExpMacroAssemblerIA32::SUCCESS, result);
CHECK_EQ(0, output[0]);
CHECK_EQ(2, output[1]);
CHECK_EQ(6, output[2]);
}
TEST(MacroAssemblerIA32AtStart) {
v8::V8::Initialize();
ContextInitializer initializer;
......
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