| Index: runtime/vm/snapshot.cc
|
| diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
|
| index 4b8695d94c8ff2cf7d82144da22ca50344fe4398..5ab4697f865893740f448bc779d107658ed8a8ff 100644
|
| --- a/runtime/vm/snapshot.cc
|
| +++ b/runtime/vm/snapshot.cc
|
| @@ -16,6 +16,7 @@
|
| #include "vm/object.h"
|
| #include "vm/object_store.h"
|
| #include "vm/snapshot_ids.h"
|
| +#include "vm/stub_code.h"
|
| #include "vm/symbols.h"
|
| #include "vm/verified_memory.h"
|
| #include "vm/version.h"
|
| @@ -171,12 +172,14 @@ intptr_t BaseReader::ReadSmiValue() {
|
| SnapshotReader::SnapshotReader(
|
| const uint8_t* buffer,
|
| intptr_t size,
|
| + const uint8_t* instructions_buffer,
|
| Snapshot::Kind kind,
|
| ZoneGrowableArray<BackRefNode>* backward_refs,
|
| Thread* thread)
|
| : BaseReader(buffer, size),
|
| + instructions_buffer_(instructions_buffer),
|
| kind_(kind),
|
| - snapshot_code_(false),
|
| + snapshot_code_(instructions_buffer != NULL),
|
| thread_(thread),
|
| zone_(thread->zone()),
|
| heap_(isolate()->heap()),
|
| @@ -194,11 +197,16 @@ SnapshotReader::SnapshotReader(
|
| stream_(TokenStream::Handle(zone_)),
|
| data_(ExternalTypedData::Handle(zone_)),
|
| typed_data_(TypedData::Handle(zone_)),
|
| + code_(Code::Handle(zone_)),
|
| error_(UnhandledException::Handle(zone_)),
|
| max_vm_isolate_object_id_(
|
| (kind == Snapshot::kFull) ?
|
| Object::vm_isolate_snapshot_object_table().Length() : 0),
|
| - backward_references_(backward_refs) {
|
| + backward_references_(backward_refs),
|
| + instructions_reader_(NULL) {
|
| + if (instructions_buffer != NULL) {
|
| + instructions_reader_ = new InstructionsReader(instructions_buffer);
|
| + }
|
| }
|
|
|
|
|
| @@ -502,7 +510,9 @@ RawObject* SnapshotReader::ReadInlinedObject(intptr_t object_id,
|
| ASSERT(!cls_.IsNull());
|
| instance_size = cls_.instance_size();
|
| }
|
| - intptr_t next_field_offset = cls_.next_field_offset();
|
| + intptr_t next_field_offset = Class::IsSignatureClass(cls_.raw())
|
| + ? Closure::InstanceSize() : cls_.next_field_offset();
|
| +
|
| intptr_t type_argument_field_offset = cls_.type_arguments_field_offset();
|
| ASSERT(next_field_offset > 0);
|
| // Instance::NextFieldOffset() returns the offset of the first field in
|
| @@ -775,6 +785,82 @@ RawTypeArguments* SnapshotReader::NewTypeArguments(intptr_t len) {
|
| }
|
|
|
|
|
| +RawObjectPool* SnapshotReader::NewObjectPool(intptr_t len) {
|
| + ASSERT(kind_ == Snapshot::kFull);
|
| + ASSERT_NO_SAFEPOINT_SCOPE();
|
| + RawObjectPool* obj = reinterpret_cast<RawObjectPool*>(
|
| + AllocateUninitialized(kObjectPoolCid, ObjectPool::InstanceSize(len)));
|
| + obj->ptr()->length_ = len;
|
| + return obj;
|
| +}
|
| +
|
| +
|
| +RawLocalVarDescriptors* SnapshotReader::NewLocalVarDescriptors(
|
| + intptr_t num_entries) {
|
| + ASSERT(kind_ == Snapshot::kFull);
|
| + ASSERT_NO_SAFEPOINT_SCOPE();
|
| + RawLocalVarDescriptors* obj = reinterpret_cast<RawLocalVarDescriptors*>(
|
| + AllocateUninitialized(kLocalVarDescriptorsCid,
|
| + LocalVarDescriptors::InstanceSize(num_entries)));
|
| + obj->ptr()->num_entries_ = num_entries;
|
| + return obj;
|
| +}
|
| +
|
| +
|
| +RawExceptionHandlers* SnapshotReader::NewExceptionHandlers(
|
| + intptr_t num_entries) {
|
| + ASSERT(kind_ == Snapshot::kFull);
|
| + ASSERT_NO_SAFEPOINT_SCOPE();
|
| + RawExceptionHandlers* obj = reinterpret_cast<RawExceptionHandlers*>(
|
| + AllocateUninitialized(kExceptionHandlersCid,
|
| + ExceptionHandlers::InstanceSize(num_entries)));
|
| + obj->ptr()->num_entries_ = num_entries;
|
| + return obj;
|
| +}
|
| +
|
| +
|
| +RawPcDescriptors* SnapshotReader::NewPcDescriptors(intptr_t len) {
|
| + ASSERT(kind_ == Snapshot::kFull);
|
| + ASSERT_NO_SAFEPOINT_SCOPE();
|
| + RawPcDescriptors* obj = reinterpret_cast<RawPcDescriptors*>(
|
| + AllocateUninitialized(kPcDescriptorsCid,
|
| + PcDescriptors::InstanceSize(len)));
|
| + obj->ptr()->length_ = len;
|
| + return obj;
|
| +}
|
| +
|
| +
|
| +RawStackmap* SnapshotReader::NewStackmap(intptr_t len) {
|
| + ASSERT(kind_ == Snapshot::kFull);
|
| + ASSERT_NO_SAFEPOINT_SCOPE();
|
| + RawStackmap* obj = reinterpret_cast<RawStackmap*>(
|
| + AllocateUninitialized(kStackmapCid, Stackmap::InstanceSize(len)));
|
| + obj->ptr()->length_ = len;
|
| + return obj;
|
| +}
|
| +
|
| +
|
| +RawContextScope* SnapshotReader::NewContextScope(intptr_t num_variables) {
|
| + ASSERT(kind_ == Snapshot::kFull);
|
| + ASSERT_NO_SAFEPOINT_SCOPE();
|
| + RawContextScope* obj = reinterpret_cast<RawContextScope*>(
|
| + AllocateUninitialized(kContextScopeCid,
|
| + ContextScope::InstanceSize(num_variables)));
|
| + obj->ptr()->num_variables_ = num_variables;
|
| + return obj;
|
| +}
|
| +
|
| +
|
| +RawCode* SnapshotReader::NewCode(intptr_t pointer_offsets_length) {
|
| + ASSERT(pointer_offsets_length == 0);
|
| + ASSERT(kind_ == Snapshot::kFull);
|
| + ASSERT_NO_SAFEPOINT_SCOPE();
|
| + RawCode* obj = reinterpret_cast<RawCode*>(
|
| + AllocateUninitialized(kCodeCid, Code::InstanceSize(0)));
|
| + return obj;
|
| +}
|
| +
|
| +
|
| RawTokenStream* SnapshotReader::NewTokenStream(intptr_t len) {
|
| ASSERT(kind_ == Snapshot::kFull);
|
| ASSERT_NO_SAFEPOINT_SCOPE();
|
| @@ -924,19 +1010,13 @@ RawFunction* SnapshotReader::NewFunction() {
|
| }
|
|
|
|
|
| -RawCode* SnapshotReader::NewCode(intptr_t pointer_offsets_length) {
|
| - ASSERT(pointer_offsets_length == 0);
|
| - ALLOC_NEW_OBJECT(Code);
|
| -}
|
| -
|
| -
|
| -RawObjectPool* SnapshotReader::NewObjectPool(intptr_t length) {
|
| - ALLOC_NEW_OBJECT(ObjectPool);
|
| +RawICData* SnapshotReader::NewICData() {
|
| + ALLOC_NEW_OBJECT(ICData);
|
| }
|
|
|
|
|
| -RawICData* SnapshotReader::NewICData() {
|
| - ALLOC_NEW_OBJECT(ICData);
|
| +RawLinkedHashMap* SnapshotReader::NewLinkedHashMap() {
|
| + ALLOC_NEW_OBJECT(LinkedHashMap);
|
| }
|
|
|
|
|
| @@ -1057,8 +1137,36 @@ RawStacktrace* SnapshotReader::NewStacktrace() {
|
| }
|
|
|
|
|
| -RawInstructions* SnapshotReader::GetInstructionsById(int32_t id) {
|
| - // TODO(rmacnak): Read from shared library.
|
| +int32_t InstructionsWriter::GetOffsetFor(RawInstructions* instructions) {
|
| + // Instructions are allocated with the code alignment and we don't write
|
| + // anything else in the text section.
|
| + ASSERT(Utils::IsAligned(stream_.bytes_written(),
|
| + OS::PreferredCodeAlignment()));
|
| +
|
| + intptr_t offset = stream_.bytes_written();
|
| + stream_.WriteBytes(reinterpret_cast<uint8_t*>(instructions) - kHeapObjectTag,
|
| + instructions->Size());
|
| + return offset;
|
| +}
|
| +
|
| +
|
| +RawInstructions* InstructionsReader::GetInstructionsAt(int32_t offset,
|
| + uword expected_tags) {
|
| + ASSERT(Utils::IsAligned(offset, OS::PreferredCodeAlignment()));
|
| +
|
| + RawInstructions* result =
|
| + reinterpret_cast<RawInstructions*>(
|
| + reinterpret_cast<uword>(buffer_) + offset + kHeapObjectTag);
|
| +
|
| + uword actual_tags = result->ptr()->tags_;
|
| + if (actual_tags != expected_tags) {
|
| + FATAL2("Instructions tag mismatch: expected %" Pd ", saw %" Pd,
|
| + expected_tags,
|
| + actual_tags);
|
| + }
|
| +
|
| + // TODO(rmacnak): The above contains stale pointers to a Code and an
|
| + // ObjectPool. Return the actual result after calling convention change.
|
| return Instructions::null();
|
| }
|
|
|
| @@ -1073,7 +1181,7 @@ intptr_t SnapshotReader::LookupInternalClass(intptr_t class_header) {
|
| }
|
| ASSERT(SerializedHeaderTag::decode(class_header) == kObjectId);
|
| intptr_t class_id = SerializedHeaderData::decode(class_header);
|
| - ASSERT(IsObjectStoreClassId(class_id));
|
| + ASSERT(IsObjectStoreClassId(class_id) || IsSingletonClassId(class_id));
|
| return class_id;
|
| }
|
|
|
| @@ -1271,15 +1379,18 @@ void SnapshotReader::ArrayReadFrom(intptr_t object_id,
|
| }
|
|
|
|
|
| -VmIsolateSnapshotReader::VmIsolateSnapshotReader(const uint8_t* buffer,
|
| - intptr_t size,
|
| - Thread* thread)
|
| - : SnapshotReader(buffer,
|
| - size,
|
| - Snapshot::kFull,
|
| - new ZoneGrowableArray<BackRefNode>(
|
| - kNumVmIsolateSnapshotReferences),
|
| - thread) {
|
| +VmIsolateSnapshotReader::VmIsolateSnapshotReader(
|
| + const uint8_t* buffer,
|
| + intptr_t size,
|
| + const uint8_t* instructions_buffer,
|
| + Thread* thread)
|
| + : SnapshotReader(buffer,
|
| + size,
|
| + instructions_buffer,
|
| + Snapshot::kFull,
|
| + new ZoneGrowableArray<BackRefNode>(
|
| + kNumVmIsolateSnapshotReferences),
|
| + thread) {
|
| }
|
|
|
|
|
| @@ -1292,6 +1403,7 @@ VmIsolateSnapshotReader::~VmIsolateSnapshotReader() {
|
| i, *(backrefs->At(i).reference()));
|
| }
|
| ResetBackwardReferenceTable();
|
| + Object::set_instructions_snapshot_buffer(instructions_buffer_);
|
| }
|
|
|
|
|
| @@ -1325,6 +1437,29 @@ RawApiError* VmIsolateSnapshotReader::ReadVmIsolateSnapshot() {
|
| // only memory.
|
| *(ArrayHandle()) ^= ReadObject();
|
|
|
| +
|
| + if (snapshot_code()) {
|
| + for (intptr_t i = 0;
|
| + i < ArgumentsDescriptor::kCachedDescriptorCount;
|
| + i++) {
|
| + *(ArrayHandle()) ^= ReadObject();
|
| + // TODO(rmacnak):
|
| + // ArgumentsDescriptor::InitOnceFromSnapshot(i, *(ArrayHandle()));
|
| + }
|
| +
|
| + ObjectPool::CheckedHandle(ReadObject()); // empty pool
|
| + PcDescriptors::CheckedHandle(ReadObject()); // empty pc desc
|
| + LocalVarDescriptors::CheckedHandle(ReadObject()); // empty var desc
|
| + ExceptionHandlers::CheckedHandle(ReadObject()); // empty exc handlers
|
| +
|
| +#define READ_STUB(name) \
|
| + *(CodeHandle()) ^= ReadObject();
|
| + // TODO(rmacnak):
|
| + // StubCode::name##_entry()->InitOnceFromSnapshot(CodeHandle())
|
| + VM_STUB_CODE_LIST(READ_STUB);
|
| +#undef READ_STUB
|
| + }
|
| +
|
| // Validate the class table.
|
| #if defined(DEBUG)
|
| isolate->ValidateClassTable();
|
| @@ -1337,9 +1472,11 @@ RawApiError* VmIsolateSnapshotReader::ReadVmIsolateSnapshot() {
|
|
|
| IsolateSnapshotReader::IsolateSnapshotReader(const uint8_t* buffer,
|
| intptr_t size,
|
| + const uint8_t* instructions_buffer,
|
| Thread* thread)
|
| : SnapshotReader(buffer,
|
| size,
|
| + instructions_buffer,
|
| Snapshot::kFull,
|
| new ZoneGrowableArray<BackRefNode>(
|
| kNumInitialReferencesInFullSnapshot),
|
| @@ -1357,6 +1494,7 @@ ScriptSnapshotReader::ScriptSnapshotReader(const uint8_t* buffer,
|
| Thread* thread)
|
| : SnapshotReader(buffer,
|
| size,
|
| + NULL, /* instructions_buffer */
|
| Snapshot::kScript,
|
| new ZoneGrowableArray<BackRefNode>(kNumInitialReferences),
|
| thread) {
|
| @@ -1373,6 +1511,7 @@ MessageSnapshotReader::MessageSnapshotReader(const uint8_t* buffer,
|
| Thread* thread)
|
| : SnapshotReader(buffer,
|
| size,
|
| + NULL, /* instructions_buffer */
|
| Snapshot::kMessage,
|
| new ZoneGrowableArray<BackRefNode>(kNumInitialReferences),
|
| thread) {
|
| @@ -1389,19 +1528,23 @@ SnapshotWriter::SnapshotWriter(Snapshot::Kind kind,
|
| ReAlloc alloc,
|
| intptr_t initial_size,
|
| ForwardList* forward_list,
|
| + InstructionsWriter* instructions_writer,
|
| bool can_send_any_object,
|
| - bool snapshot_code)
|
| + bool snapshot_code,
|
| + bool vm_isolate_is_symbolic)
|
| : BaseWriter(buffer, alloc, initial_size),
|
| kind_(kind),
|
| thread_(Thread::Current()),
|
| object_store_(thread_->isolate()->object_store()),
|
| class_table_(thread_->isolate()->class_table()),
|
| forward_list_(forward_list),
|
| + instructions_writer_(instructions_writer),
|
| exception_type_(Exceptions::kNone),
|
| exception_msg_(NULL),
|
| unmarked_objects_(false),
|
| can_send_any_object_(can_send_any_object),
|
| - snapshot_code_(snapshot_code) {
|
| + snapshot_code_(snapshot_code),
|
| + vm_isolate_is_symbolic_(vm_isolate_is_symbolic) {
|
| ASSERT(forward_list_ != NULL);
|
| }
|
|
|
| @@ -1423,80 +1566,80 @@ void SnapshotWriter::WriteObject(RawObject* rawobj) {
|
| object_id = forward_list_->AddObject(rawobj, kIsSerialized); \
|
| Raw##clazz* raw_obj = reinterpret_cast<Raw##clazz*>(rawobj); \
|
| raw_obj->WriteTo(this, object_id, kind()); \
|
| - return; \
|
| + return true; \
|
| } \
|
|
|
| -void SnapshotWriter::HandleVMIsolateObject(RawObject* rawobj) {
|
| +bool SnapshotWriter::HandleVMIsolateObject(RawObject* rawobj) {
|
| // Check if it is a singleton null object.
|
| if (rawobj == Object::null()) {
|
| WriteVMIsolateObject(kNullObject);
|
| - return;
|
| + return true;
|
| }
|
|
|
| // Check if it is a singleton sentinel object.
|
| if (rawobj == Object::sentinel().raw()) {
|
| WriteVMIsolateObject(kSentinelObject);
|
| - return;
|
| + return true;
|
| }
|
|
|
| // Check if it is a singleton sentinel object.
|
| if (rawobj == Object::transition_sentinel().raw()) {
|
| WriteVMIsolateObject(kTransitionSentinelObject);
|
| - return;
|
| + return true;
|
| }
|
|
|
| // Check if it is a singleton empty array object.
|
| if (rawobj == Object::empty_array().raw()) {
|
| WriteVMIsolateObject(kEmptyArrayObject);
|
| - return;
|
| + return true;
|
| }
|
|
|
| // Check if it is a singleton zero array object.
|
| if (rawobj == Object::zero_array().raw()) {
|
| WriteVMIsolateObject(kZeroArrayObject);
|
| - return;
|
| + return true;
|
| }
|
|
|
| // Check if it is a singleton dyanmic Type object.
|
| if (rawobj == Object::dynamic_type()) {
|
| WriteVMIsolateObject(kDynamicType);
|
| - return;
|
| + return true;
|
| }
|
|
|
| // Check if it is a singleton void Type object.
|
| if (rawobj == Object::void_type()) {
|
| WriteVMIsolateObject(kVoidType);
|
| - return;
|
| + return true;
|
| }
|
|
|
| // Check if it is a singleton boolean true object.
|
| if (rawobj == Bool::True().raw()) {
|
| WriteVMIsolateObject(kTrueValue);
|
| - return;
|
| + return true;
|
| }
|
|
|
| // Check if it is a singleton boolean false object.
|
| if (rawobj == Bool::False().raw()) {
|
| WriteVMIsolateObject(kFalseValue);
|
| - return;
|
| + return true;
|
| }
|
|
|
| // Check if it is a singleton extractor parameter types array.
|
| if (rawobj == Object::extractor_parameter_types().raw()) {
|
| WriteVMIsolateObject(kExtractorParameterTypes);
|
| - return;
|
| + return true;
|
| }
|
|
|
| // Check if it is a singleton extractor parameter names array.
|
| if (rawobj == Object::extractor_parameter_names().raw()) {
|
| WriteVMIsolateObject(kExtractorParameterNames);
|
| - return;
|
| + return true;
|
| }
|
|
|
| // Check if it is a singleton empty context scope object.
|
| if (rawobj == Object::empty_context_scope().raw()) {
|
| WriteVMIsolateObject(kEmptyContextScopeObject);
|
| - return;
|
| + return true;
|
| }
|
|
|
| // Check if it is a singleton class object which is shared by
|
| @@ -1508,7 +1651,7 @@ void SnapshotWriter::HandleVMIsolateObject(RawObject* rawobj) {
|
| if (IsSingletonClassId(class_id)) {
|
| intptr_t object_id = ObjectIdFromClassId(class_id);
|
| WriteVMIsolateObject(object_id);
|
| - return;
|
| + return true;
|
| }
|
| }
|
|
|
| @@ -1517,14 +1660,14 @@ void SnapshotWriter::HandleVMIsolateObject(RawObject* rawobj) {
|
| id = Symbols::LookupVMSymbol(rawobj);
|
| if (id != kInvalidIndex) {
|
| WriteVMIsolateObject(id);
|
| - return;
|
| + return true;
|
| }
|
|
|
| // Check if it is an object from the vm isolate snapshot object table.
|
| id = FindVmSnapshotObject(rawobj);
|
| if (id != kInvalidIndex) {
|
| WriteIndexedObject(id);
|
| - return;
|
| + return true;
|
| }
|
| } else {
|
| // In the case of script snapshots or for messages we do not use
|
| @@ -1533,7 +1676,7 @@ void SnapshotWriter::HandleVMIsolateObject(RawObject* rawobj) {
|
| intptr_t object_id = forward_list_->FindObject(rawobj);
|
| if (object_id != -1) {
|
| WriteIndexedObject(object_id);
|
| - return;
|
| + return true;
|
| } else {
|
| switch (id) {
|
| VM_OBJECT_CLASS_LIST(VM_OBJECT_WRITE)
|
| @@ -1541,7 +1684,7 @@ void SnapshotWriter::HandleVMIsolateObject(RawObject* rawobj) {
|
| object_id = forward_list_->AddObject(rawobj, kIsSerialized);
|
| RawTypedData* raw_obj = reinterpret_cast<RawTypedData*>(rawobj);
|
| raw_obj->WriteTo(this, object_id, kind());
|
| - return;
|
| + return true;
|
| }
|
| default:
|
| OS::Print("class id = %" Pd "\n", id);
|
| @@ -1550,8 +1693,13 @@ void SnapshotWriter::HandleVMIsolateObject(RawObject* rawobj) {
|
| }
|
| }
|
|
|
| + if (!vm_isolate_is_symbolic()) {
|
| + return false;
|
| + }
|
| +
|
| const Object& obj = Object::Handle(rawobj);
|
| FATAL1("Unexpected reference to object in VM isolate: %s\n", obj.ToCString());
|
| + return false;
|
| }
|
|
|
| #undef VM_OBJECT_WRITE
|
| @@ -1596,18 +1744,24 @@ class ScriptVisitor : public ObjectVisitor {
|
|
|
| FullSnapshotWriter::FullSnapshotWriter(uint8_t** vm_isolate_snapshot_buffer,
|
| uint8_t** isolate_snapshot_buffer,
|
| + uint8_t** instructions_snapshot_buffer,
|
| ReAlloc alloc,
|
| - bool snapshot_code)
|
| + bool snapshot_code,
|
| + bool vm_isolate_is_symbolic)
|
| : isolate_(Isolate::Current()),
|
| vm_isolate_snapshot_buffer_(vm_isolate_snapshot_buffer),
|
| isolate_snapshot_buffer_(isolate_snapshot_buffer),
|
| + instructions_snapshot_buffer_(instructions_snapshot_buffer),
|
| alloc_(alloc),
|
| vm_isolate_snapshot_size_(0),
|
| isolate_snapshot_size_(0),
|
| + instructions_snapshot_size_(0),
|
| forward_list_(NULL),
|
| + instructions_writer_(NULL),
|
| scripts_(Array::Handle(isolate_)),
|
| symbol_table_(Array::Handle(isolate_)),
|
| - snapshot_code_(snapshot_code) {
|
| + snapshot_code_(snapshot_code),
|
| + vm_isolate_is_symbolic_(vm_isolate_is_symbolic) {
|
| ASSERT(isolate_snapshot_buffer_ != NULL);
|
| ASSERT(alloc_ != NULL);
|
| ASSERT(isolate_ != NULL);
|
| @@ -1641,6 +1795,12 @@ FullSnapshotWriter::FullSnapshotWriter(uint8_t** vm_isolate_snapshot_buffer,
|
|
|
| forward_list_ = new ForwardList(SnapshotWriter::FirstObjectId());
|
| ASSERT(forward_list_ != NULL);
|
| +
|
| + if (instructions_snapshot_buffer != NULL) {
|
| + instructions_writer_ = new InstructionsWriter(instructions_snapshot_buffer,
|
| + alloc,
|
| + kInitialSize);
|
| + }
|
| }
|
|
|
|
|
| @@ -1658,8 +1818,10 @@ void FullSnapshotWriter::WriteVmIsolateSnapshot() {
|
| alloc_,
|
| kInitialSize,
|
| forward_list_,
|
| + instructions_writer_,
|
| true, /* can_send_any_object */
|
| - snapshot_code_);
|
| + snapshot_code_,
|
| + vm_isolate_is_symbolic_);
|
| // Write full snapshot for the VM isolate.
|
| // Setup for long jump in case there is an exception while writing
|
| // the snapshot.
|
| @@ -1685,8 +1847,26 @@ void FullSnapshotWriter::WriteVmIsolateSnapshot() {
|
| // read only memory.
|
| writer.WriteObject(scripts_.raw());
|
|
|
| - // Write out all forwarded objects.
|
| - writer.WriteForwardedObjects();
|
| + if (snapshot_code_) {
|
| + ASSERT(!vm_isolate_is_symbolic_);
|
| +
|
| + for (intptr_t i = 0;
|
| + i < ArgumentsDescriptor::kCachedDescriptorCount;
|
| + i++) {
|
| + writer.WriteObject(ArgumentsDescriptor::cached_args_descriptors_[i]);
|
| + }
|
| +
|
| + writer.WriteObject(Object::empty_object_pool().raw());
|
| + writer.WriteObject(Object::empty_descriptors().raw());
|
| + writer.WriteObject(Object::empty_var_descriptors().raw());
|
| + writer.WriteObject(Object::empty_exception_handlers().raw());
|
| +
|
| +#define WRITE_STUB(name) \
|
| + writer.WriteObject(StubCode::name##_entry()->code());
|
| + VM_STUB_CODE_LIST(WRITE_STUB);
|
| +#undef WRITE_STUB
|
| + }
|
| +
|
|
|
| writer.FillHeader(writer.kind());
|
|
|
| @@ -1703,8 +1883,10 @@ void FullSnapshotWriter::WriteIsolateFullSnapshot() {
|
| alloc_,
|
| kInitialSize,
|
| forward_list_,
|
| + instructions_writer_,
|
| true, /* can_send_any_object */
|
| - snapshot_code_);
|
| + snapshot_code_,
|
| + true /* vm_isolate_is_symbolic */);
|
| ObjectStore* object_store = isolate_->object_store();
|
| ASSERT(object_store != NULL);
|
|
|
| @@ -1739,22 +1921,50 @@ void FullSnapshotWriter::WriteIsolateFullSnapshot() {
|
| }
|
|
|
|
|
| +class WritableVMIsolateScope : StackResource {
|
| + public:
|
| + explicit WritableVMIsolateScope(Thread* thread) : StackResource(thread) {
|
| + Dart::vm_isolate()->heap()->WriteProtect(false);
|
| + }
|
| +
|
| + ~WritableVMIsolateScope() {
|
| + ASSERT(Dart::vm_isolate()->heap()->UsedInWords(Heap::kNew) == 0);
|
| + Dart::vm_isolate()->heap()->WriteProtect(true);
|
| + }
|
| +};
|
| +
|
| +
|
| void FullSnapshotWriter::WriteFullSnapshot() {
|
| - if (vm_isolate_snapshot_buffer() != NULL) {
|
| - WriteVmIsolateSnapshot();
|
| + if (!vm_isolate_is_symbolic_) {
|
| + // TODO(asiva): Don't mutate object headers during serialization.
|
| + WritableVMIsolateScope scope(Thread::Current());
|
| +
|
| + if (vm_isolate_snapshot_buffer() != NULL) {
|
| + WriteVmIsolateSnapshot();
|
| + }
|
| + WriteIsolateFullSnapshot();
|
| +
|
| + instructions_snapshot_size_ = instructions_writer_->BytesWritten();
|
| + } else {
|
| + if (vm_isolate_snapshot_buffer() != NULL) {
|
| + WriteVmIsolateSnapshot();
|
| + }
|
| + WriteIsolateFullSnapshot();
|
| }
|
| - WriteIsolateFullSnapshot();
|
| }
|
|
|
|
|
| PrecompiledSnapshotWriter::PrecompiledSnapshotWriter(
|
| uint8_t** vm_isolate_snapshot_buffer,
|
| uint8_t** isolate_snapshot_buffer,
|
| + uint8_t** instructions_snapshot_buffer,
|
| ReAlloc alloc)
|
| : FullSnapshotWriter(vm_isolate_snapshot_buffer,
|
| isolate_snapshot_buffer,
|
| + instructions_snapshot_buffer,
|
| alloc,
|
| - true /* snapshot_code */) {
|
| + true, /* snapshot_code */
|
| + false /* vm_isolate_is_symbolic */) {
|
| }
|
|
|
|
|
| @@ -1884,8 +2094,7 @@ bool SnapshotWriter::CheckAndWritePredefinedObject(RawObject* rawobj) {
|
| // Now check if it is an object from the VM isolate (NOTE: premarked objects
|
| // are considered to be objects in the VM isolate). These objects are shared
|
| // by all isolates.
|
| - if (rawobj->IsVMHeapObject()) {
|
| - HandleVMIsolateObject(rawobj);
|
| + if (rawobj->IsVMHeapObject() && HandleVMIsolateObject(rawobj)) {
|
| return true;
|
| }
|
|
|
| @@ -2077,7 +2286,9 @@ void SnapshotWriter::WriteInlinedObject(RawObject* raw) {
|
| #undef SNAPSHOT_WRITE
|
| default: break;
|
| }
|
| - UNREACHABLE();
|
| +
|
| + const Object& obj = Object::Handle(raw);
|
| + FATAL1("Unexpected inlined object: %s\n", obj.ToCString());
|
| }
|
|
|
|
|
| @@ -2273,12 +2484,14 @@ void SnapshotWriter::WriteInstance(intptr_t object_id,
|
| // Check if the instance has native fields and throw an exception if it does.
|
| CheckForNativeFields(cls);
|
|
|
| - // Check if object is a closure that is serializable, if the object is a
|
| - // closure that is not serializable this will throw an exception.
|
| - RawFunction* func = IsSerializableClosure(cls, raw);
|
| - if (func != Function::null()) {
|
| - WriteStaticImplicitClosure(object_id, func, tags);
|
| - return;
|
| + if ((kind() == Snapshot::kMessage) || (kind() == Snapshot::kScript)) {
|
| + // Check if object is a closure that is serializable, if the object is a
|
| + // closure that is not serializable this will throw an exception.
|
| + RawFunction* func = IsSerializableClosure(cls, raw);
|
| + if (func != Function::null()) {
|
| + WriteStaticImplicitClosure(object_id, func, tags);
|
| + return;
|
| + }
|
| }
|
|
|
| // Object is regular dart instance.
|
| @@ -2408,8 +2621,10 @@ ScriptSnapshotWriter::ScriptSnapshotWriter(uint8_t** buffer,
|
| alloc,
|
| kInitialSize,
|
| &forward_list_,
|
| + NULL, /* instructions_writer */
|
| true, /* can_send_any_object */
|
| - false /* snapshot_code */),
|
| + false, /* snapshot_code */
|
| + true /* vm_isolate_is_symbolic */),
|
| forward_list_(kMaxPredefinedObjectIds) {
|
| ASSERT(buffer != NULL);
|
| ASSERT(alloc != NULL);
|
| @@ -2463,8 +2678,10 @@ MessageWriter::MessageWriter(uint8_t** buffer,
|
| alloc,
|
| kInitialSize,
|
| &forward_list_,
|
| + NULL, /* instructions_writer */
|
| can_send_any_object,
|
| - false /* snapshot_code */),
|
| + false, /* snapshot_code */
|
| + true /* vm_isolate_is_symbolic */),
|
| forward_list_(kMaxPredefinedObjectIds) {
|
| ASSERT(buffer != NULL);
|
| ASSERT(alloc != NULL);
|
|
|