Index: src/compiler/js-inlining.cc |
diff --git a/src/compiler/js-inlining.cc b/src/compiler/js-inlining.cc |
index d143382dfd047a71ce3f868e92f308bd57f63d4c..2c2530da90bd323b4ab2394753af9afa26905c57 100644 |
--- a/src/compiler/js-inlining.cc |
+++ b/src/compiler/js-inlining.cc |
@@ -2,22 +2,20 @@ |
// 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/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-graph.h" |
#include "src/compiler/js-intrinsic-builder.h" |
#include "src/compiler/js-operator.h" |
-#include "src/compiler/node-aux-data-inl.h" |
#include "src/compiler/node-matchers.h" |
#include "src/compiler/node-properties-inl.h" |
#include "src/compiler/simplified-operator.h" |
-#include "src/compiler/typer.h" |
-#include "src/full-codegen.h" |
#include "src/parser.h" |
#include "src/rewriter.h" |
#include "src/scopes.h" |
@@ -107,6 +105,7 @@ class Inlinee { |
}; |
+// static |
void Inlinee::UnifyReturn(JSGraph* jsgraph) { |
Graph* graph = jsgraph->graph(); |
@@ -274,84 +273,32 @@ void Inlinee::InlineAtCall(JSGraph* jsgraph, Node* call) { |
} |
NodeProperties::ReplaceWithValue(call, value_output(), effect_output()); |
- call->RemoveAllInputs(); |
- DCHECK_EQ(0, call->UseCount()); |
-} |
- |
- |
-// TODO(turbofan) Provide such accessors for every node, possibly even |
-// generate them. |
-class JSCallFunctionAccessor { |
- public: |
- explicit JSCallFunctionAccessor(Node* call) : call_(call) { |
- DCHECK_EQ(IrOpcode::kJSCallFunction, call->opcode()); |
- } |
- |
- Node* jsfunction() { return call_->InputAt(0); } |
- |
- Node* receiver() { return call_->InputAt(1); } |
- |
- Node* formal_argument(size_t index) { |
- DCHECK(index < formal_arguments()); |
- return call_->InputAt(static_cast<int>(2 + index)); |
- } |
- |
- size_t formal_arguments() { |
- // {value_inputs} includes jsfunction and receiver. |
- size_t value_inputs = call_->op()->ValueInputCount(); |
- DCHECK_GE(call_->InputCount(), 2); |
- return value_inputs - 2; |
- } |
- |
- Node* frame_state() { return NodeProperties::GetFrameStateInput(call_); } |
- |
- private: |
- Node* call_; |
-}; |
- |
- |
-void JSInliner::AddClosureToFrameState(Node* frame_state, |
- Handle<JSFunction> jsfunction) { |
- FrameStateCallInfo call_info = OpParameter<FrameStateCallInfo>(frame_state); |
- const Operator* op = jsgraph_->common()->FrameState( |
- FrameStateType::JS_FRAME, call_info.bailout_id(), |
- call_info.state_combine(), jsfunction); |
- frame_state->set_op(op); |
+ call->Kill(); |
} |
-Node* JSInliner::CreateArgumentsAdaptorFrameState(JSCallFunctionAccessor* call, |
- Handle<JSFunction> jsfunction, |
- Zone* temp_zone) { |
- const Operator* op = jsgraph_->common()->FrameState( |
- FrameStateType::ARGUMENTS_ADAPTOR, BailoutId(-1), |
- OutputFrameStateCombine::Ignore(), jsfunction); |
- const Operator* op0 = jsgraph_->common()->StateValues(0); |
- Node* node0 = jsgraph_->graph()->NewNode(op0); |
- NodeVector params(temp_zone); |
- params.push_back(call->receiver()); |
- for (size_t argument = 0; argument != call->formal_arguments(); ++argument) { |
- params.push_back(call->formal_argument(argument)); |
- } |
- const Operator* op_param = |
- jsgraph_->common()->StateValues(static_cast<int>(params.size())); |
- Node* params_node = jsgraph_->graph()->NewNode( |
- op_param, static_cast<int>(params.size()), ¶ms.front()); |
- return jsgraph_->graph()->NewNode(op, params_node, node0, node0, |
- jsgraph_->UndefinedConstant(), |
- call->frame_state()); |
+template <typename InputIterator> |
+Node* JSInliner::CreateArgumentsAdaptorFrameState( |
+ const Handle<JSFunction>& function, InputIterator first, InputIterator last, |
+ Node* frame_state) { |
+ NodeVector parameters(zone()); |
+ parameters.insert(parameters.begin(), first, last); |
+ int const num_parameters = static_cast<int>(parameters.size()); |
+ Node* state_values0 = graph()->NewNode(common()->StateValues(0)); |
+ Node* state_values = graph()->NewNode(common()->StateValues(num_parameters), |
+ num_parameters, ¶meters.front()); |
+ return graph()->NewNode( |
+ common()->FrameState(FrameStateType::ARGUMENTS_ADAPTOR, BailoutId(-1), |
+ OutputFrameStateCombine::Ignore(), function), |
+ state_values, state_values0, state_values0, |
+ jsgraph()->UndefinedConstant(), frame_state); |
} |
-void JSInliner::TryInlineJSCall(Node* call_node) { |
- JSCallFunctionAccessor call(call_node); |
- |
- HeapObjectMatcher<JSFunction> match(call.jsfunction()); |
- if (!match.HasValue()) { |
- return; |
- } |
- |
- Handle<JSFunction> function = match.Value().handle(); |
+void JSInliner::TryInlineJSCall(Node* node) { |
+ JSCallFunctionMatcher const m(node); |
+ if (!m.function().HasValue()) return; |
+ Handle<JSFunction> const function = m.function().Value().handle(); |
if (function->shared()->native()) { |
if (FLAG_trace_turbo_inlining) { |
@@ -368,7 +315,7 @@ void JSInliner::TryInlineJSCall(Node* call_node) { |
CHECK(Compiler::ParseAndAnalyze(&info)); |
CHECK(Compiler::EnsureDeoptimizationSupport(&info)); |
- if (info.scope()->arguments() != NULL && info.strict_mode() != STRICT) { |
+ if (info.scope()->arguments() && info.strict_mode() != STRICT) { |
// For now do not inline functions that use their arguments array. |
SmartArrayPointer<char> name = function->shared()->DebugName()->ToCString(); |
if (FLAG_trace_turbo_inlining) { |
@@ -386,104 +333,83 @@ void JSInliner::TryInlineJSCall(Node* call_node) { |
info_->shared_info()->DebugName()->ToCString().get()); |
} |
- Graph graph(info.zone()); |
- JSGraph jsgraph(&graph, jsgraph_->common(), jsgraph_->javascript(), |
- jsgraph_->machine()); |
+ Graph inlinee_graph(info.zone()); |
+ JSGraph inlinee_jsgraph(&inlinee_graph, common(), javascript(), machine()); |
- AstGraphBuilder graph_builder(local_zone_, &info, &jsgraph); |
+ AstGraphBuilder graph_builder(zone(), &info, &inlinee_jsgraph); |
graph_builder.CreateGraph(); |
- Inlinee::UnifyReturn(&jsgraph); |
+ Inlinee::UnifyReturn(&inlinee_jsgraph); |
- CopyVisitor visitor(&graph, jsgraph_->graph(), info.zone()); |
+ CopyVisitor visitor(&inlinee_graph, graph(), info.zone()); |
visitor.CopyGraph(); |
- Inlinee inlinee(visitor.GetCopy(graph.start()), visitor.GetCopy(graph.end())); |
+ Inlinee inlinee(visitor.GetCopy(inlinee_graph.start()), |
+ visitor.GetCopy(inlinee_graph.end())); |
if (FLAG_turbo_deoptimization) { |
- Node* outer_frame_state = call.frame_state(); |
+ Node* outer_frame_state = m.frame_state(); |
// Insert argument adaptor frame if required. |
- if (call.formal_arguments() != inlinee.formal_parameters()) { |
- outer_frame_state = |
- CreateArgumentsAdaptorFrameState(&call, function, info.zone()); |
+ if (m.size() != inlinee.formal_parameters()) { |
+ outer_frame_state = CreateArgumentsAdaptorFrameState( |
+ function, m.begin(), m.end(), outer_frame_state); |
} |
- for (NodeVectorConstIter it = visitor.copies().begin(); |
- it != visitor.copies().end(); ++it) { |
- Node* node = *it; |
- if (node != NULL && node->opcode() == IrOpcode::kFrameState) { |
- AddClosureToFrameState(node, function); |
- NodeProperties::ReplaceFrameStateInput(node, outer_frame_state); |
+ for (auto frame_state : visitor.copies()) { |
+ if (frame_state && frame_state->opcode() == IrOpcode::kFrameState) { |
+ FrameStateCallInfo info = OpParameter<FrameStateCallInfo>(frame_state); |
+ frame_state->set_op( |
+ common()->FrameState(FrameStateType::JS_FRAME, info.bailout_id(), |
+ info.state_combine(), function)); |
+ NodeProperties::ReplaceFrameStateInput(frame_state, outer_frame_state); |
} |
} |
} |
- inlinee.InlineAtCall(jsgraph_, call_node); |
+ inlinee.InlineAtCall(jsgraph(), node); |
} |
-class JSCallRuntimeAccessor { |
- public: |
- explicit JSCallRuntimeAccessor(Node* call) : call_(call) { |
- DCHECK_EQ(IrOpcode::kJSCallRuntime, call->opcode()); |
- } |
- |
- Node* formal_argument(size_t index) { |
- DCHECK(index < formal_arguments()); |
- return call_->InputAt(static_cast<int>(index)); |
- } |
+void JSInliner::TryInlineRuntimeCall(Node* node) { |
+ JSCallRuntimeMatcher m(node); |
+ const Runtime::Function* f = m.function(); |
+ if (f->intrinsic_type != Runtime::IntrinsicType::INLINE) return; |
- size_t formal_arguments() { |
- size_t value_inputs = call_->op()->ValueInputCount(); |
- return value_inputs; |
- } |
+ JSIntrinsicBuilder intrinsic_builder(jsgraph()); |
- Node* frame_state() const { |
- return NodeProperties::GetFrameStateInput(call_); |
- } |
- Node* context() const { return NodeProperties::GetContextInput(call_); } |
- Node* control() const { return NodeProperties::GetControlInput(call_); } |
- Node* effect() const { return NodeProperties::GetEffectInput(call_); } |
- |
- const Runtime::Function* function() const { |
- return Runtime::FunctionForId(CallRuntimeParametersOf(call_->op()).id()); |
- } |
- |
- NodeVector inputs(Zone* zone) const { |
- NodeVector inputs(zone); |
- for (Node* const node : call_->inputs()) { |
- inputs.push_back(node); |
+ // TODO(turbofan): Looks like no one is verifying these arguments in the |
+ // IntrinsicsBuilder? Do we plan to do it there, or should be add code to |
+ // validate the arguments here? |
+ NodeVector arguments(zone()); |
+ arguments.insert(arguments.begin(), node->inputs().begin(), |
+ node->inputs().end()); |
+ ResultAndEffect r = |
+ intrinsic_builder.BuildGraphFor(f->function_id, arguments); |
+ if (r.first) { |
+ if (FLAG_trace_turbo_inlining) { |
+ PrintF("Inlining %s into %s\n", f->name, |
+ info_->shared_info()->DebugName()->ToCString().get()); |
} |
- return inputs; |
+ NodeProperties::ReplaceWithValue(node, r.first, r.second); |
+ node->Kill(); |
} |
- |
- private: |
- Node* call_; |
-}; |
+} |
-void JSInliner::TryInlineRuntimeCall(Node* call_node) { |
- JSCallRuntimeAccessor call(call_node); |
- const Runtime::Function* f = call.function(); |
+Graph* JSInliner::graph() const { return jsgraph()->graph(); } |
- if (f->intrinsic_type != Runtime::IntrinsicType::INLINE) { |
- return; |
- } |
- JSIntrinsicBuilder intrinsic_builder(jsgraph_); |
+CommonOperatorBuilder* JSInliner::common() const { return jsgraph()->common(); } |
- ResultAndEffect r = intrinsic_builder.BuildGraphFor( |
- f->function_id, call.inputs(jsgraph_->zone())); |
- if (r.first != NULL) { |
- if (FLAG_trace_turbo_inlining) { |
- PrintF("Inlining %s into %s\n", f->name, |
- info_->shared_info()->DebugName()->ToCString().get()); |
- } |
- NodeProperties::ReplaceWithValue(call_node, r.first, r.second); |
- call_node->RemoveAllInputs(); |
- DCHECK_EQ(0, call_node->UseCount()); |
- } |
-} |
+JSOperatorBuilder* JSInliner::javascript() const { |
+ return jsgraph()->javascript(); |
} |
+ |
+ |
+MachineOperatorBuilder* JSInliner::machine() const { |
+ return jsgraph()->machine(); |
} |
-} // namespace v8::internal::compiler |
+ |
+} // namespace compiler |
+} // namespace internal |
+} // namespace v8 |