OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #ifndef VM_CLUSTERED_SNAPSHOT_H_ | 5 #ifndef VM_CLUSTERED_SNAPSHOT_H_ |
6 #define VM_CLUSTERED_SNAPSHOT_H_ | 6 #define VM_CLUSTERED_SNAPSHOT_H_ |
7 | 7 |
8 #include "platform/assert.h" | 8 #include "platform/assert.h" |
9 #include "vm/allocation.h" | 9 #include "vm/allocation.h" |
10 #include "vm/bitfield.h" | 10 #include "vm/bitfield.h" |
11 #include "vm/datastream.h" | 11 #include "vm/datastream.h" |
12 #include "vm/exceptions.h" | 12 #include "vm/exceptions.h" |
13 #include "vm/globals.h" | 13 #include "vm/globals.h" |
14 #include "vm/growable_array.h" | 14 #include "vm/growable_array.h" |
| 15 #include "vm/hash_map.h" |
15 #include "vm/heap.h" | 16 #include "vm/heap.h" |
16 #include "vm/isolate.h" | 17 #include "vm/isolate.h" |
17 #include "vm/object.h" | 18 #include "vm/object.h" |
18 #include "vm/snapshot.h" | 19 #include "vm/snapshot.h" |
19 #include "vm/version.h" | 20 #include "vm/version.h" |
20 #include "vm/visitor.h" | 21 #include "vm/visitor.h" |
21 | 22 |
22 namespace dart { | 23 namespace dart { |
23 | 24 |
24 // Forward declarations. | 25 // Forward declarations. |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
76 // as rehashing. | 77 // as rehashing. |
77 virtual void PostLoad(const Array& refs, Snapshot::Kind kind, Zone* zone) { } | 78 virtual void PostLoad(const Array& refs, Snapshot::Kind kind, Zone* zone) { } |
78 | 79 |
79 protected: | 80 protected: |
80 // The range of the ref array that belongs to this cluster. | 81 // The range of the ref array that belongs to this cluster. |
81 intptr_t start_index_; | 82 intptr_t start_index_; |
82 intptr_t stop_index_; | 83 intptr_t stop_index_; |
83 }; | 84 }; |
84 | 85 |
85 | 86 |
86 enum { | 87 class SmiObjectIdPair { |
87 kRefTagSize = 1, | 88 public: |
88 kRefTagShift = 1, | 89 SmiObjectIdPair() : smi_(NULL), id_(0) { } |
89 kRefTagMask = 1, | 90 RawSmi* smi_; |
90 kSmiRefTag = 0x0, | 91 intptr_t id_; |
91 kHeapRefTag = 0x1, | 92 |
| 93 bool operator==(const SmiObjectIdPair& other) const { |
| 94 return (smi_ == other.smi_) && (id_ == other.id_); |
| 95 } |
92 }; | 96 }; |
93 | 97 |
94 | 98 |
| 99 class SmiObjectIdPairTrait { |
| 100 public: |
| 101 typedef RawSmi* Key; |
| 102 typedef intptr_t Value; |
| 103 typedef SmiObjectIdPair Pair; |
| 104 |
| 105 static Key KeyOf(Pair kv) { return kv.smi_; } |
| 106 static Value ValueOf(Pair kv) { return kv.id_; } |
| 107 static inline intptr_t Hashcode(Key key) { return Smi::Value(key); } |
| 108 static inline bool IsKeyEqual(Pair kv, Key key) { return kv.smi_ == key; } |
| 109 }; |
| 110 |
| 111 |
| 112 typedef DirectChainedHashMap<SmiObjectIdPairTrait> SmiObjectIdMap; |
| 113 |
| 114 |
95 class Serializer : public StackResource { | 115 class Serializer : public StackResource { |
96 public: | 116 public: |
97 Serializer(Thread* thread, | 117 Serializer(Thread* thread, |
98 Snapshot::Kind kind, | 118 Snapshot::Kind kind, |
99 uint8_t** buffer, | 119 uint8_t** buffer, |
100 ReAlloc alloc, | 120 ReAlloc alloc, |
101 intptr_t initial_size, | 121 intptr_t initial_size, |
102 InstructionsWriter* instructions_writer_); | 122 InstructionsWriter* instructions_writer_); |
103 ~Serializer(); | 123 ~Serializer(); |
104 | 124 |
105 intptr_t WriteVMSnapshot(const Array& symbols, const Array& scripts); | 125 intptr_t WriteVMSnapshot(const Array& symbols, const Array& scripts); |
106 void WriteFullSnapshot(intptr_t num_base_objects, ObjectStore* object_store); | 126 void WriteFullSnapshot(intptr_t num_base_objects, ObjectStore* object_store); |
107 | 127 |
108 void AddVMIsolateBaseObjects(); | 128 void AddVMIsolateBaseObjects(); |
109 | 129 |
110 void AddBaseObject(RawObject* base_object) { | 130 void AddBaseObject(RawObject* base_object) { |
111 AssignRef(base_object); | 131 AssignRef(base_object); |
112 num_base_objects_++; | 132 num_base_objects_++; |
113 } | 133 } |
114 | 134 |
115 void AssignRef(RawObject* object) { | 135 void AssignRef(RawObject* object) { |
116 ASSERT(next_ref_index_ != 0); | 136 ASSERT(next_ref_index_ != 0); |
117 heap_->SetObjectId(object, next_ref_index_); | 137 if (object->IsHeapObject()) { |
118 ASSERT(heap_->GetObjectId(object) == next_ref_index_); | 138 heap_->SetObjectId(object, next_ref_index_); |
| 139 ASSERT(heap_->GetObjectId(object) == next_ref_index_); |
| 140 } else { |
| 141 RawSmi* smi = Smi::RawCast(object); |
| 142 SmiObjectIdPair* existing_pair = smi_ids_.Lookup(smi); |
| 143 if (existing_pair != NULL) { |
| 144 ASSERT(existing_pair->id_ == 1); |
| 145 existing_pair->id_ = next_ref_index_; |
| 146 } else { |
| 147 SmiObjectIdPair new_pair; |
| 148 new_pair.smi_ = smi; |
| 149 new_pair.id_ = next_ref_index_; |
| 150 smi_ids_.Insert(new_pair); |
| 151 } |
| 152 } |
119 next_ref_index_++; | 153 next_ref_index_++; |
120 } | 154 } |
121 | 155 |
122 void Push(RawObject* object) { | 156 void Push(RawObject* object) { |
123 if (!object->IsHeapObject()) { | 157 if (!object->IsHeapObject()) { |
| 158 RawSmi* smi = Smi::RawCast(object); |
| 159 if (smi_ids_.Lookup(smi) == NULL) { |
| 160 SmiObjectIdPair pair; |
| 161 pair.smi_ = smi; |
| 162 pair.id_ = 1; |
| 163 smi_ids_.Insert(pair); |
| 164 stack_.Add(object); |
| 165 num_written_objects_++; |
| 166 } |
124 return; | 167 return; |
125 } | 168 } |
126 | 169 |
127 if (object->IsCode() && !Snapshot::IncludesCode(kind_)) { | 170 if (object->IsCode() && !Snapshot::IncludesCode(kind_)) { |
128 return; // Do not trace, will write null. | 171 return; // Do not trace, will write null. |
129 } | 172 } |
130 | 173 |
131 if (object->IsSendPort()) { | 174 if (object->IsSendPort()) { |
132 // TODO(rmacnak): Do a better job of resetting fields in precompilation | 175 // TODO(rmacnak): Do a better job of resetting fields in precompilation |
133 // and assert this is unreachable. | 176 // and assert this is unreachable. |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
173 void Write(T value) { | 216 void Write(T value) { |
174 WriteStream::Raw<sizeof(T), T>::Write(&stream_, value); | 217 WriteStream::Raw<sizeof(T), T>::Write(&stream_, value); |
175 } | 218 } |
176 | 219 |
177 void WriteBytes(const uint8_t* addr, intptr_t len) { | 220 void WriteBytes(const uint8_t* addr, intptr_t len) { |
178 stream_.WriteBytes(addr, len); | 221 stream_.WriteBytes(addr, len); |
179 } | 222 } |
180 | 223 |
181 void WriteRef(RawObject* object) { | 224 void WriteRef(RawObject* object) { |
182 if (!object->IsHeapObject()) { | 225 if (!object->IsHeapObject()) { |
183 ASSERT(static_cast<intptr_t>(kSmiRefTag) == | 226 RawSmi* smi = Smi::RawCast(object); |
184 static_cast<intptr_t>(kSmiTag)); | 227 intptr_t id = smi_ids_.Lookup(smi)->id_; |
185 Write<intptr_t>(reinterpret_cast<intptr_t>(object)); | 228 if (id == 0) { |
| 229 FATAL("Missing ref"); |
| 230 } |
| 231 Write<int32_t>(id); |
186 return; | 232 return; |
187 } | 233 } |
188 | 234 |
189 intptr_t id = heap_->GetObjectId(object); | 235 intptr_t id = heap_->GetObjectId(object); |
190 if (id == 0) { | 236 if (id == 0) { |
191 if (object->IsCode() && !Snapshot::IncludesCode(kind_)) { | 237 if (object->IsCode() && !Snapshot::IncludesCode(kind_)) { |
192 WriteRef(Object::null()); | 238 WriteRef(Object::null()); |
193 return; | 239 return; |
194 } | 240 } |
195 if (object->IsSendPort()) { | 241 if (object->IsSendPort()) { |
196 // TODO(rmacnak): Do a better job of resetting fields in precompilation | 242 // TODO(rmacnak): Do a better job of resetting fields in precompilation |
197 // and assert this is unreachable. | 243 // and assert this is unreachable. |
198 WriteRef(Object::null()); | 244 WriteRef(Object::null()); |
199 return; | 245 return; |
200 } | 246 } |
201 FATAL("Missing ref"); | 247 FATAL("Missing ref"); |
202 } | 248 } |
203 Write<intptr_t>((id << kRefTagShift) | kHeapRefTag); | 249 Write<int32_t>(id); |
204 } | 250 } |
205 | 251 |
206 void WriteTokenPosition(TokenPosition pos) { | 252 void WriteTokenPosition(TokenPosition pos) { |
207 Write<int32_t>(pos.SnapshotEncode()); | 253 Write<int32_t>(pos.SnapshotEncode()); |
208 } | 254 } |
209 | 255 |
210 void WriteCid(intptr_t cid) { | 256 void WriteCid(intptr_t cid) { |
211 COMPILE_ASSERT(RawObject::kClassIdTagSize <= 32); | 257 COMPILE_ASSERT(RawObject::kClassIdTagSize <= 32); |
212 Write<int32_t>(cid); | 258 Write<int32_t>(cid); |
213 } | 259 } |
(...skipping 13 matching lines...) Expand all Loading... |
227 Zone* zone_; | 273 Zone* zone_; |
228 Snapshot::Kind kind_; | 274 Snapshot::Kind kind_; |
229 WriteStream stream_; | 275 WriteStream stream_; |
230 InstructionsWriter* instructions_writer_; | 276 InstructionsWriter* instructions_writer_; |
231 SerializationCluster** clusters_by_cid_; | 277 SerializationCluster** clusters_by_cid_; |
232 GrowableArray<RawObject*> stack_; | 278 GrowableArray<RawObject*> stack_; |
233 intptr_t num_cids_; | 279 intptr_t num_cids_; |
234 intptr_t num_base_objects_; | 280 intptr_t num_base_objects_; |
235 intptr_t num_written_objects_; | 281 intptr_t num_written_objects_; |
236 intptr_t next_ref_index_; | 282 intptr_t next_ref_index_; |
| 283 SmiObjectIdMap smi_ids_; |
237 | 284 |
238 DISALLOW_IMPLICIT_CONSTRUCTORS(Serializer); | 285 DISALLOW_IMPLICIT_CONSTRUCTORS(Serializer); |
239 }; | 286 }; |
240 | 287 |
241 | 288 |
242 class Deserializer : public StackResource { | 289 class Deserializer : public StackResource { |
243 public: | 290 public: |
244 Deserializer(Thread* thread, | 291 Deserializer(Thread* thread, |
245 Snapshot::Kind kind, | 292 Snapshot::Kind kind, |
246 const uint8_t* buffer, | 293 const uint8_t* buffer, |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
293 next_ref_index_++; | 340 next_ref_index_++; |
294 } | 341 } |
295 | 342 |
296 RawObject* Ref(intptr_t index) const { | 343 RawObject* Ref(intptr_t index) const { |
297 ASSERT(index > 0); | 344 ASSERT(index > 0); |
298 ASSERT(index <= num_objects_); | 345 ASSERT(index <= num_objects_); |
299 return refs_->ptr()->data()[index]; | 346 return refs_->ptr()->data()[index]; |
300 } | 347 } |
301 | 348 |
302 RawObject* ReadRef() { | 349 RawObject* ReadRef() { |
303 intptr_t index = Read<intptr_t>(); | 350 int32_t index = Read<int32_t>(); |
304 if ((index & kRefTagMask) == kSmiRefTag) { | 351 return Ref(index); |
305 ASSERT(static_cast<intptr_t>(kSmiRefTag) == | |
306 static_cast<intptr_t>(kSmiTag)); | |
307 return reinterpret_cast<RawSmi*>(index); | |
308 } | |
309 return Ref(index >> kRefTagShift); | |
310 } | 352 } |
311 | 353 |
312 TokenPosition ReadTokenPosition() { | 354 TokenPosition ReadTokenPosition() { |
313 return TokenPosition::SnapshotDecode(Read<int32_t>()); | 355 return TokenPosition::SnapshotDecode(Read<int32_t>()); |
314 } | 356 } |
315 | 357 |
316 intptr_t ReadCid() { | 358 intptr_t ReadCid() { |
317 COMPILE_ASSERT(RawObject::kClassIdTagSize <= 32); | 359 COMPILE_ASSERT(RawObject::kClassIdTagSize <= 32); |
318 return Read<int32_t>(); | 360 return Read<int32_t>(); |
319 } | 361 } |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
469 intptr_t size_; | 511 intptr_t size_; |
470 const uint8_t* instructions_buffer_; | 512 const uint8_t* instructions_buffer_; |
471 const uint8_t* data_buffer_; | 513 const uint8_t* data_buffer_; |
472 | 514 |
473 DISALLOW_COPY_AND_ASSIGN(IsolateSnapshotReader); | 515 DISALLOW_COPY_AND_ASSIGN(IsolateSnapshotReader); |
474 }; | 516 }; |
475 | 517 |
476 } // namespace dart | 518 } // namespace dart |
477 | 519 |
478 #endif // VM_CLUSTERED_SNAPSHOT_H_ | 520 #endif // VM_CLUSTERED_SNAPSHOT_H_ |
OLD | NEW |