[vm, compiler] Reduce peak memory usage of AOT compilation.

Use more zones and handle scopes to prevent temporary allocations from having unnecessarily long lifespans.

/usr/bin/time -v gen_snapshot --snapshot-kind=app-aot-elf ... dart2js.dill
Maximum resident set size (kbytes): 821344 -> 443688 (-46.0%)

TEST=ci
Bug: b/196510517
Change-Id: I41cdcac69f485b2f33adf2c94bb11f466e6a54fb
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/210944
Commit-Queue: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Siva Annamalai <asiva@google.com>
This commit is contained in:
Ryan Macnak 2021-08-24 16:49:23 +00:00 committed by commit-bot@chromium.org
parent 87015522a3
commit a7f3ced262
5 changed files with 104 additions and 76 deletions

View file

@ -1381,6 +1381,7 @@ void ClassFinalizer::VerifyImplicitFieldOffsets() {
void ClassFinalizer::SortClasses() {
auto T = Thread::Current();
StackZone stack_zone(T);
auto Z = T->zone();
auto IG = T->isolate_group();

View file

@ -98,7 +98,7 @@ class SelectorRow {
: selector_(selector),
class_ranges_(zone, 0),
ranges_(zone, 0),
code_(Code::Handle(zone)) {}
code_(Code::ZoneHandle(zone)) {}
TableSelector* selector() const { return selector_; }
@ -408,6 +408,7 @@ DispatchTableGenerator::DispatchTableGenerator(Zone* zone)
void DispatchTableGenerator::Initialize(ClassTable* table) {
classes_ = table;
HANDLESCOPE(Thread::Current());
ReadTableSelectorInfo();
NumberSelectors();
SetupSelectorRows();

View file

@ -718,6 +718,7 @@ void Precompiler::PrecompileConstructors() {
}
void Precompiler::AddRoots() {
HANDLESCOPE(T);
// Note that <rootlibrary>.main is not a root. The appropriate main will be
// discovered through _getMainClosure.
@ -776,6 +777,7 @@ void Precompiler::Iterate() {
}
void Precompiler::CollectCallbackFields() {
HANDLESCOPE(T);
Library& lib = Library::Handle(Z);
Class& cls = Class::Handle(Z);
Class& subcls = Class::Handle(Z);
@ -790,6 +792,7 @@ void Precompiler::CollectCallbackFields() {
for (intptr_t i = 0; i < libraries_.Length(); i++) {
lib ^= libraries_.At(i);
HANDLESCOPE(T);
ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
while (it.HasNext()) {
cls = it.GetNextClass();
@ -843,6 +846,7 @@ void Precompiler::CollectCallbackFields() {
}
void Precompiler::ProcessFunction(const Function& function) {
HANDLESCOPE(T);
const intptr_t gop_offset =
FLAG_use_bare_instructions ? global_object_pool_builder()->CurrentLength()
: 0;
@ -1462,6 +1466,7 @@ void Precompiler::AddInstantiatedClass(const Class& cls) {
// Adds all values annotated with @pragma('vm:entry-point') as roots.
void Precompiler::AddAnnotatedRoots() {
HANDLESCOPE(T);
auto& lib = Library::Handle(Z);
auto& cls = Class::Handle(Z);
auto& members = Array::Handle(Z);
@ -1480,6 +1485,7 @@ void Precompiler::AddAnnotatedRoots() {
for (intptr_t i = 0; i < libraries_.Length(); i++) {
lib ^= libraries_.At(i);
HANDLESCOPE(T);
ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
while (it.HasNext()) {
cls = it.GetNextClass();
@ -1592,6 +1598,7 @@ void Precompiler::AddAnnotatedRoots() {
}
void Precompiler::CheckForNewDynamicFunctions() {
HANDLESCOPE(T);
Library& lib = Library::Handle(Z);
Class& cls = Class::Handle(Z);
Array& functions = Array::Handle(Z);
@ -1604,6 +1611,7 @@ void Precompiler::CheckForNewDynamicFunctions() {
for (intptr_t i = 0; i < libraries_.Length(); i++) {
lib ^= libraries_.At(i);
HANDLESCOPE(T);
ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
while (it.HasNext()) {
cls = it.GetNextClass();
@ -1769,6 +1777,7 @@ void Precompiler::CollectDynamicFunctionNames() {
if (!FLAG_collect_dynamic_function_names) {
return;
}
HANDLESCOPE(T);
auto& lib = Library::Handle(Z);
auto& cls = Class::Handle(Z);
auto& functions = Array::Handle(Z);
@ -1781,6 +1790,7 @@ void Precompiler::CollectDynamicFunctionNames() {
Table table(HashTables::New<Table>(100));
for (intptr_t i = 0; i < libraries_.Length(); i++) {
lib ^= libraries_.At(i);
HANDLESCOPE(T);
ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
while (it.HasNext()) {
cls = it.GetNextClass();
@ -1873,6 +1883,7 @@ void Precompiler::CollectDynamicFunctionNames() {
}
void Precompiler::TraceForRetainedFunctions() {
HANDLESCOPE(T);
Library& lib = Library::Handle(Z);
Class& cls = Class::Handle(Z);
Array& functions = Array::Handle(Z);
@ -1884,6 +1895,7 @@ void Precompiler::TraceForRetainedFunctions() {
for (intptr_t i = 0; i < libraries_.Length(); i++) {
lib ^= libraries_.At(i);
HANDLESCOPE(T);
ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
while (it.HasNext()) {
cls = it.GetNextClass();
@ -1969,6 +1981,7 @@ void Precompiler::TraceForRetainedFunctions() {
void Precompiler::FinalizeDispatchTable() {
PRECOMPILER_TIMER_SCOPE(this, FinalizeDispatchTable);
if (!FLAG_use_bare_instructions || !FLAG_use_table_dispatch) return;
HANDLESCOPE(T);
// Build the entries used to serialize the dispatch table before
// dropping functions, as we may clear references to Code objects.
const auto& entries =
@ -2083,6 +2096,7 @@ void Precompiler::ReplaceFunctionStaticCallEntries() {
}
void Precompiler::DropFunctions() {
HANDLESCOPE(T);
Library& lib = Library::Handle(Z);
Class& cls = Class::Handle(Z);
Array& functions = Array::Handle(Z);
@ -2163,6 +2177,7 @@ void Precompiler::DropFunctions() {
auto& desc = Array::Handle(Z);
for (intptr_t i = 0; i < libraries_.Length(); i++) {
lib ^= libraries_.At(i);
HANDLESCOPE(T);
ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
while (it.HasNext()) {
cls = it.GetNextClass();
@ -2232,6 +2247,7 @@ void Precompiler::DropFunctions() {
}
void Precompiler::DropFields() {
HANDLESCOPE(T);
Library& lib = Library::Handle(Z);
Class& cls = Class::Handle(Z);
Array& fields = Array::Handle(Z);
@ -2242,6 +2258,7 @@ void Precompiler::DropFields() {
SafepointWriteRwLocker ml(T, T->isolate_group()->program_lock());
for (intptr_t i = 0; i < libraries_.Length(); i++) {
lib ^= libraries_.At(i);
HANDLESCOPE(T);
ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
while (it.HasNext()) {
cls = it.GetNextClass();
@ -2294,6 +2311,7 @@ void Precompiler::DropFields() {
void Precompiler::AttachOptimizedTypeTestingStub() {
PRECOMPILER_TIMER_SCOPE(this, AttachOptimizedTypeTestingStub);
HANDLESCOPE(T);
IsolateGroup::Current()->heap()->CollectAllGarbage();
GrowableHandlePtrArray<const AbstractType> types(Z, 200);
{
@ -2359,6 +2377,7 @@ void Precompiler::AttachOptimizedTypeTestingStub() {
}
void Precompiler::TraceTypesFromRetainedClasses() {
HANDLESCOPE(T);
auto& lib = Library::Handle(Z);
auto& cls = Class::Handle(Z);
auto& members = Array::Handle(Z);
@ -2370,6 +2389,7 @@ void Precompiler::TraceTypesFromRetainedClasses() {
SafepointWriteRwLocker ml(T, T->isolate_group()->program_lock());
for (intptr_t i = 0; i < libraries_.Length(); i++) {
lib ^= libraries_.At(i);
HANDLESCOPE(T);
ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
while (it.HasNext()) {
cls = it.GetNextClass();
@ -2445,6 +2465,7 @@ void Precompiler::TraceTypesFromRetainedClasses() {
}
void Precompiler::DropMetadata() {
HANDLESCOPE(T);
SafepointWriteRwLocker ml(T, T->isolate_group()->program_lock());
Library& lib = Library::Handle(Z);
@ -2455,6 +2476,7 @@ void Precompiler::DropMetadata() {
}
void Precompiler::DropLibraryEntries() {
HANDLESCOPE(T);
Library& lib = Library::Handle(Z);
Array& dict = Array::Handle(Z);
Object& entry = Object::Handle(Z);
@ -2501,6 +2523,7 @@ void Precompiler::DropLibraryEntries() {
}
void Precompiler::DropClasses() {
HANDLESCOPE(T);
Class& cls = Class::Handle(Z);
Array& constants = Array::Handle(Z);
GrowableObjectArray& implementors = GrowableObjectArray::Handle(Z);
@ -2587,6 +2610,7 @@ void Precompiler::DropClasses() {
}
void Precompiler::DropLibraries() {
HANDLESCOPE(T);
const GrowableObjectArray& retained_libraries =
GrowableObjectArray::Handle(Z, GrowableObjectArray::New());
const Library& root_lib =
@ -2596,6 +2620,7 @@ void Precompiler::DropLibraries() {
for (intptr_t i = 0; i < libraries_.Length(); i++) {
lib ^= libraries_.At(i);
HANDLESCOPE(T);
intptr_t entries = 0;
DictionaryIterator it(lib);
while (it.HasNext()) {
@ -2824,6 +2849,7 @@ void Precompiler::DiscardCodeObjects() {
return;
}
HANDLESCOPE(T);
DiscardCodeVisitor visitor(Z, functions_to_retain_,
functions_called_dynamically_);
ProgramVisitor::WalkProgram(Z, IG, &visitor);

View file

@ -346,7 +346,7 @@ class Dedupper : public ValueObject {
DirectChainedHashMap<S> canonical_objects_;
};
void ProgramVisitor::BindStaticCalls(Zone* zone, IsolateGroup* isolate_group) {
void ProgramVisitor::BindStaticCalls(Thread* thread) {
class BindStaticCallsVisitor : public CodeVisitor {
public:
explicit BindStaticCallsVisitor(Zone* zone)
@ -422,17 +422,19 @@ void ProgramVisitor::BindStaticCalls(Zone* zone, IsolateGroup* isolate_group) {
Code& target_code_;
};
BindStaticCallsVisitor visitor(zone);
WalkProgram(zone, isolate_group, &visitor);
StackZone stack_zone(thread);
BindStaticCallsVisitor visitor(thread->zone());
WalkProgram(thread->zone(), thread->isolate_group(), &visitor);
}
DECLARE_FLAG(charp, trace_precompiler_to);
DECLARE_FLAG(charp, write_v8_snapshot_profile_to);
void ProgramVisitor::ShareMegamorphicBuckets(Zone* zone,
IsolateGroup* isolate_group) {
void ProgramVisitor::ShareMegamorphicBuckets(Thread* thread) {
StackZone stack_zone(thread);
Zone* zone = thread->zone();
const GrowableObjectArray& table = GrowableObjectArray::Handle(
zone, isolate_group->object_store()->megamorphic_cache_table());
zone, thread->isolate_group()->object_store()->megamorphic_cache_table());
if (table.IsNull()) return;
MegamorphicCache& cache = MegamorphicCache::Handle(zone);
@ -562,9 +564,7 @@ class StackMapEntryKeyIntValueTrait {
typedef DirectChainedHashMap<StackMapEntryKeyIntValueTrait> StackMapEntryIntMap;
void ProgramVisitor::NormalizeAndDedupCompressedStackMaps(
Zone* zone,
IsolateGroup* isolate_group) {
void ProgramVisitor::NormalizeAndDedupCompressedStackMaps(Thread* thread) {
// Walks all the CSMs in Code objects and collects their entry information
// for consolidation.
class CollectStackMapEntriesVisitor : public CodeVisitor {
@ -724,9 +724,10 @@ void ProgramVisitor::NormalizeAndDedupCompressedStackMaps(
CompressedStackMaps& maps_;
};
NormalizeAndDedupCompressedStackMapsVisitor dedup_visitor(zone,
isolate_group);
WalkProgram(zone, isolate_group, &dedup_visitor);
StackZone stack_zone(thread);
NormalizeAndDedupCompressedStackMapsVisitor visitor(thread->zone(),
thread->isolate_group());
WalkProgram(thread->zone(), thread->isolate_group(), &visitor);
}
class PcDescriptorsKeyValueTrait {
@ -747,8 +748,7 @@ class PcDescriptorsKeyValueTrait {
}
};
void ProgramVisitor::DedupPcDescriptors(Zone* zone,
IsolateGroup* isolate_group) {
void ProgramVisitor::DedupPcDescriptors(Thread* thread) {
class DedupPcDescriptorsVisitor
: public CodeVisitor,
public Dedupper<PcDescriptors, PcDescriptorsKeyValueTrait> {
@ -771,8 +771,9 @@ void ProgramVisitor::DedupPcDescriptors(Zone* zone,
PcDescriptors& pc_descriptor_;
};
DedupPcDescriptorsVisitor visitor(zone);
WalkProgram(zone, isolate_group, &visitor);
StackZone stack_zone(thread);
DedupPcDescriptorsVisitor visitor(thread->zone());
WalkProgram(thread->zone(), thread->isolate_group(), &visitor);
}
class TypedDataKeyValueTrait {
@ -801,8 +802,7 @@ class TypedDataDedupper : public Dedupper<TypedData, TypedDataKeyValueTrait> {
bool IsCorrectType(const Object& obj) const { return obj.IsTypedData(); }
};
void ProgramVisitor::DedupDeoptEntries(Zone* zone,
IsolateGroup* isolate_group) {
void ProgramVisitor::DedupDeoptEntries(Thread* thread) {
class DedupDeoptEntriesVisitor : public CodeVisitor,
public TypedDataDedupper {
public:
@ -836,13 +836,14 @@ void ProgramVisitor::DedupDeoptEntries(Zone* zone,
};
if (FLAG_precompiled_mode) return;
DedupDeoptEntriesVisitor visitor(zone);
WalkProgram(zone, isolate_group, &visitor);
StackZone stack_zone(thread);
DedupDeoptEntriesVisitor visitor(thread->zone());
WalkProgram(thread->zone(), thread->isolate_group(), &visitor);
}
#if defined(DART_PRECOMPILER)
void ProgramVisitor::DedupCatchEntryMovesMaps(Zone* zone,
IsolateGroup* isolate_group) {
void ProgramVisitor::DedupCatchEntryMovesMaps(Thread* thread) {
class DedupCatchEntryMovesMapsVisitor : public CodeVisitor,
public TypedDataDedupper {
public:
@ -861,8 +862,10 @@ void ProgramVisitor::DedupCatchEntryMovesMaps(Zone* zone,
};
if (!FLAG_precompiled_mode) return;
DedupCatchEntryMovesMapsVisitor visitor(zone);
WalkProgram(zone, isolate_group, &visitor);
StackZone stack_zone(thread);
DedupCatchEntryMovesMapsVisitor visitor(thread->zone());
WalkProgram(thread->zone(), thread->isolate_group(), &visitor);
}
class UnlinkedCallKeyValueTrait {
@ -883,8 +886,7 @@ class UnlinkedCallKeyValueTrait {
}
};
void ProgramVisitor::DedupUnlinkedCalls(Zone* zone,
IsolateGroup* isolate_group) {
void ProgramVisitor::DedupUnlinkedCalls(Thread* thread) {
class DedupUnlinkedCallsVisitor
: public CodeVisitor,
public Dedupper<UnlinkedCall, UnlinkedCallKeyValueTrait> {
@ -924,7 +926,8 @@ void ProgramVisitor::DedupUnlinkedCalls(Zone* zone,
if (!FLAG_precompiled_mode) return;
DedupUnlinkedCallsVisitor deduper(zone, isolate_group);
StackZone stack_zone(thread);
DedupUnlinkedCallsVisitor visitor(thread->zone(), thread->isolate_group());
// Note: in bare instructions mode we can still have object pools attached
// to code objects and these pools need to be deduplicated.
@ -935,11 +938,11 @@ void ProgramVisitor::DedupUnlinkedCalls(Zone* zone,
if (!FLAG_use_bare_instructions ||
FLAG_write_v8_snapshot_profile_to != nullptr ||
FLAG_trace_precompiler_to != nullptr) {
WalkProgram(zone, isolate_group, &deduper);
WalkProgram(thread->zone(), thread->isolate_group(), &visitor);
}
}
void ProgramVisitor::PruneSubclasses(Zone* zone, IsolateGroup* isolate_group) {
void ProgramVisitor::PruneSubclasses(Thread* thread) {
class PruneSubclassesVisitor : public ClassVisitor {
public:
explicit PruneSubclassesVisitor(Zone* zone)
@ -996,9 +999,10 @@ void ProgramVisitor::PruneSubclasses(Zone* zone, IsolateGroup* isolate_group) {
GrowableObjectArray& null_list_;
};
PruneSubclassesVisitor visitor(zone);
SafepointWriteRwLocker ml(Thread::Current(), isolate_group->program_lock());
WalkProgram(zone, isolate_group, &visitor);
StackZone stack_zone(thread);
PruneSubclassesVisitor visitor(thread->zone());
SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
WalkProgram(thread->zone(), thread->isolate_group(), &visitor);
}
#endif // defined(DART_PRECOMPILER)
@ -1024,8 +1028,7 @@ class CodeSourceMapKeyValueTrait {
}
};
void ProgramVisitor::DedupCodeSourceMaps(Zone* zone,
IsolateGroup* isolate_group) {
void ProgramVisitor::DedupCodeSourceMaps(Thread* thread) {
class DedupCodeSourceMapsVisitor
: public CodeVisitor,
public Dedupper<CodeSourceMap, CodeSourceMapKeyValueTrait> {
@ -1048,8 +1051,9 @@ void ProgramVisitor::DedupCodeSourceMaps(Zone* zone,
CodeSourceMap& code_source_map_;
};
DedupCodeSourceMapsVisitor visitor(zone);
WalkProgram(zone, isolate_group, &visitor);
StackZone stack_zone(thread);
DedupCodeSourceMapsVisitor visitor(thread->zone());
WalkProgram(thread->zone(), thread->isolate_group(), &visitor);
}
class ArrayKeyValueTrait {
@ -1078,7 +1082,7 @@ class ArrayKeyValueTrait {
}
};
void ProgramVisitor::DedupLists(Zone* zone, IsolateGroup* isolate_group) {
void ProgramVisitor::DedupLists(Thread* thread) {
class DedupListsVisitor : public CodeVisitor,
public Dedupper<Array, ArrayKeyValueTrait> {
public:
@ -1122,8 +1126,9 @@ void ProgramVisitor::DedupLists(Zone* zone, IsolateGroup* isolate_group) {
Field& field_;
};
DedupListsVisitor visitor(zone);
WalkProgram(zone, isolate_group, &visitor);
StackZone stack_zone(thread);
DedupListsVisitor visitor(thread->zone());
WalkProgram(thread->zone(), thread->isolate_group(), &visitor);
}
// Traits for comparing two [Instructions] objects for equality, which is
@ -1208,8 +1213,7 @@ class CodeKeyValueTrait {
};
#endif
void ProgramVisitor::DedupInstructions(Zone* zone,
IsolateGroup* isolate_group) {
void ProgramVisitor::DedupInstructions(Thread* thread) {
class DedupInstructionsVisitor
: public CodeVisitor,
public Dedupper<Instructions, InstructionsKeyValueTrait>,
@ -1297,33 +1301,31 @@ void ProgramVisitor::DedupInstructions(Zone* zone,
};
if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
DedupInstructionsWithSameMetadataVisitor visitor(zone);
return WalkProgram(zone, isolate_group, &visitor);
StackZone stack_zone(thread);
DedupInstructionsWithSameMetadataVisitor visitor(thread->zone());
WalkProgram(thread->zone(), thread->isolate_group(), &visitor);
return;
}
#endif // defined(DART_PRECOMPILER)
DedupInstructionsVisitor visitor(zone);
WalkProgram(zone, isolate_group, &visitor);
StackZone stack_zone(thread);
DedupInstructionsVisitor visitor(thread->zone());
WalkProgram(thread->zone(), thread->isolate_group(), &visitor);
}
void ProgramVisitor::Dedup(Thread* thread) {
auto const isolate_group = thread->isolate_group();
StackZone stack_zone(thread);
HANDLESCOPE(thread);
auto const zone = thread->zone();
BindStaticCalls(zone, isolate_group);
ShareMegamorphicBuckets(zone, isolate_group);
NormalizeAndDedupCompressedStackMaps(zone, isolate_group);
DedupPcDescriptors(zone, isolate_group);
DedupDeoptEntries(zone, isolate_group);
BindStaticCalls(thread);
ShareMegamorphicBuckets(thread);
NormalizeAndDedupCompressedStackMaps(thread);
DedupPcDescriptors(thread);
DedupDeoptEntries(thread);
#if defined(DART_PRECOMPILER)
DedupCatchEntryMovesMaps(zone, isolate_group);
DedupUnlinkedCalls(zone, isolate_group);
PruneSubclasses(zone, isolate_group);
DedupCatchEntryMovesMaps(thread);
DedupUnlinkedCalls(thread);
PruneSubclasses(thread);
#endif
DedupCodeSourceMaps(zone, isolate_group);
DedupLists(zone, isolate_group);
DedupCodeSourceMaps(thread);
DedupLists(thread);
// Reduces binary size but obfuscates profiler results.
if (FLAG_dedup_instructions) {
@ -1346,7 +1348,7 @@ void ProgramVisitor::Dedup(Thread* thread) {
if (FLAG_precompiled_mode && !FLAG_use_bare_instructions) return;
#endif
DedupInstructions(zone, isolate_group);
DedupInstructions(thread);
}
}
@ -1419,8 +1421,7 @@ class AssignLoadingUnitsCodeVisitor : public CodeVisitor {
void ProgramVisitor::AssignUnits(Thread* thread) {
StackZone stack_zone(thread);
HANDLESCOPE(thread);
Zone* zone = thread->zone();
Zone* zone = stack_zone.GetZone();
// VM stubs.
Instructions& inst = Instructions::Handle(zone);

View file

@ -106,20 +106,19 @@ class ProgramVisitor : public AllStatic {
#endif
private:
static void BindStaticCalls(Zone* zone, IsolateGroup* isolate_group);
static void ShareMegamorphicBuckets(Zone* zone, IsolateGroup* isolate_group);
static void NormalizeAndDedupCompressedStackMaps(Zone* zone,
IsolateGroup* isolate_group);
static void DedupPcDescriptors(Zone* zone, IsolateGroup* isolate_group);
static void DedupDeoptEntries(Zone* zone, IsolateGroup* isolate_group);
static void BindStaticCalls(Thread* thread);
static void ShareMegamorphicBuckets(Thread* thread);
static void NormalizeAndDedupCompressedStackMaps(Thread* thread);
static void DedupPcDescriptors(Thread* thread);
static void DedupDeoptEntries(Thread* thread);
#if defined(DART_PRECOMPILER)
static void DedupCatchEntryMovesMaps(Zone* zone, IsolateGroup* isolate_group);
static void DedupUnlinkedCalls(Zone* zone, IsolateGroup* isolate_group);
static void PruneSubclasses(Zone* zone, IsolateGroup* isolate_group);
static void DedupCatchEntryMovesMaps(Thread* thread);
static void DedupUnlinkedCalls(Thread* thread);
static void PruneSubclasses(Thread* thread);
#endif
static void DedupCodeSourceMaps(Zone* zone, IsolateGroup* isolate_group);
static void DedupLists(Zone* zone, IsolateGroup* isolate_group);
static void DedupInstructions(Zone* zone, IsolateGroup* isolate_group);
static void DedupCodeSourceMaps(Thread* thread);
static void DedupLists(Thread* thread);
static void DedupInstructions(Thread* thread);
};
} // namespace dart