Index: runtime/vm/snapshot.cc |
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc |
index b62f13b31c9952a1ae3c79b0c2156e0c2fd2cfa9..810bf8e75551c0b0bcdd721cf8321a0692a479ef 100644 |
--- a/runtime/vm/snapshot.cc |
+++ b/runtime/vm/snapshot.cc |
@@ -1190,10 +1190,7 @@ RawStacktrace* SnapshotReader::NewStacktrace() { |
int32_t InstructionsWriter::GetOffsetFor(RawInstructions* instructions) { |
- // Can't use instructions->Size() because the header was mutated by the |
- // snapshot writer. |
- intptr_t heap_size = |
- Instructions::InstanceSize(instructions->ptr()->size_); |
+ intptr_t heap_size = instructions->Size(); |
intptr_t offset = next_offset_; |
next_offset_ += heap_size; |
instructions_.Add(InstructionsData(instructions)); |
@@ -1669,6 +1666,7 @@ MessageSnapshotReader::~MessageSnapshotReader() { |
SnapshotWriter::SnapshotWriter(Snapshot::Kind kind, |
+ Thread* thread, |
uint8_t** buffer, |
ReAlloc alloc, |
intptr_t initial_size, |
@@ -1679,9 +1677,9 @@ SnapshotWriter::SnapshotWriter(Snapshot::Kind kind, |
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()), |
+ thread_(thread), |
+ object_store_(isolate()->object_store()), |
+ class_table_(isolate()->class_table()), |
forward_list_(forward_list), |
instructions_writer_(instructions_writer), |
exception_type_(Exceptions::kNone), |
@@ -1699,6 +1697,12 @@ void SnapshotWriter::WriteObject(RawObject* rawobj) { |
WriteForwardedObjects(); |
} |
+ |
+uword SnapshotWriter::GetObjectTags(RawObject* raw) { |
+ return raw->ptr()->tags_; |
+} |
+ |
+ |
#define VM_OBJECT_CLASS_LIST(V) \ |
V(OneByteString) \ |
V(Mint) \ |
@@ -1708,7 +1712,7 @@ void SnapshotWriter::WriteObject(RawObject* rawobj) { |
#define VM_OBJECT_WRITE(clazz) \ |
case clazz::kClassId: { \ |
- object_id = forward_list_->AddObject(rawobj, kIsSerialized); \ |
+ object_id = forward_list_->AddObject(zone(), rawobj, kIsSerialized); \ |
Raw##clazz* raw_obj = reinterpret_cast<Raw##clazz*>(rawobj); \ |
raw_obj->WriteTo(this, object_id, kind(), false); \ |
return true; \ |
@@ -1792,7 +1796,7 @@ bool SnapshotWriter::HandleVMIsolateObject(RawObject* rawobj) { |
switch (id) { |
VM_OBJECT_CLASS_LIST(VM_OBJECT_WRITE) |
case kTypedDataUint32ArrayCid: { |
- object_id = forward_list_->AddObject(rawobj, kIsSerialized); |
+ object_id = forward_list_->AddObject(zone(), rawobj, kIsSerialized); |
RawTypedData* raw_obj = reinterpret_cast<RawTypedData*>(rawobj); |
raw_obj->WriteTo(this, object_id, kind(), false); |
return true; |
@@ -1859,7 +1863,7 @@ FullSnapshotWriter::FullSnapshotWriter(uint8_t** vm_isolate_snapshot_buffer, |
ReAlloc alloc, |
bool snapshot_code, |
bool vm_isolate_is_symbolic) |
- : isolate_(Isolate::Current()), |
+ : thread_(Thread::Current()), |
vm_isolate_snapshot_buffer_(vm_isolate_snapshot_buffer), |
isolate_snapshot_buffer_(isolate_snapshot_buffer), |
instructions_snapshot_buffer_(instructions_snapshot_buffer), |
@@ -1869,42 +1873,41 @@ FullSnapshotWriter::FullSnapshotWriter(uint8_t** vm_isolate_snapshot_buffer, |
instructions_snapshot_size_(0), |
forward_list_(NULL), |
instructions_writer_(NULL), |
- scripts_(Array::Handle(isolate_->current_zone())), |
- symbol_table_(Array::Handle(isolate_->current_zone())), |
+ scripts_(Array::Handle(zone())), |
+ symbol_table_(Array::Handle(zone())), |
snapshot_code_(snapshot_code), |
vm_isolate_is_symbolic_(vm_isolate_is_symbolic) { |
ASSERT(isolate_snapshot_buffer_ != NULL); |
ASSERT(alloc_ != NULL); |
- ASSERT(isolate_ != NULL); |
+ ASSERT(isolate() != NULL); |
ASSERT(ClassFinalizer::AllClassesFinalized()); |
- ObjectStore* object_store = isolate_->object_store(); |
+ ASSERT(isolate() != NULL); |
+ ASSERT(heap() != NULL); |
+ ObjectStore* object_store = isolate()->object_store(); |
ASSERT(object_store != NULL); |
- Heap* heap = isolate_->heap(); |
- ASSERT(heap != NULL); |
// Ensure the class table is valid. |
#if defined(DEBUG) |
- isolate_->ValidateClassTable(); |
+ isolate()->ValidateClassTable(); |
#endif |
// Collect all the script objects and their accompanying token stream objects |
// into an array so that we can write it out as part of the VM isolate |
// snapshot. We first count the number of script objects, allocate an array |
// and then fill it up with the script objects. |
- ASSERT(isolate_ != NULL); |
- ScriptVisitor scripts_counter(isolate_); |
- heap->IterateOldObjects(&scripts_counter); |
+ ScriptVisitor scripts_counter(isolate()); |
+ heap()->IterateOldObjects(&scripts_counter); |
intptr_t count = scripts_counter.count(); |
scripts_ = Array::New(count, Heap::kOld); |
- ScriptVisitor script_visitor(isolate_, &scripts_); |
- heap->IterateOldObjects(&script_visitor); |
+ ScriptVisitor script_visitor(isolate(), &scripts_); |
+ heap()->IterateOldObjects(&script_visitor); |
// Stash the symbol table away for writing and reading into the vm isolate, |
// 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. |
symbol_table_ = object_store->symbol_table(); |
- Symbols::SetupSymbolTable(isolate_); |
+ Symbols::SetupSymbolTable(isolate()); |
- forward_list_ = new ForwardList(SnapshotWriter::FirstObjectId()); |
+ forward_list_ = new ForwardList(thread(), SnapshotWriter::FirstObjectId()); |
ASSERT(forward_list_ != NULL); |
if (instructions_snapshot_buffer != NULL) { |
@@ -1925,6 +1928,7 @@ FullSnapshotWriter::~FullSnapshotWriter() { |
void FullSnapshotWriter::WriteVmIsolateSnapshot() { |
ASSERT(vm_isolate_snapshot_buffer_ != NULL); |
SnapshotWriter writer(Snapshot::kFull, |
+ thread(), |
vm_isolate_snapshot_buffer_, |
alloc_, |
kInitialSize, |
@@ -1975,6 +1979,7 @@ void FullSnapshotWriter::WriteVmIsolateSnapshot() { |
void FullSnapshotWriter::WriteIsolateFullSnapshot() { |
SnapshotWriter writer(Snapshot::kFull, |
+ thread(), |
isolate_snapshot_buffer_, |
alloc_, |
kInitialSize, |
@@ -1983,7 +1988,7 @@ void FullSnapshotWriter::WriteIsolateFullSnapshot() { |
true, /* can_send_any_object */ |
snapshot_code_, |
true /* vm_isolate_is_symbolic */); |
- ObjectStore* object_store = isolate_->object_store(); |
+ ObjectStore* object_store = isolate()->object_store(); |
ASSERT(object_store != NULL); |
// Write full snapshot for a regular isolate. |
@@ -2010,7 +2015,6 @@ void FullSnapshotWriter::WriteIsolateFullSnapshot() { |
writer.WriteForwardedObjects(); |
writer.FillHeader(writer.kind()); |
- writer.UnmarkAll(); |
isolate_snapshot_size_ = writer.BytesWritten(); |
} else { |
@@ -2020,22 +2024,13 @@ void FullSnapshotWriter::WriteIsolateFullSnapshot() { |
void FullSnapshotWriter::WriteFullSnapshot() { |
- 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(); |
- |
+ if (vm_isolate_snapshot_buffer() != NULL) { |
+ WriteVmIsolateSnapshot(); |
+ } |
+ WriteIsolateFullSnapshot(); |
+ if (snapshot_code_) { |
instructions_writer_->WriteAssembly(); |
instructions_snapshot_size_ = instructions_writer_->BytesWritten(); |
- } else { |
- if (vm_isolate_snapshot_buffer() != NULL) { |
- WriteVmIsolateSnapshot(); |
- } |
- WriteIsolateFullSnapshot(); |
} |
} |
@@ -2057,106 +2052,42 @@ PrecompiledSnapshotWriter::PrecompiledSnapshotWriter( |
PrecompiledSnapshotWriter::~PrecompiledSnapshotWriter() {} |
-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(); |
- } else { |
- return tags; |
- } |
-} |
- |
- |
-intptr_t SnapshotWriter::GetObjectId(RawObject* raw) { |
- uword tags = raw->ptr()->tags_; |
- ASSERT(SerializedHeaderTag::decode(tags) == kObjectId); |
- return SerializedHeaderData::decode(tags); |
-} |
- |
- |
-ForwardList::ForwardList(intptr_t first_object_id) |
- : first_object_id_(first_object_id), |
+ForwardList::ForwardList(Thread* thread, intptr_t first_object_id) |
+ : thread_(thread), |
+ first_object_id_(first_object_id), |
nodes_(), |
first_unprocessed_object_id_(first_object_id) { |
- // The ForwardList encodes information in the header tag word. There cannot |
- // be any concurrent GC tasks while it is in use. |
- Thread* thread = Thread::Current(); |
- Isolate* isolate = thread->isolate(); |
- PageSpace* page_space = isolate->heap()->old_space(); |
- MonitorLocker ml(page_space->tasks_lock()); |
- while (page_space->tasks() > 0) { |
- ml.Wait(); |
- } |
- // Ensure that no GC happens while we are writing out the full snapshot. |
- thread->IncrementNoSafepointScopeDepth(); |
} |
ForwardList::~ForwardList() { |
+ heap()->ResetObjectIdTable(); |
} |
-intptr_t ForwardList::MarkAndAddObject(RawObject* raw, SerializeState state) { |
+intptr_t ForwardList::AddObject(Zone* zone, |
+ RawObject* raw, |
+ SerializeState state) { |
NoSafepointScope no_safepoint; |
intptr_t object_id = next_object_id(); |
ASSERT(object_id > 0 && object_id <= kMaxObjectId); |
- uword value = 0; |
- value = SerializedHeaderTag::update(kObjectId, value); |
- value = SerializedHeaderData::update(object_id, value); |
- uword tags = raw->ptr()->tags_; |
- ASSERT(SerializedHeaderTag::decode(tags) != kObjectId); |
- raw->ptr()->tags_ = value; |
- Node* node = new Node(raw, tags, state); |
- ASSERT(node != NULL); |
- nodes_.Add(node); |
- return object_id; |
-} |
- |
- |
-intptr_t ForwardList::AddObject(RawObject* raw, SerializeState state) { |
- NoSafepointScope no_safepoint; |
- intptr_t object_id = next_object_id(); |
- ASSERT(object_id > 0 && object_id <= kMaxObjectId); |
- uword tags = raw->ptr()->tags_; |
- ASSERT(SerializedHeaderTag::decode(tags) != kObjectId); |
- Node* node = new Node(raw, tags, state); |
+ const Object& obj = Object::ZoneHandle(zone, raw); |
+ Node* node = new Node(&obj, state); |
ASSERT(node != NULL); |
nodes_.Add(node); |
+ ASSERT(SnapshotWriter::FirstObjectId() > 0); |
+ ASSERT(object_id != 0); |
+ heap()->SetObjectId(raw, object_id); |
return object_id; |
} |
intptr_t ForwardList::FindObject(RawObject* raw) { |
NoSafepointScope no_safepoint; |
- intptr_t id; |
- for (id = first_object_id(); id < next_object_id(); ++id) { |
- const Node* node = NodeForObjectId(id); |
- if (raw == node->raw()) { |
- return id; |
- } |
- } |
- return kInvalidIndex; |
-} |
- |
- |
-void ForwardList::UnmarkAll() const { |
- for (intptr_t id = first_object_id(); id < next_object_id(); ++id) { |
- const Node* node = NodeForObjectId(id); |
- RawObject* raw = node->raw(); |
- if (SerializedHeaderTag::decode(raw->ptr()->tags_) == kObjectId) { |
- raw->ptr()->tags_ = node->tags(); // Restore original tags. |
- } |
- } |
- Thread::Current()->DecrementNoSafepointScopeDepth(); |
-} |
- |
- |
-void ForwardList::SetState(RawObject* raw, SerializeState state) { |
- uword tags = raw->ptr()->tags_; |
- ASSERT(SerializedHeaderTag::decode(tags) == kObjectId); |
- intptr_t id = SerializedHeaderData::decode(tags); |
- NodeForObjectId(id)->set_state(state); |
+ ASSERT(SnapshotWriter::FirstObjectId() > 0); |
+ intptr_t id = heap()->GetObjectId(raw); |
+ ASSERT(id == 0 || NodeForObjectId(id)->obj()->raw() == raw); |
+ return (id == 0) ? kInvalidIndex : id; |
} |
@@ -2185,10 +2116,9 @@ bool SnapshotWriter::CheckAndWritePredefinedObject(RawObject* rawobj) { |
// Check if object has already been serialized, in that case just write |
// the object id out. |
- uword tags = rawobj->ptr()->tags_; |
- if (SerializedHeaderTag::decode(tags) == kObjectId) { |
- intptr_t id = SerializedHeaderData::decode(tags); |
- WriteIndexedObject(id); |
+ intptr_t object_id = forward_list_->FindObject(rawobj); |
+ if (object_id != kInvalidIndex) { |
+ WriteIndexedObject(object_id); |
return true; |
} |
@@ -2241,7 +2171,7 @@ void SnapshotWriter::WriteObjectImpl(RawObject* raw, bool as_reference) { |
// When we know that we are dealing with leaf or shallow objects we write |
// these objects inline even when 'as_reference' is true. |
- bool write_as_reference = as_reference && !raw->IsCanonical(); |
+ const bool write_as_reference = as_reference && !raw->IsCanonical(); |
intptr_t tags = raw->ptr()->tags_; |
// Add object to the forward ref list and mark it so that future references |
@@ -2249,17 +2179,14 @@ void SnapshotWriter::WriteObjectImpl(RawObject* raw, bool as_reference) { |
// serialization state so that we do the right thing when we go through |
// the forward list. |
intptr_t class_id = raw->GetClassId(); |
+ intptr_t object_id; |
if (write_as_reference && IsSplitClassId(class_id)) { |
- forward_list_->MarkAndAddObject(raw, kIsNotSerialized); |
+ object_id = forward_list_->AddObject(zone(), raw, kIsNotSerialized); |
} else { |
- forward_list_->MarkAndAddObject(raw, kIsSerialized); |
+ object_id = forward_list_->AddObject(zone(), raw, kIsSerialized); |
} |
- intptr_t object_id; |
if (write_as_reference || !IsSplitClassId(class_id)) { |
object_id = kOmittedObjectId; |
- } else { |
- ASSERT(SerializedHeaderTag::decode(raw->ptr()->tags_) == kObjectId); |
- object_id = SerializedHeaderData::decode(raw->ptr()->tags_); |
} |
WriteMarkedObjectImpl(raw, tags, object_id, write_as_reference); |
} |
@@ -2278,7 +2205,6 @@ void SnapshotWriter::WriteMarkedObjectImpl(RawObject* raw, |
WriteInstance(raw, cls, tags, object_id, as_reference); |
return; |
} |
- |
switch (class_id) { |
#define SNAPSHOT_WRITE(clazz) \ |
case clazz::kClassId: { \ |
@@ -2322,7 +2248,8 @@ class WriteInlinedObjectVisitor : public ObjectVisitor { |
: ObjectVisitor(Isolate::Current()), writer_(writer) {} |
virtual void VisitObject(RawObject* obj) { |
- intptr_t object_id = writer_->GetObjectId(obj); |
+ intptr_t object_id = writer_->forward_list_->FindObject(obj); |
+ ASSERT(object_id != kInvalidIndex); |
intptr_t tags = writer_->GetObjectTags(obj); |
writer_->WriteMarkedObjectImpl(obj, tags, object_id, kAsInlinedObject); |
} |
@@ -2354,7 +2281,7 @@ void ForwardList::SerializeAll(ObjectVisitor* writer) { |
++id) { |
if (!NodeForObjectId(id)->is_serialized()) { |
// Write the object out in the stream. |
- RawObject* raw = NodeForObjectId(id)->raw(); |
+ RawObject* raw = NodeForObjectId(id)->obj()->raw(); |
writer->VisitObject(raw); |
// Mark object as serialized. |
@@ -2481,7 +2408,6 @@ RawFunction* SnapshotWriter::IsSerializableClosure(RawClass* cls, |
ASSERT(!errorFunc.IsNull()); |
// All other closures are errors. |
- UnmarkAll(); // Unmark objects now as we are about to print stuff. |
char* chars = OS::SCreate(thread()->zone(), |
"Illegal argument in isolate message : (object is a closure - %s %s)", |
clazz.ToCString(), errorFunc.ToCString()); |
@@ -2507,7 +2433,6 @@ void SnapshotWriter::CheckForNativeFields(RawClass* cls) { |
if (cls->ptr()->num_native_fields_ != 0) { |
// We do not allow objects with native fields in an isolate message. |
HANDLESCOPE(thread()); |
- UnmarkAll(); // Unmark objects now as we are about to print stuff. |
const Class& clazz = Class::Handle(zone(), cls); |
char* chars = OS::SCreate(thread()->zone(), |
"Illegal argument in isolate message" |
@@ -2541,7 +2466,7 @@ void SnapshotWriter::WriteInstance(RawObject* raw, |
// closure that is not serializable this will throw an exception. |
RawFunction* func = IsSerializableClosure(cls, raw); |
if (func != Function::null()) { |
- forward_list_->SetState(raw, kIsSerialized); |
+ forward_list_->SetState(object_id, kIsSerialized); |
WriteStaticImplicitClosure(object_id, func, tags); |
return; |
} |
@@ -2559,8 +2484,6 @@ void SnapshotWriter::WriteInstance(RawObject* raw, |
// Write out the class information for this object. |
WriteObjectImpl(cls, kAsInlinedObject); |
} else { |
- ASSERT(SerializedHeaderTag::decode(raw->ptr()->tags_) == kObjectId); |
- ASSERT(object_id == SerializedHeaderData::decode(raw->ptr()->tags_)); |
intptr_t next_field_offset = Class::IsSignatureClass(cls) ? |
Closure::InstanceSize() : |
cls->ptr()->next_field_offset_in_words_ << kWordSizeLog2; |
@@ -2615,7 +2538,6 @@ intptr_t SnapshotWriter::FindVmSnapshotObject(RawObject* rawobj) { |
void SnapshotWriter::ThrowException(Exceptions::ExceptionType type, |
const char* msg) { |
object_store()->clear_sticky_error(); |
- UnmarkAll(); |
if (msg != NULL) { |
const String& msg_obj = String::Handle(String::New(msg)); |
const Array& args = Array::Handle(Array::New(1)); |
@@ -2646,6 +2568,7 @@ intptr_t SnapshotWriter::FirstObjectId() { |
ScriptSnapshotWriter::ScriptSnapshotWriter(uint8_t** buffer, |
ReAlloc alloc) |
: SnapshotWriter(Snapshot::kScript, |
+ Thread::Current(), |
buffer, |
alloc, |
kInitialSize, |
@@ -2654,7 +2577,7 @@ ScriptSnapshotWriter::ScriptSnapshotWriter(uint8_t** buffer, |
true, /* can_send_any_object */ |
false, /* snapshot_code */ |
true /* vm_isolate_is_symbolic */), |
- forward_list_(kMaxPredefinedObjectIds) { |
+ forward_list_(thread(), kMaxPredefinedObjectIds) { |
ASSERT(buffer != NULL); |
ASSERT(alloc != NULL); |
} |
@@ -2683,7 +2606,6 @@ void ScriptSnapshotWriter::WriteScriptSnapshot(const Library& lib) { |
WriteObject(lib.raw()); |
FillHeader(kind()); |
- UnmarkAll(); |
} |
} else { |
ThrowException(exception_type(), exception_msg()); |
@@ -2703,6 +2625,7 @@ MessageWriter::MessageWriter(uint8_t** buffer, |
ReAlloc alloc, |
bool can_send_any_object) |
: SnapshotWriter(Snapshot::kMessage, |
+ Thread::Current(), |
buffer, |
alloc, |
kInitialSize, |
@@ -2711,7 +2634,7 @@ MessageWriter::MessageWriter(uint8_t** buffer, |
can_send_any_object, |
false, /* snapshot_code */ |
true /* vm_isolate_is_symbolic */), |
- forward_list_(kMaxPredefinedObjectIds) { |
+ forward_list_(thread(), kMaxPredefinedObjectIds) { |
ASSERT(buffer != NULL); |
ASSERT(alloc != NULL); |
} |
@@ -2727,7 +2650,6 @@ void MessageWriter::WriteMessage(const Object& obj) { |
if (setjmp(*jump.Set()) == 0) { |
NoSafepointScope no_safepoint; |
WriteObject(obj.raw()); |
- UnmarkAll(); |
} else { |
ThrowException(exception_type(), exception_msg()); |
} |