Commit 014c977f authored by Mike Stanton's avatar Mike Stanton Committed by Commit Bot

[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/+/1863939Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Reviewed-by: 's avatarMaya Lekova <mslekova@chromium.org>
Commit-Queue: Michael Stanton <mvstanton@chromium.org>
Cr-Commit-Position: refs/heads/master@{#64409}
parent 09d4a426
...@@ -452,11 +452,11 @@ class SerializerForBackgroundCompilation { ...@@ -452,11 +452,11 @@ class SerializerForBackgroundCompilation {
SUPPORTED_BYTECODE_LIST(DECLARE_VISIT_BYTECODE) SUPPORTED_BYTECODE_LIST(DECLARE_VISIT_BYTECODE)
#undef DECLARE_VISIT_BYTECODE #undef DECLARE_VISIT_BYTECODE
void ProcessSFIForCallOrConstruct(Callee const& callee, void ProcessCalleeForCallOrConstruct(Callee const& callee,
base::Optional<Hints> new_target, base::Optional<Hints> new_target,
const HintsVector& arguments, const HintsVector& arguments,
SpeculationMode speculation_mode, SpeculationMode speculation_mode,
MissingArgumentsPolicy padding); MissingArgumentsPolicy padding);
void ProcessCalleeForCallOrConstruct(Handle<Object> callee, void ProcessCalleeForCallOrConstruct(Handle<Object> callee,
base::Optional<Hints> new_target, base::Optional<Hints> new_target,
const HintsVector& arguments, const HintsVector& arguments,
...@@ -1845,7 +1845,7 @@ Hints SerializerForBackgroundCompilation::RunChildSerializer( ...@@ -1845,7 +1845,7 @@ Hints SerializerForBackgroundCompilation::RunChildSerializer(
return hints; return hints;
} }
void SerializerForBackgroundCompilation::ProcessSFIForCallOrConstruct( void SerializerForBackgroundCompilation::ProcessCalleeForCallOrConstruct(
Callee const& callee, base::Optional<Hints> new_target, Callee const& callee, base::Optional<Hints> new_target,
const HintsVector& arguments, SpeculationMode speculation_mode, const HintsVector& arguments, SpeculationMode speculation_mode,
MissingArgumentsPolicy padding) { MissingArgumentsPolicy padding) {
...@@ -1921,8 +1921,8 @@ void SerializerForBackgroundCompilation::ProcessCalleeForCallOrConstruct( ...@@ -1921,8 +1921,8 @@ void SerializerForBackgroundCompilation::ProcessCalleeForCallOrConstruct(
JSFunctionRef function(broker(), Handle<JSFunction>::cast(callee)); JSFunctionRef function(broker(), Handle<JSFunction>::cast(callee));
function.Serialize(); function.Serialize();
Callee new_callee(function.object()); Callee new_callee(function.object());
ProcessSFIForCallOrConstruct(new_callee, new_target, *actual_arguments, ProcessCalleeForCallOrConstruct(new_callee, new_target, *actual_arguments,
speculation_mode, padding); speculation_mode, padding);
} }
void SerializerForBackgroundCompilation::ProcessCallOrConstruct( void SerializerForBackgroundCompilation::ProcessCallOrConstruct(
...@@ -1965,8 +1965,8 @@ void SerializerForBackgroundCompilation::ProcessCallOrConstruct( ...@@ -1965,8 +1965,8 @@ void SerializerForBackgroundCompilation::ProcessCallOrConstruct(
// For JSCallReducer::ReduceJSCall and JSCallReducer::ReduceJSConstruct. // For JSCallReducer::ReduceJSCall and JSCallReducer::ReduceJSConstruct.
for (auto hint : callee.function_blueprints()) { for (auto hint : callee.function_blueprints()) {
ProcessSFIForCallOrConstruct(Callee(hint), new_target, arguments, ProcessCalleeForCallOrConstruct(Callee(hint), new_target, arguments,
speculation_mode, padding); speculation_mode, padding);
} }
} }
...@@ -2157,6 +2157,12 @@ void SerializerForBackgroundCompilation::ProcessBuiltinCall( ...@@ -2157,6 +2157,12 @@ void SerializerForBackgroundCompilation::ProcessBuiltinCall(
SpeculationMode::kDisallowSpeculation, SpeculationMode::kDisallowSpeculation,
kMissingArgumentsAreUndefined); kMissingArgumentsAreUndefined);
} }
for (auto blueprint : callback.function_blueprints()) {
ProcessCalleeForCallOrConstruct(Callee(blueprint), base::nullopt,
new_arguments,
SpeculationMode::kDisallowSpeculation,
kMissingArgumentsAreUndefined);
}
} }
break; break;
case Builtins::kArrayReduce: case Builtins::kArrayReduce:
...@@ -2178,9 +2184,14 @@ void SerializerForBackgroundCompilation::ProcessBuiltinCall( ...@@ -2178,9 +2184,14 @@ void SerializerForBackgroundCompilation::ProcessBuiltinCall(
SpeculationMode::kDisallowSpeculation, SpeculationMode::kDisallowSpeculation,
kMissingArgumentsAreUndefined); kMissingArgumentsAreUndefined);
} }
for (auto blueprint : callback.function_blueprints()) {
ProcessCalleeForCallOrConstruct(Callee(blueprint), base::nullopt,
new_arguments,
SpeculationMode::kDisallowSpeculation,
kMissingArgumentsAreUndefined);
}
} }
break; break;
// TODO(neis): At least for Array* we should look at blueprints too.
// TODO(neis): Might need something like a FunctionBlueprint but for // TODO(neis): Might need something like a FunctionBlueprint but for
// creating bound functions rather than creating closures. // creating bound functions rather than creating closures.
case Builtins::kFunctionPrototypeApply: case Builtins::kFunctionPrototypeApply:
...@@ -2215,6 +2226,12 @@ void SerializerForBackgroundCompilation::ProcessBuiltinCall( ...@@ -2215,6 +2226,12 @@ void SerializerForBackgroundCompilation::ProcessBuiltinCall(
SpeculationMode::kDisallowSpeculation, SpeculationMode::kDisallowSpeculation,
kMissingArgumentsAreUnknown); kMissingArgumentsAreUnknown);
} }
for (auto blueprint : arguments[0].function_blueprints()) {
ProcessCalleeForCallOrConstruct(Callee(blueprint), base::nullopt,
new_arguments,
SpeculationMode::kDisallowSpeculation,
kMissingArgumentsAreUnknown);
}
} }
break; break;
case Builtins::kFunctionPrototypeCall: case Builtins::kFunctionPrototypeCall:
......
...@@ -322,6 +322,20 @@ TEST(BoundFunctionArguments) { ...@@ -322,6 +322,20 @@ TEST(BoundFunctionArguments) {
"test(); return test;"); "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 compiler
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
......
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