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/bigint_operations.h" | 8 #include "vm/bigint_operations.h" |
9 #include "vm/bootstrap.h" | 9 #include "vm/bootstrap.h" |
10 #include "vm/class_finalizer.h" | 10 #include "vm/class_finalizer.h" |
(...skipping 924 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
935 | 935 |
936 | 936 |
937 SnapshotWriter::SnapshotWriter(Snapshot::Kind kind, | 937 SnapshotWriter::SnapshotWriter(Snapshot::Kind kind, |
938 uint8_t** buffer, | 938 uint8_t** buffer, |
939 ReAlloc alloc, | 939 ReAlloc alloc, |
940 intptr_t initial_size) | 940 intptr_t initial_size) |
941 : BaseWriter(buffer, alloc, initial_size), | 941 : BaseWriter(buffer, alloc, initial_size), |
942 kind_(kind), | 942 kind_(kind), |
943 object_store_(Isolate::Current()->object_store()), | 943 object_store_(Isolate::Current()->object_store()), |
944 class_table_(Isolate::Current()->class_table()), | 944 class_table_(Isolate::Current()->class_table()), |
945 forward_list_(), | 945 forward_list_(kMaxPredefinedObjectIds), |
946 exception_type_(Exceptions::kNone), | 946 exception_type_(Exceptions::kNone), |
947 exception_msg_(NULL) { | 947 exception_msg_(NULL) { |
948 } | 948 } |
949 | 949 |
950 | 950 |
951 void SnapshotWriter::WriteObject(RawObject* rawobj) { | 951 void SnapshotWriter::WriteObject(RawObject* rawobj) { |
952 WriteObjectImpl(rawobj); | 952 WriteObjectImpl(rawobj); |
953 WriteForwardedObjects(); | 953 WriteForwardedObjects(); |
954 } | 954 } |
955 | 955 |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1040 ASSERT(class_id == raw->GetClassId()); | 1040 ASSERT(class_id == raw->GetClassId()); |
1041 if (class_id >= kNumPredefinedCids) { | 1041 if (class_id >= kNumPredefinedCids) { |
1042 WriteInstanceRef(raw, cls); | 1042 WriteInstanceRef(raw, cls); |
1043 return; | 1043 return; |
1044 } | 1044 } |
1045 if (class_id == kArrayCid) { | 1045 if (class_id == kArrayCid) { |
1046 // Object is being referenced, add it to the forward ref list and mark | 1046 // Object is being referenced, add it to the forward ref list and mark |
1047 // it so that future references to this object in the snapshot will use | 1047 // it so that future references to this object in the snapshot will use |
1048 // this object id. Mark it as not having been serialized yet so that we | 1048 // this object id. Mark it as not having been serialized yet so that we |
1049 // will serialize the object when we go through the forward list. | 1049 // will serialize the object when we go through the forward list. |
1050 intptr_t object_id = MarkObject(raw, kIsNotSerialized); | 1050 intptr_t object_id = forward_list_.MarkAndAddObject(raw, kIsNotSerialized); |
1051 | 1051 |
1052 RawArray* rawarray = reinterpret_cast<RawArray*>(raw); | 1052 RawArray* rawarray = reinterpret_cast<RawArray*>(raw); |
1053 | 1053 |
1054 // Write out the serialization header value for this object. | 1054 // Write out the serialization header value for this object. |
1055 WriteInlinedObjectHeader(object_id); | 1055 WriteInlinedObjectHeader(object_id); |
1056 | 1056 |
1057 // Write out the class information. | 1057 // Write out the class information. |
1058 WriteIndexedObject(kArrayCid); | 1058 WriteIndexedObject(kArrayCid); |
1059 | 1059 |
1060 // Write out the length field. | 1060 // Write out the length field. |
1061 Write<RawObject*>(rawarray->ptr()->length_); | 1061 Write<RawObject*>(rawarray->ptr()->length_); |
1062 | 1062 |
1063 return; | 1063 return; |
1064 } | 1064 } |
1065 if (class_id == kImmutableArrayCid) { | 1065 if (class_id == kImmutableArrayCid) { |
1066 // Object is being referenced, add it to the forward ref list and mark | 1066 // Object is being referenced, add it to the forward ref list and mark |
1067 // it so that future references to this object in the snapshot will use | 1067 // it so that future references to this object in the snapshot will use |
1068 // this object id. Mark it as not having been serialized yet so that we | 1068 // this object id. Mark it as not having been serialized yet so that we |
1069 // will serialize the object when we go through the forward list. | 1069 // will serialize the object when we go through the forward list. |
1070 intptr_t object_id = MarkObject(raw, kIsNotSerialized); | 1070 intptr_t object_id = forward_list_.MarkAndAddObject(raw, kIsNotSerialized); |
1071 | 1071 |
1072 RawArray* rawarray = reinterpret_cast<RawArray*>(raw); | 1072 RawArray* rawarray = reinterpret_cast<RawArray*>(raw); |
1073 | 1073 |
1074 // Write out the serialization header value for this object. | 1074 // Write out the serialization header value for this object. |
1075 WriteInlinedObjectHeader(object_id); | 1075 WriteInlinedObjectHeader(object_id); |
1076 | 1076 |
1077 // Write out the class information. | 1077 // Write out the class information. |
1078 WriteIndexedObject(kImmutableArrayCid); | 1078 WriteIndexedObject(kImmutableArrayCid); |
1079 | 1079 |
1080 // Write out the length field. | 1080 // Write out the length field. |
1081 Write<RawObject*>(rawarray->ptr()->length_); | 1081 Write<RawObject*>(rawarray->ptr()->length_); |
1082 | 1082 |
1083 return; | 1083 return; |
1084 } | 1084 } |
1085 if (RawObject::IsTypedDataViewClassId(class_id)) { | 1085 if (RawObject::IsTypedDataViewClassId(class_id)) { |
1086 WriteInstanceRef(raw, cls); | 1086 WriteInstanceRef(raw, cls); |
1087 return; | 1087 return; |
1088 } | 1088 } |
1089 // Object is being referenced, add it to the forward ref list and mark | 1089 // Object is being referenced, add it to the forward ref list and mark |
1090 // it so that future references to this object in the snapshot will use | 1090 // it so that future references to this object in the snapshot will use |
1091 // this object id. Mark it as not having been serialized yet so that we | 1091 // this object id. Mark it as not having been serialized yet so that we |
1092 // will serialize the object when we go through the forward list. | 1092 // will serialize the object when we go through the forward list. |
1093 intptr_t object_id = MarkObject(raw, kIsSerialized); | 1093 intptr_t object_id = forward_list_.MarkAndAddObject(raw, kIsSerialized); |
1094 switch (class_id) { | 1094 switch (class_id) { |
1095 #define SNAPSHOT_WRITE(clazz) \ | 1095 #define SNAPSHOT_WRITE(clazz) \ |
1096 case clazz::kClassId: { \ | 1096 case clazz::kClassId: { \ |
1097 Raw##clazz* raw_obj = reinterpret_cast<Raw##clazz*>(raw); \ | 1097 Raw##clazz* raw_obj = reinterpret_cast<Raw##clazz*>(raw); \ |
1098 raw_obj->WriteTo(this, object_id, kind_); \ | 1098 raw_obj->WriteTo(this, object_id, kind_); \ |
1099 return; \ | 1099 return; \ |
1100 } \ | 1100 } \ |
1101 | 1101 |
1102 CLASS_LIST_NO_OBJECT(SNAPSHOT_WRITE) | 1102 CLASS_LIST_NO_OBJECT(SNAPSHOT_WRITE) |
1103 #undef SNAPSHOT_WRITE | 1103 #undef SNAPSHOT_WRITE |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1161 } else { | 1161 } else { |
1162 ThrowException(exception_type(), exception_msg()); | 1162 ThrowException(exception_type(), exception_msg()); |
1163 } | 1163 } |
1164 } | 1164 } |
1165 | 1165 |
1166 | 1166 |
1167 uword SnapshotWriter::GetObjectTags(RawObject* raw) { | 1167 uword SnapshotWriter::GetObjectTags(RawObject* raw) { |
1168 uword tags = raw->ptr()->tags_; | 1168 uword tags = raw->ptr()->tags_; |
1169 if (SerializedHeaderTag::decode(tags) == kObjectId) { | 1169 if (SerializedHeaderTag::decode(tags) == kObjectId) { |
1170 intptr_t id = SerializedHeaderData::decode(tags); | 1170 intptr_t id = SerializedHeaderData::decode(tags); |
1171 return forward_list_[id - kMaxPredefinedObjectIds]->tags(); | 1171 return forward_list_.NodeForObjectId(id)->tags(); |
1172 } else { | 1172 } else { |
1173 return tags; | 1173 return tags; |
1174 } | 1174 } |
1175 } | 1175 } |
1176 | 1176 |
1177 | 1177 |
1178 intptr_t SnapshotWriter::MarkObject(RawObject* raw, SerializeState state) { | 1178 intptr_t ForwardList::MarkAndAddObject(RawObject* raw, SerializeState state) { |
1179 NoGCScope no_gc; | 1179 NoGCScope no_gc; |
1180 intptr_t object_id = forward_list_.length() + kMaxPredefinedObjectIds; | 1180 intptr_t object_id = next_object_id(); |
1181 ASSERT(object_id <= kMaxObjectId); | 1181 ASSERT(object_id <= kMaxObjectId); |
1182 uword value = 0; | 1182 uword value = 0; |
1183 value = SerializedHeaderTag::update(kObjectId, value); | 1183 value = SerializedHeaderTag::update(kObjectId, value); |
1184 value = SerializedHeaderData::update(object_id, value); | 1184 value = SerializedHeaderData::update(object_id, value); |
1185 uword tags = raw->ptr()->tags_; | 1185 uword tags = raw->ptr()->tags_; |
1186 ASSERT(SerializedHeaderTag::decode(tags) != kObjectId); | 1186 ASSERT(SerializedHeaderTag::decode(tags) != kObjectId); |
1187 raw->ptr()->tags_ = value; | 1187 raw->ptr()->tags_ = value; |
1188 ForwardObjectNode* node = new ForwardObjectNode(raw, tags, state); | 1188 Node* node = new Node(raw, tags, state); |
1189 ASSERT(node != NULL); | 1189 ASSERT(node != NULL); |
1190 forward_list_.Add(node); | 1190 nodes_.Add(node); |
1191 return object_id; | 1191 return object_id; |
1192 } | 1192 } |
1193 | 1193 |
1194 | 1194 |
1195 void SnapshotWriter::UnmarkAll() { | 1195 void ForwardList::UnmarkAll() const { |
1196 NoGCScope no_gc; | 1196 NoGCScope no_gc; |
1197 for (intptr_t i = 0; i < forward_list_.length(); i++) { | 1197 for (intptr_t id = first_object_id(); id < next_object_id(); ++id) { |
1198 RawObject* raw = forward_list_[i]->raw(); | 1198 const Node* node = NodeForObjectId(id); |
1199 raw->ptr()->tags_ = forward_list_[i]->tags(); // Restore original tags. | 1199 RawObject* raw = node->raw(); |
| 1200 raw->ptr()->tags_ = node->tags(); // Restore original tags. |
1200 } | 1201 } |
1201 } | 1202 } |
1202 | 1203 |
1203 | 1204 |
1204 bool SnapshotWriter::CheckAndWritePredefinedObject(RawObject* rawobj) { | 1205 bool SnapshotWriter::CheckAndWritePredefinedObject(RawObject* rawobj) { |
1205 // Check if object can be written in one of the following ways: | 1206 // Check if object can be written in one of the following ways: |
1206 // - Smi: the Smi value is written as is (last bit is not tagged). | 1207 // - Smi: the Smi value is written as is (last bit is not tagged). |
1207 // - VM internal class (from VM isolate): (index of class in vm isolate | 0x3) | 1208 // - VM internal class (from VM isolate): (index of class in vm isolate | 0x3) |
1208 // - Object that has already been written: (negative id in stream | 0x3) | 1209 // - Object that has already been written: (negative id in stream | 0x3) |
1209 | 1210 |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1290 | 1291 |
1291 void SnapshotWriter::WriteObjectImpl(RawObject* raw) { | 1292 void SnapshotWriter::WriteObjectImpl(RawObject* raw) { |
1292 // First check if object can be written as a simple predefined type. | 1293 // First check if object can be written as a simple predefined type. |
1293 if (CheckAndWritePredefinedObject(raw)) { | 1294 if (CheckAndWritePredefinedObject(raw)) { |
1294 return; | 1295 return; |
1295 } | 1296 } |
1296 | 1297 |
1297 // Object is being serialized, add it to the forward ref list and mark | 1298 // Object is being serialized, add it to the forward ref list and mark |
1298 // it so that future references to this object in the snapshot will use | 1299 // it so that future references to this object in the snapshot will use |
1299 // an object id, instead of trying to serialize it again. | 1300 // an object id, instead of trying to serialize it again. |
1300 MarkObject(raw, kIsSerialized); | 1301 forward_list_.MarkAndAddObject(raw, kIsSerialized); |
1301 | 1302 |
1302 WriteInlinedObject(raw); | 1303 WriteInlinedObject(raw); |
1303 } | 1304 } |
1304 | 1305 |
1305 | 1306 |
1306 void SnapshotWriter::WriteInlinedObject(RawObject* raw) { | 1307 void SnapshotWriter::WriteInlinedObject(RawObject* raw) { |
1307 // Now write the object out inline in the stream as follows: | 1308 // Now write the object out inline in the stream as follows: |
1308 // - Object is seen for the first time (inlined as follows): | 1309 // - Object is seen for the first time (inlined as follows): |
1309 // (object size in multiples of kObjectAlignment | 0x1) | 1310 // (object size in multiples of kObjectAlignment | 0x1) |
1310 // serialized fields of the object | 1311 // serialized fields of the object |
1311 // ...... | 1312 // ...... |
1312 NoGCScope no_gc; | 1313 NoGCScope no_gc; |
1313 uword tags = raw->ptr()->tags_; | 1314 uword tags = raw->ptr()->tags_; |
1314 ASSERT(SerializedHeaderTag::decode(tags) == kObjectId); | 1315 ASSERT(SerializedHeaderTag::decode(tags) == kObjectId); |
1315 intptr_t object_id = SerializedHeaderData::decode(tags); | 1316 intptr_t object_id = SerializedHeaderData::decode(tags); |
1316 tags = forward_list_[object_id - kMaxPredefinedObjectIds]->tags(); | 1317 tags = forward_list_.NodeForObjectId(object_id)->tags(); |
1317 RawClass* cls = class_table_->At(RawObject::ClassIdTag::decode(tags)); | 1318 RawClass* cls = class_table_->At(RawObject::ClassIdTag::decode(tags)); |
1318 intptr_t class_id = cls->ptr()->id_; | 1319 intptr_t class_id = cls->ptr()->id_; |
1319 | 1320 |
1320 if (class_id >= kNumPredefinedCids) { | 1321 if (class_id >= kNumPredefinedCids) { |
1321 WriteInstance(object_id, raw, cls, tags); | 1322 WriteInstance(object_id, raw, cls, tags); |
1322 return; | 1323 return; |
1323 } | 1324 } |
1324 switch (class_id) { | 1325 switch (class_id) { |
1325 #define SNAPSHOT_WRITE(clazz) \ | 1326 #define SNAPSHOT_WRITE(clazz) \ |
1326 case clazz::kClassId: { \ | 1327 case clazz::kClassId: { \ |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1358 WriteInstance(object_id, raw, cls, tags); | 1359 WriteInstance(object_id, raw, cls, tags); |
1359 return; | 1360 return; |
1360 } | 1361 } |
1361 #undef SNAPSHOT_WRITE | 1362 #undef SNAPSHOT_WRITE |
1362 default: break; | 1363 default: break; |
1363 } | 1364 } |
1364 UNREACHABLE(); | 1365 UNREACHABLE(); |
1365 } | 1366 } |
1366 | 1367 |
1367 | 1368 |
| 1369 class WriteInlinedObjectVisitor : public ObjectVisitor { |
| 1370 public: |
| 1371 explicit WriteInlinedObjectVisitor(SnapshotWriter* writer) |
| 1372 : ObjectVisitor(Isolate::Current()), writer_(writer) {} |
| 1373 |
| 1374 virtual void VisitObject(RawObject* obj) { |
| 1375 writer_->WriteInlinedObject(obj); |
| 1376 } |
| 1377 |
| 1378 private: |
| 1379 SnapshotWriter* writer_; |
| 1380 }; |
| 1381 |
| 1382 |
1368 void SnapshotWriter::WriteForwardedObjects() { | 1383 void SnapshotWriter::WriteForwardedObjects() { |
| 1384 WriteInlinedObjectVisitor visitor(this); |
| 1385 forward_list_.SerializeAll(&visitor); |
| 1386 } |
| 1387 |
| 1388 |
| 1389 void ForwardList::SerializeAll(ObjectVisitor* writer) { |
1369 // Write out all objects that were added to the forward list and have | 1390 // Write out all objects that were added to the forward list and have |
1370 // not been serialized yet. These would typically be fields of instance | 1391 // not been serialized yet. These would typically be fields of instance |
1371 // objects, arrays or immutable arrays (this is done in order to avoid | 1392 // objects, arrays or immutable arrays (this is done in order to avoid |
1372 // deep recursive calls to WriteObjectImpl). | 1393 // deep recursive calls to WriteObjectImpl). |
1373 // NOTE: The forward list might grow as we process the list. | 1394 // NOTE: The forward list might grow as we process the list. |
1374 for (intptr_t i = 0; i < forward_list_.length(); i++) { | 1395 #ifdef DEBUG |
1375 if (!forward_list_[i]->is_serialized()) { | 1396 for (intptr_t i = first_object_id(); i < first_unprocessed_object_id_; ++i) { |
| 1397 ASSERT(NodeForObjectId(i)->is_serialized()); |
| 1398 } |
| 1399 #endif // DEBUG |
| 1400 for (intptr_t id = first_unprocessed_object_id_; |
| 1401 id < next_object_id(); |
| 1402 ++id) { |
| 1403 if (!NodeForObjectId(id)->is_serialized()) { |
1376 // Write the object out in the stream. | 1404 // Write the object out in the stream. |
1377 RawObject* raw = forward_list_[i]->raw(); | 1405 RawObject* raw = NodeForObjectId(id)->raw(); |
1378 WriteInlinedObject(raw); | 1406 writer->VisitObject(raw); |
1379 | 1407 |
1380 // Mark object as serialized. | 1408 // Mark object as serialized. |
1381 forward_list_[i]->set_state(kIsSerialized); | 1409 NodeForObjectId(id)->set_state(kIsSerialized); |
1382 } | 1410 } |
1383 } | 1411 } |
| 1412 first_unprocessed_object_id_ = next_object_id(); |
1384 } | 1413 } |
1385 | 1414 |
1386 | 1415 |
1387 void SnapshotWriter::WriteClassId(RawClass* cls) { | 1416 void SnapshotWriter::WriteClassId(RawClass* cls) { |
1388 ASSERT(kind_ != Snapshot::kFull); | 1417 ASSERT(kind_ != Snapshot::kFull); |
1389 int class_id = cls->ptr()->id_; | 1418 int class_id = cls->ptr()->id_; |
1390 ASSERT(!IsSingletonClassId(class_id) && !IsObjectStoreClassId(class_id)); | 1419 ASSERT(!IsSingletonClassId(class_id) && !IsObjectStoreClassId(class_id)); |
1391 // TODO(5411462): Should restrict this to only core-lib classes in this | 1420 // TODO(5411462): Should restrict this to only core-lib classes in this |
1392 // case. | 1421 // case. |
1393 // Write out the class and tags information. | 1422 // Write out the class and tags information. |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1494 | 1523 |
1495 | 1524 |
1496 void SnapshotWriter::WriteInstanceRef(RawObject* raw, RawClass* cls) { | 1525 void SnapshotWriter::WriteInstanceRef(RawObject* raw, RawClass* cls) { |
1497 // First check if object is a closure or has native fields. | 1526 // First check if object is a closure or has native fields. |
1498 CheckIfSerializable(cls); | 1527 CheckIfSerializable(cls); |
1499 | 1528 |
1500 // Object is being referenced, add it to the forward ref list and mark | 1529 // Object is being referenced, add it to the forward ref list and mark |
1501 // it so that future references to this object in the snapshot will use | 1530 // it so that future references to this object in the snapshot will use |
1502 // this object id. Mark it as not having been serialized yet so that we | 1531 // this object id. Mark it as not having been serialized yet so that we |
1503 // will serialize the object when we go through the forward list. | 1532 // will serialize the object when we go through the forward list. |
1504 intptr_t object_id = MarkObject(raw, kIsNotSerialized); | 1533 intptr_t object_id = forward_list_.MarkAndAddObject(raw, kIsNotSerialized); |
1505 | 1534 |
1506 // Write out the serialization header value for this object. | 1535 // Write out the serialization header value for this object. |
1507 WriteInlinedObjectHeader(object_id); | 1536 WriteInlinedObjectHeader(object_id); |
1508 | 1537 |
1509 // Indicate this is an instance object. | 1538 // Indicate this is an instance object. |
1510 WriteIntptrValue(SerializedHeaderData::encode(kInstanceObjectId)); | 1539 WriteIntptrValue(SerializedHeaderData::encode(kInstanceObjectId)); |
1511 | 1540 |
1512 // Write out the class information for this object. | 1541 // Write out the class information for this object. |
1513 WriteObjectImpl(cls); | 1542 WriteObjectImpl(cls); |
1514 } | 1543 } |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1576 NoGCScope no_gc; | 1605 NoGCScope no_gc; |
1577 WriteObject(obj.raw()); | 1606 WriteObject(obj.raw()); |
1578 UnmarkAll(); | 1607 UnmarkAll(); |
1579 } else { | 1608 } else { |
1580 ThrowException(exception_type(), exception_msg()); | 1609 ThrowException(exception_type(), exception_msg()); |
1581 } | 1610 } |
1582 } | 1611 } |
1583 | 1612 |
1584 | 1613 |
1585 } // namespace dart | 1614 } // namespace dart |
OLD | NEW |