Remove unnecessary code for non-zero-length global regexps.
authoryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 4 Jun 2012 08:49:17 +0000 (08:49 +0000)
committeryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 4 Jun 2012 08:49:17 +0000 (08:49 +0000)
Also fixing a bug in the arm implementation.

BUG=
TEST=regexp-global.js

Review URL: https://chromiumcodereview.appspot.com/10383280

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@11704 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/arm/regexp-macro-assembler-arm.cc
src/ia32/regexp-macro-assembler-ia32.cc
src/jsregexp.cc
src/regexp-macro-assembler.cc
src/regexp-macro-assembler.h
src/x64/regexp-macro-assembler-x64.cc
test/mjsunit/regexp-global.js

index 11790e5..ae8b8ee 100644 (file)
@@ -796,7 +796,7 @@ Handle<HeapObject> RegExpMacroAssemblerARM::GetCode(Handle<String> source) {
       for (int i = 0; i < num_saved_registers_; i += 2) {
         __ ldr(r2, register_location(i));
         __ ldr(r3, register_location(i + 1));
-        if (global()) {
+        if (i == 0 && global_with_zero_length_check()) {
           // Keep capture start in r4 for the zero-length check later.
           __ mov(r4, r2);
         }
@@ -834,18 +834,22 @@ Handle<HeapObject> RegExpMacroAssemblerARM::GetCode(Handle<String> source) {
 
       // Prepare r0 to initialize registers with its value in the next run.
       __ ldr(r0, MemOperand(frame_pointer(), kInputStartMinusOne));
-      // Special case for zero-length matches.
-      // r4: capture start index
-      __ cmp(current_input_offset(), r4);
-      // Not a zero-length match, restart.
-      __ b(ne, &load_char_start_regexp);
-      // Offset from the end is zero if we already reached the end.
-      __ cmp(current_input_offset(), Operand(0));
-      __ b(eq, &exit_label_);
-      // Advance current position after a zero-length match.
-      __ add(current_input_offset(),
-             current_input_offset(),
-             Operand((mode_ == UC16) ? 2 : 1));
+
+      if (global_with_zero_length_check()) {
+        // Special case for zero-length matches.
+        // r4: capture start index
+        __ cmp(current_input_offset(), r4);
+        // Not a zero-length match, restart.
+        __ b(ne, &load_char_start_regexp);
+        // Offset from the end is zero if we already reached the end.
+        __ cmp(current_input_offset(), Operand(0));
+        __ b(eq, &exit_label_);
+        // Advance current position after a zero-length match.
+        __ add(current_input_offset(),
+               current_input_offset(),
+               Operand((mode_ == UC16) ? 2 : 1));
+      }
+
       __ b(&load_char_start_regexp);
     } else {
       __ mov(r0, Operand(SUCCESS));
index cba1660..d62644a 100644 (file)
@@ -857,7 +857,7 @@ Handle<HeapObject> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) {
       }
       for (int i = 0; i < num_saved_registers_; i++) {
         __ mov(eax, register_location(i));
-        if (i == 0 && global()) {
+        if (i == 0 && global_with_zero_length_check()) {
           // Keep capture start in edx for the zero-length check later.
           __ mov(edx, eax);
         }
@@ -890,20 +890,23 @@ Handle<HeapObject> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) {
       // Prepare eax to initialize registers with its value in the next run.
       __ mov(eax, Operand(ebp, kInputStartMinusOne));
 
-      // Special case for zero-length matches.
-      // edx: capture start index
-      __ cmp(edi, edx);
-      // Not a zero-length match, restart.
-      __ j(not_equal, &load_char_start_regexp);
-      // edi (offset from the end) is zero if we already reached the end.
-      __ test(edi, edi);
-      __ j(zero, &exit_label_, Label::kNear);
-      // Advance current position after a zero-length match.
-      if (mode_ == UC16) {
-        __ add(edi, Immediate(2));
-      } else {
-        __ inc(edi);
+      if (global_with_zero_length_check()) {
+        // Special case for zero-length matches.
+        // edx: capture start index
+        __ cmp(edi, edx);
+        // Not a zero-length match, restart.
+        __ j(not_equal, &load_char_start_regexp);
+        // edi (offset from the end) is zero if we already reached the end.
+        __ test(edi, edi);
+        __ j(zero, &exit_label_, Label::kNear);
+        // Advance current position after a zero-length match.
+        if (mode_ == UC16) {
+          __ add(edi, Immediate(2));
+        } else {
+          __ inc(edi);
+        }
       }
+
       __ jmp(&load_char_start_regexp);
     } else {
       __ mov(eax, Immediate(SUCCESS));
index 2c8376a..ee061ed 100644 (file)
@@ -5927,7 +5927,12 @@ RegExpEngine::CompilationResult RegExpEngine::Compile(
     macro_assembler.SetCurrentPositionFromEnd(max_length);
   }
 
-  macro_assembler.set_global(is_global);
+  if (is_global) {
+    macro_assembler.set_global_mode(
+        (data->tree->min_match() > 0)
+            ? RegExpMacroAssembler::GLOBAL_NO_ZERO_LENGTH_CHECK
+            : RegExpMacroAssembler::GLOBAL);
+  }
 
   return compiler.Assemble(&macro_assembler,
                            node,
index 08568de..fe98c8e 100644 (file)
@@ -37,7 +37,7 @@ namespace internal {
 
 RegExpMacroAssembler::RegExpMacroAssembler()
   : slow_safe_compiler_(false),
-    global_(false) {
+    global_mode_(NOT_GLOBAL) {
 }
 
 
index 5b2cf4a..9fa7ed4 100644 (file)
@@ -184,14 +184,18 @@ class RegExpMacroAssembler {
   void set_slow_safe(bool ssc) { slow_safe_compiler_ = ssc; }
   bool slow_safe() { return slow_safe_compiler_; }
 
+  enum GlobalMode { NOT_GLOBAL, GLOBAL, GLOBAL_NO_ZERO_LENGTH_CHECK };
   // Set whether the regular expression has the global flag.  Exiting due to
   // a failure in a global regexp may still mean success overall.
-  void set_global(bool global) { global_ = global; }
-  bool global() { return global_; }
+  inline void set_global_mode(GlobalMode mode) { global_mode_ = mode; }
+  inline bool global() { return global_mode_ != NOT_GLOBAL; }
+  inline bool global_with_zero_length_check() {
+    return global_mode_ == GLOBAL;
+  }
 
  private:
   bool slow_safe_compiler_;
-  bool global_;
+  bool global_mode_;
 };
 
 
index cb1e029..ebbe8f2 100644 (file)
@@ -926,7 +926,7 @@ Handle<HeapObject> RegExpMacroAssemblerX64::GetCode(Handle<String> source) {
       }
       for (int i = 0; i < num_saved_registers_; i++) {
         __ movq(rax, register_location(i));
-        if (i == 0 && global()) {
+        if (i == 0 && global_with_zero_length_check()) {
           // Keep capture start in rdx for the zero-length check later.
           __ movq(rdx, rax);
         }
@@ -958,20 +958,23 @@ Handle<HeapObject> RegExpMacroAssemblerX64::GetCode(Handle<String> source) {
       // Prepare rax to initialize registers with its value in the next run.
       __ movq(rax, Operand(rbp, kInputStartMinusOne));
 
-      // Special case for zero-length matches.
-      // rdx: capture start index
-      __ cmpq(rdi, rdx);
-      // Not a zero-length match, restart.
-      __ j(not_equal, &load_char_start_regexp);
-      // rdi (offset from the end) is zero if we already reached the end.
-      __ testq(rdi, rdi);
-      __ j(zero, &exit_label_, Label::kNear);
-      // Advance current position after a zero-length match.
-      if (mode_ == UC16) {
-        __ addq(rdi, Immediate(2));
-      } else {
-        __ incq(rdi);
+      if (global_with_zero_length_check()) {
+        // Special case for zero-length matches.
+        // rdx: capture start index
+        __ cmpq(rdi, rdx);
+        // Not a zero-length match, restart.
+        __ j(not_equal, &load_char_start_regexp);
+        // rdi (offset from the end) is zero if we already reached the end.
+        __ testq(rdi, rdi);
+        __ j(zero, &exit_label_, Label::kNear);
+        // Advance current position after a zero-length match.
+        if (mode_ == UC16) {
+          __ addq(rdi, Immediate(2));
+        } else {
+          __ incq(rdi);
+        }
       }
+
       __ jmp(&load_char_start_regexp);
     } else {
       __ movq(rax, Immediate(SUCCESS));
index 12f8578..cc360d3 100644 (file)
@@ -130,3 +130,12 @@ assertEquals("4, 2!", str);
 var str = "Beasts of England, beasts of Ireland";
 str = str.replace(/(.*)/g, function(match) { return '~'; });
 assertEquals("~~", str);
+
+// Test zero-length matches that have non-zero-length sub-captures that do not
+// start at the match start position.
+str = "up up up up";
+str = str.replace(/\b(?=u(p))/g, function(match, capture) {
+                                    return capture.length;
+                                  });
+
+assertEquals("1up 1up 1up 1up", str);