Skip to content

Commit 1f58504

Browse files
mralephcommit-bot@chromium.org
authored andcommitted
[vm/compiler] Do not initialize delayed_type_arguments_ for non-generic closures
This field is only used to implement partial instantiation of generic closures - so it is irrelevant in non-generic ones. Keeping it null instead of empty_type_arguments allows to completely elide a store (which saves around 2 instructions per closure allocation) Change-Id: I1039993a1cfd1bc4b476214712d90b2c443e7cc6 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/121983 Commit-Queue: Vyacheslav Egorov <vegorov@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com>
1 parent 680a880 commit 1f58504

File tree

4 files changed

+29
-21
lines changed

4 files changed

+29
-21
lines changed

runtime/vm/compiler/backend/il_test.cc

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -157,24 +157,22 @@ ISOLATE_UNIT_TEST_CASE(IRTest_InitializingStores) {
157157
/*expected_stores=*/{"f"});
158158
RunInitializingStoresTest(root_library, "f2", CompilerPass::kJIT,
159159
/*expected_stores=*/{"g"});
160-
RunInitializingStoresTest(
161-
root_library, "f3", CompilerPass::kJIT,
162-
/*expected_stores=*/
163-
{"Closure.delayed_type_arguments", "Closure.function"});
160+
RunInitializingStoresTest(root_library, "f3", CompilerPass::kJIT,
161+
/*expected_stores=*/
162+
{"Closure.function"});
164163

165164
// Note that in JIT mode we lower context allocation in a way that hinders
166165
// removal of initializing moves so there would be some redundant stores of
167166
// null left in the graph. In AOT mode we don't apply this optimization
168167
// which enables us to remove more stores.
169-
RunInitializingStoresTest(
170-
root_library, "f4", CompilerPass::kJIT, /*expected_stores=*/
171-
{"value", "Context.parent", "Context.parent", "value",
172-
"Closure.function_type_arguments", "Closure.delayed_type_arguments",
173-
"Closure.function", "Closure.context"});
168+
RunInitializingStoresTest(root_library, "f4",
169+
CompilerPass::kJIT, /*expected_stores=*/
170+
{"value", "Context.parent", "Context.parent",
171+
"value", "Closure.function_type_arguments",
172+
"Closure.function", "Closure.context"});
174173
RunInitializingStoresTest(root_library, "f4",
175174
CompilerPass::kAOT, /*expected_stores=*/
176175
{"value", "Closure.function_type_arguments",
177-
"Closure.delayed_type_arguments",
178176
"Closure.function", "Closure.context"});
179177
}
180178

runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5108,11 +5108,15 @@ Fragment StreamingFlowGraphBuilder::BuildFunctionNode(
51085108
TokenPosition::kNoSource, Slot::Closure_function_type_arguments(),
51095109
StoreInstanceFieldInstr::Kind::kInitializing);
51105110

5111-
instructions += LoadLocal(closure);
5112-
instructions += Constant(Object::empty_type_arguments());
5113-
instructions += flow_graph_builder_->StoreInstanceField(
5114-
TokenPosition::kNoSource, Slot::Closure_delayed_type_arguments(),
5115-
StoreInstanceFieldInstr::Kind::kInitializing);
5111+
if (function.IsGeneric()) {
5112+
// Only generic functions need to have properly initialized
5113+
// delayed_type_arguments.
5114+
instructions += LoadLocal(closure);
5115+
instructions += Constant(Object::empty_type_arguments());
5116+
instructions += flow_graph_builder_->StoreInstanceField(
5117+
TokenPosition::kNoSource, Slot::Closure_delayed_type_arguments(),
5118+
StoreInstanceFieldInstr::Kind::kInitializing);
5119+
}
51165120

51175121
// Store the function and the context in the closure.
51185122
instructions += LoadLocal(closure);

runtime/vm/compiler/frontend/kernel_to_il.cc

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1398,11 +1398,15 @@ Fragment FlowGraphBuilder::BuildImplicitClosureCreation(
13981398
StoreInstanceField(TokenPosition::kNoSource, Slot::Closure_context(),
13991399
StoreInstanceFieldInstr::Kind::kInitializing);
14001400

1401-
fragment += LoadLocal(closure);
1402-
fragment += Constant(Object::empty_type_arguments());
1403-
fragment += StoreInstanceField(TokenPosition::kNoSource,
1404-
Slot::Closure_delayed_type_arguments(),
1405-
StoreInstanceFieldInstr::Kind::kInitializing);
1401+
if (target.IsGeneric()) {
1402+
// Only generic functions need to have properly initialized
1403+
// delayed_type_arguments.
1404+
fragment += LoadLocal(closure);
1405+
fragment += Constant(Object::empty_type_arguments());
1406+
fragment += StoreInstanceField(
1407+
TokenPosition::kNoSource, Slot::Closure_delayed_type_arguments(),
1408+
StoreInstanceFieldInstr::Kind::kInitializing);
1409+
}
14061410

14071411
// The context is on top of the operand stack. Store `this`. The context
14081412
// doesn't need a parent pointer because it doesn't close over anything

runtime/vm/object.cc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21696,7 +21696,9 @@ RawClosure* Closure::New(const TypeArguments& instantiator_type_arguments,
2169621696
const Context& context,
2169721697
Heap::Space space) {
2169821698
return Closure::New(instantiator_type_arguments, function_type_arguments,
21699-
Object::empty_type_arguments(), function, context, space);
21699+
function.IsGeneric() ? Object::empty_type_arguments()
21700+
: Object::null_type_arguments(),
21701+
function, context, space);
2170021702
}
2170121703

2170221704
RawClosure* Closure::New(const TypeArguments& instantiator_type_arguments,

0 commit comments

Comments
 (0)