OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 "platform/assert.h" | 7 #include "platform/assert.h" |
8 #include "vm/bootstrap.h" | 8 #include "vm/bootstrap.h" |
9 #include "vm/class_finalizer.h" | 9 #include "vm/class_finalizer.h" |
10 #include "vm/dart.h" | 10 #include "vm/dart.h" |
(...skipping 482 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
493 NewObjectPool(len)); | 493 NewObjectPool(len)); |
494 AddBackRef(object_id, &pool, kIsNotDeserialized); | 494 AddBackRef(object_id, &pool, kIsNotDeserialized); |
495 | 495 |
496 return pool.raw(); | 496 return pool.raw(); |
497 } | 497 } |
498 | 498 |
499 // For all other internal VM classes we read the object inline. | 499 // For all other internal VM classes we read the object inline. |
500 switch (class_id) { | 500 switch (class_id) { |
501 #define SNAPSHOT_READ(clazz) \ | 501 #define SNAPSHOT_READ(clazz) \ |
502 case clazz::kClassId: { \ | 502 case clazz::kClassId: { \ |
503 pobj_ = clazz::ReadFrom(this, object_id, tags, kind_); \ | 503 pobj_ = clazz::ReadFrom(this, object_id, tags, kind_, true); \ |
504 break; \ | 504 break; \ |
505 } | 505 } |
506 CLASS_LIST_NO_OBJECT(SNAPSHOT_READ) | 506 CLASS_LIST_NO_OBJECT(SNAPSHOT_READ) |
507 #undef SNAPSHOT_READ | 507 #undef SNAPSHOT_READ |
508 #define SNAPSHOT_READ(clazz) \ | 508 #define SNAPSHOT_READ(clazz) \ |
509 case kTypedData##clazz##Cid: \ | 509 case kTypedData##clazz##Cid: \ |
510 | 510 |
511 CLASS_LIST_TYPED_DATA(SNAPSHOT_READ) { | 511 CLASS_LIST_TYPED_DATA(SNAPSHOT_READ) { |
512 tags = RawObject::ClassIdTag::update(class_id, tags); | 512 tags = RawObject::ClassIdTag::update(class_id, tags); |
513 pobj_ = TypedData::ReadFrom(this, object_id, tags, kind_); | 513 pobj_ = TypedData::ReadFrom(this, object_id, tags, kind_, true); |
514 break; | 514 break; |
515 } | 515 } |
516 #undef SNAPSHOT_READ | 516 #undef SNAPSHOT_READ |
517 #define SNAPSHOT_READ(clazz) \ | 517 #define SNAPSHOT_READ(clazz) \ |
518 case kExternalTypedData##clazz##Cid: \ | 518 case kExternalTypedData##clazz##Cid: \ |
519 | 519 |
520 CLASS_LIST_TYPED_DATA(SNAPSHOT_READ) { | 520 CLASS_LIST_TYPED_DATA(SNAPSHOT_READ) { |
521 tags = RawObject::ClassIdTag::update(class_id, tags); | 521 tags = RawObject::ClassIdTag::update(class_id, tags); |
522 pobj_ = ExternalTypedData::ReadFrom(this, object_id, tags, kind_); | 522 pobj_ = ExternalTypedData::ReadFrom(this, object_id, tags, kind_, true); |
523 break; | 523 break; |
524 } | 524 } |
525 #undef SNAPSHOT_READ | 525 #undef SNAPSHOT_READ |
526 default: UNREACHABLE(); break; | 526 default: UNREACHABLE(); break; |
527 } | 527 } |
528 return pobj_.raw(); | 528 return pobj_.raw(); |
529 } | 529 } |
530 | 530 |
531 | 531 |
532 RawObject* SnapshotReader::ReadInlinedObject(intptr_t object_id, | 532 RawObject* SnapshotReader::ReadInlinedObject(intptr_t object_id, |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
611 // We do not use the tags as the implicit static closure | 611 // We do not use the tags as the implicit static closure |
612 // is going to be created in this isolate or the canonical | 612 // is going to be created in this isolate or the canonical |
613 // version already created in the isolate will be used. | 613 // version already created in the isolate will be used. |
614 return ReadStaticImplicitClosure(object_id, class_header); | 614 return ReadStaticImplicitClosure(object_id, class_header); |
615 } | 615 } |
616 ASSERT((class_header & kSmiTagMask) != kSmiTag); | 616 ASSERT((class_header & kSmiTagMask) != kSmiTag); |
617 intptr_t class_id = LookupInternalClass(class_header); | 617 intptr_t class_id = LookupInternalClass(class_header); |
618 switch (class_id) { | 618 switch (class_id) { |
619 #define SNAPSHOT_READ(clazz) \ | 619 #define SNAPSHOT_READ(clazz) \ |
620 case clazz::kClassId: { \ | 620 case clazz::kClassId: { \ |
621 pobj_ = clazz::ReadFrom(this, object_id, tags, kind_); \ | 621 pobj_ = clazz::ReadFrom(this, object_id, tags, kind_, false); \ |
622 break; \ | 622 break; \ |
623 } | 623 } |
624 CLASS_LIST_NO_OBJECT(SNAPSHOT_READ) | 624 CLASS_LIST_NO_OBJECT(SNAPSHOT_READ) |
625 #undef SNAPSHOT_READ | 625 #undef SNAPSHOT_READ |
626 #define SNAPSHOT_READ(clazz) \ | 626 #define SNAPSHOT_READ(clazz) \ |
627 case kTypedData##clazz##Cid: \ | 627 case kTypedData##clazz##Cid: \ |
628 | 628 |
629 CLASS_LIST_TYPED_DATA(SNAPSHOT_READ) { | 629 CLASS_LIST_TYPED_DATA(SNAPSHOT_READ) { |
630 tags = RawObject::ClassIdTag::update(class_id, tags); | 630 tags = RawObject::ClassIdTag::update(class_id, tags); |
631 pobj_ = TypedData::ReadFrom(this, object_id, tags, kind_); | 631 pobj_ = TypedData::ReadFrom(this, object_id, tags, kind_, false); |
632 break; | 632 break; |
633 } | 633 } |
634 #undef SNAPSHOT_READ | 634 #undef SNAPSHOT_READ |
635 #define SNAPSHOT_READ(clazz) \ | 635 #define SNAPSHOT_READ(clazz) \ |
636 case kExternalTypedData##clazz##Cid: \ | 636 case kExternalTypedData##clazz##Cid: \ |
637 | 637 |
638 CLASS_LIST_TYPED_DATA(SNAPSHOT_READ) { | 638 CLASS_LIST_TYPED_DATA(SNAPSHOT_READ) { |
639 tags = RawObject::ClassIdTag::update(class_id, tags); | 639 tags = RawObject::ClassIdTag::update(class_id, tags); |
640 pobj_ = ExternalTypedData::ReadFrom(this, object_id, tags, kind_); | 640 pobj_ = ExternalTypedData::ReadFrom(this, object_id, tags, kind_, false); |
641 break; | 641 break; |
642 } | 642 } |
643 #undef SNAPSHOT_READ | 643 #undef SNAPSHOT_READ |
644 default: UNREACHABLE(); break; | 644 default: UNREACHABLE(); break; |
645 } | 645 } |
646 AddPatchRecord(object_id, patch_object_id, patch_offset); | 646 AddPatchRecord(object_id, patch_object_id, patch_offset); |
647 return pobj_.raw(); | 647 return pobj_.raw(); |
648 } | 648 } |
649 | 649 |
650 | 650 |
(...skipping 1052 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1703 V(OneByteString) \ | 1703 V(OneByteString) \ |
1704 V(Mint) \ | 1704 V(Mint) \ |
1705 V(Bigint) \ | 1705 V(Bigint) \ |
1706 V(Double) \ | 1706 V(Double) \ |
1707 V(ImmutableArray) \ | 1707 V(ImmutableArray) \ |
1708 | 1708 |
1709 #define VM_OBJECT_WRITE(clazz) \ | 1709 #define VM_OBJECT_WRITE(clazz) \ |
1710 case clazz::kClassId: { \ | 1710 case clazz::kClassId: { \ |
1711 object_id = forward_list_->AddObject(rawobj, kIsSerialized); \ | 1711 object_id = forward_list_->AddObject(rawobj, kIsSerialized); \ |
1712 Raw##clazz* raw_obj = reinterpret_cast<Raw##clazz*>(rawobj); \ | 1712 Raw##clazz* raw_obj = reinterpret_cast<Raw##clazz*>(rawobj); \ |
1713 raw_obj->WriteTo(this, object_id, kind()); \ | 1713 raw_obj->WriteTo(this, object_id, kind(), false); \ |
1714 return true; \ | 1714 return true; \ |
1715 } \ | 1715 } \ |
1716 | 1716 |
1717 #define WRITE_VM_SINGLETON_OBJ(obj, id) \ | 1717 #define WRITE_VM_SINGLETON_OBJ(obj, id) \ |
1718 if (rawobj == obj) { \ | 1718 if (rawobj == obj) { \ |
1719 WriteVMIsolateObject(id); \ | 1719 WriteVMIsolateObject(id); \ |
1720 return true; \ | 1720 return true; \ |
1721 } \ | 1721 } \ |
1722 | 1722 |
1723 bool SnapshotWriter::HandleVMIsolateObject(RawObject* rawobj) { | 1723 bool SnapshotWriter::HandleVMIsolateObject(RawObject* rawobj) { |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1787 intptr_t object_id = forward_list_->FindObject(rawobj); | 1787 intptr_t object_id = forward_list_->FindObject(rawobj); |
1788 if (object_id != -1) { | 1788 if (object_id != -1) { |
1789 WriteIndexedObject(object_id); | 1789 WriteIndexedObject(object_id); |
1790 return true; | 1790 return true; |
1791 } else { | 1791 } else { |
1792 switch (id) { | 1792 switch (id) { |
1793 VM_OBJECT_CLASS_LIST(VM_OBJECT_WRITE) | 1793 VM_OBJECT_CLASS_LIST(VM_OBJECT_WRITE) |
1794 case kTypedDataUint32ArrayCid: { | 1794 case kTypedDataUint32ArrayCid: { |
1795 object_id = forward_list_->AddObject(rawobj, kIsSerialized); | 1795 object_id = forward_list_->AddObject(rawobj, kIsSerialized); |
1796 RawTypedData* raw_obj = reinterpret_cast<RawTypedData*>(rawobj); | 1796 RawTypedData* raw_obj = reinterpret_cast<RawTypedData*>(rawobj); |
1797 raw_obj->WriteTo(this, object_id, kind()); | 1797 raw_obj->WriteTo(this, object_id, kind(), false); |
1798 return true; | 1798 return true; |
1799 } | 1799 } |
1800 default: | 1800 default: |
1801 OS::Print("class id = %" Pd "\n", id); | 1801 OS::Print("class id = %" Pd "\n", id); |
1802 break; | 1802 break; |
1803 } | 1803 } |
1804 } | 1804 } |
1805 } | 1805 } |
1806 | 1806 |
1807 if (!vm_isolate_is_symbolic()) { | 1807 if (!vm_isolate_is_symbolic()) { |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2061 uword tags = raw->ptr()->tags_; | 2061 uword tags = raw->ptr()->tags_; |
2062 if (SerializedHeaderTag::decode(tags) == kObjectId) { | 2062 if (SerializedHeaderTag::decode(tags) == kObjectId) { |
2063 intptr_t id = SerializedHeaderData::decode(tags); | 2063 intptr_t id = SerializedHeaderData::decode(tags); |
2064 return forward_list_->NodeForObjectId(id)->tags(); | 2064 return forward_list_->NodeForObjectId(id)->tags(); |
2065 } else { | 2065 } else { |
2066 return tags; | 2066 return tags; |
2067 } | 2067 } |
2068 } | 2068 } |
2069 | 2069 |
2070 | 2070 |
| 2071 intptr_t SnapshotWriter::GetObjectId(RawObject* raw) { |
| 2072 uword tags = raw->ptr()->tags_; |
| 2073 ASSERT(SerializedHeaderTag::decode(tags) == kObjectId); |
| 2074 return SerializedHeaderData::decode(tags); |
| 2075 } |
| 2076 |
| 2077 |
2071 ForwardList::ForwardList(intptr_t first_object_id) | 2078 ForwardList::ForwardList(intptr_t first_object_id) |
2072 : first_object_id_(first_object_id), | 2079 : first_object_id_(first_object_id), |
2073 nodes_(), | 2080 nodes_(), |
2074 first_unprocessed_object_id_(first_object_id) { | 2081 first_unprocessed_object_id_(first_object_id) { |
2075 // The ForwardList encodes information in the header tag word. There cannot | 2082 // The ForwardList encodes information in the header tag word. There cannot |
2076 // be any concurrent GC tasks while it is in use. | 2083 // be any concurrent GC tasks while it is in use. |
2077 Thread* thread = Thread::Current(); | 2084 Thread* thread = Thread::Current(); |
2078 Isolate* isolate = thread->isolate(); | 2085 Isolate* isolate = thread->isolate(); |
2079 PageSpace* page_space = isolate->heap()->old_space(); | 2086 PageSpace* page_space = isolate->heap()->old_space(); |
2080 MonitorLocker ml(page_space->tasks_lock()); | 2087 MonitorLocker ml(page_space->tasks_lock()); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2138 const Node* node = NodeForObjectId(id); | 2145 const Node* node = NodeForObjectId(id); |
2139 RawObject* raw = node->raw(); | 2146 RawObject* raw = node->raw(); |
2140 if (SerializedHeaderTag::decode(raw->ptr()->tags_) == kObjectId) { | 2147 if (SerializedHeaderTag::decode(raw->ptr()->tags_) == kObjectId) { |
2141 raw->ptr()->tags_ = node->tags(); // Restore original tags. | 2148 raw->ptr()->tags_ = node->tags(); // Restore original tags. |
2142 } | 2149 } |
2143 } | 2150 } |
2144 Thread::Current()->DecrementNoSafepointScopeDepth(); | 2151 Thread::Current()->DecrementNoSafepointScopeDepth(); |
2145 } | 2152 } |
2146 | 2153 |
2147 | 2154 |
| 2155 void ForwardList::SetState(RawObject* raw, SerializeState state) { |
| 2156 uword tags = raw->ptr()->tags_; |
| 2157 ASSERT(SerializedHeaderTag::decode(tags) == kObjectId); |
| 2158 intptr_t id = SerializedHeaderData::decode(tags); |
| 2159 NodeForObjectId(id)->set_state(state); |
| 2160 } |
| 2161 |
| 2162 |
2148 bool SnapshotWriter::CheckAndWritePredefinedObject(RawObject* rawobj) { | 2163 bool SnapshotWriter::CheckAndWritePredefinedObject(RawObject* rawobj) { |
2149 // Check if object can be written in one of the following ways: | 2164 // Check if object can be written in one of the following ways: |
2150 // - Smi: the Smi value is written as is (last bit is not tagged). | 2165 // - Smi: the Smi value is written as is (last bit is not tagged). |
2151 // - VM internal class (from VM isolate): (index of class in vm isolate | 0x3) | 2166 // - VM internal class (from VM isolate): (index of class in vm isolate | 0x3) |
2152 // - Object that has already been written: (negative id in stream | 0x3) | 2167 // - Object that has already been written: (negative id in stream | 0x3) |
2153 | 2168 |
2154 NoSafepointScope no_safepoint; | 2169 NoSafepointScope no_safepoint; |
2155 | 2170 |
2156 // First check if it is a Smi (i.e not a heap object). | 2171 // First check if it is a Smi (i.e not a heap object). |
2157 if (!rawobj->IsHeapObject()) { | 2172 if (!rawobj->IsHeapObject()) { |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2217 return false; | 2232 return false; |
2218 } | 2233 } |
2219 | 2234 |
2220 | 2235 |
2221 void SnapshotWriter::WriteObjectImpl(RawObject* raw, bool as_reference) { | 2236 void SnapshotWriter::WriteObjectImpl(RawObject* raw, bool as_reference) { |
2222 // First check if object can be written as a simple predefined type. | 2237 // First check if object can be written as a simple predefined type. |
2223 if (CheckAndWritePredefinedObject(raw)) { | 2238 if (CheckAndWritePredefinedObject(raw)) { |
2224 return; | 2239 return; |
2225 } | 2240 } |
2226 | 2241 |
2227 // Objects are usually writen as references to avoid deep recursion, but in | 2242 // When we know that we are dealing with leaf or shallow objects we write |
2228 // some places we know we are dealing with leaf or shallow objects and write | 2243 // these objects inline even when 'as_reference' is true. |
2229 // them inline. | 2244 bool write_as_reference = as_reference && !raw->IsCanonical(); |
2230 if (!as_reference || raw->IsCanonical()) { | 2245 intptr_t tags = raw->ptr()->tags_; |
2231 // Object is being serialized, add it to the forward ref list and mark | 2246 |
2232 // it so that future references to this object in the snapshot will use | 2247 // Add object to the forward ref list and mark it so that future references |
2233 // an object id, instead of trying to serialize it again. | 2248 // to this object in the snapshot will use this object id. Mark the |
| 2249 // serialization state so that we do the right thing when we go through |
| 2250 // the forward list. |
| 2251 intptr_t class_id = raw->GetClassId(); |
| 2252 if (write_as_reference && IsSplitClassId(class_id)) { |
| 2253 forward_list_->MarkAndAddObject(raw, kIsNotSerialized); |
| 2254 } else { |
2234 forward_list_->MarkAndAddObject(raw, kIsSerialized); | 2255 forward_list_->MarkAndAddObject(raw, kIsSerialized); |
2235 | 2256 } |
2236 WriteInlinedObject(raw); | 2257 intptr_t object_id; |
| 2258 if (write_as_reference || !IsSplitClassId(class_id)) { |
| 2259 object_id = kOmittedObjectId; |
2237 } else { | 2260 } else { |
2238 WriteObjectRef(raw); | 2261 ASSERT(SerializedHeaderTag::decode(raw->ptr()->tags_) == kObjectId); |
| 2262 object_id = SerializedHeaderData::decode(raw->ptr()->tags_); |
2239 } | 2263 } |
| 2264 WriteMarkedObjectImpl(raw, tags, object_id, write_as_reference); |
2240 } | 2265 } |
2241 | 2266 |
2242 | 2267 |
2243 void SnapshotWriter::WriteObjectRef(RawObject* raw) { | 2268 void SnapshotWriter::WriteMarkedObjectImpl(RawObject* raw, |
| 2269 intptr_t tags, |
| 2270 intptr_t object_id, |
| 2271 bool as_reference) { |
2244 NoSafepointScope no_safepoint; | 2272 NoSafepointScope no_safepoint; |
2245 RawClass* cls = class_table_->At(raw->GetClassId()); | 2273 RawClass* cls = class_table_->At(RawObject::ClassIdTag::decode(tags)); |
2246 intptr_t class_id = cls->ptr()->id_; | 2274 intptr_t class_id = cls->ptr()->id_; |
2247 ASSERT(class_id == raw->GetClassId()); | 2275 ASSERT(class_id == RawObject::ClassIdTag::decode(tags)); |
2248 if (class_id >= kNumPredefinedCids || | 2276 if (class_id >= kNumPredefinedCids || |
2249 RawObject::IsImplicitFieldClassId(class_id)) { | 2277 RawObject::IsImplicitFieldClassId(class_id)) { |
2250 WriteInstanceRef(raw, cls); | 2278 WriteInstance(raw, cls, tags, object_id, as_reference); |
2251 return; | 2279 return; |
2252 } | 2280 } |
2253 if (class_id == kArrayCid || class_id == kImmutableArrayCid) { | |
2254 intptr_t tags = GetObjectTags(raw); | |
2255 | 2281 |
2256 // Object is being referenced, add it to the forward ref list and mark | |
2257 // it so that future references to this object in the snapshot will use | |
2258 // this object id. Mark it as not having been serialized yet so that we | |
2259 // will serialize the object when we go through the forward list. | |
2260 forward_list_->MarkAndAddObject(raw, kIsNotSerialized); | |
2261 | |
2262 RawArray* rawarray = reinterpret_cast<RawArray*>(raw); | |
2263 | |
2264 // Write out the serialization header value for this object. | |
2265 WriteInlinedObjectHeader(kOmittedObjectId); | |
2266 | |
2267 // Write out the class information. | |
2268 WriteIndexedObject(class_id); | |
2269 WriteTags(tags); | |
2270 | |
2271 // Write out the length field. | |
2272 Write<RawObject*>(rawarray->ptr()->length_); | |
2273 | |
2274 return; | |
2275 } | |
2276 if (class_id == kObjectPoolCid) { | |
2277 intptr_t tags = GetObjectTags(raw); | |
2278 | |
2279 // Object is being referenced, add it to the forward ref list and mark | |
2280 // it so that future references to this object in the snapshot will use | |
2281 // this object id. Mark it as not having been serialized yet so that we | |
2282 // will serialize the object when we go through the forward list. | |
2283 forward_list_->MarkAndAddObject(raw, kIsNotSerialized); | |
2284 | |
2285 RawObjectPool* rawpool = reinterpret_cast<RawObjectPool*>(raw); | |
2286 | |
2287 // Write out the serialization header value for this object. | |
2288 WriteInlinedObjectHeader(kOmittedObjectId); | |
2289 | |
2290 // Write out the class information. | |
2291 WriteVMIsolateObject(kObjectPoolCid); | |
2292 WriteTags(tags); | |
2293 | |
2294 // Write out the length field. | |
2295 Write<intptr_t>(rawpool->ptr()->length_); | |
2296 | |
2297 return; | |
2298 } | |
2299 // Add object to the forward ref list and mark it so that future references | |
2300 // to this object in the snapshot will use this object id. Mark it as having | |
2301 // been serialized so that we do not serialize the object when we go through | |
2302 // the forward list. | |
2303 forward_list_->MarkAndAddObject(raw, kIsSerialized); | |
2304 switch (class_id) { | 2282 switch (class_id) { |
2305 #define SNAPSHOT_WRITE(clazz) \ | 2283 #define SNAPSHOT_WRITE(clazz) \ |
2306 case clazz::kClassId: { \ | 2284 case clazz::kClassId: { \ |
2307 Raw##clazz* raw_obj = reinterpret_cast<Raw##clazz*>(raw); \ | 2285 Raw##clazz* raw_obj = reinterpret_cast<Raw##clazz*>(raw); \ |
2308 raw_obj->WriteTo(this, kOmittedObjectId, kind_); \ | 2286 raw_obj->WriteTo(this, object_id, kind_, as_reference); \ |
2309 return; \ | 2287 return; \ |
2310 } \ | 2288 } \ |
2311 | 2289 |
2312 CLASS_LIST_NO_OBJECT(SNAPSHOT_WRITE) | |
2313 #undef SNAPSHOT_WRITE | |
2314 #define SNAPSHOT_WRITE(clazz) \ | |
2315 case kTypedData##clazz##Cid: \ | |
2316 | |
2317 CLASS_LIST_TYPED_DATA(SNAPSHOT_WRITE) { | |
2318 RawTypedData* raw_obj = reinterpret_cast<RawTypedData*>(raw); | |
2319 raw_obj->WriteTo(this, kOmittedObjectId, kind_); | |
2320 return; | |
2321 } | |
2322 #undef SNAPSHOT_WRITE | |
2323 #define SNAPSHOT_WRITE(clazz) \ | |
2324 case kExternalTypedData##clazz##Cid: \ | |
2325 | |
2326 CLASS_LIST_TYPED_DATA(SNAPSHOT_WRITE) { | |
2327 RawExternalTypedData* raw_obj = | |
2328 reinterpret_cast<RawExternalTypedData*>(raw); | |
2329 raw_obj->WriteTo(this, kOmittedObjectId, kind_); | |
2330 return; | |
2331 } | |
2332 #undef SNAPSHOT_WRITE | |
2333 default: break; | |
2334 } | |
2335 UNREACHABLE(); | |
2336 } | |
2337 | |
2338 | |
2339 void SnapshotWriter::WriteInlinedObject(RawObject* raw) { | |
2340 // Now write the object out inline in the stream as follows: | |
2341 // - Object is seen for the first time (inlined as follows): | |
2342 // (object size in multiples of kObjectAlignment | 0x1) | |
2343 // serialized fields of the object | |
2344 // ...... | |
2345 NoSafepointScope no_safepoint; | |
2346 uword tags = raw->ptr()->tags_; | |
2347 ASSERT(SerializedHeaderTag::decode(tags) == kObjectId); | |
2348 intptr_t object_id = SerializedHeaderData::decode(tags); | |
2349 tags = forward_list_->NodeForObjectId(object_id)->tags(); | |
2350 RawClass* cls = class_table_->At(RawObject::ClassIdTag::decode(tags)); | |
2351 intptr_t class_id = cls->ptr()->id_; | |
2352 | |
2353 if (!IsSplitClassId(class_id)) { | |
2354 object_id = kOmittedObjectId; | |
2355 } | |
2356 | |
2357 if (class_id >= kNumPredefinedCids) { | |
2358 WriteInstance(object_id, raw, cls, tags); | |
2359 return; | |
2360 } | |
2361 switch (class_id) { | |
2362 #define SNAPSHOT_WRITE(clazz) \ | |
2363 case clazz::kClassId: { \ | |
2364 Raw##clazz* raw_obj = reinterpret_cast<Raw##clazz*>(raw); \ | |
2365 raw_obj->WriteTo(this, object_id, kind_); \ | |
2366 return; \ | |
2367 } \ | |
2368 | |
2369 CLASS_LIST_NO_OBJECT(SNAPSHOT_WRITE) | 2290 CLASS_LIST_NO_OBJECT(SNAPSHOT_WRITE) |
2370 #undef SNAPSHOT_WRITE | 2291 #undef SNAPSHOT_WRITE |
2371 #define SNAPSHOT_WRITE(clazz) \ | 2292 #define SNAPSHOT_WRITE(clazz) \ |
2372 case kTypedData##clazz##Cid: \ | 2293 case kTypedData##clazz##Cid: \ |
2373 | 2294 |
2374 CLASS_LIST_TYPED_DATA(SNAPSHOT_WRITE) { | 2295 CLASS_LIST_TYPED_DATA(SNAPSHOT_WRITE) { |
2375 RawTypedData* raw_obj = reinterpret_cast<RawTypedData*>(raw); | 2296 RawTypedData* raw_obj = reinterpret_cast<RawTypedData*>(raw); |
2376 raw_obj->WriteTo(this, object_id, kind_); | 2297 raw_obj->WriteTo(this, object_id, kind_, as_reference); |
2377 return; | 2298 return; |
2378 } | 2299 } |
2379 #undef SNAPSHOT_WRITE | 2300 #undef SNAPSHOT_WRITE |
2380 #define SNAPSHOT_WRITE(clazz) \ | 2301 #define SNAPSHOT_WRITE(clazz) \ |
2381 case kExternalTypedData##clazz##Cid: \ | 2302 case kExternalTypedData##clazz##Cid: \ |
2382 | 2303 |
2383 CLASS_LIST_TYPED_DATA(SNAPSHOT_WRITE) { | 2304 CLASS_LIST_TYPED_DATA(SNAPSHOT_WRITE) { |
2384 RawExternalTypedData* raw_obj = | 2305 RawExternalTypedData* raw_obj = |
2385 reinterpret_cast<RawExternalTypedData*>(raw); | 2306 reinterpret_cast<RawExternalTypedData*>(raw); |
2386 raw_obj->WriteTo(this, object_id, kind_); | 2307 raw_obj->WriteTo(this, object_id, kind_, as_reference); |
2387 return; | 2308 return; |
2388 } | 2309 } |
2389 #undef SNAPSHOT_WRITE | 2310 #undef SNAPSHOT_WRITE |
2390 #define SNAPSHOT_WRITE(clazz) \ | |
2391 case kTypedData##clazz##ViewCid: \ | |
2392 | |
2393 CLASS_LIST_TYPED_DATA(SNAPSHOT_WRITE) | |
2394 case kByteDataViewCid: { | |
2395 WriteInstance(object_id, raw, cls, tags); | |
2396 return; | |
2397 } | |
2398 #undef SNAPSHOT_WRITE | |
2399 default: break; | 2311 default: break; |
2400 } | 2312 } |
2401 | 2313 |
2402 const Object& obj = Object::Handle(raw); | 2314 const Object& obj = Object::Handle(raw); |
2403 FATAL1("Unexpected inlined object: %s\n", obj.ToCString()); | 2315 FATAL1("Unexpected object: %s\n", obj.ToCString()); |
2404 } | 2316 } |
2405 | 2317 |
2406 | 2318 |
2407 class WriteInlinedObjectVisitor : public ObjectVisitor { | 2319 class WriteInlinedObjectVisitor : public ObjectVisitor { |
2408 public: | 2320 public: |
2409 explicit WriteInlinedObjectVisitor(SnapshotWriter* writer) | 2321 explicit WriteInlinedObjectVisitor(SnapshotWriter* writer) |
2410 : ObjectVisitor(Isolate::Current()), writer_(writer) {} | 2322 : ObjectVisitor(Isolate::Current()), writer_(writer) {} |
2411 | 2323 |
2412 virtual void VisitObject(RawObject* obj) { | 2324 virtual void VisitObject(RawObject* obj) { |
2413 writer_->WriteInlinedObject(obj); | 2325 intptr_t object_id = writer_->GetObjectId(obj); |
| 2326 intptr_t tags = writer_->GetObjectTags(obj); |
| 2327 writer_->WriteMarkedObjectImpl(obj, tags, object_id, kAsInlinedObject); |
2414 } | 2328 } |
2415 | 2329 |
2416 private: | 2330 private: |
2417 SnapshotWriter* writer_; | 2331 SnapshotWriter* writer_; |
2418 }; | 2332 }; |
2419 | 2333 |
2420 | 2334 |
2421 void SnapshotWriter::WriteForwardedObjects() { | 2335 void SnapshotWriter::WriteForwardedObjects() { |
2422 WriteInlinedObjectVisitor visitor(this); | 2336 WriteInlinedObjectVisitor visitor(this); |
2423 forward_list_->SerializeAll(&visitor); | 2337 forward_list_->SerializeAll(&visitor); |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2501 WriteObjectImpl(cls->ptr()->name_, kAsInlinedObject); | 2415 WriteObjectImpl(cls->ptr()->name_, kAsInlinedObject); |
2502 WriteObjectImpl(func->ptr()->name_, kAsInlinedObject); | 2416 WriteObjectImpl(func->ptr()->name_, kAsInlinedObject); |
2503 } | 2417 } |
2504 | 2418 |
2505 | 2419 |
2506 void SnapshotWriter::ArrayWriteTo(intptr_t object_id, | 2420 void SnapshotWriter::ArrayWriteTo(intptr_t object_id, |
2507 intptr_t array_kind, | 2421 intptr_t array_kind, |
2508 intptr_t tags, | 2422 intptr_t tags, |
2509 RawSmi* length, | 2423 RawSmi* length, |
2510 RawTypeArguments* type_arguments, | 2424 RawTypeArguments* type_arguments, |
2511 RawObject* data[]) { | 2425 RawObject* data[], |
2512 intptr_t len = Smi::Value(length); | 2426 bool as_reference) { |
| 2427 if (as_reference) { |
| 2428 // Write out the serialization header value for this object. |
| 2429 WriteInlinedObjectHeader(kOmittedObjectId); |
2513 | 2430 |
2514 // Write out the serialization header value for this object. | 2431 // Write out the class information. |
2515 WriteInlinedObjectHeader(object_id); | 2432 WriteIndexedObject(array_kind); |
| 2433 WriteTags(tags); |
2516 | 2434 |
2517 // Write out the class and tags information. | 2435 // Write out the length field. |
2518 WriteIndexedObject(array_kind); | 2436 Write<RawObject*>(length); |
2519 WriteTags(tags); | 2437 } else { |
| 2438 intptr_t len = Smi::Value(length); |
2520 | 2439 |
2521 // Write out the length field. | 2440 // Write out the serialization header value for this object. |
2522 Write<RawObject*>(length); | 2441 WriteInlinedObjectHeader(object_id); |
2523 | 2442 |
2524 // Write out the type arguments. | 2443 // Write out the class and tags information. |
2525 WriteObjectImpl(type_arguments, kAsInlinedObject); | 2444 WriteIndexedObject(array_kind); |
| 2445 WriteTags(tags); |
2526 | 2446 |
2527 // Write out the individual object ids. | 2447 // Write out the length field. |
2528 bool as_reference = RawObject::IsCanonical(tags) ? false : true; | 2448 Write<RawObject*>(length); |
2529 for (intptr_t i = 0; i < len; i++) { | 2449 |
2530 WriteObjectImpl(data[i], as_reference); | 2450 // Write out the type arguments. |
| 2451 WriteObjectImpl(type_arguments, kAsInlinedObject); |
| 2452 |
| 2453 // Write out the individual object ids. |
| 2454 bool write_as_reference = RawObject::IsCanonical(tags) ? false : true; |
| 2455 for (intptr_t i = 0; i < len; i++) { |
| 2456 WriteObjectImpl(data[i], write_as_reference); |
| 2457 } |
2531 } | 2458 } |
2532 } | 2459 } |
2533 | 2460 |
2534 | 2461 |
2535 RawFunction* SnapshotWriter::IsSerializableClosure(RawClass* cls, | 2462 RawFunction* SnapshotWriter::IsSerializableClosure(RawClass* cls, |
2536 RawObject* obj) { | 2463 RawObject* obj) { |
2537 if (Class::IsSignatureClass(cls)) { | 2464 if (Class::IsSignatureClass(cls)) { |
2538 // 'obj' is a closure as its class is a signature class, extract | 2465 // 'obj' is a closure as its class is a signature class, extract |
2539 // the function object to check if this closure can be sent in an | 2466 // the function object to check if this closure can be sent in an |
2540 // isolate message. | 2467 // isolate message. |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2594 void SnapshotWriter::SetWriteException(Exceptions::ExceptionType type, | 2521 void SnapshotWriter::SetWriteException(Exceptions::ExceptionType type, |
2595 const char* msg) { | 2522 const char* msg) { |
2596 set_exception_type(type); | 2523 set_exception_type(type); |
2597 set_exception_msg(msg); | 2524 set_exception_msg(msg); |
2598 // The more specific error is set up in SnapshotWriter::ThrowException(). | 2525 // The more specific error is set up in SnapshotWriter::ThrowException(). |
2599 thread()->long_jump_base()-> | 2526 thread()->long_jump_base()-> |
2600 Jump(1, Object::snapshot_writer_error()); | 2527 Jump(1, Object::snapshot_writer_error()); |
2601 } | 2528 } |
2602 | 2529 |
2603 | 2530 |
2604 void SnapshotWriter::WriteInstance(intptr_t object_id, | 2531 void SnapshotWriter::WriteInstance(RawObject* raw, |
2605 RawObject* raw, | |
2606 RawClass* cls, | 2532 RawClass* cls, |
2607 intptr_t tags) { | 2533 intptr_t tags, |
| 2534 intptr_t object_id, |
| 2535 bool as_reference) { |
2608 // Check if the instance has native fields and throw an exception if it does. | 2536 // Check if the instance has native fields and throw an exception if it does. |
2609 CheckForNativeFields(cls); | 2537 CheckForNativeFields(cls); |
2610 | 2538 |
2611 if ((kind() == Snapshot::kMessage) || (kind() == Snapshot::kScript)) { | 2539 if ((kind() == Snapshot::kMessage) || (kind() == Snapshot::kScript)) { |
2612 // Check if object is a closure that is serializable, if the object is a | 2540 // Check if object is a closure that is serializable, if the object is a |
2613 // closure that is not serializable this will throw an exception. | 2541 // closure that is not serializable this will throw an exception. |
2614 RawFunction* func = IsSerializableClosure(cls, raw); | 2542 RawFunction* func = IsSerializableClosure(cls, raw); |
2615 if (func != Function::null()) { | 2543 if (func != Function::null()) { |
| 2544 forward_list_->SetState(raw, kIsSerialized); |
2616 WriteStaticImplicitClosure(object_id, func, tags); | 2545 WriteStaticImplicitClosure(object_id, func, tags); |
2617 return; | 2546 return; |
2618 } | 2547 } |
2619 } | 2548 } |
2620 | 2549 |
2621 // Object is regular dart instance. | 2550 // Object is regular dart instance. |
2622 intptr_t next_field_offset = Class::IsSignatureClass(cls) ? | 2551 if (as_reference) { |
2623 Closure::InstanceSize() : | 2552 // Write out the serialization header value for this object. |
2624 cls->ptr()->next_field_offset_in_words_ << kWordSizeLog2; | 2553 WriteInlinedObjectHeader(kOmittedObjectId); |
2625 ASSERT(next_field_offset > 0); | |
2626 | 2554 |
2627 // Write out the serialization header value for this object. | 2555 // Indicate this is an instance object. |
2628 WriteInlinedObjectHeader(object_id); | 2556 Write<int32_t>(SerializedHeaderData::encode(kInstanceObjectId)); |
| 2557 WriteTags(tags); |
2629 | 2558 |
2630 // Indicate this is an instance object. | 2559 // Write out the class information for this object. |
2631 Write<int32_t>(SerializedHeaderData::encode(kInstanceObjectId)); | 2560 WriteObjectImpl(cls, kAsInlinedObject); |
| 2561 } else { |
| 2562 ASSERT(SerializedHeaderTag::decode(raw->ptr()->tags_) == kObjectId); |
| 2563 ASSERT(object_id == SerializedHeaderData::decode(raw->ptr()->tags_)); |
| 2564 intptr_t next_field_offset = Class::IsSignatureClass(cls) ? |
| 2565 Closure::InstanceSize() : |
| 2566 cls->ptr()->next_field_offset_in_words_ << kWordSizeLog2; |
| 2567 ASSERT(next_field_offset > 0); |
2632 | 2568 |
2633 // Write out the tags. | 2569 // Write out the serialization header value for this object. |
2634 WriteTags(tags); | 2570 WriteInlinedObjectHeader(object_id); |
2635 | 2571 |
2636 // Write out the class information for this object. | 2572 // Indicate this is an instance object. |
2637 WriteObjectImpl(cls, kAsInlinedObject); | 2573 Write<int32_t>(SerializedHeaderData::encode(kInstanceObjectId)); |
2638 | 2574 |
2639 // Write out all the fields for the object. | 2575 // Write out the tags. |
2640 // Instance::NextFieldOffset() returns the offset of the first field in | 2576 WriteTags(tags); |
2641 // a Dart object. | 2577 |
2642 bool as_reference = RawObject::IsCanonical(tags) ? false : true; | 2578 // Write out the class information for this object. |
2643 intptr_t offset = Instance::NextFieldOffset(); | 2579 WriteObjectImpl(cls, kAsInlinedObject); |
2644 while (offset < next_field_offset) { | 2580 |
2645 RawObject* raw_obj = *reinterpret_cast<RawObject**>( | 2581 // Write out all the fields for the object. |
2646 reinterpret_cast<uword>(raw->ptr()) + offset); | 2582 // Instance::NextFieldOffset() returns the offset of the first field in |
2647 WriteObjectImpl(raw_obj, as_reference); | 2583 // a Dart object. |
2648 offset += kWordSize; | 2584 bool write_as_reference = RawObject::IsCanonical(tags) ? false : true; |
| 2585 intptr_t offset = Instance::NextFieldOffset(); |
| 2586 while (offset < next_field_offset) { |
| 2587 RawObject* raw_obj = *reinterpret_cast<RawObject**>( |
| 2588 reinterpret_cast<uword>(raw->ptr()) + offset); |
| 2589 WriteObjectImpl(raw_obj, write_as_reference); |
| 2590 offset += kWordSize; |
| 2591 } |
2649 } | 2592 } |
2650 return; | 2593 return; |
2651 } | 2594 } |
2652 | 2595 |
2653 | 2596 |
2654 void SnapshotWriter::WriteInstanceRef(RawObject* raw, RawClass* cls) { | |
2655 // Check if the instance has native fields and throw an exception if it does. | |
2656 CheckForNativeFields(cls); | |
2657 | |
2658 // Check if object is a closure that is serializable, if the object is a | |
2659 // closure that is not serializable this will throw an exception. | |
2660 RawFunction* func = IsSerializableClosure(cls, raw); | |
2661 if (func != Function::null()) { | |
2662 // Add object to the forward ref list and mark it so that future references | |
2663 // to this object in the snapshot will use this object id. Mark it as having | |
2664 // been serialized so that we do not serialize the object when we go through | |
2665 // the forward list. | |
2666 forward_list_->MarkAndAddObject(raw, kIsSerialized); | |
2667 uword tags = raw->ptr()->tags_; | |
2668 ASSERT(SerializedHeaderTag::decode(tags) == kObjectId); | |
2669 intptr_t object_id = SerializedHeaderData::decode(tags); | |
2670 tags = forward_list_->NodeForObjectId(object_id)->tags(); | |
2671 WriteStaticImplicitClosure(object_id, func, tags); | |
2672 return; | |
2673 } | |
2674 | |
2675 // Object is being referenced, add it to the forward ref list and mark | |
2676 // it so that future references to this object in the snapshot will use | |
2677 // this object id. Mark it as not having been serialized yet so that we | |
2678 // will serialize the object when we go through the forward list. | |
2679 intptr_t tags = raw->ptr()->tags_; | |
2680 forward_list_->MarkAndAddObject(raw, kIsNotSerialized); | |
2681 | |
2682 // Write out the serialization header value for this object. | |
2683 WriteInlinedObjectHeader(kOmittedObjectId); | |
2684 | |
2685 // Indicate this is an instance object. | |
2686 Write<int32_t>(SerializedHeaderData::encode(kInstanceObjectId)); | |
2687 WriteTags(tags); | |
2688 | |
2689 // Write out the class information for this object. | |
2690 WriteObjectImpl(cls, kAsInlinedObject); | |
2691 } | |
2692 | |
2693 | |
2694 bool SnapshotWriter::AllowObjectsInDartLibrary(RawLibrary* library) { | 2597 bool SnapshotWriter::AllowObjectsInDartLibrary(RawLibrary* library) { |
2695 return (library == object_store()->collection_library() || | 2598 return (library == object_store()->collection_library() || |
2696 library == object_store()->core_library() || | 2599 library == object_store()->core_library() || |
2697 library == object_store()->typed_data_library()); | 2600 library == object_store()->typed_data_library()); |
2698 } | 2601 } |
2699 | 2602 |
2700 | 2603 |
2701 intptr_t SnapshotWriter::FindVmSnapshotObject(RawObject* rawobj) { | 2604 intptr_t SnapshotWriter::FindVmSnapshotObject(RawObject* rawobj) { |
2702 intptr_t length = Object::vm_isolate_snapshot_object_table().Length(); | 2605 intptr_t length = Object::vm_isolate_snapshot_object_table().Length(); |
2703 for (intptr_t i = 0; i < length; i++) { | 2606 for (intptr_t i = 0; i < length; i++) { |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2825 NoSafepointScope no_safepoint; | 2728 NoSafepointScope no_safepoint; |
2826 WriteObject(obj.raw()); | 2729 WriteObject(obj.raw()); |
2827 UnmarkAll(); | 2730 UnmarkAll(); |
2828 } else { | 2731 } else { |
2829 ThrowException(exception_type(), exception_msg()); | 2732 ThrowException(exception_type(), exception_msg()); |
2830 } | 2733 } |
2831 } | 2734 } |
2832 | 2735 |
2833 | 2736 |
2834 } // namespace dart | 2737 } // namespace dart |
OLD | NEW |