| Index: src/compiler/js-inlining.cc
|
| diff --git a/src/compiler/js-inlining.cc b/src/compiler/js-inlining.cc
|
| index 8762a975876b54ac9f337a92b0ae487f1aefd265..b70a3d270b92039d2aee862c53f596cc5b0061e5 100644
|
| --- a/src/compiler/js-inlining.cc
|
| +++ b/src/compiler/js-inlining.cc
|
| @@ -2,6 +2,8 @@
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| +#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"
|
| @@ -9,6 +11,7 @@
|
| #include "src/compiler/graph-inl.h"
|
| #include "src/compiler/graph-visualizer.h"
|
| #include "src/compiler/js-inlining.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"
|
| @@ -32,7 +35,12 @@ class InlinerVisitor : public NullNodeVisitor {
|
| GenericGraphVisit::Control Post(Node* node) {
|
| switch (node->opcode()) {
|
| case IrOpcode::kJSCallFunction:
|
| - inliner_->TryInlineCall(node);
|
| + inliner_->TryInlineJSCall(node);
|
| + break;
|
| + case IrOpcode::kJSCallRuntime:
|
| + if (FLAG_turbo_inlining_intrinsics) {
|
| + inliner_->TryInlineRuntimeCall(node);
|
| + }
|
| break;
|
| default:
|
| break;
|
| @@ -51,16 +59,6 @@ void JSInliner::Inline() {
|
| }
|
|
|
|
|
| -// TODO(sigurds) Find a home for this function and reuse it everywhere (esp. in
|
| -// test cases, where similar code is currently duplicated).
|
| -static void Parse(Handle<JSFunction> function, CompilationInfoWithZone* info) {
|
| - CHECK(Parser::Parse(info));
|
| - CHECK(Rewriter::Rewrite(info));
|
| - CHECK(Scope::Analyze(info));
|
| - CHECK(Compiler::EnsureDeoptimizationSupport(info));
|
| -}
|
| -
|
| -
|
| // A facade on a JSFunction's graph to facilitate inlining. It assumes the
|
| // that the function graph has only one return statement, and provides
|
| // {UnifyReturn} to convert a function graph to that end.
|
| @@ -285,22 +283,9 @@ void Inlinee::InlineAtCall(JSGraph* jsgraph, Node* call) {
|
| }
|
| }
|
|
|
| - // Iterate over all uses of the call node.
|
| - iter = call->uses().begin();
|
| - while (iter != call->uses().end()) {
|
| - if (NodeProperties::IsEffectEdge(iter.edge())) {
|
| - iter.UpdateToAndIncrement(effect_output());
|
| - } else if (NodeProperties::IsControlEdge(iter.edge())) {
|
| - UNREACHABLE();
|
| - } else {
|
| - DCHECK(NodeProperties::IsValueEdge(iter.edge()));
|
| - iter.UpdateToAndIncrement(value_output());
|
| - }
|
| - }
|
| + NodeProperties::ReplaceWithValue(call, value_output(), effect_output());
|
| call->RemoveAllInputs();
|
| DCHECK_EQ(0, call->UseCount());
|
| - // TODO(sigurds) Remove this once we copy.
|
| - unique_return()->RemoveAllInputs();
|
| }
|
|
|
|
|
| @@ -368,7 +353,7 @@ Node* JSInliner::CreateArgumentsAdaptorFrameState(JSCallFunctionAccessor* call,
|
| }
|
|
|
|
|
| -void JSInliner::TryInlineCall(Node* call_node) {
|
| +void JSInliner::TryInlineJSCall(Node* call_node) {
|
| JSCallFunctionAccessor call(call_node);
|
|
|
| HeapObjectMatcher<JSFunction> match(call.jsfunction());
|
| @@ -389,9 +374,10 @@ void JSInliner::TryInlineCall(Node* call_node) {
|
| }
|
|
|
| CompilationInfoWithZone info(function);
|
| - Parse(function, &info);
|
| + CHECK(Compiler::ParseAndAnalyze(&info));
|
| + CHECK(Compiler::EnsureDeoptimizationSupport(&info));
|
|
|
| - if (info.scope()->arguments() != NULL) {
|
| + if (info.scope()->arguments() != NULL && 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) {
|
| @@ -413,7 +399,7 @@ void JSInliner::TryInlineCall(Node* call_node) {
|
| JSGraph jsgraph(&graph, jsgraph_->common(), jsgraph_->javascript(),
|
| jsgraph_->machine());
|
|
|
| - AstGraphBuilder graph_builder(&info, &jsgraph);
|
| + AstGraphBuilder graph_builder(local_zone_, &info, &jsgraph);
|
| graph_builder.CreateGraph();
|
| Inlinee::UnifyReturn(&jsgraph);
|
|
|
| @@ -440,6 +426,72 @@ void JSInliner::TryInlineCall(Node* call_node) {
|
|
|
| inlinee.InlineAtCall(jsgraph_, call_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));
|
| + }
|
| +
|
| + size_t formal_arguments() {
|
| + size_t value_inputs = OperatorProperties::GetValueInputCount(call_->op());
|
| + return value_inputs;
|
| + }
|
| +
|
| + 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(OpParameter<Runtime::FunctionId>(call_));
|
| + }
|
| +
|
| + NodeVector inputs(Zone* zone) const {
|
| + NodeVector inputs(zone);
|
| + for (InputIter it = call_->inputs().begin(); it != call_->inputs().end();
|
| + ++it) {
|
| + inputs.push_back(*it);
|
| + }
|
| + return inputs;
|
| + }
|
| +
|
| + private:
|
| + Node* call_;
|
| +};
|
| +
|
| +
|
| +void JSInliner::TryInlineRuntimeCall(Node* call_node) {
|
| + JSCallRuntimeAccessor call(call_node);
|
| + const Runtime::Function* f = call.function();
|
| +
|
| + if (f->intrinsic_type != Runtime::IntrinsicType::INLINE) {
|
| + return;
|
| + }
|
| +
|
| + JSIntrinsicBuilder intrinsic_builder(jsgraph_);
|
| +
|
| + 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());
|
| + }
|
| +}
|
| }
|
| }
|
| } // namespace v8::internal::compiler
|
|
|