From 6fce49609b0a678fb37aedee4dea9b2e48a57264 Mon Sep 17 00:00:00 2001 From: "bmeurer@chromium.org" Date: Fri, 20 Sep 2013 10:47:09 +0000 Subject: [PATCH] Allow IfBuilder's to join existing (captured) continuations. 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 | 22 ++++++++++++++++++++ src/hydrogen.h | 53 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/src/hydrogen.cc b/src/hydrogen.cc index cf42530cd7..caa595bfeb 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -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_); diff --git a/src/hydrogen.h b/src/hydrogen.h index d0e47aab71..a371fa571b 100644 --- a/src/hydrogen.h +++ b/src/hydrogen.h @@ -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(arg); + // if_whatever.Then(); + // ... + // if_whatever.Else(); + // ... + // if_whatever.JoinContinuation(&cont); + // ... + // IfBuilder if_something(this); + // if_something.If(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();