[turbofan] Finally get rid of the generic algorithm.
R=svenpanne@chromium.org Review URL: https://codereview.chromium.org/944803002 Cr-Commit-Position: refs/heads/master@{#26760}
This commit is contained in:
parent
b9f006a404
commit
5bbe693e48
2
BUILD.gn
2
BUILD.gn
@ -535,9 +535,7 @@ source_set("v8_base") {
|
||||
"src/compiler/frame.h",
|
||||
"src/compiler/gap-resolver.cc",
|
||||
"src/compiler/gap-resolver.h",
|
||||
"src/compiler/generic-algorithm.h",
|
||||
"src/compiler/graph-builder.h",
|
||||
"src/compiler/graph-inl.h",
|
||||
"src/compiler/graph-reducer.cc",
|
||||
"src/compiler/graph-reducer.h",
|
||||
"src/compiler/graph-replay.cc",
|
||||
|
@ -1,120 +0,0 @@
|
||||
// Copyright 2013 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_COMPILER_GENERIC_ALGORITHM_H_
|
||||
#define V8_COMPILER_GENERIC_ALGORITHM_H_
|
||||
|
||||
#include <stack>
|
||||
#include <vector>
|
||||
|
||||
#include "src/compiler/graph.h"
|
||||
#include "src/compiler/node.h"
|
||||
#include "src/zone-containers.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
namespace compiler {
|
||||
|
||||
class Graph;
|
||||
class Node;
|
||||
|
||||
// GenericGraphVisit allows visitation of graphs of nodes and edges in pre- and
|
||||
// post-order. Visitation uses an explicitly allocated stack rather than the
|
||||
// execution stack to avoid stack overflow.
|
||||
class GenericGraphVisit {
|
||||
public:
|
||||
// struct Visitor {
|
||||
// void Pre(Node* current);
|
||||
// void Post(Node* current);
|
||||
// void PreEdge(Node* from, int index, Node* to);
|
||||
// void PostEdge(Node* from, int index, Node* to);
|
||||
// }
|
||||
template <class Visitor>
|
||||
static void Visit(Graph* graph, Zone* zone, Node** root_begin,
|
||||
Node** root_end, Visitor* visitor) {
|
||||
typedef typename Node::InputEdges::iterator Iterator;
|
||||
typedef std::pair<Iterator, Iterator> NodeState;
|
||||
typedef std::stack<NodeState, ZoneDeque<NodeState> > NodeStateStack;
|
||||
NodeStateStack stack((ZoneDeque<NodeState>(zone)));
|
||||
BoolVector visited(graph->NodeCount(), false, zone);
|
||||
Node* current = *root_begin;
|
||||
while (true) {
|
||||
DCHECK(current != NULL);
|
||||
const int id = current->id();
|
||||
DCHECK(id >= 0);
|
||||
DCHECK(id < graph->NodeCount()); // Must be a valid id.
|
||||
bool visit = !GetVisited(&visited, id);
|
||||
if (visit) {
|
||||
visitor->Pre(current);
|
||||
SetVisited(&visited, id);
|
||||
}
|
||||
Iterator begin(visit ? current->input_edges().begin()
|
||||
: current->input_edges().end());
|
||||
Iterator end(current->input_edges().end());
|
||||
stack.push(NodeState(begin, end));
|
||||
Node* post_order_node = current;
|
||||
while (true) {
|
||||
NodeState top = stack.top();
|
||||
if (top.first == top.second) {
|
||||
if (visit) {
|
||||
visitor->Post(post_order_node);
|
||||
SetVisited(&visited, post_order_node->id());
|
||||
}
|
||||
stack.pop();
|
||||
if (stack.empty()) {
|
||||
if (++root_begin == root_end) return;
|
||||
current = *root_begin;
|
||||
break;
|
||||
}
|
||||
post_order_node = (*stack.top().first).from();
|
||||
visit = true;
|
||||
} else {
|
||||
visitor->PreEdge((*top.first).from(), (*top.first).index(),
|
||||
(*top.first).to());
|
||||
current = (*top.first).to();
|
||||
if (!GetVisited(&visited, current->id())) break;
|
||||
}
|
||||
top = stack.top();
|
||||
visitor->PostEdge((*top.first).from(), (*top.first).index(),
|
||||
(*top.first).to());
|
||||
++stack.top().first;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class Visitor>
|
||||
static void Visit(Graph* graph, Zone* zone, Node* current, Visitor* visitor) {
|
||||
Node* array[] = {current};
|
||||
Visit<Visitor>(graph, zone, &array[0], &array[1], visitor);
|
||||
}
|
||||
|
||||
struct NullNodeVisitor {
|
||||
void Pre(Node* node) {}
|
||||
void Post(Node* node) {}
|
||||
void PreEdge(Node* from, int index, Node* to) {}
|
||||
void PostEdge(Node* from, int index, Node* to) {}
|
||||
};
|
||||
|
||||
private:
|
||||
static void SetVisited(BoolVector* visited, int id) {
|
||||
if (id >= static_cast<int>(visited->size())) {
|
||||
// Resize and set all values to unvisited.
|
||||
visited->resize((3 * id) / 2, false);
|
||||
}
|
||||
visited->at(id) = true;
|
||||
}
|
||||
|
||||
static bool GetVisited(BoolVector* visited, int id) {
|
||||
if (id >= static_cast<int>(visited->size())) return false;
|
||||
return visited->at(id);
|
||||
}
|
||||
};
|
||||
|
||||
typedef GenericGraphVisit::NullNodeVisitor NullNodeVisitor;
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_COMPILER_GENERIC_ALGORITHM_H_
|
@ -1,25 +0,0 @@
|
||||
// Copyright 2013 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_COMPILER_GRAPH_INL_H_
|
||||
#define V8_COMPILER_GRAPH_INL_H_
|
||||
|
||||
#include "src/compiler/generic-algorithm.h"
|
||||
#include "src/compiler/graph.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
namespace compiler {
|
||||
|
||||
template <class Visitor>
|
||||
void Graph::VisitNodeInputsFromEnd(Visitor* visitor) {
|
||||
Zone tmp_zone;
|
||||
GenericGraphVisit::Visit<Visitor>(this, &tmp_zone, end(), visitor);
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_COMPILER_GRAPH_INL_H_
|
@ -2,14 +2,15 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "src/compiler/js-inlining.h"
|
||||
|
||||
#include "src/ast.h"
|
||||
#include "src/ast-numbering.h"
|
||||
#include "src/compiler/access-builder.h"
|
||||
#include "src/compiler/all-nodes.h"
|
||||
#include "src/compiler/ast-graph-builder.h"
|
||||
#include "src/compiler/common-operator.h"
|
||||
#include "src/compiler/graph-inl.h"
|
||||
#include "src/compiler/graph-visualizer.h"
|
||||
#include "src/compiler/js-inlining.h"
|
||||
#include "src/compiler/js-operator.h"
|
||||
#include "src/compiler/node-matchers.h"
|
||||
#include "src/compiler/node-properties.h"
|
||||
@ -20,7 +21,6 @@
|
||||
#include "src/rewriter.h"
|
||||
#include "src/scopes.h"
|
||||
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
namespace compiler {
|
||||
@ -56,28 +56,7 @@ class JSCallFunctionAccessor {
|
||||
};
|
||||
|
||||
|
||||
Reduction JSInliner::Reduce(Node* node) {
|
||||
if (node->opcode() != IrOpcode::kJSCallFunction) return NoChange();
|
||||
|
||||
JSCallFunctionAccessor call(node);
|
||||
HeapObjectMatcher<JSFunction> match(call.jsfunction());
|
||||
if (!match.HasValue()) return NoChange();
|
||||
|
||||
Handle<JSFunction> jsfunction = match.Value().handle();
|
||||
|
||||
if (jsfunction->shared()->native()) {
|
||||
if (FLAG_trace_turbo_inlining) {
|
||||
SmartArrayPointer<char> name =
|
||||
jsfunction->shared()->DebugName()->ToCString();
|
||||
PrintF("Not Inlining %s into %s because inlinee is native\n", name.get(),
|
||||
info_->shared_info()->DebugName()->ToCString().get());
|
||||
}
|
||||
return NoChange();
|
||||
}
|
||||
|
||||
return TryInlineJSCall(node, jsfunction);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// A facade on a JSFunction's graph to facilitate inlining. It assumes the
|
||||
// that the function graph has only one return statement, and provides
|
||||
@ -174,71 +153,59 @@ void Inlinee::UnifyReturn(JSGraph* jsgraph) {
|
||||
}
|
||||
|
||||
|
||||
class CopyVisitor : public NullNodeVisitor {
|
||||
class CopyVisitor {
|
||||
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),
|
||||
: sentinel_op_(IrOpcode::kDead, Operator::kNoProperties, "Sentinel", 0, 0,
|
||||
0, 0, 0, 0),
|
||||
sentinel_(target_graph->NewNode(&sentinel_op_)),
|
||||
copies_(source_graph->NodeCount(), sentinel_, temp_zone),
|
||||
source_graph_(source_graph),
|
||||
target_graph_(target_graph),
|
||||
temp_zone_(temp_zone),
|
||||
sentinel_op_(IrOpcode::kDead, Operator::kNoProperties, "sentinel", 0, 0,
|
||||
0, 0, 0, 0) {}
|
||||
temp_zone_(temp_zone) {}
|
||||
|
||||
void Post(Node* original) {
|
||||
NodeVector inputs(temp_zone_);
|
||||
for (Node* const node : original->inputs()) {
|
||||
inputs.push_back(GetCopy(node));
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
Node* GetCopy(Node* original) {
|
||||
Node* copy = copies_[original->id()];
|
||||
if (copy == NULL) {
|
||||
copy = GetSentinel(original);
|
||||
}
|
||||
DCHECK(copy);
|
||||
return copy;
|
||||
}
|
||||
Node* GetCopy(Node* orig) { return copies_[orig->id()]; }
|
||||
|
||||
void CopyGraph() {
|
||||
source_graph_->VisitNodeInputsFromEnd(this);
|
||||
ReplaceSentinels();
|
||||
NodeVector inputs(temp_zone_);
|
||||
// TODO(bmeurer): AllNodes should be turned into something like
|
||||
// Graph::CollectNodesReachableFromEnd() and the gray set stuff should be
|
||||
// removed since it's only needed by the visualizer.
|
||||
AllNodes all(temp_zone_, source_graph_);
|
||||
// Copy all nodes reachable from end.
|
||||
for (Node* orig : all.live) {
|
||||
Node* copy = GetCopy(orig);
|
||||
if (copy != sentinel_) {
|
||||
// Mapping already exists.
|
||||
continue;
|
||||
}
|
||||
// Copy the node.
|
||||
inputs.clear();
|
||||
for (Node* input : orig->inputs()) inputs.push_back(copies_[input->id()]);
|
||||
copy = target_graph_->NewNode(orig->op(), orig->InputCount(), &inputs[0]);
|
||||
copies_[orig->id()] = copy;
|
||||
}
|
||||
// For missing inputs.
|
||||
for (Node* orig : all.live) {
|
||||
Node* copy = copies_[orig->id()];
|
||||
for (int i = 0; i < copy->InputCount(); ++i) {
|
||||
Node* input = copy->InputAt(i);
|
||||
if (input == sentinel_) {
|
||||
copy->ReplaceInput(i, GetCopy(orig->InputAt(i)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const NodeVector& copies() { return copies_; }
|
||||
const NodeVector& copies() const { return copies_; }
|
||||
|
||||
private:
|
||||
void ReplaceSentinels() {
|
||||
for (NodeId id = 0; id < source_graph_->NodeCount(); ++id) {
|
||||
Node* sentinel = sentinels_[id];
|
||||
if (sentinel == NULL) continue;
|
||||
Node* copy = copies_[id];
|
||||
DCHECK(copy);
|
||||
sentinel->ReplaceUses(copy);
|
||||
}
|
||||
}
|
||||
|
||||
Node* GetSentinel(Node* original) {
|
||||
if (sentinels_[original->id()] == NULL) {
|
||||
sentinels_[original->id()] = target_graph_->NewNode(&sentinel_op_);
|
||||
}
|
||||
return sentinels_[original->id()];
|
||||
}
|
||||
|
||||
Operator const sentinel_op_;
|
||||
Node* const sentinel_;
|
||||
NodeVector copies_;
|
||||
NodeVector sentinels_;
|
||||
Graph* source_graph_;
|
||||
Graph* target_graph_;
|
||||
Zone* temp_zone_;
|
||||
Operator sentinel_op_;
|
||||
Graph* const source_graph_;
|
||||
Graph* const target_graph_;
|
||||
Zone* const temp_zone_;
|
||||
};
|
||||
|
||||
|
||||
@ -299,6 +266,8 @@ Reduction Inlinee::InlineAtCall(JSGraph* jsgraph, Node* call) {
|
||||
return Reducer::Replace(value_output());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
void JSInliner::AddClosureToFrameState(Node* frame_state,
|
||||
Handle<JSFunction> jsfunction) {
|
||||
@ -333,9 +302,25 @@ Node* JSInliner::CreateArgumentsAdaptorFrameState(JSCallFunctionAccessor* call,
|
||||
}
|
||||
|
||||
|
||||
Reduction JSInliner::TryInlineJSCall(Node* call_node,
|
||||
Handle<JSFunction> function) {
|
||||
JSCallFunctionAccessor call(call_node);
|
||||
Reduction JSInliner::Reduce(Node* node) {
|
||||
if (node->opcode() != IrOpcode::kJSCallFunction) return NoChange();
|
||||
|
||||
JSCallFunctionAccessor call(node);
|
||||
HeapObjectMatcher<JSFunction> match(call.jsfunction());
|
||||
if (!match.HasValue()) return NoChange();
|
||||
|
||||
Handle<JSFunction> function = match.Value().handle();
|
||||
|
||||
if (function->shared()->native()) {
|
||||
if (FLAG_trace_turbo_inlining) {
|
||||
SmartArrayPointer<char> name =
|
||||
function->shared()->DebugName()->ToCString();
|
||||
PrintF("Not Inlining %s into %s because inlinee is native\n", name.get(),
|
||||
info_->shared_info()->DebugName()->ToCString().get());
|
||||
}
|
||||
return NoChange();
|
||||
}
|
||||
|
||||
CompilationInfoWithZone info(function);
|
||||
|
||||
if (!Compiler::ParseAndAnalyze(&info)) return NoChange();
|
||||
@ -388,7 +373,7 @@ Reduction JSInliner::TryInlineJSCall(Node* call_node,
|
||||
}
|
||||
}
|
||||
|
||||
return inlinee.InlineAtCall(jsgraph_, call_node);
|
||||
return inlinee.InlineAtCall(jsgraph_, node);
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
|
@ -19,10 +19,9 @@ class JSInliner FINAL : public Reducer {
|
||||
JSInliner(Zone* local_zone, CompilationInfo* info, JSGraph* jsgraph)
|
||||
: local_zone_(local_zone), info_(info), jsgraph_(jsgraph) {}
|
||||
|
||||
Reduction Reduce(Node* node) OVERRIDE;
|
||||
Reduction Reduce(Node* node) FINAL;
|
||||
|
||||
private:
|
||||
friend class InlinerVisitor;
|
||||
Zone* local_zone_;
|
||||
CompilationInfo* info_;
|
||||
JSGraph* jsgraph_;
|
||||
@ -31,11 +30,10 @@ class JSInliner FINAL : public Reducer {
|
||||
Handle<JSFunction> jsfunction,
|
||||
Zone* temp_zone);
|
||||
void AddClosureToFrameState(Node* frame_state, Handle<JSFunction> jsfunction);
|
||||
Reduction TryInlineJSCall(Node* node, Handle<JSFunction> jsfunction);
|
||||
static void UnifyReturn(Graph* graph);
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace v8::internal::compiler
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_COMPILER_JS_INLINING_H_
|
||||
|
@ -8,7 +8,7 @@
|
||||
#include "src/base/bits.h"
|
||||
#include "src/compiler/common-operator.h"
|
||||
#include "src/compiler/control-reducer.h"
|
||||
#include "src/compiler/graph-inl.h"
|
||||
#include "src/compiler/graph.h"
|
||||
#include "src/compiler/js-graph.h"
|
||||
#include "src/compiler/node-properties.h"
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "src/compiler/graph-inl.h"
|
||||
#include "src/compiler/js-graph.h"
|
||||
#include "src/compiler/js-typed-lowering.h"
|
||||
#include "src/compiler/machine-operator.h"
|
||||
|
@ -6,7 +6,6 @@
|
||||
|
||||
#include "src/base/utils/random-number-generator.h"
|
||||
#include "src/codegen.h"
|
||||
#include "src/compiler/graph-inl.h"
|
||||
#include "src/compiler/js-graph.h"
|
||||
#include "src/compiler/machine-operator-reducer.h"
|
||||
#include "src/compiler/operator-properties.h"
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include "graph-tester.h"
|
||||
#include "src/compiler/common-operator.h"
|
||||
#include "src/compiler/graph.h"
|
||||
#include "src/compiler/graph-inl.h"
|
||||
#include "src/compiler/graph-visualizer.h"
|
||||
#include "src/compiler/node.h"
|
||||
#include "src/compiler/operator.h"
|
||||
@ -20,45 +19,6 @@ using namespace v8::internal::compiler;
|
||||
static Operator dummy_operator(IrOpcode::kParameter, Operator::kNoWrite,
|
||||
"dummy", 0, 0, 0, 1, 0, 0);
|
||||
|
||||
class PreNodeVisitor : public NullNodeVisitor {
|
||||
public:
|
||||
void Pre(Node* node) {
|
||||
printf("NODE ID: %d\n", node->id());
|
||||
nodes_.push_back(node);
|
||||
}
|
||||
std::vector<Node*> nodes_;
|
||||
};
|
||||
|
||||
|
||||
class PostNodeVisitor : public NullNodeVisitor {
|
||||
public:
|
||||
void Post(Node* node) {
|
||||
printf("NODE ID: %d\n", node->id());
|
||||
nodes_.push_back(node);
|
||||
}
|
||||
std::vector<Node*> nodes_;
|
||||
};
|
||||
|
||||
|
||||
TEST(TestInputNodePreOrderVisitSimple) {
|
||||
GraphWithStartNodeTester graph;
|
||||
Node* n2 = graph.NewNode(&dummy_operator, graph.start());
|
||||
Node* n3 = graph.NewNode(&dummy_operator, n2);
|
||||
Node* n4 = graph.NewNode(&dummy_operator, n2, n3);
|
||||
Node* n5 = graph.NewNode(&dummy_operator, n4, n2);
|
||||
graph.SetEnd(n5);
|
||||
|
||||
PreNodeVisitor node_visitor;
|
||||
graph.VisitNodeInputsFromEnd(&node_visitor);
|
||||
CHECK_EQ(5, static_cast<int>(node_visitor.nodes_.size()));
|
||||
CHECK(n5->id() == node_visitor.nodes_[0]->id());
|
||||
CHECK(n4->id() == node_visitor.nodes_[1]->id());
|
||||
CHECK(n2->id() == node_visitor.nodes_[2]->id());
|
||||
CHECK(graph.start()->id() == node_visitor.nodes_[3]->id());
|
||||
CHECK(n3->id() == node_visitor.nodes_[4]->id());
|
||||
}
|
||||
|
||||
|
||||
TEST(TestPrintNodeGraphToNodeGraphviz) {
|
||||
GraphWithStartNodeTester graph;
|
||||
Node* n2 = graph.NewNode(&dummy_operator, graph.start());
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
#include "test/unittests/compiler/instruction-selector-unittest.h"
|
||||
|
||||
#include "src/compiler/graph-inl.h"
|
||||
#include "src/compiler/graph.h"
|
||||
#include "src/flags.h"
|
||||
#include "test/unittests/compiler/compiler-test-utils.h"
|
||||
|
||||
|
@ -442,9 +442,7 @@
|
||||
'../../src/compiler/frame.h',
|
||||
'../../src/compiler/gap-resolver.cc',
|
||||
'../../src/compiler/gap-resolver.h',
|
||||
'../../src/compiler/generic-algorithm.h',
|
||||
'../../src/compiler/graph-builder.h',
|
||||
'../../src/compiler/graph-inl.h',
|
||||
'../../src/compiler/graph-reducer.cc',
|
||||
'../../src/compiler/graph-reducer.h',
|
||||
'../../src/compiler/graph-replay.cc',
|
||||
|
Loading…
Reference in New Issue
Block a user