Fixed bug in interest propagation caused by following the loop edge
authorchristian.plesner.hansen@gmail.com <christian.plesner.hansen@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 17 Dec 2008 13:16:38 +0000 (13:16 +0000)
committerchristian.plesner.hansen@gmail.com <christian.plesner.hansen@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 17 Dec 2008 13:16:38 +0000 (13:16 +0000)
out of a loop choice node before the continuation edge.

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

src/jsregexp.cc
src/jsregexp.h
test/cctest/test-regexp.cc

index fe5bf05d26af08ca21134f476d940f49ae2a89c1..4855443debffd54d9f9a88a9cdb12d4a50d0a2be 100644 (file)
@@ -1596,6 +1596,11 @@ FOR_EACH_NODE_TYPE(DEFINE_ACCEPT)
 #undef DEFINE_ACCEPT
 
 
+void LoopChoiceNode::Accept(NodeVisitor* visitor) {
+  visitor->VisitLoopChoice(this);
+}
+
+
 // -------------------------------------------------------------------
 // Emit code.
 
@@ -2070,6 +2075,20 @@ int ChoiceNode::GreedyLoopTextLength(GuardedAlternative* alternative) {
 }
 
 
+void LoopChoiceNode::AddLoopAlternative(GuardedAlternative alt) {
+  ASSERT_EQ(loop_node_, NULL);
+  AddAlternative(alt);
+  loop_node_ = alt.node();
+}
+
+
+void LoopChoiceNode::AddContinueAlternative(GuardedAlternative alt) {
+  ASSERT_EQ(continue_node_, NULL);
+  AddAlternative(alt);
+  continue_node_ = alt.node();
+}
+
+
 bool LoopChoiceNode::Emit(RegExpCompiler* compiler,
                           GenerationVariant* variant) {
   RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
@@ -2680,7 +2699,7 @@ RegExpNode* RegExpQuantifier::ToNode(int min,
   bool has_max = max < RegExpTree::kInfinity;
   bool needs_counter = has_min || has_max;
   int reg_ctr = needs_counter ? compiler->AllocateRegister() : -1;
-  ChoiceNode* center = new LoopChoiceNode(2);
+  LoopChoiceNode* center = new LoopChoiceNode();
   RegExpNode* loop_return = needs_counter
       ? static_cast<RegExpNode*>(ActionNode::IncrementRegister(reg_ctr, center))
       : static_cast<RegExpNode*>(center);
@@ -2696,11 +2715,11 @@ RegExpNode* RegExpQuantifier::ToNode(int min,
     rest_alt.AddGuard(rest_guard);
   }
   if (is_greedy) {
-    center->AddAlternative(body_alt);
-    center->AddAlternative(rest_alt);
+    center->AddLoopAlternative(body_alt);
+    center->AddContinueAlternative(rest_alt);
   } else {
-    center->AddAlternative(rest_alt);
-    center->AddAlternative(body_alt);
+    center->AddContinueAlternative(rest_alt);
+    center->AddLoopAlternative(body_alt);
   }
   if (needs_counter) {
     return ActionNode::SetRegister(reg_ctr, 0, center);
@@ -3358,6 +3377,22 @@ void AssertionPropagation::VisitChoice(ChoiceNode* that) {
 }
 
 
+void AssertionPropagation::VisitLoopChoice(LoopChoiceNode* that) {
+  NodeInfo* info = that->info();
+  for (int i = 0; i < that->alternatives()->length(); i++) {
+    RegExpNode* node = that->alternatives()->at(i).node();
+    if (node != that->loop_node()) {
+      EnsureAnalyzed(node);
+      info->AddFromFollowing(node->info());
+    }
+  }
+  // Check the loop last since it may need the value of this node
+  // to get a correct result.
+  EnsureAnalyzed(that->loop_node());
+  info->AddFromFollowing(that->loop_node()->info());
+}
+
+
 void AssertionPropagation::VisitBackReference(BackReferenceNode* that) {
   EnsureAnalyzed(that->on_success());
 }
index 0cac1724ab7221106fc1c5708bf381a03bf0f337..5280a2225ea6dccc37bea2f70f03fa3fea200557 100644 (file)
@@ -912,9 +912,28 @@ class ChoiceNode: public RegExpNode {
 
 class LoopChoiceNode: public ChoiceNode {
  public:
-  explicit LoopChoiceNode(int expected_size) : ChoiceNode(expected_size) { }
+  explicit LoopChoiceNode()
+      : ChoiceNode(2),
+        loop_node_(NULL),
+        continue_node_(NULL) { }
+  void AddLoopAlternative(GuardedAlternative alt);
+  void AddContinueAlternative(GuardedAlternative alt);
   virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant);
   virtual LoopChoiceNode* Clone() { return new LoopChoiceNode(*this); }
+  RegExpNode* loop_node() { return loop_node_; }
+  RegExpNode* continue_node() { return continue_node_; }
+  virtual void Accept(NodeVisitor* visitor);
+
+ private:
+  // AddAlternative is made private for loop nodes because alternatives
+  // should not be added freely, we need to keep track of which node
+  // goes back to the node itself.
+  void AddAlternative(GuardedAlternative node) {
+    ChoiceNode::AddAlternative(node);
+  }
+
+  RegExpNode* loop_node_;
+  RegExpNode* continue_node_;
 };
 
 
@@ -1024,6 +1043,7 @@ class NodeVisitor {
   virtual void Visit##Type(Type##Node* that) = 0;
 FOR_EACH_NODE_TYPE(DECLARE_VISIT)
 #undef DECLARE_VISIT
+  virtual void VisitLoopChoice(LoopChoiceNode* that) { VisitChoice(that); }
 };
 
 
@@ -1105,6 +1125,7 @@ class AssertionPropagation: public NodeVisitor {
   virtual void Visit##Type(Type##Node* that);
 FOR_EACH_NODE_TYPE(DECLARE_VISIT)
 #undef DECLARE_VISIT
+  virtual void VisitLoopChoice(LoopChoiceNode* that);
 
  private:
   bool ignore_case_;
index b89c037981ab6128ecbb6f8a6f13201ca688d2c1..19ced1615acf390312091e8179c91377a156254d 100644 (file)
@@ -1466,5 +1466,5 @@ TEST(CharClassDifference) {
 
 TEST(Graph) {
   V8::Initialize(NULL);
-  Execute("\\bboy\\b", false, true, true);
+  Execute("\\b\\w+\\b", false, true, true);
 }