| 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
|
|
|