Index: runtime/vm/snapshot.cc |
=================================================================== |
--- runtime/vm/snapshot.cc (revision 45789) |
+++ runtime/vm/snapshot.cc (working copy) |
@@ -7,6 +7,7 @@ |
#include "platform/assert.h" |
#include "vm/bootstrap.h" |
#include "vm/class_finalizer.h" |
+#include "vm/dart.h" |
#include "vm/dart_entry.h" |
#include "vm/exceptions.h" |
#include "vm/heap.h" |
@@ -21,6 +22,7 @@ |
namespace dart { |
+static const int kNumVmIsolateSnapshotReferences = 32 * KB; |
static const int kNumInitialReferencesInFullSnapshot = 160 * KB; |
static const int kNumInitialReferences = 64; |
@@ -161,11 +163,13 @@ |
} |
-SnapshotReader::SnapshotReader(const uint8_t* buffer, |
- intptr_t size, |
- Snapshot::Kind kind, |
- Isolate* isolate, |
- Zone* zone) |
+SnapshotReader::SnapshotReader( |
+ const uint8_t* buffer, |
+ intptr_t size, |
+ Snapshot::Kind kind, |
+ ZoneGrowableArray<BackRefNode>* backward_refs, |
+ Isolate* isolate, |
+ Zone* zone) |
: BaseReader(buffer, size), |
kind_(kind), |
isolate_(isolate), |
@@ -185,9 +189,9 @@ |
stream_(TokenStream::Handle(isolate)), |
data_(ExternalTypedData::Handle(isolate)), |
error_(UnhandledException::Handle(isolate)), |
- backward_references_((kind == Snapshot::kFull) ? |
- kNumInitialReferencesInFullSnapshot : |
- kNumInitialReferences) { |
+ max_vm_isolate_object_id_( |
+ Object::vm_isolate_snapshot_object_table().Length()), |
+ backward_references_(backward_refs) { |
} |
@@ -196,10 +200,10 @@ |
LongJumpScope jump; |
if (setjmp(*jump.Set()) == 0) { |
PassiveObject& obj = PassiveObject::Handle(isolate(), ReadObjectImpl()); |
- for (intptr_t i = 0; i < backward_references_.length(); i++) { |
- if (!backward_references_[i].is_deserialized()) { |
+ for (intptr_t i = 0; i < backward_references_->length(); i++) { |
+ if (!(*backward_references_)[i].is_deserialized()) { |
ReadObjectImpl(); |
- backward_references_[i].set_state(kIsDeserialized); |
+ (*backward_references_)[i].set_state(kIsDeserialized); |
} |
} |
return obj.raw(); |
@@ -292,7 +296,8 @@ |
intptr_t SnapshotReader::NextAvailableObjectId() const { |
- return backward_references_.length() + kMaxPredefinedObjectIds; |
+ return backward_references_->length() + |
+ kMaxPredefinedObjectIds + max_vm_isolate_object_id_; |
} |
@@ -314,6 +319,11 @@ |
} |
+RawObject* SnapshotReader::VmIsolateSnapshotObject(intptr_t index) const { |
+ return Object::vm_isolate_snapshot_object_table().At(index); |
+} |
+ |
+ |
RawObject* SnapshotReader::ReadObjectImpl(intptr_t header_value) { |
if (IsVMIsolateObject(header_value)) { |
return ReadVMIsolateObject(header_value); |
@@ -447,9 +457,11 @@ |
Object* obj, |
DeserializeState state) { |
intptr_t index = (id - kMaxPredefinedObjectIds); |
- ASSERT(index == backward_references_.length()); |
+ ASSERT(index >= max_vm_isolate_object_id_); |
+ index -= max_vm_isolate_object_id_; |
+ ASSERT(index == backward_references_->length()); |
BackRefNode node(obj, state); |
- backward_references_.Add(node); |
+ backward_references_->Add(node); |
} |
@@ -456,8 +468,10 @@ |
Object* SnapshotReader::GetBackRef(intptr_t id) { |
ASSERT(id >= kMaxPredefinedObjectIds); |
intptr_t index = (id - kMaxPredefinedObjectIds); |
- if (index < backward_references_.length()) { |
- return backward_references_[index].reference(); |
+ ASSERT(index >= max_vm_isolate_object_id_); |
+ index -= max_vm_isolate_object_id_; |
+ if (index < backward_references_->length()) { |
+ return (*backward_references_)[index].reference(); |
} |
return NULL; |
} |
@@ -504,10 +518,10 @@ |
for (intptr_t i = 0; i <= num_flds; i++) { |
*(object_store->from() + i) = ReadObjectImpl(); |
} |
- for (intptr_t i = 0; i < backward_references_.length(); i++) { |
- if (!backward_references_[i].is_deserialized()) { |
+ for (intptr_t i = 0; i < backward_references_->length(); i++) { |
+ if (!(*backward_references_)[i].is_deserialized()) { |
ReadObjectImpl(); |
- backward_references_[i].set_state(kIsDeserialized); |
+ (*backward_references_)[i].set_state(kIsDeserialized); |
} |
} |
@@ -979,8 +993,12 @@ |
return GetType(object_store(), object_id); // return type obj. |
} |
} |
- Object* object = GetBackRef(object_id); |
- return object->raw(); |
+ ASSERT(object_id >= kMaxPredefinedObjectIds); |
+ intptr_t index = (object_id - kMaxPredefinedObjectIds); |
+ if (index < max_vm_isolate_object_id_) { |
+ return VmIsolateSnapshotObject(index); |
+ } |
+ return GetBackRef(object_id)->raw(); |
} |
@@ -1108,18 +1126,134 @@ |
result.SetTypeArguments(*TypeArgumentsHandle()); |
bool is_canonical = RawObject::IsCanonical(tags); |
+ Object& obj = Object::Handle(isolate()); |
for (intptr_t i = 0; i < len; i++) { |
*PassiveObjectHandle() = is_canonical ? ReadObjectImpl() : ReadObjectRef(); |
+ obj = (*PassiveObjectHandle()).raw(); |
result.SetAt(i, *PassiveObjectHandle()); |
} |
} |
+VmIsolateSnapshotReader::VmIsolateSnapshotReader(const uint8_t* buffer, |
+ intptr_t size, |
+ Zone* zone) |
+ : SnapshotReader(buffer, |
+ size, |
+ Snapshot::kFull, |
+ new ZoneGrowableArray<BackRefNode>( |
+ kNumVmIsolateSnapshotReferences), |
+ Dart::vm_isolate(), |
+ zone) { |
+} |
+ |
+ |
+VmIsolateSnapshotReader::~VmIsolateSnapshotReader() { |
+ intptr_t len = GetBackwardReferenceTable()->length(); |
+ Object::InitVmIsolateSnapshotObjectTable(len); |
+ ZoneGrowableArray<BackRefNode>* backrefs = GetBackwardReferenceTable(); |
+ for (intptr_t i = 0; i < len; i++) { |
+ Object::vm_isolate_snapshot_object_table().SetAt( |
+ i, *(backrefs->At(i).reference())); |
+ } |
+ ResetBackwardReferenceTable(); |
+} |
+ |
+ |
+RawApiError* VmIsolateSnapshotReader::ReadVmIsolateSnapshot() { |
+ ASSERT(kind() == Snapshot::kFull); |
+ Isolate* isolate = Isolate::Current(); |
+ ASSERT(isolate != NULL); |
+ ASSERT(isolate == Dart::vm_isolate()); |
+ ObjectStore* object_store = isolate->object_store(); |
+ ASSERT(object_store != NULL); |
+ |
+ // First read the version string, and check that it matches. |
+ RawApiError* error = VerifyVersion(); |
+ if (error != ApiError::null()) { |
+ return error; |
+ } |
+ |
+ // The version string matches. Read the rest of the snapshot. |
+ |
+ { |
+ NoSafepointScope no_safepoint; |
+ HeapLocker hl(isolate, old_space()); |
+ |
+ // Read in the symbol table. |
+ object_store->symbol_table_ = reinterpret_cast<RawArray*>(ReadObject()); |
+ |
+ // Validate the class table. |
+#if defined(DEBUG) |
+ isolate->ValidateClassTable(); |
+#endif |
+ |
+ return ApiError::null(); |
+ } |
+} |
+ |
+ |
+IsolateSnapshotReader::IsolateSnapshotReader(const uint8_t* buffer, |
+ intptr_t size, |
+ Isolate* isolate, |
+ Zone* zone) |
+ : SnapshotReader(buffer, |
+ size, |
+ Snapshot::kFull, |
+ new ZoneGrowableArray<BackRefNode>( |
+ kNumInitialReferencesInFullSnapshot), |
+ isolate, |
+ zone) { |
+} |
+ |
+ |
+IsolateSnapshotReader::~IsolateSnapshotReader() { |
+ ResetBackwardReferenceTable(); |
+} |
+ |
+ |
+ScriptSnapshotReader::ScriptSnapshotReader(const uint8_t* buffer, |
+ intptr_t size, |
+ Isolate* isolate, |
+ Zone* zone) |
+ : SnapshotReader(buffer, |
+ size, |
+ Snapshot::kScript, |
+ new ZoneGrowableArray<BackRefNode>(kNumInitialReferences), |
+ isolate, |
+ zone) { |
+} |
+ |
+ |
+ScriptSnapshotReader::~ScriptSnapshotReader() { |
+ ResetBackwardReferenceTable(); |
+} |
+ |
+ |
+MessageSnapshotReader::MessageSnapshotReader(const uint8_t* buffer, |
+ intptr_t size, |
+ Isolate* isolate, |
+ Zone* zone) |
+ : SnapshotReader(buffer, |
+ size, |
+ Snapshot::kMessage, |
+ new ZoneGrowableArray<BackRefNode>(kNumInitialReferences), |
+ isolate, |
+ zone) { |
+} |
+ |
+ |
+MessageSnapshotReader::~MessageSnapshotReader() { |
+ ResetBackwardReferenceTable(); |
+} |
+ |
+ |
SnapshotWriter::SnapshotWriter(Snapshot::Kind kind, |
uint8_t** buffer, |
ReAlloc alloc, |
intptr_t initial_size, |
+ ForwardList* forward_list, |
bool can_send_any_object) |
: BaseWriter(buffer, alloc, initial_size), |
kind_(kind), |
@@ -1126,11 +1260,12 @@ |
isolate_(Isolate::Current()), |
object_store_(isolate_->object_store()), |
class_table_(isolate_->class_table()), |
- forward_list_(kMaxPredefinedObjectIds), |
+ forward_list_(forward_list), |
exception_type_(Exceptions::kNone), |
exception_msg_(NULL), |
unmarked_objects_(false), |
can_send_any_object_(can_send_any_object) { |
+ ASSERT(forward_list_ != NULL); |
} |
@@ -1202,7 +1337,6 @@ |
} |
} |
- |
// Check it is a predefined symbol in the VM isolate. |
id = Symbols::LookupVMSymbol(rawobj); |
if (id != kInvalidIndex) { |
@@ -1210,6 +1344,12 @@ |
return; |
} |
+ // Check if it is an object from the vm isolate snapshot object table. |
+ id = FindVmSnapshotObject(rawobj); |
+ if (id != kInvalidIndex) { |
+ WriteIndexedObject(id); |
+ return; |
+ } |
UNREACHABLE(); |
} |
@@ -1233,7 +1373,7 @@ |
// it so that future references to this object in the snapshot will use |
// this object id. Mark it as not having been serialized yet so that we |
// will serialize the object when we go through the forward list. |
- forward_list_.MarkAndAddObject(raw, kIsNotSerialized); |
+ forward_list_->MarkAndAddObject(raw, kIsNotSerialized); |
RawArray* rawarray = reinterpret_cast<RawArray*>(raw); |
@@ -1253,7 +1393,7 @@ |
// it so that future references to this object in the snapshot will use |
// this object id. Mark it as not having been serialized yet so that we |
// will serialize the object when we go through the forward list. |
- forward_list_.MarkAndAddObject(raw, kIsNotSerialized); |
+ forward_list_->MarkAndAddObject(raw, kIsNotSerialized); |
RawArray* rawarray = reinterpret_cast<RawArray*>(raw); |
@@ -1276,7 +1416,7 @@ |
// to this object in the snapshot will use this object id. Mark it as having |
// been serialized so that we do not serialize the object when we go through |
// the forward list. |
- forward_list_.MarkAndAddObject(raw, kIsSerialized); |
+ forward_list_->MarkAndAddObject(raw, kIsSerialized); |
switch (class_id) { |
#define SNAPSHOT_WRITE(clazz) \ |
case clazz::kClassId: { \ |
@@ -1312,27 +1452,100 @@ |
} |
-void FullSnapshotWriter::WriteFullSnapshot() { |
- ASSERT(isolate() != NULL); |
- ObjectStore* object_store = isolate()->object_store(); |
+FullSnapshotWriter::FullSnapshotWriter(uint8_t** vm_isolate_snapshot_buffer, |
+ uint8_t** isolate_snapshot_buffer, |
+ ReAlloc alloc) |
+ : vm_isolate_snapshot_buffer_(vm_isolate_snapshot_buffer), |
+ isolate_snapshot_buffer_(isolate_snapshot_buffer), |
+ alloc_(alloc), |
+ vm_isolate_snapshot_size_(0), |
+ isolate_snapshot_size_(0), |
+ forward_list_(SnapshotWriter::FirstObjectId()) { |
+ ASSERT(isolate_snapshot_buffer_ != NULL); |
+ ASSERT(alloc_ != NULL); |
+} |
+ |
+ |
+void FullSnapshotWriter::WriteVmIsolateSnapshot() { |
+ ASSERT(vm_isolate_snapshot_buffer_ != NULL); |
+ SnapshotWriter writer(Snapshot::kFull, |
+ vm_isolate_snapshot_buffer_, |
+ alloc_, |
+ kInitialSize, |
+ &forward_list_, |
+ true); // Can send any kind of object. |
+ Isolate* isolate = writer.isolate(); |
+ ASSERT(isolate != NULL); |
+ ObjectStore* object_store = isolate->object_store(); |
ASSERT(object_store != NULL); |
ASSERT(ClassFinalizer::AllClassesFinalized()); |
// Ensure the class table is valid. |
#if defined(DEBUG) |
- isolate()->ValidateClassTable(); |
+ isolate->ValidateClassTable(); |
#endif |
+ // Write full snapshot for a regular isolate. |
// Setup for long jump in case there is an exception while writing |
// the snapshot. |
LongJumpScope jump; |
if (setjmp(*jump.Set()) == 0) { |
// Reserve space in the output buffer for a snapshot header. |
- ReserveHeader(); |
+ writer.ReserveHeader(); |
// Write out the version string. |
- WriteVersion(); |
+ writer.WriteVersion(); |
+ // Write out the symbol table. |
+ { |
+ NoSafepointScope no_safepoint; |
+ |
+ // Write out the symbol table and reset the symbol table for the |
+ // regular isolate so that we do not write these symbols into the |
+ // snapshot of a regular dart isolate. |
+ writer.WriteObject(object_store->symbol_table()); |
+ |
+ writer.FillHeader(writer.kind()); |
+ } |
+ vm_isolate_snapshot_size_ = writer.BytesWritten(); |
+ // Reset the symbol table for the regular isolate so that we do not |
+ // write these symbols into the snapshot of a regular dart isolate. |
+ Symbols::SetupSymbolTable(isolate); |
+ } else { |
+ writer.ThrowException(writer.exception_type(), writer.exception_msg()); |
+ } |
+} |
+ |
+ |
+void FullSnapshotWriter::WriteIsolateFullSnapshot() { |
+ SnapshotWriter writer(Snapshot::kFull, |
+ isolate_snapshot_buffer_, |
+ alloc_, |
+ kInitialSize, |
+ &forward_list_, |
+ true); |
+ Isolate* isolate = writer.isolate(); |
+ ASSERT(isolate != NULL); |
+ ObjectStore* object_store = isolate->object_store(); |
+ ASSERT(object_store != NULL); |
+ ASSERT(ClassFinalizer::AllClassesFinalized()); |
+ |
+ // Ensure the class table is valid. |
+#if defined(DEBUG) |
+ isolate->ValidateClassTable(); |
+#endif |
+ |
+ // Write full snapshot for a regular isolate. |
+ // Setup for long jump in case there is an exception while writing |
+ // the snapshot. |
+ LongJumpScope jump; |
+ if (setjmp(*jump.Set()) == 0) { |
+ // Reserve space in the output buffer for a snapshot header. |
+ writer.ReserveHeader(); |
+ |
+ // Write out the version string. |
+ writer.WriteVersion(); |
+ |
// Write out the full snapshot. |
{ |
NoSafepointScope no_safepoint; |
@@ -1339,26 +1552,35 @@ |
// Write out all the objects in the object store of the isolate which |
// is the root set for all dart allocated objects at this point. |
- SnapshotWriterVisitor visitor(this, false); |
+ SnapshotWriterVisitor visitor(&writer, false); |
object_store->VisitObjectPointers(&visitor); |
// Write out all forwarded objects. |
- WriteForwardedObjects(); |
+ writer.WriteForwardedObjects(); |
- FillHeader(kind()); |
- UnmarkAll(); |
+ writer.FillHeader(writer.kind()); |
+ writer.UnmarkAll(); |
} |
+ isolate_snapshot_size_ = writer.BytesWritten(); |
} else { |
- ThrowException(exception_type(), exception_msg()); |
+ writer.ThrowException(writer.exception_type(), writer.exception_msg()); |
} |
} |
+void FullSnapshotWriter::WriteFullSnapshot() { |
+ if (vm_isolate_snapshot_buffer() != NULL) { |
+ WriteVmIsolateSnapshot(); |
+ } |
+ WriteIsolateFullSnapshot(); |
+} |
+ |
+ |
uword SnapshotWriter::GetObjectTags(RawObject* raw) { |
uword tags = raw->ptr()->tags_; |
if (SerializedHeaderTag::decode(tags) == kObjectId) { |
intptr_t id = SerializedHeaderData::decode(tags); |
- return forward_list_.NodeForObjectId(id)->tags(); |
+ return forward_list_->NodeForObjectId(id)->tags(); |
} else { |
return tags; |
} |
@@ -1392,7 +1614,7 @@ |
intptr_t ForwardList::MarkAndAddObject(RawObject* raw, SerializeState state) { |
NoSafepointScope no_safepoint; |
intptr_t object_id = next_object_id(); |
- ASSERT(object_id <= kMaxObjectId); |
+ ASSERT(object_id > 0 && object_id <= kMaxObjectId); |
uword value = 0; |
value = SerializedHeaderTag::update(kObjectId, value); |
value = SerializedHeaderData::update(object_id, value); |
@@ -1407,11 +1629,13 @@ |
void ForwardList::UnmarkAll() const { |
- NoSafepointScope no_safepoint; |
- for (intptr_t id = first_object_id(); id < next_object_id(); ++id) { |
- const Node* node = NodeForObjectId(id); |
- RawObject* raw = node->raw(); |
- raw->ptr()->tags_ = node->tags(); // Restore original tags. |
+ { |
+ NoSafepointScope no_safepoint; |
+ for (intptr_t id = first_object_id(); id < next_object_id(); ++id) { |
+ const Node* node = NodeForObjectId(id); |
+ RawObject* raw = node->raw(); |
+ raw->ptr()->tags_ = node->tags(); // Restore original tags. |
+ } |
} |
} |
@@ -1512,7 +1736,7 @@ |
// Object is being serialized, add it to the forward ref list and mark |
// it so that future references to this object in the snapshot will use |
// an object id, instead of trying to serialize it again. |
- forward_list_.MarkAndAddObject(raw, kIsSerialized); |
+ forward_list_->MarkAndAddObject(raw, kIsSerialized); |
WriteInlinedObject(raw); |
} |
@@ -1528,7 +1752,7 @@ |
uword tags = raw->ptr()->tags_; |
ASSERT(SerializedHeaderTag::decode(tags) == kObjectId); |
intptr_t object_id = SerializedHeaderData::decode(tags); |
- tags = forward_list_.NodeForObjectId(object_id)->tags(); |
+ tags = forward_list_->NodeForObjectId(object_id)->tags(); |
RawClass* cls = class_table_->At(RawObject::ClassIdTag::decode(tags)); |
intptr_t class_id = cls->ptr()->id_; |
@@ -1600,7 +1824,7 @@ |
void SnapshotWriter::WriteForwardedObjects() { |
WriteInlinedObjectVisitor visitor(this); |
- forward_list_.SerializeAll(&visitor); |
+ forward_list_->SerializeAll(&visitor); |
} |
@@ -1842,11 +2066,11 @@ |
// to this object in the snapshot will use this object id. Mark it as having |
// been serialized so that we do not serialize the object when we go through |
// the forward list. |
- forward_list_.MarkAndAddObject(raw, kIsSerialized); |
+ forward_list_->MarkAndAddObject(raw, kIsSerialized); |
uword tags = raw->ptr()->tags_; |
ASSERT(SerializedHeaderTag::decode(tags) == kObjectId); |
intptr_t object_id = SerializedHeaderData::decode(tags); |
- tags = forward_list_.NodeForObjectId(object_id)->tags(); |
+ tags = forward_list_->NodeForObjectId(object_id)->tags(); |
WriteStaticImplicitClosure(object_id, func, tags); |
return; |
} |
@@ -1855,7 +2079,7 @@ |
// it so that future references to this object in the snapshot will use |
// this object id. Mark it as not having been serialized yet so that we |
// will serialize the object when we go through the forward list. |
- forward_list_.MarkAndAddObject(raw, kIsNotSerialized); |
+ forward_list_->MarkAndAddObject(raw, kIsNotSerialized); |
// Write out the serialization header value for this object. |
WriteInlinedObjectHeader(kOmittedObjectId); |
@@ -1874,6 +2098,17 @@ |
} |
+intptr_t SnapshotWriter::FindVmSnapshotObject(RawObject* rawobj) { |
+ intptr_t length = Object::vm_isolate_snapshot_object_table().Length(); |
+ for (intptr_t i = 0; i < length; i++) { |
+ if (Object::vm_isolate_snapshot_object_table().At(i) == rawobj) { |
+ return (i + kMaxPredefinedObjectIds); |
+ } |
+ } |
+ return kInvalidIndex; |
+} |
+ |
+ |
void SnapshotWriter::ThrowException(Exceptions::ExceptionType type, |
const char* msg) { |
object_store()->clear_sticky_error(); |
@@ -1898,6 +2133,27 @@ |
} |
+intptr_t SnapshotWriter::FirstObjectId() { |
+ intptr_t max_vm_isolate_object_id = |
+ Object::vm_isolate_snapshot_object_table().Length(); |
+ return kMaxPredefinedObjectIds + max_vm_isolate_object_id; |
+} |
+ |
+ |
+ScriptSnapshotWriter::ScriptSnapshotWriter(uint8_t** buffer, |
+ ReAlloc alloc) |
+ : SnapshotWriter(Snapshot::kScript, |
+ buffer, |
+ alloc, |
+ kInitialSize, |
+ &forward_list_, |
+ true), |
+ forward_list_(SnapshotWriter::FirstObjectId()) { |
+ ASSERT(buffer != NULL); |
+ ASSERT(alloc != NULL); |
+} |
+ |
+ |
void ScriptSnapshotWriter::WriteScriptSnapshot(const Library& lib) { |
ASSERT(kind() == Snapshot::kScript); |
ASSERT(isolate() != NULL); |
@@ -1941,6 +2197,21 @@ |
} |
+MessageWriter::MessageWriter(uint8_t** buffer, |
+ ReAlloc alloc, |
+ bool can_send_any_object) |
+ : SnapshotWriter(Snapshot::kMessage, |
+ buffer, |
+ alloc, |
+ kInitialSize, |
+ &forward_list_, |
+ can_send_any_object), |
+ forward_list_(SnapshotWriter::FirstObjectId()) { |
+ ASSERT(buffer != NULL); |
+ ASSERT(alloc != NULL); |
+} |
+ |
+ |
void MessageWriter::WriteMessage(const Object& obj) { |
ASSERT(kind() == Snapshot::kMessage); |
ASSERT(isolate() != NULL); |