Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 20bf2fc

Browse files
mkustermanncommit-bot@chromium.org
authored andcommitted
[vm/compiler] Make precompiler prune invocation dispatchers the same way we do for regular/closure functions
The precompiler has a notion of when a function should get its code generated, when it should retain a functions types. This information is used to prune function objects after AOT compilation. This CL introduces the same pruning logic which we do for regular functions as well as closure functions to invocation dispatchers. Change-Id: I5c8a75f0cc822c71e876b8e2c9648d9976745895 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/154002 Commit-Queue: Martin Kustermann <[email protected]> Reviewed-by: Tess Strickland <[email protected]>
1 parent c54f38f commit 20bf2fc

File tree

2 files changed

+68
-32
lines changed

2 files changed

+68
-32
lines changed

runtime/vm/compiler/aot/precompiler.cc

Lines changed: 67 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1461,6 +1461,7 @@ void Precompiler::TraceForRetainedFunctions() {
14611461
Library& lib = Library::Handle(Z);
14621462
Class& cls = Class::Handle(Z);
14631463
Array& functions = Array::Handle(Z);
1464+
String& name = String::Handle(Z);
14641465
Function& function = Function::Handle(Z);
14651466
Function& function2 = Function::Handle(Z);
14661467
GrowableObjectArray& closures = GrowableObjectArray::Handle(Z);
@@ -1487,6 +1488,19 @@ void Precompiler::TraceForRetainedFunctions() {
14871488
AddTypesOf(function);
14881489
}
14891490
}
1491+
1492+
{
1493+
functions = cls.invocation_dispatcher_cache();
1494+
InvocationDispatcherTable dispatchers(functions);
1495+
for (auto dispatcher : dispatchers) {
1496+
name = dispatcher.Get<Class::kInvocationDispatcherName>();
1497+
if (name.IsNull()) break; // Reached last entry.
1498+
function = dispatcher.Get<Class::kInvocationDispatcherFunction>();
1499+
if (possibly_retained_functions_.ContainsKey(function)) {
1500+
AddTypesOf(function);
1501+
}
1502+
}
1503+
}
14901504
}
14911505
}
14921506

@@ -1601,6 +1615,26 @@ void Precompiler::DropFunctions() {
16011615
GrowableObjectArray& retained_functions = GrowableObjectArray::Handle(Z);
16021616
GrowableObjectArray& closures = GrowableObjectArray::Handle(Z);
16031617

1618+
auto drop_function = [&](const Function& function) {
1619+
if (function.HasCode()) {
1620+
code = function.CurrentCode();
1621+
function.ClearCode();
1622+
// Wrap the owner of the code object in case the code object will be
1623+
// serialized but the function object will not.
1624+
owner = code.owner();
1625+
owner = WeakSerializationReference::Wrap(Z, owner);
1626+
code.set_owner(owner);
1627+
}
1628+
dropped_function_count_++;
1629+
if (FLAG_trace_precompiler) {
1630+
THR_Print("Dropping function %s\n",
1631+
function.ToLibNamePrefixedQualifiedCString());
1632+
}
1633+
};
1634+
1635+
auto& dispatchers_array = Array::Handle(Z);
1636+
auto& name = String::Handle(Z);
1637+
auto& desc = Array::Handle(Z);
16041638
for (intptr_t i = 0; i < libraries_.Length(); i++) {
16051639
lib ^= libraries_.At(i);
16061640
ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
@@ -1610,26 +1644,12 @@ void Precompiler::DropFunctions() {
16101644
retained_functions = GrowableObjectArray::New();
16111645
for (intptr_t j = 0; j < functions.Length(); j++) {
16121646
function ^= functions.At(j);
1613-
bool retain = functions_to_retain_.ContainsKey(function);
16141647
function.DropUncompiledImplicitClosureFunction();
16151648
function.ClearBytecode();
1616-
if (retain) {
1649+
if (functions_to_retain_.ContainsKey(function)) {
16171650
retained_functions.Add(function);
16181651
} else {
1619-
if (function.HasCode()) {
1620-
code = function.CurrentCode();
1621-
function.ClearCode();
1622-
// Wrap the owner of the code object in case the code object will be
1623-
// serialized but the function object will not.
1624-
owner = code.owner();
1625-
owner = WeakSerializationReference::Wrap(Z, owner);
1626-
code.set_owner(owner);
1627-
}
1628-
dropped_function_count_++;
1629-
if (FLAG_trace_precompiler) {
1630-
THR_Print("Dropping function %s\n",
1631-
function.ToLibNamePrefixedQualifiedCString());
1632-
}
1652+
drop_function(function);
16331653
}
16341654
}
16351655

@@ -1639,32 +1659,47 @@ void Precompiler::DropFunctions() {
16391659
} else {
16401660
cls.SetFunctions(Object::empty_array());
16411661
}
1662+
1663+
retained_functions = GrowableObjectArray::New();
1664+
{
1665+
dispatchers_array = cls.invocation_dispatcher_cache();
1666+
InvocationDispatcherTable dispatchers(dispatchers_array);
1667+
for (auto dispatcher : dispatchers) {
1668+
name = dispatcher.Get<Class::kInvocationDispatcherName>();
1669+
if (name.IsNull()) break; // Reached last entry.
1670+
desc = dispatcher.Get<Class::kInvocationDispatcherArgsDesc>();
1671+
function = dispatcher.Get<Class::kInvocationDispatcherFunction>();
1672+
if (functions_to_retain_.ContainsKey(function)) {
1673+
retained_functions.Add(name);
1674+
retained_functions.Add(desc);
1675+
retained_functions.Add(function);
1676+
} else {
1677+
drop_function(function);
1678+
}
1679+
}
1680+
}
1681+
if (retained_functions.Length() > 0) {
1682+
// Last entry must be null.
1683+
retained_functions.Add(Object::null_object());
1684+
retained_functions.Add(Object::null_object());
1685+
retained_functions.Add(Object::null_object());
1686+
functions = Array::MakeFixedLength(retained_functions);
1687+
} else {
1688+
functions = Object::empty_array().raw();
1689+
}
1690+
cls.set_invocation_dispatcher_cache(functions);
16421691
}
16431692
}
16441693

16451694
closures = isolate()->object_store()->closure_functions();
16461695
retained_functions = GrowableObjectArray::New();
16471696
for (intptr_t j = 0; j < closures.Length(); j++) {
16481697
function ^= closures.At(j);
1649-
bool retain = functions_to_retain_.ContainsKey(function);
16501698
function.ClearBytecode();
1651-
if (retain) {
1699+
if (functions_to_retain_.ContainsKey(function)) {
16521700
retained_functions.Add(function);
16531701
} else {
1654-
if (function.HasCode()) {
1655-
code = function.CurrentCode();
1656-
function.ClearCode();
1657-
// Wrap the owner of the code object in case the code object will be
1658-
// serialized but the function object will not.
1659-
owner = code.owner();
1660-
owner = WeakSerializationReference::Wrap(Z, owner);
1661-
code.set_owner(owner);
1662-
}
1663-
dropped_function_count_++;
1664-
if (FLAG_trace_precompiler) {
1665-
THR_Print("Dropping function %s\n",
1666-
function.ToLibNamePrefixedQualifiedCString());
1667-
}
1702+
drop_function(function);
16681703
}
16691704
}
16701705
isolate()->object_store()->set_closure_functions(retained_functions);

runtime/vm/object.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1773,6 +1773,7 @@ class Class : public Object {
17731773
friend class InterpreterHelpers;
17741774
friend class Intrinsifier;
17751775
friend class ProgramWalker;
1776+
friend class Precompiler;
17761777
};
17771778

17781779
// Classification of type genericity according to type parameter owners.

0 commit comments

Comments
 (0)