review
authorchristian.plesner.hansen@gmail.com <christian.plesner.hansen@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 23 Jan 2009 07:46:44 +0000 (07:46 +0000)
committerchristian.plesner.hansen@gmail.com <christian.plesner.hansen@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 23 Jan 2009 07:46:44 +0000 (07:46 +0000)
git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1130 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/ast.cc
src/ast.h
src/jsregexp.cc
test/mjsunit/ascii-regexp-subject.js
test/mjsunit/mjsunit.status

index 5034151..a5f4dc8 100644 (file)
@@ -244,6 +244,36 @@ Interval RegExpQuantifier::CaptureRegisters() {
 }
 
 
+bool RegExpAssertion::IsAnchored() {
+  return type() == RegExpAssertion::START_OF_INPUT;
+}
+
+
+bool RegExpAlternative::IsAnchored() {
+  return this->nodes()->at(0)->IsAnchored();
+}
+
+
+bool RegExpDisjunction::IsAnchored() {
+  ZoneList<RegExpTree*>* alternatives = this->alternatives();
+  for (int i = 0; i < alternatives->length(); i++) {
+    if (!alternatives->at(i)->IsAnchored())
+      return false;
+  }
+  return true;
+}
+
+
+bool RegExpLookahead::IsAnchored() {
+  return is_positive() && body()->IsAnchored();
+}
+
+
+bool RegExpCapture::IsAnchored() {
+  return body()->IsAnchored();
+}
+
+
 // Convert regular expression trees to a simple sexp representation.
 // This representation should be different from the input grammar
 // in as many cases as possible, to make it more difficult for incorrect
@@ -417,6 +447,7 @@ SmartPointer<const char> RegExpTree::ToString() {
 
 RegExpDisjunction::RegExpDisjunction(ZoneList<RegExpTree*>* alternatives)
     : alternatives_(alternatives) {
+  ASSERT(alternatives->length() > 1);
   RegExpTree* first_alternative = alternatives->at(0);
   min_match_ = first_alternative->min_match();
   max_match_ = first_alternative->max_match();
@@ -430,6 +461,7 @@ RegExpDisjunction::RegExpDisjunction(ZoneList<RegExpTree*>* alternatives)
 
 RegExpAlternative::RegExpAlternative(ZoneList<RegExpTree*>* nodes)
     : nodes_(nodes) {
+  ASSERT(nodes->length() > 1);
   min_match_ = 0;
   max_match_ = 0;
   for (int i = 0; i < nodes->length(); i++) {
index 063e882..00bfddb 100644 (file)
--- a/src/ast.h
+++ b/src/ast.h
@@ -1253,6 +1253,7 @@ class RegExpTree: public ZoneObject {
   virtual RegExpNode* ToNode(RegExpCompiler* compiler,
                              RegExpNode* on_success) = 0;
   virtual bool IsTextElement() { return false; }
+  virtual bool IsAnchored() { return false; }
   virtual int min_match() = 0;
   virtual int max_match() = 0;
   // Returns the interval of registers used for captures within this
@@ -1277,6 +1278,7 @@ class RegExpDisjunction: public RegExpTree {
   virtual RegExpDisjunction* AsDisjunction();
   virtual Interval CaptureRegisters();
   virtual bool IsDisjunction();
+  virtual bool IsAnchored();
   virtual int min_match() { return min_match_; }
   virtual int max_match() { return max_match_; }
   ZoneList<RegExpTree*>* alternatives() { return alternatives_; }
@@ -1296,6 +1298,7 @@ class RegExpAlternative: public RegExpTree {
   virtual RegExpAlternative* AsAlternative();
   virtual Interval CaptureRegisters();
   virtual bool IsAlternative();
+  virtual bool IsAnchored();
   virtual int min_match() { return min_match_; }
   virtual int max_match() { return max_match_; }
   ZoneList<RegExpTree*>* nodes() { return nodes_; }
@@ -1322,6 +1325,7 @@ class RegExpAssertion: public RegExpTree {
                              RegExpNode* on_success);
   virtual RegExpAssertion* AsAssertion();
   virtual bool IsAssertion();
+  virtual bool IsAnchored();
   virtual int min_match() { return 0; }
   virtual int max_match() { return 0; }
   Type type() { return type_; }
@@ -1495,6 +1499,7 @@ class RegExpCapture: public RegExpTree {
                             RegExpCompiler* compiler,
                             RegExpNode* on_success);
   virtual RegExpCapture* AsCapture();
+  virtual bool IsAnchored();
   virtual Interval CaptureRegisters();
   virtual bool IsCapture();
   virtual int min_match() { return body_->min_match(); }
@@ -1525,6 +1530,7 @@ class RegExpLookahead: public RegExpTree {
   virtual RegExpLookahead* AsLookahead();
   virtual Interval CaptureRegisters();
   virtual bool IsLookahead();
+  virtual bool IsAnchored();
   virtual int min_match() { return 0; }
   virtual int max_match() { return 0; }
   RegExpTree* body() { return body_; }
index befaa38..5a782f8 100644 (file)
@@ -4643,17 +4643,17 @@ Handle<FixedArray> RegExpEngine::Compile(RegExpCompileData* data,
                                                     0,
                                                     &compiler,
                                                     compiler.accept());
-  // Add a .*? at the beginning, outside the body capture.
-  // Note: We could choose to not add this if the regexp is anchored at
-  //   the start of the input but I'm not sure how best to do that and
-  //   since we don't even handle ^ yet I'm saving that optimization for
-  //   later.
-  RegExpNode* node = RegExpQuantifier::ToNode(0,
-                                              RegExpTree::kInfinity,
-                                              false,
-                                              new RegExpCharacterClass('*'),
-                                              &compiler,
-                                              captured_body);
+  RegExpNode* node = captured_body;
+  if (!data->tree->IsAnchored()) {
+    // Add a .*? at the beginning, outside the body capture, unless
+    // this expression is anchored at the beginning.
+    node = RegExpQuantifier::ToNode(0,
+                                    RegExpTree::kInfinity,
+                                    false,
+                                    new RegExpCharacterClass('*'),
+                                    &compiler,
+                                    captured_body);
+  }
   data->node = node;
   Analysis analysis(ignore_case);
   analysis.EnsureAnalyzed(node);
index 01d0697..e0c2f84 100644 (file)
@@ -37,9 +37,13 @@ for (i = 0; i < 18; i++) {
   s = s + s;
 }
 
-var re = /^bar/;
-
-for (i = 0; i < 1000; i++) {
-  re.test(s);
-  re = new RegExp("^bar");
+function repeatRegexp(re) {
+  for (i = 0; i < 1000; i++) {
+    re.test(s);
+  }
 }
+
+repeatRegexp(/^bar/);
+repeatRegexp(/^foo|^bar|^baz/);
+repeatRegexp(/(^bar)/);
+repeatRegexp(/(?=^bar)\w+/);
index f15fc75..c354300 100644 (file)
@@ -44,10 +44,6 @@ regexp-loop-capture: PASS || FAIL
 
 [ $arch == arm ]
 
-# Optimize regexp search for non-multiline initial ^.
-# http://code.google.com/p/v8/issues/detail?id=198
-ascii-regexp-subject: PASS || FAIL
-
 # Slow tests which times out in debug mode.
 try: PASS, SKIP if $mode == debug
 debug-scripts-request: PASS, SKIP if $mode == debug