Removed rep-cmps{w,b} from CheckCharacters to improve performance.
authorlrn@chromium.org <lrn@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 16 Dec 2008 14:21:00 +0000 (14:21 +0000)
committerlrn@chromium.org <lrn@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 16 Dec 2008 14:21:00 +0000 (14:21 +0000)
git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@984 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/assembler-ia32.cc
src/assembler-ia32.h
src/regexp-macro-assembler-ia32.cc
src/regexp-macro-assembler-ia32.h
test/cctest/test-regexp.cc

index c174ea04adc582a23f6650ceaf18a98db0975dcf..051624bb6067f8a2d2e1f05b729ea46be3506b65 100644 (file)
@@ -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.
 }
 
 
index 2abf24aaa1cbf7cce44567705de7df1ce849a471..1e2f45dbf66f19fac028951d039be72127af9cdb 100644 (file)
@@ -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);
index 4539b345d32a865515101b1d9209dc3fffdab528..fe38075b4f010ac589051f6d030cc8ac992af986 100644 (file)
@@ -193,47 +193,28 @@ void RegExpMacroAssemblerIA32::CheckCharacters(Vector<const uc16> str,
     BranchOrBacktrack(greater, on_failure);
   }
 
-  if (str.length() <= kMaxInlineStringTests) {
-    for (int i = 0; i < str.length(); i++) {
-      if (mode_ == ASCII) {
-        __ cmpb(Operand(esi, edi, times_1, byte_offset + i),
-                static_cast<int8_t>(str[i]));
-      } else {
-        ASSERT(mode_ == UC16);
-        __ cmpw(Operand(esi, edi, times_1, byte_offset + i * sizeof(uc16)),
-                Immediate(str[i]));
-      }
-      BranchOrBacktrack(not_equal, on_failure);
-    }
-    return;
+  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;
   }
 
-  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]);
+  for (int i = 0; i < str.length(); i++) {
+    if (mode_ == ASCII) {
+      __ cmpb(Operand(esi, edi, times_1, byte_offset + i),
+              static_cast<int8_t>(str[i]));
+    } else {
+      ASSERT(mode_ == UC16);
+      __ cmpw(Operand(esi, edi, times_1, byte_offset + i * sizeof(uc16)),
+              Immediate(str[i]));
     }
-  } else {
-    ASSERT(mode_ == UC16);
-    memcpy(constant_buffer.location(),
-           str.start(),
-           str.length() * sizeof(uc16));
+    BranchOrBacktrack(not_equal, on_failure);
   }
-
-  __ 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);
 }
 
index f4918b652496667f880ac82eabcfc6211c99690b..7c2d5728e469c5eae257f5c24551daf636484813 100644 (file)
@@ -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,
index 9ce2ee1e88b509ab11435ce600f14d4123bb9ba9..1acce88851ec8a07934280f6199ee6a1dd06b819 100644 (file)
@@ -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;