@@ -1403,11 +1403,26 @@ class CodeSerializationCluster : public SerializationCluster {
14031403 objects_.Add (code);
14041404 }
14051405
1406- if (!(s->kind () == Snapshot::kFullAOT && FLAG_use_bare_instructions)) {
1406+ if (s->kind () == Snapshot::kFullAOT && FLAG_use_bare_instructions) {
1407+ if (FLAG_retain_function_objects) {
1408+ ObjectPoolPtr pool = code->ptr ()->object_pool_ ;
1409+ if ((pool != ObjectPool::null ()) && s->InCurrentLoadingUnit (code)) {
1410+ const intptr_t length = pool->ptr ()->length_ ;
1411+ uint8_t * entry_bits = pool->ptr ()->entry_bits ();
1412+ for (intptr_t i = 0 ; i < length; i++) {
1413+ auto entry_type = ObjectPool::TypeBits::decode (entry_bits[i]);
1414+ if (entry_type == ObjectPool::EntryType::kTaggedObject ) {
1415+ s->Push (pool->ptr ()->data ()[i].raw_obj_ );
1416+ }
1417+ }
1418+ }
1419+ }
1420+ } else {
14071421 if (s->InCurrentLoadingUnit (code->ptr ()->object_pool_ )) {
14081422 s->Push (code->ptr ()->object_pool_ );
14091423 }
14101424 }
1425+
14111426 s->Push (code->ptr ()->owner_ );
14121427 s->Push (code->ptr ()->exception_handlers_ );
14131428 s->Push (code->ptr ()->pc_descriptors_ );
@@ -1519,21 +1534,6 @@ class CodeSerializationCluster : public SerializationCluster {
15191534 }
15201535
15211536 void WriteAlloc (Serializer* s) {
1522- Sort (&objects_);
1523- auto loading_units = s->loading_units ();
1524- if ((loading_units != nullptr ) &&
1525- (s->current_loading_unit_id () == LoadingUnit::kRootId )) {
1526- for (intptr_t i = LoadingUnit::kRootId + 1 ; i < loading_units->length ();
1527- i++) {
1528- auto unit_objects = loading_units->At (i)->deferred_objects ();
1529- Sort (unit_objects);
1530- for (intptr_t j = 0 ; j < unit_objects->length (); j++) {
1531- deferred_objects_.Add (unit_objects->At (j)->raw ());
1532- }
1533- }
1534- }
1535- s->PrepareInstructions (&objects_);
1536-
15371537 s->WriteCid (kCodeCid );
15381538 const intptr_t count = objects_.length ();
15391539 s->WriteUnsigned (count);
@@ -1679,7 +1679,8 @@ class CodeSerializationCluster : public SerializationCluster {
16791679 s->Write <int32_t >(code->ptr ()->state_bits_ );
16801680 }
16811681
1682- GrowableArray<CodePtr>* discovered_objects () { return &objects_; }
1682+ GrowableArray<CodePtr>* objects () { return &objects_; }
1683+ GrowableArray<CodePtr>* deferred_objects () { return &deferred_objects_; }
16831684
16841685 // Some code objects would have their owners dropped from the snapshot,
16851686 // which makes it is impossible to recover program structure when
@@ -1843,12 +1844,17 @@ class ObjectPoolSerializationCluster : public SerializationCluster {
18431844 ObjectPoolPtr pool = ObjectPool::RawCast (object);
18441845 objects_.Add (pool);
18451846
1846- const intptr_t length = pool->ptr ()->length_ ;
1847- uint8_t * entry_bits = pool->ptr ()->entry_bits ();
1848- for (intptr_t i = 0 ; i < length; i++) {
1849- auto entry_type = ObjectPool::TypeBits::decode (entry_bits[i]);
1850- if (entry_type == ObjectPool::EntryType::kTaggedObject ) {
1851- s->Push (pool->ptr ()->data ()[i].raw_obj_ );
1847+ if (s->kind () == Snapshot::kFullAOT && FLAG_use_bare_instructions &&
1848+ FLAG_retain_function_objects) {
1849+ // Treat pool as weak.
1850+ } else {
1851+ const intptr_t length = pool->ptr ()->length_ ;
1852+ uint8_t * entry_bits = pool->ptr ()->entry_bits ();
1853+ for (intptr_t i = 0 ; i < length; i++) {
1854+ auto entry_type = ObjectPool::TypeBits::decode (entry_bits[i]);
1855+ if (entry_type == ObjectPool::EntryType::kTaggedObject ) {
1856+ s->Push (pool->ptr ()->data ()[i].raw_obj_ );
1857+ }
18521858 }
18531859 }
18541860 }
@@ -1867,6 +1873,9 @@ class ObjectPoolSerializationCluster : public SerializationCluster {
18671873 }
18681874
18691875 void WriteFill (Serializer* s) {
1876+ bool weak = s->kind () == Snapshot::kFullAOT && FLAG_use_bare_instructions &&
1877+ FLAG_retain_function_objects;
1878+
18701879 const intptr_t count = objects_.length ();
18711880 for (intptr_t i = 0 ; i < count; i++) {
18721881 ObjectPoolPtr pool = objects_[i];
@@ -1887,7 +1896,12 @@ class ObjectPoolSerializationCluster : public SerializationCluster {
18871896 s->WriteElementRef (StubCode::CallBootstrapNative ().raw (), j);
18881897 break ;
18891898 }
1890- s->WriteElementRef (entry.raw_obj_ , j);
1899+ if (weak && !s->HasRef (entry.raw_obj_ )) {
1900+ // Any value will do, but null has the shortest id.
1901+ s->WriteElementRef (Object::null (), j);
1902+ } else {
1903+ s->WriteElementRef (entry.raw_obj_ , j);
1904+ }
18911905 break ;
18921906 }
18931907 case ObjectPool::EntryType::kImmediate : {
@@ -5269,19 +5283,26 @@ class UnitSerializationRoots : public SerializationRoots {
52695283 const Object* deferred_object = (*unit_->deferred_objects ())[i];
52705284 ASSERT (deferred_object->IsCode ());
52715285 CodePtr code = static_cast <CodePtr>(deferred_object->raw ());
5272- if (!FLAG_use_bare_instructions) {
5286+ if (FLAG_use_bare_instructions) {
5287+ if (FLAG_retain_function_objects) {
5288+ ObjectPoolPtr pool = code->ptr ()->object_pool_ ;
5289+ if (pool != ObjectPool::null ()) {
5290+ const intptr_t length = pool->ptr ()->length_ ;
5291+ uint8_t * entry_bits = pool->ptr ()->entry_bits ();
5292+ for (intptr_t i = 0 ; i < length; i++) {
5293+ auto entry_type = ObjectPool::TypeBits::decode (entry_bits[i]);
5294+ if (entry_type == ObjectPool::EntryType::kTaggedObject ) {
5295+ s->Push (pool->ptr ()->data ()[i].raw_obj_ );
5296+ }
5297+ }
5298+ }
5299+ }
5300+ } else {
52735301 s->Push (code->ptr ()->object_pool_ );
52745302 }
52755303 s->Push (code->ptr ()->compressed_stackmaps_ );
52765304 s->Push (code->ptr ()->code_source_map_ );
52775305 }
5278- {
5279- GrowableArray<CodePtr> raw_codes (num_deferred_objects);
5280- for (intptr_t i = 0 ; i < num_deferred_objects; i++) {
5281- raw_codes.Add ((*unit_->deferred_objects ())[i]->raw ());
5282- }
5283- s->PrepareInstructions (&raw_codes);
5284- }
52855306 }
52865307
52875308 void WriteRoots (Serializer* s) {
@@ -5307,6 +5328,27 @@ class UnitSerializationRoots : public SerializationRoots {
53075328 s->WriteRootRef (code->ptr ()->compressed_stackmaps_ , " deferred-code" );
53085329 s->WriteRootRef (code->ptr ()->code_source_map_ , " deferred-code" );
53095330 }
5331+
5332+ if (FLAG_use_bare_instructions && FLAG_retain_function_objects) {
5333+ ObjectPoolPtr pool =
5334+ s->isolate_group ()->object_store ()->global_object_pool ();
5335+ const intptr_t length = pool->ptr ()->length_ ;
5336+ uint8_t * entry_bits = pool->ptr ()->entry_bits ();
5337+ intptr_t last_write = 0 ;
5338+ for (intptr_t i = 0 ; i < length; i++) {
5339+ auto entry_type = ObjectPool::TypeBits::decode (entry_bits[i]);
5340+ if (entry_type == ObjectPool::EntryType::kTaggedObject ) {
5341+ if (s->IsWritten (pool->ptr ()->data ()[i].raw_obj_ )) {
5342+ intptr_t skip = i - last_write;
5343+ s->WriteUnsigned (skip);
5344+ s->WriteRootRef (pool->ptr ()->data ()[i].raw_obj_ ,
5345+ " deferred-literal" );
5346+ last_write = i;
5347+ }
5348+ }
5349+ }
5350+ s->WriteUnsigned (length - last_write);
5351+ }
53105352#endif
53115353 }
53125354
@@ -5351,6 +5393,20 @@ class UnitDeserializationRoots : public DeserializationRoots {
53515393 static_cast <CodeSourceMapPtr>(d->ReadRef ());
53525394 }
53535395
5396+ if (FLAG_use_bare_instructions && FLAG_retain_function_objects) {
5397+ ObjectPoolPtr pool =
5398+ d->isolate_group ()->object_store ()->global_object_pool ();
5399+ const intptr_t length = pool->ptr ()->length_ ;
5400+ uint8_t * entry_bits = pool->ptr ()->entry_bits ();
5401+ for (intptr_t i = d->ReadUnsigned (); i < length; i += d->ReadUnsigned ()) {
5402+ auto entry_type = ObjectPool::TypeBits::decode (entry_bits[i]);
5403+ ASSERT (entry_type == ObjectPool::EntryType::kTaggedObject );
5404+ // The existing entry will usually be null, but it might also be an
5405+ // equivalent object that was duplicated in another loading unit.
5406+ pool->ptr ()->data ()[i].raw_obj_ = d->ReadRef ();
5407+ }
5408+ }
5409+
53545410 // Reinitialize the dispatch table by rereading the table's serialization
53555411 // in the root snapshot.
53565412 IsolateGroup* group = d->thread ()->isolate ()->group ();
@@ -5776,11 +5832,58 @@ bool Serializer::InCurrentLoadingUnit(ObjectPtr obj, bool record) {
57765832}
57775833
57785834#if !defined(DART_PRECOMPILED_RUNTIME)
5779- void Serializer::PrepareInstructions (GrowableArray<CodePtr>* code_objects) {
5835+ void Serializer::PrepareInstructions () {
5836+ if (!Snapshot::IncludesCode (kind ())) return ;
5837+
5838+ CodeSerializationCluster* cluster =
5839+ static_cast <CodeSerializationCluster*>(clusters_by_cid_[kCodeCid ]);
5840+
5841+ // Code objects that have identical/duplicate instructions must be adjacent in
5842+ // the order that Code objects are written because the encoding of the
5843+ // reference from the Code to the Instructions assumes monotonically
5844+ // increasing offsets as part of a delta encoding. Also the code order table
5845+ // that allows for mapping return addresses back to Code objects depends on
5846+ // this sorting.
5847+ if (cluster != nullptr ) {
5848+ CodeSerializationCluster::Sort (cluster->objects ());
5849+ }
5850+ if ((loading_units_ != nullptr ) &&
5851+ (current_loading_unit_id_ == LoadingUnit::kRootId )) {
5852+ for (intptr_t i = LoadingUnit::kRootId + 1 ; i < loading_units_->length ();
5853+ i++) {
5854+ auto unit_objects = loading_units_->At (i)->deferred_objects ();
5855+ CodeSerializationCluster::Sort (unit_objects);
5856+ for (intptr_t j = 0 ; j < unit_objects->length (); j++) {
5857+ cluster->deferred_objects ()->Add (unit_objects->At (j)->raw ());
5858+ }
5859+ }
5860+ }
5861+
57805862#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32)
57815863 if ((kind () == Snapshot::kFullAOT ) && FLAG_use_bare_instructions) {
5864+ // Group the code objects whose instructions are not being deferred in this
5865+ // snapshot unit in the order they will be written: first the code objects
5866+ // encountered for this first time in this unit being written by the
5867+ // CodeSerializationCluster, then code object previously deferred whose
5868+ // instructions are now written by UnitSerializationRoots. This order needs
5869+ // to be known to finalize bare-instructions-mode's PC-relative calls.
5870+ GrowableArray<CodePtr> code_objects;
5871+ if (cluster != nullptr ) {
5872+ auto in = cluster->objects ();
5873+ for (intptr_t i = 0 ; i < in->length (); i++) {
5874+ code_objects.Add (in->At (i));
5875+ }
5876+ }
5877+ if (loading_units_ != nullptr ) {
5878+ auto in =
5879+ loading_units_->At (current_loading_unit_id_)->deferred_objects ();
5880+ for (intptr_t i = 0 ; i < in->length (); i++) {
5881+ code_objects.Add (in->At (i)->raw ());
5882+ }
5883+ }
5884+
57825885 GrowableArray<ImageWriterCommand> writer_commands;
5783- RelocateCodeObjects (vm_, code_objects, &writer_commands);
5886+ RelocateCodeObjects (vm_, & code_objects, &writer_commands);
57845887 image_writer_->PrepareForSerialization (&writer_commands);
57855888 }
57865889#endif // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32)
@@ -6030,6 +6133,8 @@ ZoneGrowableArray<Object*>* Serializer::Serialize(SerializationRoots* roots) {
60306133 }
60316134#endif
60326135
6136+ PrepareInstructions ();
6137+
60336138 intptr_t num_objects = num_base_objects_ + num_written_objects_;
60346139#if defined(ARCH_IS_64_BIT)
60356140 if (!Utils::IsInt (32 , num_objects)) {
@@ -6147,8 +6252,7 @@ void Serializer::WriteDispatchTable(const Array& entries) {
61476252 ASSERT (code_cluster != nullptr );
61486253 // Reference IDs in a cluster are allocated sequentially, so we can use the
61496254 // first code object's reference ID to calculate the cluster index.
6150- const intptr_t first_code_id =
6151- RefId (code_cluster->discovered_objects ()->At (0 ));
6255+ const intptr_t first_code_id = RefId (code_cluster->objects ()->At (0 ));
61526256 // The first object in the code cluster must have its reference ID allocated.
61536257 ASSERT (IsAllocatedReference (first_code_id));
61546258
0 commit comments