From: sigurds@chromium.org Date: Tue, 19 Aug 2014 12:48:44 +0000 (+0000) Subject: Revert "Add initial support for inlining." X-Git-Tag: upstream/4.7.83~7552 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b488b2ed299ec3f2e7c38337d6a97e360b359920;p=platform%2Fupstream%2Fv8.git Revert "Add initial support for inlining." This reverts commit r23197. TBR=titzer@chromium.org Review URL: https://codereview.chromium.org/481413002 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23198 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/BUILD.gn b/BUILD.gn index f5501fb5a..ea182420c 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -499,8 +499,6 @@ source_set("v8_base") { "src/compiler/js-generic-lowering.h", "src/compiler/js-graph.cc", "src/compiler/js-graph.h", - "src/compiler/js-inlining.cc", - "src/compiler/js-inlining.h", "src/compiler/js-operator.h", "src/compiler/js-typed-lowering.cc", "src/compiler/js-typed-lowering.h", diff --git a/src/compiler/generic-graph.h b/src/compiler/generic-graph.h index e8de9ebd9..a55545654 100644 --- a/src/compiler/generic-graph.h +++ b/src/compiler/generic-graph.h @@ -22,7 +22,6 @@ class GenericGraphBase : public ZoneObject { NodeId NextNodeID() { return next_node_id_++; } NodeId NodeCount() const { return next_node_id_; } - void SetNextNodeId(NodeId next) { next_node_id_ = next; } private: Zone* zone_; diff --git a/src/compiler/generic-node.h b/src/compiler/generic-node.h index aadee7611..287d852f5 100644 --- a/src/compiler/generic-node.h +++ b/src/compiler/generic-node.h @@ -204,12 +204,6 @@ class GenericNode::Inputs::iterator { ++index_; return *this; } - iterator& UpdateToAndIncrement(GenericNode* new_to) { - typename GenericNode::Input* input = GetInput(); - input->Update(new_to); - index_++; - return *this; - } int index() { return index_; } private: diff --git a/src/compiler/js-context-specialization.cc b/src/compiler/js-context-specialization.cc index b54d5d99c..bdf142763 100644 --- a/src/compiler/js-context-specialization.cc +++ b/src/compiler/js-context-specialization.cc @@ -15,6 +15,26 @@ namespace v8 { namespace internal { namespace compiler { +// TODO(titzer): factor this out to a common routine with js-typed-lowering. +static void ReplaceEffectfulWithValue(Node* node, Node* value) { + Node* effect = NULL; + if (OperatorProperties::HasEffectInput(node->op())) { + effect = NodeProperties::GetEffectInput(node); + } + + // Requires distinguishing between value and effect edges. + UseIter iter = node->uses().begin(); + while (iter != node->uses().end()) { + if (NodeProperties::IsEffectEdge(iter.edge())) { + DCHECK_NE(NULL, effect); + iter = iter.UpdateToAndIncrement(effect); + } else { + iter = iter.UpdateToAndIncrement(value); + } + } +} + + class ContextSpecializationVisitor : public NullNodeVisitor { public: explicit ContextSpecializationVisitor(JSContextSpecializer* spec) @@ -25,16 +45,14 @@ class ContextSpecializationVisitor : public NullNodeVisitor { case IrOpcode::kJSLoadContext: { Reduction r = spec_->ReduceJSLoadContext(node); if (r.Changed() && r.replacement() != node) { - NodeProperties::ReplaceWithValue(node, r.replacement()); - node->RemoveAllInputs(); + ReplaceEffectfulWithValue(node, r.replacement()); } break; } case IrOpcode::kJSStoreContext: { Reduction r = spec_->ReduceJSStoreContext(node); if (r.Changed() && r.replacement() != node) { - NodeProperties::ReplaceWithValue(node, r.replacement()); - node->RemoveAllInputs(); + ReplaceEffectfulWithValue(node, r.replacement()); } break; } @@ -50,8 +68,7 @@ class ContextSpecializationVisitor : public NullNodeVisitor { void JSContextSpecializer::SpecializeToContext() { - NodeProperties::ReplaceWithValue(context_, - jsgraph_->Constant(info_->context())); + ReplaceEffectfulWithValue(context_, jsgraph_->Constant(info_->context())); ContextSpecializationVisitor visitor(this); jsgraph_->graph()->VisitNodeInputsFromEnd(&visitor); diff --git a/src/compiler/js-inlining.cc b/src/compiler/js-inlining.cc deleted file mode 100644 index 5dcc0e1e4..000000000 --- a/src/compiler/js-inlining.cc +++ /dev/null @@ -1,327 +0,0 @@ -// Copyright 2014 the V8 project authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "src/compiler/ast-graph-builder.h" -#include "src/compiler/common-operator.h" -#include "src/compiler/generic-node-inl.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-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/parser.h" -#include "src/rewriter.h" -#include "src/scopes.h" - - -namespace v8 { -namespace internal { -namespace compiler { - -class InlinerVisitor : public NullNodeVisitor { - public: - explicit InlinerVisitor(JSInliner* inliner) : inliner_(inliner) {} - - GenericGraphVisit::Control Post(Node* node) { - switch (node->opcode()) { - case IrOpcode::kJSCallFunction: - inliner_->TryInlineCall(node); - break; - default: - break; - } - return GenericGraphVisit::CONTINUE; - } - - private: - JSInliner* inliner_; -}; - - -void JSInliner::Inline() { - InlinerVisitor visitor(this); - jsgraph_->graph()->VisitNodeInputsFromEnd(&visitor); -} - - -static void MoveWithDependencies(Graph* graph, Node* node, Node* old_block, - Node* new_block) { - if (OperatorProperties::HasControlInput(node->op())) { - // Check if we have left the old_block. - if (NodeProperties::GetControlInput(node) != old_block) return; - // If not, move this node to the new_block. - NodeProperties::ReplaceControlInput(node, new_block); - } - // Independent of whether a node has a control input or not, - // it might have a dependency that is pinned to old_block. - for (InputIter iter = node->inputs().begin(); iter != node->inputs().end(); - ++iter) { - if (NodeProperties::IsControlEdge(iter.edge())) continue; - MoveWithDependencies(graph, *iter, old_block, new_block); - } -} - - -static void MoveAllControlNodes(Node* from, Node* to) { - for (UseIter iter = from->uses().begin(); iter != from->uses().end();) { - if (NodeProperties::IsControlEdge(iter.edge())) { - iter.UpdateToAndIncrement(to); - } else { - ++iter; - } - } -} - - -// 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 function, CompilationInfoWithZone* info) { - CHECK(Parser::Parse(info)); - StrictMode strict_mode = info->function()->strict_mode(); - info->SetStrictMode(strict_mode); - info->SetOptimizing(BailoutId::None(), Handle(function->code())); - CHECK(Rewriter::Rewrite(info)); - CHECK(Scope::Analyze(info)); - CHECK_NE(NULL, info->scope()); - Handle scope_info = ScopeInfo::Create(info->scope(), info->zone()); - info->shared_info()->set_scope_info(*scope_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. -// InlineAtCall will create some new nodes using {graph}'s builders (and hence -// those nodes will live in {graph}'s zone. -class Inlinee { - public: - explicit Inlinee(JSGraph* graph) : jsgraph_(graph) {} - - Graph* graph() { return jsgraph_->graph(); } - JSGraph* jsgraph() { return jsgraph_; } - - // Returns the last regular control node, that is - // the last control node before the end node. - Node* end_block() { return NodeProperties::GetControlInput(unique_return()); } - - // Return the effect output of the graph, - // that is the effect input of the return statement of the inlinee. - Node* effect_output() { - return NodeProperties::GetEffectInput(unique_return()); - } - // Return the value output of the graph, - // that is the value input of the return statement of the inlinee. - Node* value_output() { - return NodeProperties::GetValueInput(unique_return(), 0); - } - // Return the unique return statement of the graph. - Node* unique_return() { - Node* unique_return = - NodeProperties::GetControlInput(jsgraph_->graph()->end()); - DCHECK_EQ(IrOpcode::kReturn, unique_return->opcode()); - return unique_return; - } - // Inline this graph at {call}, use {jsgraph} and its zone to create - // any new nodes. - void InlineAtCall(JSGraph* jsgraph, Node* call); - // Ensure that only a single return reaches the end node. - void UnifyReturn(); - - private: - JSGraph* jsgraph_; -}; - - -void Inlinee::UnifyReturn() { - Graph* graph = jsgraph_->graph(); - - Node* final_merge = NodeProperties::GetControlInput(graph->end(), 0); - if (final_merge->opcode() == IrOpcode::kReturn) { - // nothing to do - return; - } - DCHECK_EQ(IrOpcode::kMerge, final_merge->opcode()); - - int predecessors = - OperatorProperties::GetControlInputCount(final_merge->op()); - Operator* op_phi = jsgraph_->common()->Phi(predecessors); - Operator* op_ephi = jsgraph_->common()->EffectPhi(predecessors); - - std::vector values; - std::vector effects; - // Iterate over all control flow predecessors, - // which must be return statements. - InputIter iter = final_merge->inputs().begin(); - while (iter != final_merge->inputs().end()) { - Node* input = *iter; - switch (input->opcode()) { - case IrOpcode::kReturn: - values.push_back(NodeProperties::GetValueInput(input, 0)); - effects.push_back(NodeProperties::GetEffectInput(input)); - iter.UpdateToAndIncrement(NodeProperties::GetControlInput(input)); - input->RemoveAllInputs(); - break; - default: - UNREACHABLE(); - ++iter; - break; - } - } - values.push_back(final_merge); - effects.push_back(final_merge); - Node* phi = graph->NewNode(op_phi, values.size(), values.data()); - Node* ephi = graph->NewNode(op_ephi, effects.size(), effects.data()); - Node* new_return = - graph->NewNode(jsgraph_->common()->Return(), phi, ephi, final_merge); - graph->end()->ReplaceInput(0, new_return); -} - - -void Inlinee::InlineAtCall(JSGraph* jsgraph, Node* call) { - MachineOperatorBuilder machine(jsgraph->zone()); - - Node* control = NodeProperties::GetControlInput(call); - // Move all the nodes to the end block. - MoveAllControlNodes(control, end_block()); - // Now move the ones the call depends on back up. - // We have to do this back-and-forth to treat the case where the call is - // pinned to the start block. - MoveWithDependencies(graph(), call, end_block(), control); - - // The inlinee uses the context from the JSFunction object. This will - // also be the effect dependency for the inlinee as it produces an effect. - // TODO(sigurds) Use simplified load once it is ready. - Node* context = jsgraph->graph()->NewNode( - machine.Load(kMachAnyTagged), NodeProperties::GetValueInput(call, 0), - jsgraph->Int32Constant(JSFunction::kContextOffset - kHeapObjectTag), - NodeProperties::GetEffectInput(call)); - - // {inlinee_inputs} counts JSFunction, Receiver, arguments, context, - // but not effect, control. - int inlinee_inputs = graph()->start()->op()->OutputCount(); - // Context is last argument. - int inlinee_context_index = inlinee_inputs - 1; - // {inliner_inputs} counts JSFunction, Receiver, arguments, but not - // context, effect, control. - int inliner_inputs = OperatorProperties::GetValueInputCount(call->op()); - // Iterate over all uses of the start node. - UseIter iter = graph()->start()->uses().begin(); - while (iter != graph()->start()->uses().end()) { - Node* use = *iter; - switch (use->opcode()) { - case IrOpcode::kParameter: { - int index = 1 + static_cast*>(use->op())->parameter(); - if (index < inliner_inputs && index < inlinee_context_index) { - // There is an input from the call, and the index is a value - // projection but not the context, so rewire the input. - NodeProperties::ReplaceWithValue(*iter, call->InputAt(index)); - } else if (index == inlinee_context_index) { - // This is the context projection, rewire it to the context from the - // JSFunction object. - NodeProperties::ReplaceWithValue(*iter, context); - } else if (index < inlinee_context_index) { - // Call has fewer arguments than required, fill with undefined. - NodeProperties::ReplaceWithValue(*iter, jsgraph->UndefinedConstant()); - } else { - // We got too many arguments, discard for now. - // TODO(sigurds): Fix to treat arguments array correctly. - } - ++iter; - break; - } - default: - if (NodeProperties::IsEffectEdge(iter.edge())) { - iter.UpdateToAndIncrement(context); - } else if (NodeProperties::IsControlEdge(iter.edge())) { - iter.UpdateToAndIncrement(control); - } else { - UNREACHABLE(); - } - break; - } - } - - // 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()); - } - } - call->RemoveAllInputs(); - DCHECK_EQ(0, call->UseCount()); - // TODO(sigurds) Remove this once we copy. - unique_return()->RemoveAllInputs(); -} - - -void JSInliner::TryInlineCall(Node* node) { - DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode()); - - ValueMatcher > match(node->InputAt(0)); - if (!match.HasValue()) { - return; - } - - Handle function = match.Value(); - - if (function->shared()->native()) { - if (FLAG_trace_turbo_inlining) { - SmartArrayPointer 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; - } - - CompilationInfoWithZone info(function); - Parse(function, &info); - - if (info.scope()->arguments() != NULL) { - // For now do not inline functions that use their arguments array. - SmartArrayPointer name = function->shared()->DebugName()->ToCString(); - if (FLAG_trace_turbo_inlining) { - PrintF( - "Not Inlining %s into %s because inlinee uses arguments " - "array\n", - name.get(), info_->shared_info()->DebugName()->ToCString().get()); - } - return; - } - - if (FLAG_trace_turbo_inlining) { - SmartArrayPointer name = function->shared()->DebugName()->ToCString(); - PrintF("Inlining %s into %s\n", name.get(), - info_->shared_info()->DebugName()->ToCString().get()); - } - - Graph graph(info_->zone()); - graph.SetNextNodeId(jsgraph_->graph()->NextNodeID()); - - Typer typer(info_->zone()); - CommonOperatorBuilder common(info_->zone()); - JSGraph jsgraph(&graph, &common, &typer); - - AstGraphBuilder graph_builder(&info, &jsgraph); - graph_builder.CreateGraph(); - - Inlinee inlinee(&jsgraph); - inlinee.UnifyReturn(); - inlinee.InlineAtCall(jsgraph_, node); - - jsgraph_->graph()->SetNextNodeId(inlinee.graph()->NextNodeID()); -} -} -} -} // namespace v8::internal::compiler diff --git a/src/compiler/js-inlining.h b/src/compiler/js-inlining.h deleted file mode 100644 index a43457197..000000000 --- a/src/compiler/js-inlining.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2014 the V8 project authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef V8_COMPILER_JS_INLINING_H_ -#define V8_COMPILER_JS_INLINING_H_ - -#include "src/compiler/js-graph.h" -#include "src/v8.h" - -namespace v8 { -namespace internal { -namespace compiler { - -class JSInliner { - public: - JSInliner(CompilationInfo* info, JSGraph* jsgraph) - : info_(info), jsgraph_(jsgraph) {} - - void Inline(); - void TryInlineCall(Node* node); - - private: - friend class InlinerVisitor; - CompilationInfo* info_; - JSGraph* jsgraph_; - - static void UnifyReturn(Graph* graph); -}; -} -} -} // namespace v8::internal::compiler - -#endif // V8_COMPILER_JS_INLINING_H_ diff --git a/src/compiler/js-typed-lowering.cc b/src/compiler/js-typed-lowering.cc index 4c166e0dc..361cb94f0 100644 --- a/src/compiler/js-typed-lowering.cc +++ b/src/compiler/js-typed-lowering.cc @@ -17,18 +17,39 @@ namespace compiler { // - relax effects from generic but not-side-effecting operations // - relax effects for ToNumber(mixed) +// Replace value uses of {node} with {value} and effect uses of {node} with +// {effect}. If {effect == NULL}, then use the effect input to {node}. +// TODO(titzer): move into a GraphEditor? +static void ReplaceUses(Node* node, Node* value, Node* effect) { + if (value == effect) { + // Effect and value updates are the same; no special iteration needed. + if (value != node) node->ReplaceUses(value); + return; + } + + if (effect == NULL) effect = NodeProperties::GetEffectInput(node); + + // The iteration requires distinguishing between value and effect edges. + UseIter iter = node->uses().begin(); + while (iter != node->uses().end()) { + if (NodeProperties::IsEffectEdge(iter.edge())) { + iter = iter.UpdateToAndIncrement(effect); + } else { + iter = iter.UpdateToAndIncrement(value); + } + } +} + // Relax the effects of {node} by immediately replacing effect uses of {node} // with the effect input to {node}. // TODO(turbofan): replace the effect input to {node} with {graph->start()}. // TODO(titzer): move into a GraphEditor? -static void RelaxEffects(Node* node) { - NodeProperties::ReplaceWithValue(node, node, NULL); -} +static void RelaxEffects(Node* node) { ReplaceUses(node, node, NULL); } Reduction JSTypedLowering::ReplaceEagerly(Node* old, Node* node) { - NodeProperties::ReplaceWithValue(old, node, node); + ReplaceUses(old, node, node); return Reducer::Changed(node); } @@ -501,7 +522,7 @@ Reduction JSTypedLowering::ReduceJSToBooleanInput(Node* input) { static Reduction ReplaceWithReduction(Node* node, Reduction reduction) { if (reduction.Changed()) { - NodeProperties::ReplaceWithValue(node, reduction.replacement()); + ReplaceUses(node, reduction.replacement(), NULL); return reduction; } return Reducer::NoChange(); @@ -552,13 +573,13 @@ Reduction JSTypedLowering::Reduce(Node* node) { // !x => BooleanNot(x) value = graph()->NewNode(simplified()->BooleanNot(), result.replacement()); - NodeProperties::ReplaceWithValue(node, value); + ReplaceUses(node, value, NULL); return Changed(value); } else { // !x => BooleanNot(JSToBoolean(x)) value = graph()->NewNode(simplified()->BooleanNot(), node); node->set_op(javascript()->ToBoolean()); - NodeProperties::ReplaceWithValue(node, value, node); + ReplaceUses(node, value, node); // Note: ReplaceUses() smashes all uses, so smash it back here. value->ReplaceInput(0, node); return ReplaceWith(value); diff --git a/src/compiler/node-properties-inl.h b/src/compiler/node-properties-inl.h index 4a0f1573b..2d63b0cc1 100644 --- a/src/compiler/node-properties-inl.h +++ b/src/compiler/node-properties-inl.h @@ -148,28 +148,6 @@ inline void NodeProperties::RemoveNonValueInputs(Node* node) { } -// Replace value uses of {node} with {value} and effect uses of {node} with -// {effect}. If {effect == NULL}, then use the effect input to {node}. -inline void NodeProperties::ReplaceWithValue(Node* node, Node* value, - Node* effect) { - DCHECK(!OperatorProperties::HasControlOutput(node->op())); - if (effect == NULL && OperatorProperties::HasEffectInput(node->op())) { - effect = NodeProperties::GetEffectInput(node); - } - - // Requires distinguishing between value and effect edges. - UseIter iter = node->uses().begin(); - while (iter != node->uses().end()) { - if (NodeProperties::IsEffectEdge(iter.edge())) { - DCHECK_NE(NULL, effect); - iter = iter.UpdateToAndIncrement(effect); - } else { - iter = iter.UpdateToAndIncrement(value); - } - } -} - - // ----------------------------------------------------------------------------- // Type Bounds. diff --git a/src/compiler/node-properties.h b/src/compiler/node-properties.h index 584344485..6088a0a3a 100644 --- a/src/compiler/node-properties.h +++ b/src/compiler/node-properties.h @@ -33,8 +33,6 @@ class NodeProperties { static inline void ReplaceEffectInput(Node* node, Node* effect, int index = 0); static inline void RemoveNonValueInputs(Node* node); - static inline void ReplaceWithValue(Node* node, Node* value, - Node* effect = NULL); static inline Bounds GetBounds(Node* node); static inline void SetBounds(Node* node, Bounds bounds); diff --git a/src/compiler/pipeline.cc b/src/compiler/pipeline.cc index bc1513ad5..2e9ef98b6 100644 --- a/src/compiler/pipeline.cc +++ b/src/compiler/pipeline.cc @@ -13,7 +13,6 @@ #include "src/compiler/instruction-selector.h" #include "src/compiler/js-context-specialization.h" #include "src/compiler/js-generic-lowering.h" -#include "src/compiler/js-inlining.h" #include "src/compiler/js-typed-lowering.h" #include "src/compiler/phi-reducer.h" #include "src/compiler/register-allocator.h" @@ -187,22 +186,14 @@ Handle Pipeline::GenerateCode() { VerifyAndPrintGraph(&graph, "Initial untyped"); if (FLAG_context_specialization) { - SourcePositionTable::Scope pos(&source_positions, - SourcePosition::Unknown()); + SourcePositionTable::Scope pos_(&source_positions, + SourcePosition::Unknown()); // Specialize the code to the context as aggressively as possible. JSContextSpecializer spec(info(), &jsgraph, context_node); spec.SpecializeToContext(); VerifyAndPrintGraph(&graph, "Context specialized"); } - if (FLAG_turbo_inlining) { - SourcePositionTable::Scope pos(&source_positions, - SourcePosition::Unknown()); - JSInliner inliner(info(), &jsgraph); - inliner.Inline(); - VerifyAndPrintGraph(&graph, "Inlined"); - } - // Print a replay of the initial graph. if (FLAG_print_turbo_replay) { GraphReplayPrinter::PrintReplay(&graph); diff --git a/src/flag-definitions.h b/src/flag-definitions.h index 868802cf6..16fe48ade 100644 --- a/src/flag-definitions.h +++ b/src/flag-definitions.h @@ -338,8 +338,6 @@ DEFINE_BOOL(turbo_source_positions, false, DEFINE_BOOL(context_specialization, true, "enable context specialization in TurboFan") DEFINE_BOOL(turbo_deoptimization, false, "enable deoptimization in TurboFan") -DEFINE_BOOL(turbo_inlining, false, "enable inlining in TurboFan") -DEFINE_BOOL(trace_turbo_inlining, false, "trace TurboFan inlining") DEFINE_INT(typed_array_max_size_in_heap, 64, "threshold for in-heap typed array") diff --git a/test/cctest/cctest.gyp b/test/cctest/cctest.gyp index e31fa869a..559dd6bf2 100644 --- a/test/cctest/cctest.gyp +++ b/test/cctest/cctest.gyp @@ -71,7 +71,6 @@ 'compiler/test-pipeline.cc', 'compiler/test-representation-change.cc', 'compiler/test-run-deopt.cc', - 'compiler/test-run-inlining.cc', 'compiler/test-run-intrinsics.cc', 'compiler/test-run-jsbranches.cc', 'compiler/test-run-jscalls.cc', diff --git a/test/cctest/compiler/test-run-inlining.cc b/test/cctest/compiler/test-run-inlining.cc deleted file mode 100644 index 565bff67e..000000000 --- a/test/cctest/compiler/test-run-inlining.cc +++ /dev/null @@ -1,180 +0,0 @@ -// Copyright 2014 the V8 project authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "src/v8.h" - -#include "test/cctest/compiler/function-tester.h" - -using namespace v8::internal; -using namespace v8::internal::compiler; - -// TODO(sigurds) At the moment we do not write optimization frames when -// inlining, thus the reported stack depth changes depending on inlining. -// AssertStackDepth checks the stack depth at a simple way to ensure that -// inlining actually occurs. -// Once inlining creates optimization frames, all these unit tests need to -// check that the optimization frame is there. - - -static void AssertStackDepth(const v8::FunctionCallbackInfo& args) { - v8::HandleScope scope(args.GetIsolate()); - v8::Handle stackTrace = v8::StackTrace::CurrentStackTrace( - args.GetIsolate(), 10, v8::StackTrace::kDetailed); - CHECK_EQ(args[0]->ToInt32()->Value(), stackTrace->GetFrameCount()); -} - - -static void InstallAssertStackDepthHelper(v8::Isolate* isolate) { - v8::Local context = isolate->GetCurrentContext(); - v8::Local t = - v8::FunctionTemplate::New(isolate, AssertStackDepth); - context->Global()->Set(v8_str("AssertStackDepth"), t->GetFunction()); -} - - -TEST(SimpleInlining) { - i::FLAG_turbo_inlining = true; - FunctionTester T( - "(function(){" - "function foo(s) { AssertStackDepth(1); return s; };" - "function bar(s, t) { return foo(s); };" - "return bar;})();"); - - InstallAssertStackDepthHelper(CcTest::isolate()); - T.CheckCall(T.Val(1), T.Val(1), T.Val(2)); -} - - -TEST(SimpleInliningContext) { - i::FLAG_turbo_inlining = true; - FunctionTester T( - "(function () {" - "function foo(s) { AssertStackDepth(1); var x = 12; return s + x; };" - "function bar(s, t) { return foo(s); };" - "return bar;" - "})();"); - - InstallAssertStackDepthHelper(CcTest::isolate()); - T.CheckCall(T.Val(13), T.Val(1), T.Val(2)); -} - - -TEST(CaptureContext) { - i::FLAG_turbo_inlining = true; - FunctionTester T( - "var f = (function () {" - "var x = 42;" - "function bar(s) { return x + s; };" - "return (function (s) { return bar(s); });" - "})();" - "(function (s) { return f(s)})"); - - InstallAssertStackDepthHelper(CcTest::isolate()); - T.CheckCall(T.Val(42 + 12), T.Val(12), T.undefined()); -} - - -// TODO(sigurds) For now we do not inline any native functions. If we do at -// some point, change this test. -TEST(DontInlineEval) { - i::FLAG_turbo_inlining = true; - FunctionTester T( - "var x = 42;" - "(function () {" - "function bar(s, t) { return eval(\"AssertStackDepth(2); x\") };" - "return bar;" - "})();"); - - InstallAssertStackDepthHelper(CcTest::isolate()); - T.CheckCall(T.Val(42), T.Val("x"), T.undefined()); -} - - -TEST(InlineOmitArguments) { - i::FLAG_turbo_inlining = true; - FunctionTester T( - "(function () {" - "var x = 42;" - "function bar(s, t, u, v) { AssertStackDepth(1); return x + s; };" - "return (function (s,t) { return bar(s); });" - "})();"); - - InstallAssertStackDepthHelper(CcTest::isolate()); - T.CheckCall(T.Val(42 + 12), T.Val(12), T.undefined()); -} - - -TEST(InlineSurplusArguments) { - i::FLAG_turbo_inlining = true; - FunctionTester T( - "(function () {" - "var x = 42;" - "function foo(s) { AssertStackDepth(1); return x + s; };" - "function bar(s,t) { return foo(s,t,13); };" - "return bar;" - "})();"); - - InstallAssertStackDepthHelper(CcTest::isolate()); - T.CheckCall(T.Val(42 + 12), T.Val(12), T.undefined()); -} - - -TEST(InlineTwice) { - i::FLAG_turbo_inlining = true; - FunctionTester T( - "(function () {" - "var x = 42;" - "function bar(s) { AssertStackDepth(1); return x + s; };" - "return (function (s,t) { return bar(s) + bar(t); });" - "})();"); - - InstallAssertStackDepthHelper(CcTest::isolate()); - T.CheckCall(T.Val(2 * 42 + 12 + 4), T.Val(12), T.Val(4)); -} - - -TEST(InlineTwiceDependent) { - i::FLAG_turbo_inlining = true; - FunctionTester T( - "(function () {" - "var x = 42;" - "function foo(s) { AssertStackDepth(1); return x + s; };" - "function bar(s,t) { return foo(foo(s)); };" - "return bar;" - "})();"); - - InstallAssertStackDepthHelper(CcTest::isolate()); - T.CheckCall(T.Val(42 + 42 + 12), T.Val(12), T.Val(4)); -} - - -TEST(InlineTwiceDependentDiamond) { - i::FLAG_turbo_inlining = true; - FunctionTester T( - "(function () {" - "function foo(s) { if (true) {" - " return 12 } else { return 13; } };" - "function bar(s,t) { return foo(foo(1)); };" - "return bar;" - "})();"); - - InstallAssertStackDepthHelper(CcTest::isolate()); - T.CheckCall(T.Val(12), T.undefined(), T.undefined()); -} - - -TEST(InlineTwiceDependentDiamondReal) { - i::FLAG_turbo_inlining = true; - FunctionTester T( - "(function () {" - "var x = 41;" - "function foo(s) { AssertStackDepth(1); if (s % 2 == 0) {" - " return x - s } else { return x + s; } };" - "function bar(s,t) { return foo(foo(s)); };" - "return bar;" - "})();"); - - InstallAssertStackDepthHelper(CcTest::isolate()); - T.CheckCall(T.Val(-11), T.Val(11), T.Val(4)); -} diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp index a715acc8f..3b832852e 100644 --- a/tools/gyp/v8.gyp +++ b/tools/gyp/v8.gyp @@ -384,8 +384,6 @@ '../../src/compiler/js-generic-lowering.h', '../../src/compiler/js-graph.cc', '../../src/compiler/js-graph.h', - '../../src/compiler/js-inlining.cc', - '../../src/compiler/js-inlining.h', '../../src/compiler/js-operator.h', '../../src/compiler/js-typed-lowering.cc', '../../src/compiler/js-typed-lowering.h',