| 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 |