diff --git a/src/hydrogen-osr.cc b/src/hydrogen-osr.cc new file mode 100644 index 0000000000..19a1c77442 --- /dev/null +++ b/src/hydrogen-osr.cc @@ -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(length, zone); + + for (int i = 0; i < first_expression_index; ++i) { + HUnknownOSRValue* osr_value = builder_->Add(); + 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(); + environment->Push(osr_value); + osr_values_->Add(osr_value, zone); + } + } + + builder_->AddSimulate(osr_entry_id); + builder_->Add(osr_entry_id); + HContext* context = builder_->Add(); + 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* 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 index 0000000000..0c6b65d0d4 --- /dev/null +++ b/src/hydrogen-osr.h @@ -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* osr_values_; +}; + +} } // namespace v8::internal + +#endif // V8_HYDROGEN_OSR_H_ diff --git a/src/hydrogen.cc b/src/hydrogen.cc index 5c50ed0437..c5f48189d3 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -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* bailout_reason) { } CollectPhis(); - if (has_osr_loop_entry()) { - const ZoneList* 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(); @@ -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* osr_values = - new(zone()) ZoneList(length, zone()); - - for (int i = 0; i < first_expression_index; ++i) { - HUnknownOSRValue* osr_value = Add(); - 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(); - environment()->Push(osr_value); - osr_values->Add(osr_value, zone()); - } - } - - graph()->set_osr_values(osr_values); - - AddSimulate(osr_entry_id); - Add(osr_entry_id); - HContext* context = Add(); - 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); diff --git a/src/hydrogen.h b/src/hydrogen.h index 3a8d242b8c..f80aca1e3c 100644 --- a/src/hydrogen.h +++ b/src/hydrogen.h @@ -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* osr_values() { - return osr_values_.get(); - } - - void set_osr_values(ZoneList* 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 constant_invalid_context_; SetOncePointer arguments_object_; - SetOncePointer osr_loop_entry_; - SetOncePointer > 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); }; diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp index 8378bc8bba..ab8f19726c 100644 --- a/tools/gyp/v8.gyp +++ b/tools/gyp/v8.gyp @@ -349,6 +349,8 @@ '../../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',