| Index: runtime/vm/clustered_snapshot.cc
|
| diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
|
| index 4d4ab986aedf043973d900e3b0925433fa0e01a4..8b0cfb749a762583f85ab6453b4c8da93b43e046 100644
|
| --- a/runtime/vm/clustered_snapshot.cc
|
| +++ b/runtime/vm/clustered_snapshot.cc
|
| @@ -4786,25 +4786,35 @@ void Serializer::AddVMIsolateBaseObjects() {
|
| }
|
|
|
| intptr_t Serializer::WriteVMSnapshot(const Array& symbols,
|
| - const Array& scripts) {
|
| + ZoneGrowableArray<Object*>* seed_objects,
|
| + ZoneGrowableArray<Code*>* seed_code) {
|
| NoSafepointScope no_safepoint;
|
|
|
| AddVMIsolateBaseObjects();
|
|
|
| // Push roots.
|
| Push(symbols.raw());
|
| - Push(scripts.raw());
|
| if (Snapshot::IncludesCode(kind_)) {
|
| for (intptr_t i = 0; i < StubCode::NumEntries(); i++) {
|
| Push(StubCode::EntryAt(i)->code());
|
| }
|
| }
|
| + if (seed_objects != NULL) {
|
| + for (intptr_t i = 0; i < seed_objects->length(); i++) {
|
| + Push((*seed_objects)[i]->raw());
|
| + }
|
| + }
|
| + if (seed_code != NULL) {
|
| + for (intptr_t i = 0; i < seed_code->length(); i++) {
|
| + Code* code = (*seed_code)[i];
|
| + GetTextOffset(code->instructions(), code->raw());
|
| + }
|
| + }
|
|
|
| Serialize();
|
|
|
| // Write roots.
|
| WriteRef(symbols.raw());
|
| - WriteRef(scripts.raw());
|
| if (Snapshot::IncludesCode(kind_)) {
|
| for (intptr_t i = 0; i < StubCode::NumEntries(); i++) {
|
| WriteRef(StubCode::EntryAt(i)->code());
|
| @@ -4823,16 +4833,43 @@ intptr_t Serializer::WriteVMSnapshot(const Array& symbols,
|
| return next_ref_index_ - 1;
|
| }
|
|
|
| +// Collects Instructions from the VM isolate and adds them to object id table
|
| +// with offsets that will refer to the VM snapshot, causing them to be shared
|
| +// across isolates.
|
| +class SeedInstructionsVisitor : public ObjectVisitor {
|
| + public:
|
| + SeedInstructionsVisitor(uword text_base, Heap* heap)
|
| + : text_base_(text_base), heap_(heap) {}
|
| +
|
| + void VisitObject(RawObject* obj) {
|
| + if (obj->IsInstructions()) {
|
| + uword addr = reinterpret_cast<uword>(obj) - kHeapObjectTag;
|
| + int32_t offset = addr - text_base_;
|
| + heap_->SetObjectId(obj, -offset);
|
| + }
|
| + }
|
| +
|
| + private:
|
| + uword text_base_;
|
| + Heap* heap_;
|
| +};
|
| +
|
| void Serializer::WriteIsolateSnapshot(intptr_t num_base_objects,
|
| ObjectStore* object_store) {
|
| NoSafepointScope no_safepoint;
|
|
|
| if (num_base_objects == 0) {
|
| - // Units tests not writing a new vm isolate.
|
| + // Not writing a new vm isolate: use the one this VM was loaded from.
|
| const Array& base_objects = Object::vm_isolate_snapshot_object_table();
|
| for (intptr_t i = 1; i < base_objects.Length(); i++) {
|
| AddBaseObject(base_objects.At(i));
|
| }
|
| + const uint8_t* text_base = Dart::vm_snapshot_instructions();
|
| + if (text_base != NULL) {
|
| + SeedInstructionsVisitor visitor(reinterpret_cast<uword>(text_base),
|
| + heap_);
|
| + Dart::vm_isolate()->heap()->VisitObjectsImagePages(&visitor);
|
| + }
|
| } else {
|
| // Base objects carried over from WriteVMIsolateSnapshot.
|
| num_base_objects_ += num_base_objects;
|
| @@ -5195,7 +5232,6 @@ void Deserializer::ReadVMSnapshot() {
|
| // Read roots.
|
| symbol_table ^= ReadRef();
|
| isolate()->object_store()->set_symbol_table(symbol_table);
|
| - ReadRef(); // Script list.
|
| if (Snapshot::IncludesCode(kind_)) {
|
| Code& code = Code::Handle(zone_);
|
| for (intptr_t i = 0; i < StubCode::NumEntries(); i++) {
|
| @@ -5276,38 +5312,37 @@ void Deserializer::ReadIsolateSnapshot(ObjectStore* object_store) {
|
| Bootstrap::SetupNativeResolver();
|
| }
|
|
|
| -// An object visitor which will iterate over all the token stream objects in the
|
| -// heap and either count them or collect them into an array. This is used during
|
| -// full snapshot generation of the VM isolate to write out all token streams so
|
| -// they will be shared across all isolates.
|
| -class SnapshotTokenStreamVisitor : public ObjectVisitor {
|
| +// An object visitor which iterates the heap looking for objects to write into
|
| +// the VM isolate's snapshot, causing them to be shared across isolates.
|
| +class SeedVMIsolateVisitor : public ObjectVisitor {
|
| public:
|
| - explicit SnapshotTokenStreamVisitor(Thread* thread)
|
| - : objHandle_(Object::Handle(thread->zone())),
|
| - count_(0),
|
| - token_streams_(NULL) {}
|
| -
|
| - SnapshotTokenStreamVisitor(Thread* thread, const Array* token_streams)
|
| - : objHandle_(Object::Handle(thread->zone())),
|
| - count_(0),
|
| - token_streams_(token_streams) {}
|
| + SeedVMIsolateVisitor(Zone* zone, bool include_code)
|
| + : zone_(zone),
|
| + include_code_(include_code),
|
| + objects_(new (zone) ZoneGrowableArray<Object*>(4 * KB)),
|
| + code_(new (zone) ZoneGrowableArray<Code*>(4 * KB)) {}
|
|
|
| void VisitObject(RawObject* obj) {
|
| if (obj->IsTokenStream()) {
|
| - if (token_streams_ != NULL) {
|
| - objHandle_ = obj;
|
| - token_streams_->SetAt(count_, objHandle_);
|
| + objects_->Add(&Object::Handle(zone_, obj));
|
| + } else if (include_code_) {
|
| + if (obj->IsStackMap() || obj->IsPcDescriptors() ||
|
| + obj->IsCodeSourceMap()) {
|
| + objects_->Add(&Object::Handle(zone_, obj));
|
| + } else if (obj->IsCode()) {
|
| + code_->Add(&Code::Handle(zone_, Code::RawCast(obj)));
|
| }
|
| - count_ += 1;
|
| }
|
| }
|
|
|
| - intptr_t count() const { return count_; }
|
| + ZoneGrowableArray<Object*>* objects() { return objects_; }
|
| + ZoneGrowableArray<Code*>* code() { return code_; }
|
|
|
| private:
|
| - Object& objHandle_;
|
| - intptr_t count_;
|
| - const Array* token_streams_;
|
| + Zone* zone_;
|
| + bool include_code_;
|
| + ZoneGrowableArray<Object*>* objects_;
|
| + ZoneGrowableArray<Code*>* code_;
|
| };
|
|
|
| FullSnapshotWriter::FullSnapshotWriter(Snapshot::Kind kind,
|
| @@ -5325,7 +5360,8 @@ FullSnapshotWriter::FullSnapshotWriter(Snapshot::Kind kind,
|
| isolate_snapshot_size_(0),
|
| vm_image_writer_(vm_image_writer),
|
| isolate_image_writer_(isolate_image_writer),
|
| - token_streams_(Array::Handle(zone())),
|
| + seed_objects_(NULL),
|
| + seed_code_(NULL),
|
| saved_symbol_table_(Array::Handle(zone())),
|
| new_vm_symbol_table_(Array::Handle(zone())),
|
| clustered_vm_size_(0),
|
| @@ -5356,22 +5392,13 @@ FullSnapshotWriter::FullSnapshotWriter(Snapshot::Kind kind,
|
| NOT_IN_PRODUCT(TimelineDurationScope tds(
|
| thread(), Timeline::GetIsolateStream(), "PrepareNewVMIsolate"));
|
|
|
| - // Collect all the 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
|
| - // token streams, allocate an array and then fill it up with the token
|
| - // streams.
|
| - {
|
| - HeapIterationScope iteration(thread());
|
| - SnapshotTokenStreamVisitor token_streams_counter(thread());
|
| - iteration.IterateObjects(&token_streams_counter);
|
| - iteration.IterateVMIsolateObjects(&token_streams_counter);
|
| - intptr_t count = token_streams_counter.count();
|
| - token_streams_ = Array::New(count, Heap::kOld);
|
| - SnapshotTokenStreamVisitor script_visitor(thread(), &token_streams_);
|
| - iteration.IterateObjects(&script_visitor);
|
| - iteration.IterateVMIsolateObjects(&script_visitor);
|
| - ASSERT(script_visitor.count() == count);
|
| - }
|
| + HeapIterationScope iteration(thread());
|
| + SeedVMIsolateVisitor visitor(thread()->zone(),
|
| + Snapshot::IncludesCode(kind));
|
| + iteration.IterateObjects(&visitor);
|
| + iteration.IterateVMIsolateObjects(&visitor);
|
| + seed_objects_ = visitor.objects();
|
| + seed_code_ = visitor.code();
|
|
|
| // Tuck away the current symbol table.
|
| saved_symbol_table_ = object_store->symbol_table();
|
| @@ -5397,7 +5424,6 @@ FullSnapshotWriter::~FullSnapshotWriter() {
|
| saved_symbol_table_ = Array::null();
|
| }
|
| new_vm_symbol_table_ = Array::null();
|
| - token_streams_ = Array::null();
|
| }
|
|
|
| intptr_t FullSnapshotWriter::WriteVMSnapshot() {
|
| @@ -5414,8 +5440,8 @@ intptr_t FullSnapshotWriter::WriteVMSnapshot() {
|
| // - the symbol table
|
| // - all the token streams
|
| // - the stub code (precompiled snapshots only)
|
| - intptr_t num_objects =
|
| - serializer.WriteVMSnapshot(new_vm_symbol_table_, token_streams_);
|
| + intptr_t num_objects = serializer.WriteVMSnapshot(new_vm_symbol_table_,
|
| + seed_objects_, seed_code_);
|
| serializer.FillHeader(serializer.kind());
|
| clustered_vm_size_ = serializer.bytes_written();
|
|
|
| @@ -5520,6 +5546,7 @@ RawApiError* FullSnapshotReader::ReadVMSnapshot() {
|
| ASSERT(data_buffer_ != NULL);
|
| thread_->isolate()->SetupImagePage(data_buffer_,
|
| /* is_executable */ false);
|
| + Dart::set_vm_snapshot_instructions(instructions_buffer_);
|
| }
|
|
|
| deserializer.ReadVMSnapshot();
|
|
|