27
27
#include " vm/timeline.h"
28
28
#include " vm/version.h"
29
29
30
- #define LOG_SECTION_BOUNDARIES false
31
-
32
30
namespace dart {
33
31
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
+
34
39
#if defined(DART_PRECOMPILER)
35
40
DEFINE_FLAG (charp,
36
41
write_v8_snapshot_profile_to,
@@ -101,27 +106,34 @@ void Deserializer::InitializeHeader(RawObject* raw,
101
106
102
107
#if !defined(DART_PRECOMPILED_RUNTIME)
103
108
void 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 ();
109
111
intptr_t start_objects = serializer->next_ref_index ();
110
112
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 ();
112
115
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);
114
125
num_objects_ += (stop_objects - start_objects);
115
126
}
116
127
117
128
void SerializationCluster::WriteAndMeasureFill (Serializer* serializer) {
118
- if (LOG_SECTION_BOUNDARIES) {
119
- OS::PrintErr (" Data + %" Px " : Fill %s\n " , serializer->bytes_written (),
120
- name_);
121
- }
122
129
intptr_t start = serializer->bytes_written ();
123
130
WriteFill (serializer);
124
131
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
+ }
125
137
size_ += (stop - start);
126
138
}
127
139
@@ -2008,8 +2020,11 @@ class PcDescriptorsDeserializationCluster : public DeserializationCluster {
2008
2020
// PcDescriptor, CompressedStackMaps, OneByteString, TwoByteString
2009
2021
class RODataSerializationCluster : public SerializationCluster {
2010
2022
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) {}
2013
2028
~RODataSerializationCluster () {}
2014
2029
2015
2030
void Trace (Serializer* s, RawObject* object) {
@@ -2037,9 +2052,9 @@ class RODataSerializationCluster : public SerializationCluster {
2037
2052
RawObject* object = objects_[i];
2038
2053
s->AssignRef (object);
2039
2054
if (cid_ == kOneByteStringCid || cid_ == kTwoByteStringCid ) {
2040
- s->TraceStartWritingObject (name () , object, String::RawCast (object));
2055
+ s->TraceStartWritingObject (type_ , object, String::RawCast (object));
2041
2056
} else {
2042
- s->TraceStartWritingObject (name () , object, nullptr );
2057
+ s->TraceStartWritingObject (type_ , object, nullptr );
2043
2058
}
2044
2059
uint32_t offset = s->GetDataOffset (object);
2045
2060
s->TraceDataOffset (offset);
@@ -2060,6 +2075,7 @@ class RODataSerializationCluster : public SerializationCluster {
2060
2075
private:
2061
2076
const intptr_t cid_;
2062
2077
GrowableArray<RawObject*> objects_;
2078
+ const char * const type_;
2063
2079
};
2064
2080
#endif // !DART_PRECOMPILED_RUNTIME
2065
2081
@@ -4565,6 +4581,23 @@ void Serializer::TraceEndWritingObject() {
4565
4581
}
4566
4582
}
4567
4583
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
+
4568
4601
SerializationCluster* Serializer::NewClusterForClass (intptr_t cid) {
4569
4602
#if defined(DART_PRECOMPILED_RUNTIME)
4570
4603
UNREACHABLE ();
@@ -4586,18 +4619,8 @@ SerializationCluster* Serializer::NewClusterForClass(intptr_t cid) {
4586
4619
}
4587
4620
4588
4621
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);
4601
4624
}
4602
4625
}
4603
4626
@@ -4792,13 +4815,6 @@ intptr_t Serializer::GetDataSize() const {
4792
4815
return image_writer_->data_size ();
4793
4816
}
4794
4817
4795
- intptr_t Serializer::GetTextSize () const {
4796
- if (image_writer_ == NULL ) {
4797
- return 0 ;
4798
- }
4799
- return image_writer_->text_size ();
4800
- }
4801
-
4802
4818
void Serializer::Push (RawObject* object) {
4803
4819
if (!object->IsHeapObject ()) {
4804
4820
RawSmi* smi = Smi::RawCast (object);
@@ -5030,19 +5046,36 @@ void Serializer::PrintSnapshotSizes() {
5030
5046
clusters_by_size.Add (cluster);
5031
5047
}
5032
5048
}
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;
5034
5057
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
+ }
5036
5065
}
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 ;
5039
5073
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_));
5042
5075
}
5043
5076
clusters_by_size.Sort (CompareClusters);
5044
5077
double total_size =
5045
- static_cast <double >(bytes_written () + GetDataSize () + GetTextSize () );
5078
+ static_cast <double >(bytes_written () + GetDataSize () + text_size );
5046
5079
double cumulative_fraction = 0.0 ;
5047
5080
for (intptr_t i = 0 ; i < clusters_by_size.length (); i++) {
5048
5081
SerializationCluster* cluster = clusters_by_size[i];
@@ -5178,6 +5211,36 @@ static const char* kObjectStoreFieldNames[] = {
5178
5211
5179
5212
void Serializer::WriteIsolateSnapshot (intptr_t num_base_objects,
5180
5213
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
+
5181
5244
NoSafepointScope no_safepoint;
5182
5245
5183
5246
if (num_base_objects == 0 ) {
@@ -5199,19 +5262,53 @@ void Serializer::WriteIsolateSnapshot(intptr_t num_base_objects,
5199
5262
Push (*p);
5200
5263
}
5201
5264
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
+
5202
5274
Serialize ();
5203
5275
5204
5276
// Write roots.
5205
5277
for (RawObject** p = from; p <= to; p++) {
5206
5278
WriteRootRef (*p, kObjectStoreFieldNames [p - from]);
5207
5279
}
5208
5280
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
5215
5312
5216
5313
#if defined(DEBUG)
5217
5314
Write<int32_t >(kSectionMarker );
@@ -5776,11 +5873,13 @@ void Deserializer::ReadIsolateSnapshot(ObjectStore* object_store) {
5776
5873
*p = ReadRef ();
5777
5874
}
5778
5875
5876
+ #if defined(DART_PRECOMPILED_RUNTIME)
5779
5877
// Deserialize dispatch table
5780
5878
const Array& code_array =
5781
5879
Array::Handle (zone_, object_store->code_order_table ());
5782
5880
thread ()->isolate ()->set_dispatch_table (
5783
5881
DispatchTable::Deserialize (this , code_array));
5882
+ #endif
5784
5883
5785
5884
#if defined(DEBUG)
5786
5885
int32_t section_marker = Read<int32_t >();
0 commit comments