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 |