Factor out OSR-related graph-building functionality from hydrogen.cc.

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
This commit is contained in:
titzer@chromium.org 2013-07-04 09:20:07 +00:00
parent fea5ebe90f
commit bddf08b0b1
5 changed files with 218 additions and 101 deletions

123
src/hydrogen-osr.cc Normal file
View File

@ -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

70
src/hydrogen-osr.h Normal file
View File

@ -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_

View 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);

View 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);
};

View File

@ -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',