if (typeof console === 'undefined') console = {log:print}; | |
const TESTS = []; | |
function foo(x) { | |
"use strict"; | |
return x; | |
} | |
(function() { | |
TESTS.push( | |
function callUnderApplication() { | |
foo(); | |
foo(); | |
foo(); | |
foo(); | |
foo(); | |
foo(); | |
foo(); | |
foo(); | |
}, | |
function callOverApplication1() { | |
foo(null, null); | |
foo(null, null); | |
foo(null, null); | |
foo(null, null); | |
foo(null, null); | |
foo(null, null); | |
foo(null, null); | |
foo(null, null); | |
}, | |
function callOverApplication2() { | |
foo(null, null, null); | |
foo(null, null, null); | |
foo(null, null, null); | |
foo(null, null, null); | |
foo(null, null, null); | |
foo(null, null, null); | |
foo(null, null, null); | |
foo(null, null, null); | |
} | |
); | |
})(); | |
const N = 1e7; | |
function test(fn) { | |
var result; | |
for (var i = 0; i < N; ++i) { | |
result = fn(); | |
} | |
return result; | |
} | |
test(x => x); // Pollute call feedback early on. | |
for (var j = 0; j < TESTS.length; ++j) { | |
test(TESTS[j]); | |
} | |
for (var j = 0; j < TESTS.length; ++j) { | |
var startTime = Date.now(); | |
test(TESTS[j]); | |
console.log(`${TESTS[j].name}: ${Date.now() - startTime} ms.`); | |
} |
// Copyright 2013-2019 Benedikt Meurer | |
// | |
// Licensed under the Apache License, Version 2.0 (the "License"); | |
// you may not use this file except in compliance with the License. | |
// You may obtain a copy of the License at | |
// | |
// <https://www.apache.org/licenses/LICENSE-2.0> | |
// | |
// Unless required by applicable law or agreed to in writing, software | |
// distributed under the License is distributed on an "AS IS" BASIS, | |
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
// See the License for the specific language governing permissions and | |
// limitations under the License. | |
if (typeof console === 'undefined') console = {log:print}; | |
const TESTS = []; | |
function foo(x) { | |
"use strict"; | |
return x; | |
} | |
(function() { | |
TESTS.push( | |
function callUnderApplication() { | |
foo(); | |
foo(); | |
foo(); | |
foo(); | |
foo(); | |
foo(); | |
foo(); | |
foo(); | |
}, | |
function callProperApplication() { | |
foo(null); | |
foo(null); | |
foo(null); | |
foo(null); | |
foo(null); | |
foo(null); | |
foo(null); | |
foo(null); | |
}, | |
function callOverApplication1() { | |
foo(null, null); | |
foo(null, null); | |
foo(null, null); | |
foo(null, null); | |
foo(null, null); | |
foo(null, null); | |
foo(null, null); | |
foo(null, null); | |
}, | |
function callOverApplication2() { | |
foo(null, null, null); | |
foo(null, null, null); | |
foo(null, null, null); | |
foo(null, null, null); | |
foo(null, null, null); | |
foo(null, null, null); | |
foo(null, null, null); | |
foo(null, null, null); | |
} | |
); | |
})(); | |
const N = 1e7; | |
function test(fn) { | |
var result; | |
for (var i = 0; i < N; ++i) { | |
result = fn(); | |
} | |
return result; | |
} | |
test(x => x); // Pollute call feedback early on. | |
for (var j = 0; j < TESTS.length; ++j) { | |
test(TESTS[j]); | |
} | |
for (var j = 0; j < TESTS.length; ++j) { | |
var startTime = Date.now(); | |
test(TESTS[j]); | |
console.log(`${TESTS[j].name}: ${Date.now() - startTime} ms.`); | |
} |
diff --git a/src/compiler/js-typed-lowering.cc b/src/compiler/js-typed-lowering.cc | |
index 22139d941c..273f22bf79 100644 | |
--- a/src/compiler/js-typed-lowering.cc | |
+++ b/src/compiler/js-typed-lowering.cc | |
@@ -1612,7 +1612,7 @@ Reduction JSTypedLowering::ReduceJSCallForwardVarargs(Node* node) { | |
Reduction JSTypedLowering::ReduceJSCall(Node* node) { | |
DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); | |
CallParameters const& p = CallParametersOf(node->op()); | |
- int const arity = static_cast<int>(p.arity() - 2); | |
+ int arity = static_cast<int>(p.arity() - 2); | |
ConvertReceiverMode convert_mode = p.convert_mode(); | |
Node* target = NodeProperties::GetValueInput(node, 0); | |
Type target_type = NodeProperties::GetType(target); | |
@@ -1673,18 +1673,28 @@ Reduction JSTypedLowering::ReduceJSCall(Node* node) { | |
Node* argument_count = jsgraph()->Constant(arity); | |
if (NeedsArgumentAdaptorFrame(shared, arity)) { | |
- // Patch {node} to an indirect call via the ArgumentsAdaptorTrampoline. | |
- Callable callable = CodeFactory::ArgumentAdaptor(isolate()); | |
- node->InsertInput(graph()->zone(), 0, | |
- jsgraph()->HeapConstant(callable.code())); | |
- node->InsertInput(graph()->zone(), 2, new_target); | |
- node->InsertInput(graph()->zone(), 3, argument_count); | |
- node->InsertInput( | |
- graph()->zone(), 4, | |
- jsgraph()->Constant(shared.internal_formal_parameter_count())); | |
- NodeProperties::ChangeOp( | |
- node, common()->Call(Linkage::GetStubCallDescriptor( | |
- graph()->zone(), callable.descriptor(), 1 + arity, flags))); | |
+ const int num_decl_parms = shared.internal_formal_parameter_count(); | |
+ if (arity > num_decl_parms) { | |
+ while (arity > num_decl_parms) { | |
+ node->RemoveInput(arity + 1); | |
+ arity--; | |
+ } | |
+ } else { | |
+ while (arity < num_decl_parms) { | |
+ node->InsertInput(graph()->zone(), arity + 2, | |
+ jsgraph()->UndefinedConstant()); | |
+ arity++; | |
+ } | |
+ } | |
+ | |
+ // Patch {node} to a direct call. | |
+ node->InsertInput(graph()->zone(), arity + 2, new_target); | |
+ node->InsertInput(graph()->zone(), arity + 3, argument_count); | |
+ NodeProperties::ChangeOp(node, | |
+ common()->Call(Linkage::GetJSCallDescriptor( | |
+ graph()->zone(), false, 1 + arity, | |
+ flags | CallDescriptor::kCanUseRoots))); | |
+ | |
} else if (shared.HasBuiltinId() && | |
Builtins::HasCppImplementation(shared.builtin_id())) { | |
// Patch {node} to a direct CEntry call. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment