| Index: src/compiler/js-inlining.cc
|
| diff --git a/src/compiler/js-inlining.cc b/src/compiler/js-inlining.cc
|
| index 91d0823daebe4fd24cf72d31cb195382be71fb07..135e6a1c8319abc828d302754dda491f650853c6 100644
|
| --- a/src/compiler/js-inlining.cc
|
| +++ b/src/compiler/js-inlining.cc
|
| @@ -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,60 @@ 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) {}
|
| +
|
| + Node* GetCopy(Node* orig) { return copies_[orig->id()]; }
|
|
|
| - void Post(Node* original) {
|
| + void CopyGraph() {
|
| NodeVector inputs(temp_zone_);
|
| - for (Node* const node : original->inputs()) {
|
| - inputs.push_back(GetCopy(node));
|
| + // 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.empty() ? nullptr : &inputs[0]);
|
| + copies_[orig->id()] = copy;
|
| }
|
| -
|
| - // 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);
|
| + // 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)));
|
| + }
|
| + }
|
| }
|
| - DCHECK(copy);
|
| - return copy;
|
| }
|
|
|
| - void CopyGraph() {
|
| - source_graph_->VisitNodeInputsFromEnd(this);
|
| - ReplaceSentinels();
|
| - }
|
| -
|
| - 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 +267,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 +303,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 +374,7 @@ Reduction JSInliner::TryInlineJSCall(Node* call_node,
|
| }
|
| }
|
|
|
| - return inlinee.InlineAtCall(jsgraph_, call_node);
|
| + return inlinee.InlineAtCall(jsgraph_, node);
|
| }
|
|
|
| } // namespace compiler
|
|
|