2727#include " vm/timeline.h"
2828#include " vm/version.h"
2929
30- #define LOG_SECTION_BOUNDARIES false
31-
3230namespace dart {
3331
32+ #if !defined(DART_PRECOMPILED_RUNTIME)
33+ DEFINE_FLAG (bool ,
34+ print_cluster_information,
35+ false ,
36+ " Print information about clusters written to snapshot" );
37+ #endif
38+
3439#if defined(DART_PRECOMPILER)
3540DEFINE_FLAG (charp,
3641 write_v8_snapshot_profile_to,
@@ -101,27 +106,34 @@ void Deserializer::InitializeHeader(RawObject* raw,
101106
102107#if !defined(DART_PRECOMPILED_RUNTIME)
103108void SerializationCluster::WriteAndMeasureAlloc (Serializer* serializer) {
104- if (LOG_SECTION_BOUNDARIES) {
105- OS::PrintErr (" Data + %" Px " : Alloc %s\n " , serializer->bytes_written (),
106- name_);
107- }
108- intptr_t start_size = serializer->bytes_written () + serializer->GetDataSize ();
109+ intptr_t start_size = serializer->bytes_written ();
110+ intptr_t start_data = serializer->GetDataSize ();
109111 intptr_t start_objects = serializer->next_ref_index ();
110112 WriteAlloc (serializer);
111- intptr_t stop_size = serializer->bytes_written () + serializer->GetDataSize ();
113+ intptr_t stop_size = serializer->bytes_written ();
114+ intptr_t stop_data = serializer->GetDataSize ();
112115 intptr_t stop_objects = serializer->next_ref_index ();
113- size_ += (stop_size - start_size);
116+ if (FLAG_print_cluster_information) {
117+ const int hex_size = kWordSize * 2 ;
118+ OS::PrintErr (" Snapshot 0x%0*.*" Px " (%" Pd " ), " , hex_size, hex_size,
119+ start_size, stop_size - start_size);
120+ OS::PrintErr (" Data 0x%0*.*" Px " (%" Pd " ): " , hex_size, hex_size,
121+ start_data, stop_data - start_data);
122+ OS::PrintErr (" Alloc %s (%" Pd " )\n " , name (), stop_objects - start_objects);
123+ }
124+ size_ += (stop_size - start_size) + (stop_data - start_data);
114125 num_objects_ += (stop_objects - start_objects);
115126}
116127
117128void SerializationCluster::WriteAndMeasureFill (Serializer* serializer) {
118- if (LOG_SECTION_BOUNDARIES) {
119- OS::PrintErr (" Data + %" Px " : Fill %s\n " , serializer->bytes_written (),
120- name_);
121- }
122129 intptr_t start = serializer->bytes_written ();
123130 WriteFill (serializer);
124131 intptr_t stop = serializer->bytes_written ();
132+ if (FLAG_print_cluster_information) {
133+ const int hex_size = kWordSize * 2 ;
134+ OS::PrintErr (" Snapshot 0x%0*.*" Px " (%" Pd " ): Fill %s\n " , hex_size,
135+ hex_size, start, stop - start, name ());
136+ }
125137 size_ += (stop - start);
126138}
127139
@@ -2008,8 +2020,11 @@ class PcDescriptorsDeserializationCluster : public DeserializationCluster {
20082020// PcDescriptor, CompressedStackMaps, OneByteString, TwoByteString
20092021class RODataSerializationCluster : public SerializationCluster {
20102022 public:
2011- RODataSerializationCluster (const char * name, intptr_t cid)
2012- : SerializationCluster(name), cid_(cid) {}
2023+ RODataSerializationCluster (Zone* zone, const char * type, intptr_t cid)
2024+ : SerializationCluster(ImageWriter::TagObjectTypeAsReadOnly(zone, type)),
2025+ cid_ (cid),
2026+ objects_(),
2027+ type_(type) {}
20132028 ~RODataSerializationCluster () {}
20142029
20152030 void Trace (Serializer* s, RawObject* object) {
@@ -2037,9 +2052,9 @@ class RODataSerializationCluster : public SerializationCluster {
20372052 RawObject* object = objects_[i];
20382053 s->AssignRef (object);
20392054 if (cid_ == kOneByteStringCid || cid_ == kTwoByteStringCid ) {
2040- s->TraceStartWritingObject (name () , object, String::RawCast (object));
2055+ s->TraceStartWritingObject (type_ , object, String::RawCast (object));
20412056 } else {
2042- s->TraceStartWritingObject (name () , object, nullptr );
2057+ s->TraceStartWritingObject (type_ , object, nullptr );
20432058 }
20442059 uint32_t offset = s->GetDataOffset (object);
20452060 s->TraceDataOffset (offset);
@@ -2060,6 +2075,7 @@ class RODataSerializationCluster : public SerializationCluster {
20602075 private:
20612076 const intptr_t cid_;
20622077 GrowableArray<RawObject*> objects_;
2078+ const char * const type_;
20632079};
20642080#endif // !DART_PRECOMPILED_RUNTIME
20652081
@@ -4565,6 +4581,23 @@ void Serializer::TraceEndWritingObject() {
45654581 }
45664582}
45674583
4584+ const char * Serializer::ReadOnlyObjectType (intptr_t cid) {
4585+ switch (cid) {
4586+ case kPcDescriptorsCid :
4587+ return " PcDescriptors" ;
4588+ case kCodeSourceMapCid :
4589+ return " CodeSourceMap" ;
4590+ case kCompressedStackMapsCid :
4591+ return " CompressedStackMaps" ;
4592+ case kOneByteStringCid :
4593+ return " OneByteString" ;
4594+ case kTwoByteStringCid :
4595+ return " TwoByteString" ;
4596+ default :
4597+ return nullptr ;
4598+ }
4599+ }
4600+
45684601SerializationCluster* Serializer::NewClusterForClass (intptr_t cid) {
45694602#if defined(DART_PRECOMPILED_RUNTIME)
45704603 UNREACHABLE ();
@@ -4586,18 +4619,8 @@ SerializationCluster* Serializer::NewClusterForClass(intptr_t cid) {
45864619 }
45874620
45884621 if (Snapshot::IncludesCode (kind_)) {
4589- switch (cid) {
4590- case kPcDescriptorsCid :
4591- return new (Z) RODataSerializationCluster (" (RO)PcDescriptors" , cid);
4592- case kCodeSourceMapCid :
4593- return new (Z) RODataSerializationCluster (" (RO)CodeSourceMap" , cid);
4594- case kCompressedStackMapsCid :
4595- return new (Z)
4596- RODataSerializationCluster (" (RO)CompressedStackMaps" , cid);
4597- case kOneByteStringCid :
4598- return new (Z) RODataSerializationCluster (" (RO)OneByteString" , cid);
4599- case kTwoByteStringCid :
4600- return new (Z) RODataSerializationCluster (" (RO)TwoByteString" , cid);
4622+ if (auto const type = ReadOnlyObjectType (cid)) {
4623+ return new (Z) RODataSerializationCluster (Z, type, cid);
46014624 }
46024625 }
46034626
@@ -4792,13 +4815,6 @@ intptr_t Serializer::GetDataSize() const {
47924815 return image_writer_->data_size ();
47934816}
47944817
4795- intptr_t Serializer::GetTextSize () const {
4796- if (image_writer_ == NULL ) {
4797- return 0 ;
4798- }
4799- return image_writer_->text_size ();
4800- }
4801-
48024818void Serializer::Push (RawObject* object) {
48034819 if (!object->IsHeapObject ()) {
48044820 RawSmi* smi = Smi::RawCast (object);
@@ -5030,19 +5046,36 @@ void Serializer::PrintSnapshotSizes() {
50305046 clusters_by_size.Add (cluster);
50315047 }
50325048 }
5033- if (GetTextSize () != 0 ) {
5049+ intptr_t text_size = 0 ;
5050+ if (image_writer_ != nullptr ) {
5051+ auto const text_object_count = image_writer_->GetTextObjectCount ();
5052+ text_size = image_writer_->text_size ();
5053+ intptr_t trampoline_count, trampoline_size;
5054+ image_writer_->GetTrampolineInfo (&trampoline_count, &trampoline_size);
5055+ auto const instructions_count = text_object_count - trampoline_count;
5056+ auto const instructions_size = text_size - trampoline_size;
50345057 clusters_by_size.Add (new (zone_) FakeSerializationCluster (
5035- " (RO)Instructions" , 0 , GetTextSize ()));
5058+ ImageWriter::TagObjectTypeAsReadOnly (zone_, " Instructions" ),
5059+ instructions_count, instructions_size));
5060+ if (trampoline_size > 0 ) {
5061+ clusters_by_size.Add (new (zone_) FakeSerializationCluster (
5062+ ImageWriter::TagObjectTypeAsReadOnly (zone_, " Trampoline" ),
5063+ trampoline_count, trampoline_size));
5064+ }
50365065 }
5037- // An null dispatch table will serialize to a single byte.
5038- if (dispatch_table_size_ > 1 ) {
5066+ // The dispatch_table_size_ will be 0 if the snapshot did not include a
5067+ // dispatch table (i.e., the VM snapshot). For a precompiled isolate
5068+ // snapshot, we always serialize at least _one_ byte for the DispatchTable.
5069+ if (dispatch_table_size_ > 0 ) {
5070+ auto const dispatch_table = isolate ()->dispatch_table ();
5071+ auto const entry_count =
5072+ dispatch_table != nullptr ? dispatch_table->length () : 0 ;
50395073 clusters_by_size.Add (new (zone_) FakeSerializationCluster (
5040- " (RO)DispatchTable" , isolate ()->dispatch_table ()->length (),
5041- dispatch_table_size_));
5074+ " DispatchTable" , entry_count, dispatch_table_size_));
50425075 }
50435076 clusters_by_size.Sort (CompareClusters);
50445077 double total_size =
5045- static_cast <double >(bytes_written () + GetDataSize () + GetTextSize () );
5078+ static_cast <double >(bytes_written () + GetDataSize () + text_size );
50465079 double cumulative_fraction = 0.0 ;
50475080 for (intptr_t i = 0 ; i < clusters_by_size.length (); i++) {
50485081 SerializationCluster* cluster = clusters_by_size[i];
@@ -5178,6 +5211,36 @@ static const char* kObjectStoreFieldNames[] = {
51785211
51795212void Serializer::WriteIsolateSnapshot (intptr_t num_base_objects,
51805213 ObjectStore* object_store) {
5214+ #if defined(DART_PRECOMPILER)
5215+ // We should treat the dispatch table as a root object and trace the
5216+ // Code objects it references via entry points. Otherwise, an non-empty
5217+ // entry could be invalid on deserialization if the corresponding Code
5218+ // object was not reachable from the existing snapshot roots.
5219+ //
5220+ // Since the dispatch table only stores entry points, we have to find the
5221+ // Code objects before entering the NoSafepointScope, since looking up a
5222+ // Code object from the entry point cannot be done during one.
5223+ auto const dispatch_table = isolate ()->dispatch_table ();
5224+ // Check that we only have dispatch tables in precompiled mode, so we can
5225+ // elide them from the snapshot when not creating a precompiled snapshot.
5226+ ASSERT (dispatch_table == nullptr || kind () == Snapshot::kFullAOT );
5227+ // We collect the Code objects for each entry, storing null if there is none.
5228+ auto const dispatch_table_length =
5229+ dispatch_table != nullptr ? dispatch_table->length () : 0 ;
5230+ GrowableHandlePtrArray<const Code> dispatch_table_roots (
5231+ zone_, dispatch_table_length);
5232+ if (dispatch_table != nullptr ) {
5233+ auto & code = Code::Handle (zone_);
5234+ auto const entries = dispatch_table->array ();
5235+ for (intptr_t i = 0 ; i < dispatch_table_length; i++) {
5236+ auto const entry = entries[i];
5237+ code = entry != 0 ? Code::LookupCode (entry) : Code::null ();
5238+ ASSERT (entry == 0 || !code.IsNull ());
5239+ dispatch_table_roots.Add (code);
5240+ }
5241+ }
5242+ #endif
5243+
51815244 NoSafepointScope no_safepoint;
51825245
51835246 if (num_base_objects == 0 ) {
@@ -5199,19 +5262,53 @@ void Serializer::WriteIsolateSnapshot(intptr_t num_base_objects,
51995262 Push (*p);
52005263 }
52015264
5265+ #if defined(DART_PRECOMPILER)
5266+ // Push the Code objects collected from the dispatch table.
5267+ for (intptr_t i = 0 ; i < dispatch_table_length; i++) {
5268+ const auto & code = dispatch_table_roots.At (i);
5269+ if (code.IsNull ()) continue ;
5270+ Push (code.raw ());
5271+ }
5272+ #endif
5273+
52025274 Serialize ();
52035275
52045276 // Write roots.
52055277 for (RawObject** p = from; p <= to; p++) {
52065278 WriteRootRef (*p, kObjectStoreFieldNames [p - from]);
52075279 }
52085280
5209- // Serialize dispatch table.
5210- GrowableArray<RawCode*>* code_objects =
5211- static_cast <CodeSerializationCluster*>(clusters_by_cid_[kCodeCid ])
5212- ->discovered_objects ();
5213- dispatch_table_size_ = DispatchTable::Serialize (
5214- this , isolate ()->dispatch_table (), *code_objects);
5281+ #if defined(DART_PRECOMPILER)
5282+ // Serialize dispatch table for precompiled snapshots only.
5283+ if (kind () == Snapshot::kFullAOT ) {
5284+ GrowableArray<RawCode*>* code_objects =
5285+ static_cast <CodeSerializationCluster*>(clusters_by_cid_[kCodeCid ])
5286+ ->discovered_objects ();
5287+ dispatch_table_size_ = DispatchTable::Serialize (
5288+ this , isolate ()->dispatch_table (), *code_objects);
5289+ ASSERT (dispatch_table_length == 0 || dispatch_table_size_ > 1 );
5290+
5291+ if (profile_writer_ != nullptr ) {
5292+ // Grab an unused ref index for a unique object id for the dispatch table.
5293+ const auto dispatch_table_id = next_ref_index_++;
5294+ const V8SnapshotProfileWriter::ObjectId dispatch_table_snapshot_id (
5295+ V8SnapshotProfileWriter::kSnapshot , dispatch_table_id);
5296+ profile_writer_->AddRoot (dispatch_table_snapshot_id, " dispatch_table" );
5297+ profile_writer_->SetObjectTypeAndName (dispatch_table_snapshot_id,
5298+ " DispatchTable" , nullptr );
5299+ profile_writer_->AttributeBytesTo (dispatch_table_snapshot_id,
5300+ dispatch_table_size_);
5301+ for (intptr_t i = 0 ; i < dispatch_table_length; i++) {
5302+ const auto & code = dispatch_table_roots.At (i);
5303+ const V8SnapshotProfileWriter::ObjectId code_id (
5304+ V8SnapshotProfileWriter::kSnapshot , WriteRefId (code.raw ()));
5305+ profile_writer_->AttributeReferenceTo (
5306+ dispatch_table_snapshot_id,
5307+ {code_id, V8SnapshotProfileWriter::Reference::kElement , i});
5308+ }
5309+ }
5310+ }
5311+ #endif
52155312
52165313#if defined(DEBUG)
52175314 Write<int32_t >(kSectionMarker );
@@ -5776,11 +5873,13 @@ void Deserializer::ReadIsolateSnapshot(ObjectStore* object_store) {
57765873 *p = ReadRef ();
57775874 }
57785875
5876+ #if defined(DART_PRECOMPILED_RUNTIME)
57795877 // Deserialize dispatch table
57805878 const Array& code_array =
57815879 Array::Handle (zone_, object_store->code_order_table ());
57825880 thread ()->isolate ()->set_dispatch_table (
57835881 DispatchTable::Deserialize (this , code_array));
5882+ #endif
57845883
57855884#if defined(DEBUG)
57865885 int32_t section_marker = Read<int32_t >();
0 commit comments