Commit 76fd6f25 authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Remove inlining support for the deprecated pipeline.

The deprecated pipeline is used for asm.js only, where we forcibly
disable inlining anyways (for performance reasons), so inlining via
the AstGraphBuilder is essentially dead code by now, thus there's no
point in trying to keep that around in the code base.

Also nuke the test-run-inlining.cc file, which would require some heavy
surgery (for probably little benefit), and move the useful tests for
mjsunit tests instead.

BUG=v8:2206,v8:5657
R=yangguo@chromium.org

Review-Url: https://codereview.chromium.org/2527053002
Cr-Commit-Position: refs/heads/master@{#41245}
parent f0d3cf5b
......@@ -4,15 +4,13 @@
#include "src/compiler/js-inlining.h"
#include "src/ast/ast-numbering.h"
#include "src/ast/ast.h"
#include "src/compilation-info.h"
#include "src/compiler.h"
#include "src/compiler/all-nodes.h"
#include "src/compiler/ast-graph-builder.h"
#include "src/compiler/ast-loop-assignment-analyzer.h"
#include "src/compiler/bytecode-graph-builder.h"
#include "src/compiler/common-operator.h"
#include "src/compiler/compiler-source-position-table.h"
#include "src/compiler/graph-reducer.h"
#include "src/compiler/js-operator.h"
#include "src/compiler/node-matchers.h"
......@@ -21,7 +19,6 @@
#include "src/compiler/simplified-operator.h"
#include "src/isolate-inl.h"
#include "src/parsing/parse-info.h"
#include "src/parsing/rewriter.h"
namespace v8 {
namespace internal {
......@@ -384,6 +381,14 @@ Reduction JSInliner::ReduceJSCall(Node* node, Handle<JSFunction> function) {
JSCallAccessor call(node);
Handle<SharedFunctionInfo> shared_info(function->shared());
// Inlining is only supported in the bytecode pipeline.
if (!info_->is_optimizing_from_bytecode()) {
TRACE("Inlining %s into %s is not supported in the deprecated pipeline\n",
shared_info->DebugName()->ToCString().get(),
info_->shared_info()->DebugName()->ToCString().get());
return NoChange();
}
// Function must be inlineable.
if (!shared_info->IsInlineable()) {
TRACE("Not inlining %s into %s because callee is not inlineable\n",
......@@ -487,9 +492,9 @@ Reduction JSInliner::ReduceJSCall(Node* node, Handle<JSFunction> function) {
ParseInfo parse_info(&zone, shared_info);
CompilationInfo info(&parse_info, function);
if (info_->is_deoptimization_enabled()) info.MarkAsDeoptimizationEnabled();
if (info_->is_optimizing_from_bytecode()) info.MarkAsOptimizeFromBytecode();
info.MarkAsOptimizeFromBytecode();
if (info.is_optimizing_from_bytecode() && !Compiler::EnsureBytecode(&info)) {
if (!Compiler::EnsureBytecode(&info)) {
TRACE("Not inlining %s into %s because bytecode generation failed\n",
shared_info->DebugName()->ToCString().get(),
info_->shared_info()->DebugName()->ToCString().get());
......@@ -499,25 +504,6 @@ Reduction JSInliner::ReduceJSCall(Node* node, Handle<JSFunction> function) {
return NoChange();
}
if (!info.is_optimizing_from_bytecode() &&
!Compiler::ParseAndAnalyze(info.parse_info())) {
TRACE("Not inlining %s into %s because parsing failed\n",
shared_info->DebugName()->ToCString().get(),
info_->shared_info()->DebugName()->ToCString().get());
if (info_->isolate()->has_pending_exception()) {
info_->isolate()->clear_pending_exception();
}
return NoChange();
}
if (!info.is_optimizing_from_bytecode() &&
!Compiler::EnsureDeoptimizationSupport(&info)) {
TRACE("Not inlining %s into %s because deoptimization support failed\n",
shared_info->DebugName()->ToCString().get(),
info_->shared_info()->DebugName()->ToCString().get());
return NoChange();
}
// Remember that we inlined this function. This needs to be called right
// after we ensure deoptimization support so that the code flusher
// does not remove the code with the deoptimization support.
......@@ -538,7 +524,7 @@ Reduction JSInliner::ReduceJSCall(Node* node, Handle<JSFunction> function) {
// Create the subgraph for the inlinee.
Node* start;
Node* end;
if (info.is_optimizing_from_bytecode()) {
{
// Run the BytecodeGraphBuilder to create the subgraph.
Graph::SubgraphScope scope(graph());
BytecodeGraphBuilder graph_builder(&zone, &info, jsgraph(),
......@@ -546,22 +532,6 @@ Reduction JSInliner::ReduceJSCall(Node* node, Handle<JSFunction> function) {
inlining_id);
graph_builder.CreateGraph(false);
// Extract the inlinee start/end nodes.
start = graph()->start();
end = graph()->end();
} else {
// Run the loop assignment analyzer on the inlinee.
AstLoopAssignmentAnalyzer loop_assignment_analyzer(&zone, &info);
LoopAssignmentAnalysis* loop_assignment =
loop_assignment_analyzer.Analyze();
// Run the AstGraphBuilder to create the subgraph.
Graph::SubgraphScope scope(graph());
AstGraphBuilderWithPositions graph_builder(
&zone, &info, jsgraph(), call.frequency(), loop_assignment,
source_positions_, inlining_id);
graph_builder.CreateGraph(false);
// Extract the inlinee start/end nodes.
start = graph()->start();
end = graph()->end();
......
......@@ -552,9 +552,6 @@ PipelineCompilationJob::Status PipelineCompilationJob::PrepareJobImpl() {
if (!FLAG_always_opt) {
info()->MarkAsBailoutOnUninitialized();
}
if (FLAG_turbo_inlining) {
info()->MarkAsInliningEnabled();
}
}
if (!info()->shared_info()->asm_function() || FLAG_turbo_asm_deoptimization) {
info()->MarkAsDeoptimizationEnabled();
......@@ -564,6 +561,8 @@ PipelineCompilationJob::Status PipelineCompilationJob::PrepareJobImpl() {
}
if (!info()->is_optimizing_from_bytecode()) {
if (!Compiler::EnsureDeoptimizationSupport(info())) return FAILED;
} else if (FLAG_turbo_inlining) {
info()->MarkAsInliningEnabled();
}
linkage_ = new (&zone_) Linkage(Linkage::ComputeIncoming(&zone_, info()));
......
......@@ -44,7 +44,6 @@ v8_executable("cctest") {
"compiler/test-run-bytecode-graph-builder.cc",
"compiler/test-run-calls-to-external-references.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",
......
......@@ -64,7 +64,6 @@
'compiler/test-run-bytecode-graph-builder.cc',
'compiler/test-run-calls-to-external-references.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',
......
// 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/compilation-info.h"
#include "src/frames-inl.h"
#include "test/cctest/compiler/function-tester.h"
namespace v8 {
namespace internal {
namespace compiler {
namespace {
// Helper to determine inline count via JavaScriptFrame::GetFunctions.
// Note that a count of 1 indicates that no inlining has occured.
void AssertInlineCount(const v8::FunctionCallbackInfo<v8::Value>& args) {
JavaScriptFrameIterator it(CcTest::i_isolate());
int frames_seen = 0;
JavaScriptFrame* topmost = it.frame();
while (!it.done()) {
JavaScriptFrame* frame = it.frame();
List<JSFunction*> functions(2);
frame->GetFunctions(&functions);
PrintF("%d %s, inline count: %d\n", frames_seen,
frame->function()->shared()->DebugName()->ToCString().get(),
functions.length());
frames_seen++;
it.Advance();
}
List<JSFunction*> functions(2);
topmost->GetFunctions(&functions);
CHECK_EQ(args[0]
->ToInt32(args.GetIsolate()->GetCurrentContext())
.ToLocalChecked()
->Value(),
functions.length());
}
void InstallAssertInlineCountHelper(v8::Isolate* isolate) {
v8::Local<v8::Context> context = isolate->GetCurrentContext();
v8::Local<v8::FunctionTemplate> t =
v8::FunctionTemplate::New(isolate, AssertInlineCount);
CHECK(context->Global()
->Set(context, v8_str("AssertInlineCount"),
t->GetFunction(context).ToLocalChecked())
.FromJust());
}
const uint32_t kRestrictedInliningFlags = 0;
const uint32_t kInlineFlags = CompilationInfo::kInliningEnabled;
} // namespace
TEST(SimpleInlining) {
FunctionTester T(
"function foo(s) { AssertInlineCount(2); return s; };"
"function bar(s, t) { return foo(s); };"
"bar;",
kInlineFlags);
InstallAssertInlineCountHelper(CcTest::isolate());
T.CheckCall(T.Val(1), T.Val(1), T.Val(2));
}
TEST(SimpleInliningDeopt) {
FunctionTester T(
"function foo(s) { %DeoptimizeFunction(bar); return s; };"
"function bar(s, t) { return foo(s); };"
"bar;",
kInlineFlags);
InstallAssertInlineCountHelper(CcTest::isolate());
T.CheckCall(T.Val(1), T.Val(1), T.Val(2));
}
TEST(SimpleInliningDeoptSelf) {
FunctionTester T(
"function foo(s) { %_DeoptimizeNow(); return s; };"
"function bar(s, t) { return foo(s); };"
"bar;",
kInlineFlags);
InstallAssertInlineCountHelper(CcTest::isolate());
T.CheckCall(T.Val(1), T.Val(1), T.Val(2));
}
TEST(SimpleInliningContext) {
FunctionTester T(
"function foo(s) { AssertInlineCount(2); var x = 12; return s + x; };"
"function bar(s, t) { return foo(s); };"
"bar;",
kInlineFlags);
InstallAssertInlineCountHelper(CcTest::isolate());
T.CheckCall(T.Val(13), T.Val(1), T.Val(2));
}
TEST(SimpleInliningContextDeopt) {
FunctionTester T(
"function foo(s) {"
" AssertInlineCount(2); %DeoptimizeFunction(bar); var x = 12;"
" return s + x;"
"};"
"function bar(s, t) { return foo(s); };"
"bar;",
kInlineFlags);
InstallAssertInlineCountHelper(CcTest::isolate());
T.CheckCall(T.Val(13), T.Val(1), T.Val(2));
}
TEST(CaptureContext) {
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) })",
kInlineFlags);
InstallAssertInlineCountHelper(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) {
FunctionTester T(
"var x = 42;"
"function bar(s, t) { return eval(\"AssertInlineCount(1); x\") };"
"bar;",
kInlineFlags);
InstallAssertInlineCountHelper(CcTest::isolate());
T.CheckCall(T.Val(42), T.Val("x"), T.undefined());
}
TEST(InlineOmitArguments) {
FunctionTester T(
"var x = 42;"
"function bar(s, t, u, v) { AssertInlineCount(2); return x + s; };"
"function foo(s, t) { return bar(s); };"
"foo;",
kInlineFlags);
InstallAssertInlineCountHelper(CcTest::isolate());
T.CheckCall(T.Val(42 + 12), T.Val(12), T.undefined());
}
TEST(InlineOmitArgumentsObject) {
FunctionTester T(
"function bar(s, t, u, v) { AssertInlineCount(2); return arguments; };"
"function foo(s, t) { var args = bar(s);"
" return args.length == 1 &&"
" args[0] == 11; };"
"foo;",
kInlineFlags);
InstallAssertInlineCountHelper(CcTest::isolate());
T.CheckCall(T.true_value(), T.Val(11), T.undefined());
}
TEST(InlineOmitArgumentsDeopt) {
FunctionTester T(
"function foo(s,t,u,v) { AssertInlineCount(2);"
" %DeoptimizeFunction(bar); return baz(); };"
"function bar() { return foo(11); };"
"function baz() { return foo.arguments.length == 1 &&"
" foo.arguments[0] == 11; }"
"bar;",
kInlineFlags);
InstallAssertInlineCountHelper(CcTest::isolate());
T.CheckCall(T.true_value(), T.Val(12), T.Val(14));
}
TEST(InlineSurplusArguments) {
FunctionTester T(
"var x = 42;"
"function foo(s) { AssertInlineCount(2); return x + s; };"
"function bar(s, t) { return foo(s, t, 13); };"
"bar;",
kInlineFlags);
InstallAssertInlineCountHelper(CcTest::isolate());
T.CheckCall(T.Val(42 + 12), T.Val(12), T.undefined());
}
TEST(InlineSurplusArgumentsObject) {
FunctionTester T(
"function foo(s) { AssertInlineCount(2); return arguments; };"
"function bar(s, t) { var args = foo(s, t, 13);"
" return args.length == 3 &&"
" args[0] == 11 &&"
" args[1] == 12 &&"
" args[2] == 13; };"
"bar;",
kInlineFlags);
InstallAssertInlineCountHelper(CcTest::isolate());
T.CheckCall(T.true_value(), T.Val(11), T.Val(12));
}
TEST(InlineSurplusArgumentsDeopt) {
FunctionTester T(
"function foo(s) { AssertInlineCount(2); %DeoptimizeFunction(bar);"
" return baz(); };"
"function bar() { return foo(13, 14, 15); };"
"function baz() { return foo.arguments.length == 3 &&"
" foo.arguments[0] == 13 &&"
" foo.arguments[1] == 14 &&"
" foo.arguments[2] == 15; }"
"bar;",
kInlineFlags);
InstallAssertInlineCountHelper(CcTest::isolate());
T.CheckCall(T.true_value(), T.Val(12), T.Val(14));
}
TEST(InlineTwice) {
FunctionTester T(
"var x = 42;"
"function bar(s) { AssertInlineCount(2); return x + s; };"
"function foo(s, t) { return bar(s) + bar(t); };"
"foo;",
kInlineFlags);
InstallAssertInlineCountHelper(CcTest::isolate());
T.CheckCall(T.Val(2 * 42 + 12 + 4), T.Val(12), T.Val(4));
}
TEST(InlineTwiceDependent) {
FunctionTester T(
"var x = 42;"
"function foo(s) { AssertInlineCount(2); return x + s; };"
"function bar(s,t) { return foo(foo(s)); };"
"bar;",
kInlineFlags);
InstallAssertInlineCountHelper(CcTest::isolate());
T.CheckCall(T.Val(42 + 42 + 12), T.Val(12), T.Val(4));
}
TEST(InlineTwiceDependentDiamond) {
FunctionTester T(
"var x = 41;"
"function foo(s) { AssertInlineCount(2); if (s % 2 == 0) {"
" return x - s } else { return x + s; } };"
"function bar(s,t) { return foo(foo(s)); };"
"bar;",
kInlineFlags);
InstallAssertInlineCountHelper(CcTest::isolate());
T.CheckCall(T.Val(-11), T.Val(11), T.Val(4));
}
TEST(InlineTwiceDependentDiamondDifferent) {
FunctionTester T(
"var x = 41;"
"function foo(s,t) { AssertInlineCount(2); if (s % 2 == 0) {"
" return x - s * t } else { return x + s * t; } };"
"function bar(s,t) { return foo(foo(s, 3), 5); };"
"bar;",
kInlineFlags);
InstallAssertInlineCountHelper(CcTest::isolate());
T.CheckCall(T.Val(-329), T.Val(11), T.Val(4));
}
TEST(InlineLoopGuardedEmpty) {
FunctionTester T(
"function foo(s) { AssertInlineCount(2); if (s) while (s); return s; };"
"function bar(s,t) { return foo(s); };"
"bar;",
kInlineFlags);
InstallAssertInlineCountHelper(CcTest::isolate());
T.CheckCall(T.Val(0.0), T.Val(0.0), T.Val(4));
}
TEST(InlineLoopGuardedOnce) {
FunctionTester T(
"function foo(s,t) { AssertInlineCount(2); if (t > 0) while (s > 0) {"
" s = s - 1; }; return s; };"
"function bar(s,t) { return foo(s,t); };"
"bar;",
kInlineFlags);
InstallAssertInlineCountHelper(CcTest::isolate());
T.CheckCall(T.Val(0.0), T.Val(11), T.Val(4));
}
TEST(InlineLoopGuardedTwice) {
FunctionTester T(
"function foo(s,t) { AssertInlineCount(2); if (t > 0) while (s > 0) {"
" s = s - 1; }; return s; };"
"function bar(s,t) { return foo(foo(s,t),t); };"
"bar;",
kInlineFlags);
InstallAssertInlineCountHelper(CcTest::isolate());
T.CheckCall(T.Val(0.0), T.Val(11), T.Val(4));
}
TEST(InlineLoopUnguardedEmpty) {
FunctionTester T(
"function foo(s) { AssertInlineCount(2); while (s); return s; };"
"function bar(s, t) { return foo(s); };"
"bar;",
kInlineFlags);
InstallAssertInlineCountHelper(CcTest::isolate());
T.CheckCall(T.Val(0.0), T.Val(0.0), T.Val(4));
}
TEST(InlineLoopUnguardedOnce) {
FunctionTester T(
"function foo(s) { AssertInlineCount(2); while (s) {"
" s = s - 1; }; return s; };"
"function bar(s, t) { return foo(s); };"
"bar;",
kInlineFlags);
InstallAssertInlineCountHelper(CcTest::isolate());
T.CheckCall(T.Val(0.0), T.Val(0.0), T.Val(4));
}
TEST(InlineLoopUnguardedTwice) {
FunctionTester T(
"function foo(s) { AssertInlineCount(2); while (s > 0) {"
" s = s - 1; }; return s; };"
"function bar(s,t) { return foo(foo(s,t),t); };"
"bar;",
kInlineFlags);
InstallAssertInlineCountHelper(CcTest::isolate());
T.CheckCall(T.Val(0.0), T.Val(0.0), T.Val(4));
}
TEST(InlineStrictIntoNonStrict) {
FunctionTester T(
"var x = Object.create({}, { y: { value:42, writable:false } });"
"function foo(s) { 'use strict';"
" x.y = 9; };"
"function bar(s,t) { return foo(s); };"
"bar;",
kInlineFlags);
InstallAssertInlineCountHelper(CcTest::isolate());
T.CheckThrows(T.undefined(), T.undefined());
}
TEST(InlineNonStrictIntoStrict) {
FunctionTester T(
"var x = Object.create({}, { y: { value:42, writable:false } });"
"function foo(s) { x.y = 9; return x.y; };"
"function bar(s,t) { \'use strict\'; return foo(s); };"
"bar;",
kInlineFlags);
InstallAssertInlineCountHelper(CcTest::isolate());
T.CheckCall(T.Val(42), T.undefined(), T.undefined());
}
TEST(InlineWithArguments) {
FunctionTester T(
"function foo(s,t,u) { AssertInlineCount(2);"
" return foo.arguments.length == 3 &&"
" foo.arguments[0] == 13 &&"
" foo.arguments[1] == 14 &&"
" foo.arguments[2] == 15;"
"}"
"function bar() { return foo(13, 14, 15); };"
"bar;",
kInlineFlags);
InstallAssertInlineCountHelper(CcTest::isolate());
T.CheckCall(T.true_value(), T.Val(12), T.Val(14));
}
TEST(InlineBuiltin) {
FunctionTester T(
"function foo(s,t,u) { AssertInlineCount(2); return true; }"
"function bar() { return foo(); };"
"%SetForceInlineFlag(foo);"
"bar;",
kRestrictedInliningFlags);
InstallAssertInlineCountHelper(CcTest::isolate());
T.CheckCall(T.true_value());
}
TEST(InlineNestedBuiltin) {
FunctionTester T(
"function foo(s,t,u) { AssertInlineCount(3); return true; }"
"function baz(s,t,u) { return foo(s,t,u); }"
"function bar() { return baz(); };"
"%SetForceInlineFlag(foo);"
"%SetForceInlineFlag(baz);"
"bar;",
kRestrictedInliningFlags);
InstallAssertInlineCountHelper(CcTest::isolate());
T.CheckCall(T.true_value());
}
TEST(InlineSelfRecursive) {
FunctionTester T(
"function foo(x) { "
" AssertInlineCount(1);"
" if (x == 1) return foo(12);"
" return x;"
"}"
"foo;",
kInlineFlags);
InstallAssertInlineCountHelper(CcTest::isolate());
T.CheckCall(T.Val(12), T.Val(1));
}
TEST(InlineMutuallyRecursive) {
FunctionTester T(
"function bar(x) { AssertInlineCount(2); return foo(x); }"
"function foo(x) { "
" if (x == 1) return bar(42);"
" return x;"
"}"
"foo;",
kInlineFlags);
InstallAssertInlineCountHelper(CcTest::isolate());
T.CheckCall(T.Val(42), T.Val(1));
}
} // namespace compiler
} // namespace internal
} // namespace v8
// Copyright 2016 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.
// Flags: --allow-natives-syntax
var foo = (function() {
var x = 42;
function bar(s) { return x + s; }
return (function (s) { return bar(s); })
})();
var baz = (function (s) { return foo(s) });
%OptimizeFunctionOnNextCall(baz);
assertEquals(42 + 12, baz(12));
// Copyright 2016 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.
// Flags: --allow-natives-syntax
function foo(s) {
%DeoptimizeFunction(bar);
var x = 12;
return s + x;
}
function bar(s, t) {
return foo(s);
}
%OptimizeFunctionOnNextCall(bar);
assertEquals(13, bar(1, 2));
// Copyright 2016 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.
// Flags: --allow-natives-syntax
function foo(s, t, u, v) {
%DeoptimizeFunction(bar);
return baz();
}
function bar() {
return foo(11);
}
function baz() {
return foo.arguments.length == 1 && foo.arguments[0] == 11;
}
%OptimizeFunctionOnNextCall(bar);
assertEquals(true, bar(12, 14));
// Copyright 2016 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.
// Flags: --allow-natives-syntax
function bar(s, t, u, v) { return arguments; }
function foo(s, t) {
var args = bar(s);
return args.length == 1 && args[0] == 11;
}
%OptimizeFunctionOnNextCall(foo);
assertEquals(true, foo(11));
// Copyright 2016 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.
// Flags: --allow-natives-syntax
var x = 42;
function bar(s, t, u, v) { return x + s; }
function foo(s, t) { return bar(s); }
%OptimizeFunctionOnNextCall(foo);
assertEquals(42 + 12, foo(12));
// Copyright 2016 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.
// Flags: --allow-natives-syntax
function foo(s) {
%DeoptimizeFunction(bar);
return baz();
}
function bar() { return foo(13, 14, 15); }
function baz() {
return foo.arguments.length == 3 &&
foo.arguments[0] == 13 &&
foo.arguments[1] == 14 &&
foo.arguments[2] == 15;
}
%OptimizeFunctionOnNextCall(bar);
assertEquals(true, bar(12, 14));
// Copyright 2016 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.
// Flags: --allow-natives-syntax
function foo(s) { return arguments; }
function bar(s, t) {
var args = foo(s, t, 13);
return args.length == 3 &&
args[0] == 11 &&
args[1] == 12 &&
args[2] == 13;
}
%OptimizeFunctionOnNextCall(bar);
assertEquals(true, bar(11, 12));
// Copyright 2016 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.
// Flags: --allow-natives-syntax
var x = 42;
function foo(s) { return x + s; }
function bar(s, t) { return foo(s, t, 13); }
%OptimizeFunctionOnNextCall(bar);
assertEquals(42 + 12, bar(12));
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment