| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 #include "vm/snapshot.h" | 5 #include "vm/snapshot.h" |
| 6 | 6 |
| 7 #include "vm/assert.h" | 7 #include "vm/assert.h" |
| 8 #include "vm/bootstrap.h" | 8 #include "vm/bootstrap.h" |
| 9 #include "vm/heap.h" | 9 #include "vm/heap.h" |
| 10 #include "vm/object.h" | 10 #include "vm/object.h" |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 163 ASSERT(object_id >= kMaxPredefinedObjectIds); | 163 ASSERT(object_id >= kMaxPredefinedObjectIds); |
| 164 intptr_t index = object_id - kMaxPredefinedObjectIds; | 164 intptr_t index = object_id - kMaxPredefinedObjectIds; |
| 165 ASSERT(index < backward_references_.length()); | 165 ASSERT(index < backward_references_.length()); |
| 166 return backward_references_[index]->raw(); | 166 return backward_references_[index]->raw(); |
| 167 } | 167 } |
| 168 | 168 |
| 169 | 169 |
| 170 RawObject* SnapshotReader::ReadInlinedObject(intptr_t object_id) { | 170 RawObject* SnapshotReader::ReadInlinedObject(intptr_t object_id) { |
| 171 // Read the class header information and lookup the class. | 171 // Read the class header information and lookup the class. |
| 172 intptr_t class_header = Read<intptr_t>(); | 172 intptr_t class_header = Read<intptr_t>(); |
| 173 intptr_t tags = Read<intptr_t>(); |
| 173 Class& cls = Class::Handle(); | 174 Class& cls = Class::Handle(); |
| 175 Object& obj = Object::Handle(); |
| 174 if (SerializedHeaderData::decode(class_header) == kInstanceId) { | 176 if (SerializedHeaderData::decode(class_header) == kInstanceId) { |
| 175 // Object is regular dart instance. | 177 // Object is regular dart instance. |
| 176 Instance& result = Instance::ZoneHandle(); | 178 Instance& result = Instance::ZoneHandle(); |
| 177 AddBackwardReference(object_id, &result); | 179 AddBackwardReference(object_id, &result); |
| 178 | 180 |
| 179 cls ^= ReadObject(); | 181 cls ^= ReadObject(); |
| 180 ASSERT(!cls.IsNull()); | 182 ASSERT(!cls.IsNull()); |
| 181 intptr_t instance_size = cls.instance_size(); | 183 intptr_t instance_size = cls.instance_size(); |
| 182 ASSERT(instance_size > 0); | 184 ASSERT(instance_size > 0); |
| 183 // Allocate the instance and read in all the fields for the object. | 185 // Allocate the instance and read in all the fields for the object. |
| 184 RawObject* raw = Object::Allocate(cls, instance_size, Heap::kNew); | 186 RawObject* raw = Object::Allocate(cls, instance_size, Heap::kNew); |
| 185 result ^= raw; | 187 result ^= raw; |
| 186 intptr_t offset = Object::InstanceSize(); | 188 intptr_t offset = Object::InstanceSize(); |
| 187 Object& obj = Object::Handle(); | |
| 188 while (offset < instance_size) { | 189 while (offset < instance_size) { |
| 189 obj = ReadObject(); | 190 obj = ReadObject(); |
| 190 result.SetFieldAtOffset(offset, obj); | 191 result.SetFieldAtOffset(offset, obj); |
| 191 offset += kWordSize; | 192 offset += kWordSize; |
| 192 } | 193 } |
| 194 if (kind_ == Snapshot::kFull) { |
| 195 result.SetCreatedFromSnapshot(); |
| 196 } |
| 193 return result.raw(); | 197 return result.raw(); |
| 194 } else { | 198 } else { |
| 195 ASSERT((class_header & kSmiTagMask) != 0); | 199 ASSERT((class_header & kSmiTagMask) != 0); |
| 196 cls ^= LookupInternalClass(class_header); | 200 cls ^= LookupInternalClass(class_header); |
| 197 ASSERT(!cls.IsNull()); | 201 ASSERT(!cls.IsNull()); |
| 198 } | 202 } |
| 199 switch (cls.instance_kind()) { | 203 switch (cls.instance_kind()) { |
| 200 #define SNAPSHOT_READ(clazz) \ | 204 #define SNAPSHOT_READ(clazz) \ |
| 201 case clazz::kInstanceKind: { \ | 205 case clazz::kInstanceKind: { \ |
| 202 return clazz::ReadFrom(this, object_id, kind_); \ | 206 obj = clazz::ReadFrom(this, object_id, tags, kind_); \ |
| 207 break; \ |
| 203 } | 208 } |
| 204 CLASS_LIST_NO_OBJECT(SNAPSHOT_READ) | 209 CLASS_LIST_NO_OBJECT(SNAPSHOT_READ) |
| 205 #undef SNAPSHOT_READ | 210 #undef SNAPSHOT_READ |
| 206 default: break; | 211 default: UNREACHABLE(); break; |
| 207 } | 212 } |
| 208 UNREACHABLE(); | 213 if (kind_ == Snapshot::kFull) { |
| 209 return Object::null(); | 214 obj.SetCreatedFromSnapshot(); |
| 215 } |
| 216 return obj.raw(); |
| 210 } | 217 } |
| 211 | 218 |
| 212 | 219 |
| 213 void MessageWriter::WriteMessage(intptr_t field_count, intptr_t *data) { | 220 void MessageWriter::WriteMessage(intptr_t field_count, intptr_t *data) { |
| 214 // Write out the serialization header value for this object. | 221 // Write out the serialization header value for this object. |
| 215 WriteObjectHeader(kInlined, kMaxPredefinedObjectIds); | 222 WriteSerializationMarker(kInlined, kMaxPredefinedObjectIds); |
| 216 | 223 |
| 217 // Write out the class information. | 224 // Write out the class and tags information. |
| 218 WriteObjectHeader(kObjectId, ObjectStore::kArrayClass); | 225 WriteObjectHeader(ObjectStore::kArrayClass, 0); |
| 219 | 226 |
| 220 // Write out the length field. | 227 // Write out the length field. |
| 221 Write<RawObject*>(Smi::New(field_count)); | 228 Write<RawObject*>(Smi::New(field_count)); |
| 222 | 229 |
| 223 // Write out the type arguments. | 230 // Write out the type arguments. |
| 224 WriteObjectHeader(kObjectId, Object::kNullObject); | 231 WriteIndexedObject(Object::kNullObject); |
| 225 | 232 |
| 226 // Write out the individual Smis. | 233 // Write out the individual Smis. |
| 227 for (int i = 0; i < field_count; i++) { | 234 for (int i = 0; i < field_count; i++) { |
| 228 Write<RawObject*>(Integer::New(data[i])); | 235 Write<RawObject*>(Integer::New(data[i])); |
| 229 } | 236 } |
| 230 | 237 |
| 231 FinalizeBuffer(); | 238 FinalizeBuffer(); |
| 232 } | 239 } |
| 233 | 240 |
| 234 | 241 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 246 // writing a snap shot. | 253 // writing a snap shot. |
| 247 | 254 |
| 248 // First check if it is a Smi (i.e not a heap object). | 255 // First check if it is a Smi (i.e not a heap object). |
| 249 if (!rawobj->IsHeapObject()) { | 256 if (!rawobj->IsHeapObject()) { |
| 250 Write<RawObject*>(rawobj); | 257 Write<RawObject*>(rawobj); |
| 251 return; | 258 return; |
| 252 } | 259 } |
| 253 | 260 |
| 254 // Check if it is a singleton null object which is shared by all isolates. | 261 // Check if it is a singleton null object which is shared by all isolates. |
| 255 if (rawobj == Object::null()) { | 262 if (rawobj == Object::null()) { |
| 256 WriteObjectHeader(kObjectId, Object::kNullObject); | 263 WriteIndexedObject(Object::kNullObject); |
| 257 return; | 264 return; |
| 258 } | 265 } |
| 259 | 266 |
| 260 // Check if it is a singleton sentinel object which is shared by all isolates. | 267 // Check if it is a singleton sentinel object which is shared by all isolates. |
| 261 if (rawobj == Object::sentinel()) { | 268 if (rawobj == Object::sentinel()) { |
| 262 WriteObjectHeader(kObjectId, Object::kSentinelObject); | 269 WriteIndexedObject(Object::kSentinelObject); |
| 263 return; | 270 return; |
| 264 } | 271 } |
| 265 | 272 |
| 266 // Check if it is a singleton class object which is shared by | 273 // Check if it is a singleton class object which is shared by |
| 267 // all isolates. | 274 // all isolates. |
| 268 RawClass* raw_class = reinterpret_cast<RawClass*>(rawobj); | 275 RawClass* raw_class = reinterpret_cast<RawClass*>(rawobj); |
| 269 intptr_t index = Object::GetSingletonClassIndex(raw_class); | 276 intptr_t index = Object::GetSingletonClassIndex(raw_class); |
| 270 if (index != Object::kInvalidIndex) { | 277 if (index != Object::kInvalidIndex) { |
| 271 WriteObjectHeader(kObjectId, index); | 278 WriteIndexedObject(index); |
| 272 return; | 279 return; |
| 273 } | 280 } |
| 274 | 281 |
| 275 // Check if it is a singleton boolean true value. | 282 // Check if it is a singleton boolean true value. |
| 276 if (rawobj == object_store()->true_value()) { | 283 if (rawobj == object_store()->true_value()) { |
| 277 WriteObjectHeader(kObjectId, ObjectStore::kTrueValue); | 284 WriteIndexedObject(ObjectStore::kTrueValue); |
| 278 return; | 285 return; |
| 279 } | 286 } |
| 280 | 287 |
| 281 // Check if it is a singleton boolean false value. | 288 // Check if it is a singleton boolean false value. |
| 282 if (rawobj == object_store()->false_value()) { | 289 if (rawobj == object_store()->false_value()) { |
| 283 WriteObjectHeader(kObjectId, ObjectStore::kFalseValue); | 290 WriteIndexedObject(ObjectStore::kFalseValue); |
| 284 return; | 291 return; |
| 285 } | 292 } |
| 286 | 293 |
| 287 // Check if classes are not being serialized and it is preinitialized type. | 294 // Check if classes are not being serialized and it is preinitialized type. |
| 288 if (kind_ != Snapshot::kFull) { | 295 if (kind_ != Snapshot::kFull) { |
| 289 RawType* raw_type = reinterpret_cast<RawType*>(rawobj); | 296 RawType* raw_type = reinterpret_cast<RawType*>(rawobj); |
| 290 index = object_store()->GetTypeIndex(raw_type); | 297 index = object_store()->GetTypeIndex(raw_type); |
| 291 if (index != ObjectStore::kInvalidIndex) { | 298 if (index != ObjectStore::kInvalidIndex) { |
| 292 WriteObjectHeader(kObjectId, index); | 299 WriteIndexedObject(index); |
| 293 return; | 300 return; |
| 294 } | 301 } |
| 295 } | 302 } |
| 296 | 303 |
| 297 // Now write the object out inline in the stream. | 304 // Now write the object out inline in the stream. |
| 298 WriteInlinedObject(rawobj); | 305 WriteInlinedObject(rawobj); |
| 299 } | 306 } |
| 300 | 307 |
| 301 | 308 |
| 302 void SnapshotWriter::WriteObjectHeader(SerializedHeaderType type, intptr_t id) { | |
| 303 uword value = 0; | |
| 304 value = SerializedHeaderTag::update(type, value); | |
| 305 value = SerializedHeaderData::update(id, value); | |
| 306 Write<uword>(value); | |
| 307 } | |
| 308 | |
| 309 | |
| 310 void SnapshotWriter::UnmarkAll() { | 309 void SnapshotWriter::UnmarkAll() { |
| 311 NoGCScope no_gc; | 310 NoGCScope no_gc; |
| 312 for (intptr_t i = 0; i < forward_list_.length(); i++) { | 311 for (intptr_t i = 0; i < forward_list_.length(); i++) { |
| 313 RawObject* raw = forward_list_[i]->raw(); | 312 RawObject* raw = forward_list_[i]->raw(); |
| 314 raw->ptr()->class_ = forward_list_[i]->cls(); // Restore original class. | 313 raw->ptr()->class_ = forward_list_[i]->cls(); // Restore original class. |
| 315 } | 314 } |
| 316 } | 315 } |
| 317 | 316 |
| 318 | 317 |
| 319 void SnapshotWriter::WriteFullSnapshot() { | 318 void SnapshotWriter::WriteFullSnapshot() { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 348 | 347 |
| 349 | 348 |
| 350 void SnapshotWriter::WriteInlinedObject(RawObject* raw) { | 349 void SnapshotWriter::WriteInlinedObject(RawObject* raw) { |
| 351 NoGCScope no_gc; | 350 NoGCScope no_gc; |
| 352 RawClass* cls = raw->ptr()->class_; | 351 RawClass* cls = raw->ptr()->class_; |
| 353 | 352 |
| 354 // Check if object has already been serialized, in that | 353 // Check if object has already been serialized, in that |
| 355 // case just write the object id out. | 354 // case just write the object id out. |
| 356 if (SerializedHeaderTag::decode(reinterpret_cast<uword>(cls)) == kObjectId) { | 355 if (SerializedHeaderTag::decode(reinterpret_cast<uword>(cls)) == kObjectId) { |
| 357 intptr_t id = SerializedHeaderData::decode(reinterpret_cast<intptr_t>(cls)); | 356 intptr_t id = SerializedHeaderData::decode(reinterpret_cast<intptr_t>(cls)); |
| 358 WriteObjectHeader(kObjectId, id); | 357 WriteIndexedObject(id); |
| 359 return; | 358 return; |
| 360 } | 359 } |
| 361 | 360 |
| 362 // Object is being serialized, add it to the forward ref list and mark | 361 // Object is being serialized, add it to the forward ref list and mark |
| 363 // it so that future references to this object in the snapshot will use | 362 // it so that future references to this object in the snapshot will use |
| 364 // an object id, instead of trying to serialize it again. | 363 // an object id, instead of trying to serialize it again. |
| 365 intptr_t object_id = MarkObject(raw, cls); | 364 intptr_t object_id = MarkObject(raw, cls); |
| 366 | 365 |
| 367 ObjectKind kind = cls->ptr()->instance_kind_; | 366 ObjectKind kind = cls->ptr()->instance_kind_; |
| 368 if (kind == Instance::kInstanceKind) { | 367 if (kind == Instance::kInstanceKind) { |
| 369 // Object is regular dart instance. | 368 // Object is regular dart instance. |
| 370 // TODO(5411462): figure out what we need to do if an object with native | 369 // TODO(5411462): figure out what we need to do if an object with native |
| 371 // fields is serialized (throw exception or serialize a null object). | 370 // fields is serialized (throw exception or serialize a null object). |
| 372 ASSERT(cls->ptr()->num_native_fields_ == 0); | 371 ASSERT(cls->ptr()->num_native_fields_ == 0); |
| 373 intptr_t instance_size = cls->ptr()->instance_size_; | 372 intptr_t instance_size = cls->ptr()->instance_size_; |
| 374 ASSERT(instance_size != 0); | 373 ASSERT(instance_size != 0); |
| 375 | 374 |
| 376 // Write out the serialization header value for this object. | 375 // Write out the serialization header value for this object. |
| 377 WriteObjectHeader(kInlined, object_id); | 376 WriteSerializationMarker(kInlined, object_id); |
| 378 | 377 |
| 379 // Indicate this is an instance object. | 378 // Indicate this is an instance object. |
| 380 Write<intptr_t>(SerializedHeaderData::encode(kInstanceId)); | 379 Write<intptr_t>(SerializedHeaderData::encode(kInstanceId)); |
| 381 | 380 |
| 381 // Write out the tags. |
| 382 Write<intptr_t>(raw->ptr()->tags_); |
| 383 |
| 382 // Write out the class information for this object. | 384 // Write out the class information for this object. |
| 383 WriteObject(cls); | 385 WriteObject(cls); |
| 384 | 386 |
| 385 // Write out all the fields for the object. | 387 // Write out all the fields for the object. |
| 386 intptr_t offset = Object::InstanceSize(); | 388 intptr_t offset = Object::InstanceSize(); |
| 387 while (offset < instance_size) { | 389 while (offset < instance_size) { |
| 388 WriteObject(*reinterpret_cast<RawObject**>( | 390 WriteObject(*reinterpret_cast<RawObject**>( |
| 389 reinterpret_cast<uword>(raw->ptr()) + offset)); | 391 reinterpret_cast<uword>(raw->ptr()) + offset)); |
| 390 offset += kWordSize; | 392 offset += kWordSize; |
| 391 } | 393 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 404 default: break; | 406 default: break; |
| 405 } | 407 } |
| 406 UNREACHABLE(); | 408 UNREACHABLE(); |
| 407 } | 409 } |
| 408 | 410 |
| 409 | 411 |
| 410 void SnapshotWriter::WriteClassId(RawClass* cls) { | 412 void SnapshotWriter::WriteClassId(RawClass* cls) { |
| 411 ASSERT(kind_ != Snapshot::kFull); | 413 ASSERT(kind_ != Snapshot::kFull); |
| 412 int id = object_store()->GetClassIndex(cls); | 414 int id = object_store()->GetClassIndex(cls); |
| 413 if (IsSingletonClassId(id) || IsObjectStoreClassId(id)) { | 415 if (IsSingletonClassId(id) || IsObjectStoreClassId(id)) { |
| 414 WriteObjectHeader(kObjectId, id); | 416 WriteIndexedObject(id); |
| 415 } else { | 417 } else { |
| 416 // TODO(5411462): Should restrict this to only core-lib classes in this | 418 // TODO(5411462): Should restrict this to only core-lib classes in this |
| 417 // case. | 419 // case. |
| 418 // Write out the class information. | 420 // Write out the class and tags information. |
| 419 WriteObjectHeader(kObjectId, Object::kClassClass); | 421 WriteObjectHeader(Object::kClassClass, cls->ptr()->tags_); |
| 420 // Write out the library url and class name. | 422 // Write out the library url and class name. |
| 421 RawLibrary* library = cls->ptr()->library_; | 423 RawLibrary* library = cls->ptr()->library_; |
| 422 ASSERT(library != Library::null()); | 424 ASSERT(library != Library::null()); |
| 423 WriteObject(library->ptr()->url_); | 425 WriteObject(library->ptr()->url_); |
| 424 WriteObject(cls->ptr()->name_); | 426 WriteObject(cls->ptr()->name_); |
| 425 } | 427 } |
| 426 } | 428 } |
| 427 | 429 |
| 428 | 430 |
| 429 void ScriptSnapshotWriter::WriteScriptSnapshot() { | 431 void ScriptSnapshotWriter::WriteScriptSnapshot() { |
| 430 // TODO(asiva): Need to implement this. | 432 // TODO(asiva): Need to implement this. |
| 431 UNIMPLEMENTED(); | 433 UNIMPLEMENTED(); |
| 432 } | 434 } |
| 433 | 435 |
| 434 | 436 |
| 435 void SnapshotWriterVisitor::VisitPointers(RawObject** first, RawObject** last) { | 437 void SnapshotWriterVisitor::VisitPointers(RawObject** first, RawObject** last) { |
| 436 for (RawObject** current = first; current <= last; current++) { | 438 for (RawObject** current = first; current <= last; current++) { |
| 437 RawObject* raw_obj = *current; | 439 RawObject* raw_obj = *current; |
| 438 writer_->WriteObject(raw_obj); | 440 writer_->WriteObject(raw_obj); |
| 439 } | 441 } |
| 440 } | 442 } |
| 441 | 443 |
| 442 } // namespace dart | 444 } // namespace dart |
| OLD | NEW |