Reduction Reduce(Node* node) {
Typer typer(zone());
- JSGraph jsgraph(graph(), common(), &typer);
+ MachineOperatorBuilder machine(WordRepresentation());
+ JSOperatorBuilder javascript(zone());
+ JSGraph jsgraph(graph(), common(), &javascript, &typer, &machine);
CompilationInfo info(isolate(), zone());
Linkage linkage(&info);
- MachineOperatorBuilder machine(WordRepresentation());
ChangeLowering reducer(&jsgraph, &linkage, &machine);
return reducer.Reduce(node);
}
NodeId NextNodeID() { return next_node_id_++; }
NodeId NodeCount() const { return next_node_id_; }
- void SetNextNodeId(NodeId next) { next_node_id_ = next; }
private:
Zone* zone_;
#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 {
// 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.
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(); }
private:
Graph* graph_;
CommonOperatorBuilder* common_;
- JSOperatorBuilder javascript_;
+ JSOperatorBuilder* javascript_;
Typer* typer_;
+ MachineOperatorBuilder* machine_;
SetOncePointer<Node> c_entry_stub_constant_;
SetOncePointer<Node> undefined_constant_;
// 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.
}
// 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) {
int predecessors =
OperatorProperties::GetControlInputCount(final_merge->op());
- const Operator* op_phi =
- jsgraph_->common()->Phi(kMachAnyTagged, predecessors);
- const Operator* op_ephi = jsgraph_->common()->EffectPhi(predecessors);
- NodeVector values(jsgraph_->zone());
- NodeVector effects(jsgraph_->zone());
+ const Operator* op_phi = jsgraph->common()->Phi(kMachAnyTagged, predecessors);
+ const Operator* op_ephi = jsgraph->common()->EffectPhi(predecessors);
+
+ 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();
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);
}
+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(), static_cast<int>(inputs.size()),
+ (inputs.empty() ? NULL : &inputs.front()));
+ copies_[original->id()] = copy;
+ return GenericGraphVisit::CONTINUE;
+ }
+
+ Node* GetCopy(Node* original) {
+ Node* copy = copies_[original->id()];
+ if (copy == NULL) {
+ copy = GetSentinel(original);
+ }
+ DCHECK_NE(NULL, copy);
+ 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.
// {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: {
}
-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;
}
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);
}
}
}
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);
}
Typer typer(zone());
MachineOperatorBuilder machine;
CommonOperatorBuilder common(zone());
- JSGraph jsgraph(&graph, &common, &typer);
+ JSOperatorBuilder javascript(zone());
+ JSGraph jsgraph(&graph, &common, &javascript, &typer, &machine);
Node* context_node;
{
PhaseStats graph_builder_stats(info(), PhaseStats::CREATE_GRAPH,
Reduction Reduce(Node* node) {
Typer typer(zone());
MachineOperatorBuilder machine;
- JSGraph jsgraph(graph(), common(), &typer);
+ JSOperatorBuilder javascript(zone());
+ JSGraph jsgraph(graph(), common(), &javascript, &typer, &machine);
SimplifiedOperatorReducer reducer(&jsgraph, &machine);
return reducer.Reduce(node);
}
DEFINE_BOOL(turbo_deoptimization, false, "enable deoptimization in TurboFan")
DEFINE_BOOL(turbo_inlining, false, "enable inlining in TurboFan")
DEFINE_BOOL(trace_turbo_inlining, false, "trace TurboFan inlining")
+DEFINE_IMPLICATION(turbo_inlining, turbo_types)
DEFINE_INT(typed_array_max_size_in_heap, 64,
"threshold for in-heap typed array")
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;
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_() {}
Graph main_graph_;
CommonOperatorBuilder main_common_;
+ JSOperatorBuilder main_javascript_;
Typer main_typer_;
+ MachineOperatorBuilder main_machine_;
};
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; }
: DirectGraphBuilder(new (main_zone()) Graph(main_zone())),
common_(main_zone()),
javascript_(main_zone()),
+ machine_(),
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(); }
private:
CommonOperatorBuilder common_;
JSOperatorBuilder javascript_;
+ MachineOperatorBuilder machine_;
SimplifiedOperatorBuilder simplified_;
Typer typer_;
JSGraph jsgraph_;
}
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();
unop(NULL),
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);
MachineOperatorBuilder machine;
CommonOperatorBuilder common;
Graph graph;
+ JSOperatorBuilder javascript;
Typer typer;
JSGraph jsgraph;
Node* maxuint32;
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_;
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;
class TestingGraph : public HandleAndZoneScope, public GraphAndBuilders {
public:
Typer typer;
+ JSOperatorBuilder javascript;
JSGraph jsgraph;
Node* p0;
Node* p1;
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 =