Add copy support in inliner.

Refactors JSGraph to ensure that the zone operators are created in
can be different from the Graph's zone.

R=mstarzinger@chromium.org

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23804 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
sigurds@chromium.org 2014-09-09 13:20:09 +00:00
parent 01d63e43b2
commit 1f9215ba8d
14 changed files with 151 additions and 57 deletions

View File

@ -74,10 +74,12 @@ class ChangeLoweringTest : public GraphTest {
Reduction Reduce(Node* node) {
Typer typer(zone());
JSGraph jsgraph(graph(), common(), &typer);
MachineOperatorBuilder machine(zone(), WordRepresentation());
JSOperatorBuilder javascript(zone());
JSGraph jsgraph(graph(), common(), &javascript, &typer, &machine);
CompilationInfo info(isolate(), zone());
Linkage linkage(&info);
MachineOperatorBuilder machine(zone(), WordRepresentation());
ChangeLowering reducer(&jsgraph, &linkage, &machine);
return reducer.Reduce(node);
}

View File

@ -22,7 +22,6 @@ class GenericGraphBase : public ZoneObject {
NodeId NextNodeID() { return next_node_id_++; }
NodeId NodeCount() const { return next_node_id_; }
void SetNextNodeId(NodeId next) { next_node_id_ = next; }
private:
Zone* zone_;

View File

@ -9,6 +9,7 @@
#include "src/compiler/common-operator.h"
#include "src/compiler/graph.h"
#include "src/compiler/js-operator.h"
#include "src/compiler/machine-operator.h"
#include "src/compiler/node-properties.h"
namespace v8 {
@ -22,11 +23,14 @@ class Typer;
// constants, and various helper methods.
class JSGraph : public ZoneObject {
public:
JSGraph(Graph* graph, CommonOperatorBuilder* common, Typer* typer)
JSGraph(Graph* graph, CommonOperatorBuilder* common,
JSOperatorBuilder* javascript, Typer* typer,
MachineOperatorBuilder* machine)
: graph_(graph),
common_(common),
javascript_(zone()),
javascript_(javascript),
typer_(typer),
machine_(machine),
cache_(zone()) {}
// Canonicalized global constants.
@ -73,8 +77,9 @@ class JSGraph : public ZoneObject {
return Constant(immediate);
}
JSOperatorBuilder* javascript() { return &javascript_; }
JSOperatorBuilder* javascript() { return javascript_; }
CommonOperatorBuilder* common() { return common_; }
MachineOperatorBuilder* machine() { return machine_; }
Graph* graph() { return graph_; }
Zone* zone() { return graph()->zone(); }
Isolate* isolate() { return zone()->isolate(); }
@ -82,8 +87,9 @@ class JSGraph : public ZoneObject {
private:
Graph* graph_;
CommonOperatorBuilder* common_;
JSOperatorBuilder javascript_;
JSOperatorBuilder* javascript_;
Typer* typer_;
MachineOperatorBuilder* machine_;
SetOncePointer<Node> c_entry_stub_constant_;
SetOncePointer<Node> undefined_constant_;

View File

@ -67,14 +67,9 @@ static void Parse(Handle<JSFunction> function, CompilationInfoWithZone* info) {
// A facade on a JSFunction's graph to facilitate inlining. It assumes the
// that the function graph has only one return statement, and provides
// {UnifyReturn} to convert a function graph to that end.
// InlineAtCall will create some new nodes using {graph}'s builders (and hence
// those nodes will live in {graph}'s zone.
class Inlinee {
public:
explicit Inlinee(JSGraph* graph) : jsgraph_(graph) {}
Graph* graph() { return jsgraph_->graph(); }
JSGraph* jsgraph() { return jsgraph_; }
Inlinee(Node* start, Node* end) : start_(start), end_(end) {}
// Returns the last regular control node, that is
// the last control node before the end node.
@ -92,24 +87,25 @@ class Inlinee {
}
// Return the unique return statement of the graph.
Node* unique_return() {
Node* unique_return =
NodeProperties::GetControlInput(jsgraph_->graph()->end());
Node* unique_return = NodeProperties::GetControlInput(end_);
DCHECK_EQ(IrOpcode::kReturn, unique_return->opcode());
return unique_return;
}
// Inline this graph at {call}, use {jsgraph} and its zone to create
// any new nodes.
void InlineAtCall(JSGraph* jsgraph, Node* call);
// Ensure that only a single return reaches the end node.
void UnifyReturn();
static void UnifyReturn(JSGraph* jsgraph);
private:
JSGraph* jsgraph_;
Node* start_;
Node* end_;
};
void Inlinee::UnifyReturn() {
Graph* graph = jsgraph_->graph();
void Inlinee::UnifyReturn(JSGraph* jsgraph) {
Graph* graph = jsgraph->graph();
Node* final_merge = NodeProperties::GetControlInput(graph->end(), 0);
if (final_merge->opcode() == IrOpcode::kReturn) {
@ -120,11 +116,11 @@ void Inlinee::UnifyReturn() {
int predecessors =
OperatorProperties::GetControlInputCount(final_merge->op());
Operator* op_phi = jsgraph_->common()->Phi(kMachAnyTagged, predecessors);
Operator* op_ephi = jsgraph_->common()->EffectPhi(predecessors);
Operator* op_phi = jsgraph->common()->Phi(kMachAnyTagged, predecessors);
Operator* op_ephi = jsgraph->common()->EffectPhi(predecessors);
NodeVector values(jsgraph_->zone());
NodeVector effects(jsgraph_->zone());
NodeVector values(jsgraph->zone());
NodeVector effects(jsgraph->zone());
// Iterate over all control flow predecessors,
// which must be return statements.
InputIter iter = final_merge->inputs().begin();
@ -150,14 +146,81 @@ void Inlinee::UnifyReturn() {
Node* ephi = graph->NewNode(op_ephi, static_cast<int>(effects.size()),
&effects.front());
Node* new_return =
graph->NewNode(jsgraph_->common()->Return(), phi, ephi, final_merge);
graph->NewNode(jsgraph->common()->Return(), phi, ephi, final_merge);
graph->end()->ReplaceInput(0, new_return);
}
void Inlinee::InlineAtCall(JSGraph* jsgraph, Node* call) {
MachineOperatorBuilder machine(jsgraph->zone());
class CopyVisitor : public NullNodeVisitor {
public:
CopyVisitor(Graph* source_graph, Graph* target_graph, Zone* temp_zone)
: copies_(source_graph->NodeCount(), NULL, temp_zone),
sentinels_(source_graph->NodeCount(), NULL, temp_zone),
source_graph_(source_graph),
target_graph_(target_graph),
temp_zone_(temp_zone),
sentinel_op_(IrOpcode::kDead, Operator::kNoProperties, 0, 0,
"sentinel") {}
GenericGraphVisit::Control Post(Node* original) {
NodeVector inputs(temp_zone_);
for (InputIter it = original->inputs().begin();
it != original->inputs().end(); ++it) {
inputs.push_back(GetCopy(*it));
}
// Reuse the operator in the copy. This assumes that op lives in a zone
// that lives longer than graph()'s zone.
Node* copy =
target_graph_->NewNode(original->op(), inputs.size(), &inputs.front());
copies_[original->id()] = copy;
return GenericGraphVisit::CONTINUE;
}
Node* GetCopy(Node* original) {
Node* copy = copies_[original->id()];
if (copy == NULL) {
copy = GetSentinel(original);
}
return copy;
}
void CopyGraph() {
source_graph_->VisitNodeInputsFromEnd(this);
ReplaceSentinels();
}
const NodeVector& copies() { return copies_; }
private:
void ReplaceSentinels() {
for (int id = 0; id < source_graph_->NodeCount(); ++id) {
Node* sentinel = sentinels_[id];
if (sentinel == NULL) continue;
Node* copy = copies_[id];
DCHECK_NE(NULL, copy);
sentinel->ReplaceUses(copy);
}
}
Node* GetSentinel(Node* original) {
Node* sentinel = sentinels_[original->id()];
if (sentinel == NULL) {
sentinel = target_graph_->NewNode(&sentinel_op_);
}
return sentinel;
}
NodeVector copies_;
NodeVector sentinels_;
Graph* source_graph_;
Graph* target_graph_;
Zone* temp_zone_;
SimpleOperator sentinel_op_;
};
void Inlinee::InlineAtCall(JSGraph* jsgraph, Node* call) {
// The scheduler is smart enough to place our code; we just ensure {control}
// becomes the control input of the start of the inlinee.
Node* control = NodeProperties::GetControlInput(call);
@ -166,21 +229,22 @@ void Inlinee::InlineAtCall(JSGraph* jsgraph, Node* call) {
// also be the effect dependency for the inlinee as it produces an effect.
// TODO(sigurds) Use simplified load once it is ready.
Node* context = jsgraph->graph()->NewNode(
machine.Load(kMachAnyTagged), NodeProperties::GetValueInput(call, 0),
jsgraph->machine()->Load(kMachAnyTagged),
NodeProperties::GetValueInput(call, 0),
jsgraph->Int32Constant(JSFunction::kContextOffset - kHeapObjectTag),
NodeProperties::GetEffectInput(call));
// {inlinee_inputs} counts JSFunction, Receiver, arguments, context,
// but not effect, control.
int inlinee_inputs = graph()->start()->op()->OutputCount();
int inlinee_inputs = start_->op()->OutputCount();
// Context is last argument.
int inlinee_context_index = inlinee_inputs - 1;
// {inliner_inputs} counts JSFunction, Receiver, arguments, but not
// context, effect, control.
int inliner_inputs = OperatorProperties::GetValueInputCount(call->op());
// Iterate over all uses of the start node.
UseIter iter = graph()->start()->uses().begin();
while (iter != graph()->start()->uses().end()) {
UseIter iter = start_->uses().begin();
while (iter != start_->uses().end()) {
Node* use = *iter;
switch (use->opcode()) {
case IrOpcode::kParameter: {
@ -234,10 +298,10 @@ void Inlinee::InlineAtCall(JSGraph* jsgraph, Node* call) {
}
void JSInliner::TryInlineCall(Node* node) {
DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode());
void JSInliner::TryInlineCall(Node* call) {
DCHECK_EQ(IrOpcode::kJSCallFunction, call->opcode());
HeapObjectMatcher<JSFunction> match(node->InputAt(0));
HeapObjectMatcher<JSFunction> match(call->InputAt(0));
if (!match.HasValue()) {
return;
}
@ -275,21 +339,20 @@ void JSInliner::TryInlineCall(Node* node) {
info_->shared_info()->DebugName()->ToCString().get());
}
Graph graph(info_->zone());
graph.SetNextNodeId(jsgraph_->graph()->NextNodeID());
Typer typer(info_->zone());
CommonOperatorBuilder common(info_->zone());
JSGraph jsgraph(&graph, &common, &typer);
Graph graph(info.zone());
Typer typer(info.zone());
JSGraph jsgraph(&graph, jsgraph_->common(), jsgraph_->javascript(), &typer,
jsgraph_->machine());
AstGraphBuilder graph_builder(&info, &jsgraph);
graph_builder.CreateGraph();
Inlinee::UnifyReturn(&jsgraph);
Inlinee inlinee(&jsgraph);
inlinee.UnifyReturn();
inlinee.InlineAtCall(jsgraph_, node);
CopyVisitor visitor(&graph, jsgraph_->graph(), info.zone());
visitor.CopyGraph();
jsgraph_->graph()->SetNextNodeId(inlinee.graph()->NextNodeID());
Inlinee inlinee(visitor.GetCopy(graph.start()), visitor.GetCopy(graph.end()));
inlinee.InlineAtCall(jsgraph_, call);
}
}
}

View File

@ -20,7 +20,8 @@ class MachineOperatorReducerTest : public GraphTest {
protected:
Reduction Reduce(Node* node) {
Typer typer(zone());
JSGraph jsgraph(graph(), common(), &typer);
JSOperatorBuilder javascript(zone());
JSGraph jsgraph(graph(), common(), &javascript, &typer, &machine_);
MachineOperatorReducer reducer(&jsgraph);
return reducer.Reduce(node);
}

View File

@ -170,7 +170,9 @@ Handle<Code> Pipeline::GenerateCode() {
// typer could sweep over later.
Typer typer(zone());
CommonOperatorBuilder common(zone());
JSGraph jsgraph(&graph, &common, &typer);
JSOperatorBuilder javascript(zone());
MachineOperatorBuilder machine(zone());
JSGraph jsgraph(&graph, &common, &javascript, &typer, &machine);
Node* context_node;
{
PhaseStats graph_builder_stats(info(), PhaseStats::CREATE_GRAPH,
@ -256,7 +258,6 @@ Handle<Code> Pipeline::GenerateCode() {
SourcePositionTable::Scope pos(&source_positions,
SourcePosition::Unknown());
Linkage linkage(info());
MachineOperatorBuilder machine(zone());
ValueNumberingReducer vn_reducer(zone());
SimplifiedOperatorReducer simple_reducer(&jsgraph, &machine);
ChangeLowering lowering(&jsgraph, &linkage, &machine);
@ -281,7 +282,6 @@ Handle<Code> Pipeline::GenerateCode() {
"generic lowering");
SourcePositionTable::Scope pos(&source_positions,
SourcePosition::Unknown());
MachineOperatorBuilder machine(zone());
JSGenericLowering lowering(info(), &jsgraph, &machine);
GraphReducer graph_reducer(&graph);
graph_reducer.AddReducer(&lowering);

View File

@ -23,7 +23,8 @@ class SimplifiedOperatorReducerTest : public GraphTest {
Reduction Reduce(Node* node) {
Typer typer(zone());
MachineOperatorBuilder machine(zone());
JSGraph jsgraph(graph(), common(), &typer);
JSOperatorBuilder javascript(zone());
JSGraph jsgraph(graph(), common(), &javascript, &typer, &machine);
SimplifiedOperatorReducer reducer(&jsgraph, &machine);
return reducer.Reduce(node);
}

View File

@ -31,10 +31,13 @@ class ChangesLoweringTester : public GraphBuilderTester<ReturnType> {
explicit ChangesLoweringTester(MachineType p0 = kMachNone)
: GraphBuilderTester<ReturnType>(p0),
typer(this->zone()),
jsgraph(this->graph(), this->common(), &typer),
javascript(this->zone()),
jsgraph(this->graph(), this->common(), &javascript, &typer,
this->machine()),
function(Handle<JSFunction>::null()) {}
Typer typer;
JSOperatorBuilder javascript;
JSGraph jsgraph;
Handle<JSFunction> function;

View File

@ -17,10 +17,16 @@ using namespace v8::internal::compiler;
class JSCacheTesterHelper {
protected:
explicit JSCacheTesterHelper(Zone* zone)
: main_graph_(zone), main_common_(zone), main_typer_(zone) {}
: main_graph_(zone),
main_common_(zone),
main_javascript_(zone),
main_typer_(zone),
main_machine_(zone) {}
Graph main_graph_;
CommonOperatorBuilder main_common_;
JSOperatorBuilder main_javascript_;
Typer main_typer_;
MachineOperatorBuilder main_machine_;
};
@ -30,7 +36,8 @@ class JSConstantCacheTester : public HandleAndZoneScope,
public:
JSConstantCacheTester()
: JSCacheTesterHelper(main_zone()),
JSGraph(&main_graph_, &main_common_, &main_typer_) {}
JSGraph(&main_graph_, &main_common_, &main_javascript_, &main_typer_,
&main_machine_) {}
Type* upper(Node* node) { return NodeProperties::GetBounds(node).upper; }

View File

@ -22,9 +22,10 @@ class ContextSpecializationTester : public HandleAndZoneScope,
: DirectGraphBuilder(new (main_zone()) Graph(main_zone())),
common_(main_zone()),
javascript_(main_zone()),
machine_(main_zone()),
simplified_(main_zone()),
typer_(main_zone()),
jsgraph_(graph(), common(), &typer_),
jsgraph_(graph(), common(), &javascript_, &typer_, &machine_),
info_(main_isolate(), main_zone()) {}
Factory* factory() { return main_isolate()->factory(); }
@ -37,6 +38,7 @@ class ContextSpecializationTester : public HandleAndZoneScope,
private:
CommonOperatorBuilder common_;
JSOperatorBuilder javascript_;
MachineOperatorBuilder machine_;
SimplifiedOperatorBuilder simplified_;
Typer typer_;
JSGraph jsgraph_;

View File

@ -50,7 +50,7 @@ class JSTypedLoweringTester : public HandleAndZoneScope {
}
Node* reduce(Node* node) {
JSGraph jsgraph(&graph, &common, &typer);
JSGraph jsgraph(&graph, &common, &javascript, &typer, &machine);
JSTypedLowering reducer(&jsgraph);
Reduction reduction = reducer.Reduce(node);
if (reduction.Changed()) return reduction.replacement();

View File

@ -55,8 +55,9 @@ class ReducerTester : public HandleAndZoneScope {
machine(main_zone()),
common(main_zone()),
graph(main_zone()),
javascript(main_zone()),
typer(main_zone()),
jsgraph(&graph, &common, &typer),
jsgraph(&graph, &common, &javascript, &typer, &machine),
maxuint32(Constant<int32_t>(kMaxUInt32)) {
Node* s = graph.NewNode(common.Start(num_parameters));
graph.SetStart(s);
@ -68,6 +69,7 @@ class ReducerTester : public HandleAndZoneScope {
MachineOperatorBuilder machine;
CommonOperatorBuilder common;
Graph graph;
JSOperatorBuilder javascript;
Typer typer;
JSGraph jsgraph;
Node* maxuint32;

View File

@ -25,13 +25,16 @@ class RepresentationChangerTester : public HandleAndZoneScope,
explicit RepresentationChangerTester(int num_parameters = 0)
: GraphAndBuilders(main_zone()),
typer_(main_zone()),
jsgraph_(main_graph_, &main_common_, &typer_),
javascript_(main_zone()),
jsgraph_(main_graph_, &main_common_, &javascript_, &typer_,
&main_machine_),
changer_(&jsgraph_, &main_simplified_, &main_machine_, main_isolate()) {
Node* s = graph()->NewNode(common()->Start(num_parameters));
graph()->SetStart(s);
}
Typer typer_;
JSOperatorBuilder javascript_;
JSGraph jsgraph_;
RepresentationChanger changer_;

View File

@ -36,10 +36,13 @@ class SimplifiedLoweringTester : public GraphBuilderTester<ReturnType> {
MachineType p4 = kMachNone)
: GraphBuilderTester<ReturnType>(p0, p1, p2, p3, p4),
typer(this->zone()),
jsgraph(this->graph(), this->common(), &typer),
javascript(this->zone()),
jsgraph(this->graph(), this->common(), &javascript, &typer,
this->machine()),
lowering(&jsgraph) {}
Typer typer;
JSOperatorBuilder javascript;
JSGraph jsgraph;
SimplifiedLowering lowering;
@ -626,6 +629,7 @@ TEST(RunAccessTests_Smi) {
class TestingGraph : public HandleAndZoneScope, public GraphAndBuilders {
public:
Typer typer;
JSOperatorBuilder javascript;
JSGraph jsgraph;
Node* p0;
Node* p1;
@ -636,7 +640,8 @@ class TestingGraph : public HandleAndZoneScope, public GraphAndBuilders {
explicit TestingGraph(Type* p0_type, Type* p1_type = Type::None())
: GraphAndBuilders(main_zone()),
typer(main_zone()),
jsgraph(graph(), common(), &typer) {
javascript(main_zone()),
jsgraph(graph(), common(), &javascript, &typer, machine()) {
start = graph()->NewNode(common()->Start(2));
graph()->SetStart(start);
ret =