Allow IfBuilder's to join existing (captured) continuations.
authorbmeurer@chromium.org <bmeurer@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 20 Sep 2013 10:47:09 +0000 (10:47 +0000)
committerbmeurer@chromium.org <bmeurer@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 20 Sep 2013 10:47:09 +0000 (10:47 +0000)
R=mvstanton@chromium.org

Review URL: https://codereview.chromium.org/23452049

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

src/hydrogen.cc
src/hydrogen.h

index cf42530..caa595b 100644 (file)
@@ -806,6 +806,28 @@ void HGraphBuilder::IfBuilder::CaptureContinuation(
 }
 
 
+void HGraphBuilder::IfBuilder::JoinContinuation(HIfContinuation* continuation) {
+  ASSERT(!finished_);
+  ASSERT(!captured_);
+  HBasicBlock* true_block = last_true_block_ == NULL
+      ? first_true_block_
+      : last_true_block_;
+  HBasicBlock* false_block = did_else_ && (first_false_block_ != NULL)
+      ? builder_->current_block()
+      : first_false_block_;
+  if (true_block != NULL && !true_block->IsFinished()) {
+    ASSERT(continuation->IsTrueReachable());
+    true_block->GotoNoSimulate(continuation->true_branch());
+  }
+  if (false_block != NULL && !false_block->IsFinished()) {
+    ASSERT(continuation->IsFalseReachable());
+    false_block->GotoNoSimulate(continuation->false_branch());
+  }
+  captured_ = true;
+  End();
+}
+
+
 void HGraphBuilder::IfBuilder::Then() {
   ASSERT(!captured_);
   ASSERT(!finished_);
index d0e47aa..a371fa5 100644 (file)
@@ -941,7 +941,12 @@ class FunctionState V8_FINAL {
 
 class HIfContinuation V8_FINAL {
  public:
-  HIfContinuation() { continuation_captured_ = false; }
+  HIfContinuation() : continuation_captured_(false) {}
+  HIfContinuation(HBasicBlock* true_branch,
+                  HBasicBlock* false_branch,
+                  int position = RelocInfo::kNoPosition)
+      : continuation_captured_(true), true_branch_(true_branch),
+        false_branch_(false_branch), position_(position) {}
   ~HIfContinuation() { ASSERT(!continuation_captured_); }
 
   void Capture(HBasicBlock* true_branch,
@@ -970,6 +975,10 @@ class HIfContinuation V8_FINAL {
     return IsTrueReachable() || IsFalseReachable();
   }
 
+  HBasicBlock* true_branch() const { return true_branch_; }
+  HBasicBlock* false_branch() const { return false_branch_; }
+
+ private:
   bool continuation_captured_;
   HBasicBlock* true_branch_;
   HBasicBlock* false_branch_;
@@ -1380,8 +1389,50 @@ class HGraphBuilder {
     void Or();
     void And();
 
+    // Captures the current state of this IfBuilder in the specified
+    // continuation and ends this IfBuilder.
     void CaptureContinuation(HIfContinuation* continuation);
 
+    // Joins the specified continuation from this IfBuilder and ends this
+    // IfBuilder. This appends a Goto instruction from the true branch of
+    // this IfBuilder to the true branch of the continuation unless the
+    // true branch of this IfBuilder is already finished. And vice versa
+    // for the false branch.
+    //
+    // The basic idea is as follows: You have several nested IfBuilder's
+    // that you want to join based on two possible outcomes (i.e. success
+    // and failure, or whatever). You can do this easily using this method
+    // now, for example:
+    //
+    //   HIfContinuation cont(graph()->CreateBasicBlock(),
+    //                        graph()->CreateBasicBlock());
+    //   ...
+    //     IfBuilder if_whatever(this);
+    //     if_whatever.If<Condition>(arg);
+    //     if_whatever.Then();
+    //     ...
+    //     if_whatever.Else();
+    //     ...
+    //     if_whatever.JoinContinuation(&cont);
+    //   ...
+    //     IfBuilder if_something(this);
+    //     if_something.If<Condition>(arg1, arg2);
+    //     if_something.Then();
+    //     ...
+    //     if_something.Else();
+    //     ...
+    //     if_something.JoinContinuation(&cont);
+    //   ...
+    //   IfBuilder if_finally(this, &cont);
+    //   if_finally.Then();
+    //   // continues after then code of if_whatever or if_something.
+    //   ...
+    //   if_finally.Else();
+    //   // continues after else code of if_whatever or if_something.
+    //   ...
+    //   if_finally.End();
+    void JoinContinuation(HIfContinuation* continuation);
+
     void Then();
     void Else();
     void End();