Factor out OSR-related graph-building functionality from hydrogen.cc.
authortitzer@chromium.org <titzer@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 4 Jul 2013 09:20:07 +0000 (09:20 +0000)
committertitzer@chromium.org <titzer@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 4 Jul 2013 09:20:07 +0000 (09:20 +0000)
BUG=

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

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

src/hydrogen-osr.cc [new file with mode: 0644]
src/hydrogen-osr.h [new file with mode: 0644]
src/hydrogen.cc
src/hydrogen.h
tools/gyp/v8.gyp

diff --git a/src/hydrogen-osr.cc b/src/hydrogen-osr.cc
new file mode 100644 (file)
index 0000000..19a1c77
--- /dev/null
@@ -0,0 +1,123 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "hydrogen.h"
+#include "hydrogen-osr.h"
+
+namespace v8 {
+namespace internal {
+
+// True iff. we are compiling for OSR and the statement is the entry.
+bool HOsrBuilder::HasOsrEntryAt(IterationStatement* statement) {
+  return statement->OsrEntryId() == builder_->current_info()->osr_ast_id();
+}
+
+
+// Build a new loop header block and set it as the current block.
+HBasicBlock *HOsrBuilder::BuildLoopEntry() {
+  HBasicBlock* loop_entry = builder_->CreateLoopHeaderBlock();
+  builder_->current_block()->Goto(loop_entry);
+  builder_->set_current_block(loop_entry);
+  return loop_entry;
+}
+
+
+HBasicBlock* HOsrBuilder::BuildPossibleOsrLoopEntry(
+    IterationStatement* statement) {
+  // Check if there is an OSR here first.
+  if (!HasOsrEntryAt(statement)) return BuildLoopEntry();
+
+  Zone* zone = builder_->zone();
+  HGraph* graph = builder_->graph();
+
+  // only one OSR point per compile is allowed.
+  ASSERT(graph->osr() == NULL);
+
+  // remember this builder as the one OSR builder in the graph.
+  graph->set_osr(this);
+
+  HBasicBlock* non_osr_entry = graph->CreateBasicBlock();
+  osr_entry_ = graph->CreateBasicBlock();
+  HValue* true_value = graph->GetConstantTrue();
+  HBranch* test = new(zone) HBranch(true_value, non_osr_entry, osr_entry_);
+  builder_->current_block()->Finish(test);
+
+  HBasicBlock* loop_predecessor = graph->CreateBasicBlock();
+  non_osr_entry->Goto(loop_predecessor);
+
+  builder_->set_current_block(osr_entry_);
+  osr_entry_->set_osr_entry();
+  BailoutId osr_entry_id = statement->OsrEntryId();
+
+  HEnvironment *environment = builder_->environment();
+  int first_expression_index = environment->first_expression_index();
+  int length = environment->length();
+  osr_values_ = new(zone) ZoneList<HUnknownOSRValue*>(length, zone);
+
+  for (int i = 0; i < first_expression_index; ++i) {
+    HUnknownOSRValue* osr_value = builder_->Add<HUnknownOSRValue>();
+    environment->Bind(i, osr_value);
+    osr_values_->Add(osr_value, zone);
+  }
+
+  if (first_expression_index != length) {
+    environment->Drop(length - first_expression_index);
+    for (int i = first_expression_index; i < length; ++i) {
+      HUnknownOSRValue* osr_value = builder_->Add<HUnknownOSRValue>();
+      environment->Push(osr_value);
+      osr_values_->Add(osr_value, zone);
+    }
+  }
+
+  builder_->AddSimulate(osr_entry_id);
+  builder_->Add<HOsrEntry>(osr_entry_id);
+  HContext* context = builder_->Add<HContext>();
+  environment->BindContext(context);
+  builder_->current_block()->Goto(loop_predecessor);
+  loop_predecessor->SetJoinId(statement->EntryId());
+  builder_->set_current_block(loop_predecessor);
+
+  // Create the final loop entry
+  osr_loop_entry_ = BuildLoopEntry();
+  return osr_loop_entry_;
+}
+
+
+void HOsrBuilder::FinishGraph() {
+  // do nothing for now.
+}
+
+
+void HOsrBuilder::FinishOsrValues() {
+  const ZoneList<HPhi*>* phis = osr_loop_entry_->phis();
+  for (int j = 0; j < phis->length(); j++) {
+    HPhi* phi = phis->at(j);
+    osr_values_->at(phi->merged_index())->set_incoming_value(phi);
+  }
+}
+
+} }  // namespace v8::internal
diff --git a/src/hydrogen-osr.h b/src/hydrogen-osr.h
new file mode 100644 (file)
index 0000000..0c6b65d
--- /dev/null
@@ -0,0 +1,70 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_HYDROGEN_OSR_H_
+#define V8_HYDROGEN_OSR_H_
+
+#include "hydrogen.h"
+#include "ast.h"
+#include "zone.h"
+
+namespace v8 {
+namespace internal {
+
+// Responsible for building graph parts related to OSR and otherwise
+// setting up the graph to do an OSR compile.
+class HOsrBuilder : public ZoneObject {
+ public:
+  explicit HOsrBuilder(HOptimizedGraphBuilder* builder)
+    : builder_(builder),
+      osr_entry_(NULL),
+      osr_loop_entry_(NULL),
+      osr_values_(NULL) { }
+  // Creates the loop entry block for the given statement, setting up OSR
+  // entries as necessary, and sets the current block to the new block.
+  HBasicBlock* BuildPossibleOsrLoopEntry(IterationStatement* statement);
+
+  // Process the hydrogen graph after it has been completed, performing
+  // any OSR-specific cleanups or changes.
+  void FinishGraph();
+
+  // Process the OSR values and phis after initial graph optimization.
+  void FinishOsrValues();
+
+ private:
+  HBasicBlock* BuildLoopEntry();
+  bool HasOsrEntryAt(IterationStatement* statement);
+
+  HOptimizedGraphBuilder* builder_;
+  HBasicBlock* osr_entry_;
+  HBasicBlock* osr_loop_entry_;
+  ZoneList<HUnknownOSRValue*>* osr_values_;
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_HYDROGEN_OSR_H_
index 5c50ed0..c5f4818 100644 (file)
@@ -37,6 +37,7 @@
 #include "hydrogen-escape-analysis.h"
 #include "hydrogen-infer-representation.h"
 #include "hydrogen-gvn.h"
+#include "hydrogen-osr.h"
 #include "hydrogen-uint32-analysis.h"
 #include "lithium-allocator.h"
 #include "parser.h"
@@ -1915,7 +1916,8 @@ HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info)
       break_scope_(NULL),
       inlined_count_(0),
       globals_(10, info->zone()),
-      inline_bailout_(false) {
+      inline_bailout_(false),
+      osr_(new(info->zone()) HOsrBuilder(this)) {
   // This is not initialized in the initializer list because the
   // constructor for the initial state relies on function_state_ == NULL
   // to know it's the initial state.
@@ -1983,6 +1985,7 @@ HGraph::HGraph(CompilationInfo* info)
       values_(16, info->zone()),
       phi_list_(NULL),
       uint32_instructions_(NULL),
+      osr_(NULL),
       info_(info),
       zone_(info->zone()),
       is_recursive_(false),
@@ -3532,6 +3535,9 @@ bool HOptimizedGraphBuilder::BuildGraph() {
       !type_info->matches_inlined_type_change_checksum(composite_checksum));
   type_info->set_inlined_type_change_checksum(composite_checksum);
 
+  // Perform any necessary OSR-specific cleanups or changes to the graph.
+  osr_->FinishGraph();
+
   return true;
 }
 
@@ -3575,13 +3581,7 @@ bool HGraph::Optimize(SmartArrayPointer<char>* bailout_reason) {
   }
   CollectPhis();
 
-  if (has_osr_loop_entry()) {
-    const ZoneList<HPhi*>* phis = osr_loop_entry()->phis();
-    for (int j = 0; j < phis->length(); j++) {
-      HPhi* phi = phis->at(j);
-      osr_values()->at(phi->merged_index())->set_incoming_value(phi);
-    }
-  }
+  if (has_osr()) osr()->FinishOsrValues();
 
   Run<HInferRepresentationPhase>();
 
@@ -4689,59 +4689,6 @@ void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
 }
 
 
-bool HOptimizedGraphBuilder::HasOsrEntryAt(IterationStatement* statement) {
-  return statement->OsrEntryId() == current_info()->osr_ast_id();
-}
-
-
-bool HOptimizedGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) {
-  if (!HasOsrEntryAt(statement)) return false;
-
-  HBasicBlock* non_osr_entry = graph()->CreateBasicBlock();
-  HBasicBlock* osr_entry = graph()->CreateBasicBlock();
-  HValue* true_value = graph()->GetConstantTrue();
-  HBranch* test = new(zone()) HBranch(true_value, non_osr_entry, osr_entry);
-  current_block()->Finish(test);
-
-  HBasicBlock* loop_predecessor = graph()->CreateBasicBlock();
-  non_osr_entry->Goto(loop_predecessor);
-
-  set_current_block(osr_entry);
-  osr_entry->set_osr_entry();
-  BailoutId osr_entry_id = statement->OsrEntryId();
-  int first_expression_index = environment()->first_expression_index();
-  int length = environment()->length();
-  ZoneList<HUnknownOSRValue*>* osr_values =
-      new(zone()) ZoneList<HUnknownOSRValue*>(length, zone());
-
-  for (int i = 0; i < first_expression_index; ++i) {
-    HUnknownOSRValue* osr_value = Add<HUnknownOSRValue>();
-    environment()->Bind(i, osr_value);
-    osr_values->Add(osr_value, zone());
-  }
-
-  if (first_expression_index != length) {
-    environment()->Drop(length - first_expression_index);
-    for (int i = first_expression_index; i < length; ++i) {
-      HUnknownOSRValue* osr_value = Add<HUnknownOSRValue>();
-      environment()->Push(osr_value);
-      osr_values->Add(osr_value, zone());
-    }
-  }
-
-  graph()->set_osr_values(osr_values);
-
-  AddSimulate(osr_entry_id);
-  Add<HOsrEntry>(osr_entry_id);
-  HContext* context = Add<HContext>();
-  environment()->BindContext(context);
-  current_block()->Goto(loop_predecessor);
-  loop_predecessor->SetJoinId(statement->EntryId());
-  set_current_block(loop_predecessor);
-  return true;
-}
-
-
 void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt,
                                            HBasicBlock* loop_entry,
                                            BreakAndContinueInfo* break_info) {
@@ -4761,11 +4708,7 @@ void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
   ASSERT(current_block() != NULL);
   ASSERT(current_block()->HasPredecessor());
   ASSERT(current_block() != NULL);
-  bool osr_entry = PreProcessOsrEntry(stmt);
-  HBasicBlock* loop_entry = CreateLoopHeaderBlock();
-  current_block()->Goto(loop_entry);
-  set_current_block(loop_entry);
-  if (osr_entry) graph()->set_osr_loop_entry(loop_entry);
+  HBasicBlock* loop_entry = osr_->BuildPossibleOsrLoopEntry(stmt);
 
   BreakAndContinueInfo break_info(stmt);
   CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info));
@@ -4804,12 +4747,7 @@ void HOptimizedGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
   ASSERT(current_block() != NULL);
   ASSERT(current_block()->HasPredecessor());
   ASSERT(current_block() != NULL);
-  bool osr_entry = PreProcessOsrEntry(stmt);
-  HBasicBlock* loop_entry = CreateLoopHeaderBlock();
-  current_block()->Goto(loop_entry);
-  set_current_block(loop_entry);
-  if (osr_entry) graph()->set_osr_loop_entry(loop_entry);
-
+  HBasicBlock* loop_entry = osr_->BuildPossibleOsrLoopEntry(stmt);
 
   // If the condition is constant true, do not generate a branch.
   HBasicBlock* loop_successor = NULL;
@@ -4851,11 +4789,7 @@ void HOptimizedGraphBuilder::VisitForStatement(ForStatement* stmt) {
     CHECK_ALIVE(Visit(stmt->init()));
   }
   ASSERT(current_block() != NULL);
-  bool osr_entry = PreProcessOsrEntry(stmt);
-  HBasicBlock* loop_entry = CreateLoopHeaderBlock();
-  current_block()->Goto(loop_entry);
-  set_current_block(loop_entry);
-  if (osr_entry) graph()->set_osr_loop_entry(loop_entry);
+  HBasicBlock* loop_entry = osr_->BuildPossibleOsrLoopEntry(stmt);
 
   HBasicBlock* loop_successor = NULL;
   if (stmt->cond() != NULL) {
@@ -4939,11 +4873,7 @@ void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
   HForInCacheArray::cast(array)->set_index_cache(
       HForInCacheArray::cast(index_cache));
 
-  bool osr_entry = PreProcessOsrEntry(stmt);
-  HBasicBlock* loop_entry = CreateLoopHeaderBlock();
-  current_block()->Goto(loop_entry);
-  set_current_block(loop_entry);
-  if (osr_entry) graph()->set_osr_loop_entry(loop_entry);
+  HBasicBlock* loop_entry = osr_->BuildPossibleOsrLoopEntry(stmt);
 
   HValue* index = environment()->ExpressionStackAt(0);
   HValue* limit = environment()->ExpressionStackAt(1);
index 3a8d242..f80aca1 100644 (file)
@@ -46,6 +46,7 @@ class FunctionState;
 class HEnvironment;
 class HGraph;
 class HLoopInformation;
+class HOsrBuilder;
 class HTracer;
 class LAllocator;
 class LChunk;
@@ -358,24 +359,16 @@ class HGraph: public ZoneObject {
   void Verify(bool do_full_verify) const;
 #endif
 
-  bool has_osr_loop_entry() {
-    return osr_loop_entry_.is_set();
+  bool has_osr() {
+    return osr_ != NULL;
   }
 
-  HBasicBlock* osr_loop_entry() {
-    return osr_loop_entry_.get();
+  void set_osr(HOsrBuilder* osr) {
+    osr_ = osr;
   }
 
-  void set_osr_loop_entry(HBasicBlock* entry) {
-    osr_loop_entry_.set(entry);
-  }
-
-  ZoneList<HUnknownOSRValue*>* osr_values() {
-    return osr_values_.get();
-  }
-
-  void set_osr_values(ZoneList<HUnknownOSRValue*>* values) {
-    osr_values_.set(values);
+  HOsrBuilder* osr() {
+    return osr_;
   }
 
   int update_type_change_checksum(int delta) {
@@ -495,8 +488,7 @@ class HGraph: public ZoneObject {
   SetOncePointer<HConstant> constant_invalid_context_;
   SetOncePointer<HArgumentsObject> arguments_object_;
 
-  SetOncePointer<HBasicBlock> osr_loop_entry_;
-  SetOncePointer<ZoneList<HUnknownOSRValue*> > osr_values_;
+  HOsrBuilder* osr_;
 
   CompilationInfo* info_;
   Zone* zone_;
@@ -1438,7 +1430,6 @@ class HGraphBuilder {
   int no_side_effects_scope_count_;
 };
 
-
 class HOptimizedGraphBuilder: public HGraphBuilder, public AstVisitor {
  public:
   // A class encapsulating (lazily-allocated) break and continue blocks for
@@ -1596,8 +1587,6 @@ class HOptimizedGraphBuilder: public HGraphBuilder, public AstVisitor {
   void VisitArithmeticExpression(BinaryOperation* expr);
 
   bool PreProcessOsrEntry(IterationStatement* statement);
-  // True iff. we are compiling for OSR and the statement is the entry.
-  bool HasOsrEntryAt(IterationStatement* statement);
   void VisitLoopBody(IterationStatement* stmt,
                      HBasicBlock* loop_entry,
                      BreakAndContinueInfo* break_info);
@@ -1959,9 +1948,12 @@ class HOptimizedGraphBuilder: public HGraphBuilder, public AstVisitor {
 
   bool inline_bailout_;
 
+  HOsrBuilder* osr_;
+
   friend class FunctionState;  // Pushes and pops the state stack.
   friend class AstContext;  // Pushes and pops the AST context stack.
   friend class KeyedLoadFastElementStub;
+  friend class HOsrBuilder;
 
   DISALLOW_COPY_AND_ASSIGN(HOptimizedGraphBuilder);
 };
index 8378bc8..ab8f197 100644 (file)
         '../../src/hydrogen-infer-representation.h',
         '../../src/hydrogen-uint32-analysis.cc',
         '../../src/hydrogen-uint32-analysis.h',
+        '../../src/hydrogen-osr.cc',
+        '../../src/hydrogen-osr.h',
         '../../src/ic-inl.h',
         '../../src/ic.cc',
         '../../src/ic.h',