[TurboFan] concurrent support to inline anonymous callback closures

TurboFan can normally inline an arrow function closure callback like:

[1, 2, 3].map(x => x * x);

The serializer has information to support this in the form of
FunctionBlueprint Hints, though it's not exploiting them. This CL
remedies that.

Bug: v8:7790
Change-Id: I8fc10f04ffc9bd2ea03cd761e8a5a41258000c76
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1863939
Reviewed-by: Georg Neis <neis@chromium.org>
Reviewed-by: Maya Lekova <mslekova@chromium.org>
Commit-Queue: Michael Stanton <mvstanton@chromium.org>
Cr-Commit-Position: refs/heads/master@{#64409}
This commit is contained in:
Mike Stanton 2019-10-21 11:23:55 +02:00 committed by Commit Bot
parent 09d4a426ba
commit 014c977f98
2 changed files with 42 additions and 11 deletions

View File

@ -452,11 +452,11 @@ class SerializerForBackgroundCompilation {
SUPPORTED_BYTECODE_LIST(DECLARE_VISIT_BYTECODE)
#undef DECLARE_VISIT_BYTECODE
void ProcessSFIForCallOrConstruct(Callee const& callee,
base::Optional<Hints> new_target,
const HintsVector& arguments,
SpeculationMode speculation_mode,
MissingArgumentsPolicy padding);
void ProcessCalleeForCallOrConstruct(Callee const& callee,
base::Optional<Hints> new_target,
const HintsVector& arguments,
SpeculationMode speculation_mode,
MissingArgumentsPolicy padding);
void ProcessCalleeForCallOrConstruct(Handle<Object> callee,
base::Optional<Hints> new_target,
const HintsVector& arguments,
@ -1845,7 +1845,7 @@ Hints SerializerForBackgroundCompilation::RunChildSerializer(
return hints;
}
void SerializerForBackgroundCompilation::ProcessSFIForCallOrConstruct(
void SerializerForBackgroundCompilation::ProcessCalleeForCallOrConstruct(
Callee const& callee, base::Optional<Hints> new_target,
const HintsVector& arguments, SpeculationMode speculation_mode,
MissingArgumentsPolicy padding) {
@ -1921,8 +1921,8 @@ void SerializerForBackgroundCompilation::ProcessCalleeForCallOrConstruct(
JSFunctionRef function(broker(), Handle<JSFunction>::cast(callee));
function.Serialize();
Callee new_callee(function.object());
ProcessSFIForCallOrConstruct(new_callee, new_target, *actual_arguments,
speculation_mode, padding);
ProcessCalleeForCallOrConstruct(new_callee, new_target, *actual_arguments,
speculation_mode, padding);
}
void SerializerForBackgroundCompilation::ProcessCallOrConstruct(
@ -1965,8 +1965,8 @@ void SerializerForBackgroundCompilation::ProcessCallOrConstruct(
// For JSCallReducer::ReduceJSCall and JSCallReducer::ReduceJSConstruct.
for (auto hint : callee.function_blueprints()) {
ProcessSFIForCallOrConstruct(Callee(hint), new_target, arguments,
speculation_mode, padding);
ProcessCalleeForCallOrConstruct(Callee(hint), new_target, arguments,
speculation_mode, padding);
}
}
@ -2157,6 +2157,12 @@ void SerializerForBackgroundCompilation::ProcessBuiltinCall(
SpeculationMode::kDisallowSpeculation,
kMissingArgumentsAreUndefined);
}
for (auto blueprint : callback.function_blueprints()) {
ProcessCalleeForCallOrConstruct(Callee(blueprint), base::nullopt,
new_arguments,
SpeculationMode::kDisallowSpeculation,
kMissingArgumentsAreUndefined);
}
}
break;
case Builtins::kArrayReduce:
@ -2178,9 +2184,14 @@ void SerializerForBackgroundCompilation::ProcessBuiltinCall(
SpeculationMode::kDisallowSpeculation,
kMissingArgumentsAreUndefined);
}
for (auto blueprint : callback.function_blueprints()) {
ProcessCalleeForCallOrConstruct(Callee(blueprint), base::nullopt,
new_arguments,
SpeculationMode::kDisallowSpeculation,
kMissingArgumentsAreUndefined);
}
}
break;
// TODO(neis): At least for Array* we should look at blueprints too.
// TODO(neis): Might need something like a FunctionBlueprint but for
// creating bound functions rather than creating closures.
case Builtins::kFunctionPrototypeApply:
@ -2215,6 +2226,12 @@ void SerializerForBackgroundCompilation::ProcessBuiltinCall(
SpeculationMode::kDisallowSpeculation,
kMissingArgumentsAreUnknown);
}
for (auto blueprint : arguments[0].function_blueprints()) {
ProcessCalleeForCallOrConstruct(Callee(blueprint), base::nullopt,
new_arguments,
SpeculationMode::kDisallowSpeculation,
kMissingArgumentsAreUnknown);
}
}
break;
case Builtins::kFunctionPrototypeCall:

View File

@ -322,6 +322,20 @@ TEST(BoundFunctionArguments) {
"test(); return test;");
}
TEST(ArrowFunctionInlined) {
// The loop is to ensure there is a feedback vector for the arrow function
// {b}.
CheckForSerializedInlinee(
"function foo() {"
" let b = x => x * x;"
" let a = [1, 2, 3].map(b);"
" return b;"
"}"
"%EnsureFeedbackVectorForFunction(foo);"
"for (let i = 0; i < 100; ++i) foo();"
"return foo;");
}
} // namespace compiler
} // namespace internal
} // namespace v8