Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(482)

Side by Side Diff: runtime/vm/snapshot.cc

Issue 2032153003: Use clustered serialization for full snapshots. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: round2 Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/snapshot.h ('k') | runtime/vm/snapshot_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/bootstrap.h" 8 #include "vm/bootstrap.h"
9 #include "vm/class_finalizer.h" 9 #include "vm/class_finalizer.h"
10 #include "vm/dart.h" 10 #include "vm/dart.h"
(...skipping 11 matching lines...) Expand all
22 #include "vm/verified_memory.h" 22 #include "vm/verified_memory.h"
23 #include "vm/version.h" 23 #include "vm/version.h"
24 24
25 // We currently only expect the Dart mutator to read snapshots. 25 // We currently only expect the Dart mutator to read snapshots.
26 #define ASSERT_NO_SAFEPOINT_SCOPE() \ 26 #define ASSERT_NO_SAFEPOINT_SCOPE() \
27 isolate()->AssertCurrentThreadIsMutator(); \ 27 isolate()->AssertCurrentThreadIsMutator(); \
28 ASSERT(thread()->no_safepoint_scope_depth() != 0) 28 ASSERT(thread()->no_safepoint_scope_depth() != 0)
29 29
30 namespace dart { 30 namespace dart {
31 31
32 static const int kNumVmIsolateSnapshotReferences = 32 * KB;
33 static const int kNumInitialReferencesInFullSnapshot = 160 * KB;
34 static const int kNumInitialReferences = 64; 32 static const int kNumInitialReferences = 64;
35 33
36 34
37 static bool IsSingletonClassId(intptr_t class_id) { 35 static bool IsSingletonClassId(intptr_t class_id) {
38 // Check if this is a singleton object class which is shared by all isolates. 36 // Check if this is a singleton object class which is shared by all isolates.
39 return ((class_id >= kClassCid && class_id <= kUnwindErrorCid) || 37 return ((class_id >= kClassCid && class_id <= kUnwindErrorCid) ||
40 (class_id >= kNullCid && class_id <= kVoidCid)); 38 (class_id >= kNullCid && class_id <= kVoidCid));
41 } 39 }
42 40
43 41
(...skipping 535 matching lines...) Expand 10 before | Expand all | Expand 10 after
579 } 577 }
580 ~HeapLocker() { 578 ~HeapLocker() {
581 page_space_->ReleaseDataLock(); 579 page_space_->ReleaseDataLock();
582 } 580 }
583 581
584 private: 582 private:
585 PageSpace* page_space_; 583 PageSpace* page_space_;
586 }; 584 };
587 585
588 586
589 RawApiError* SnapshotReader::ReadFullSnapshot() {
590 ASSERT(Snapshot::IsFull(kind_));
591 Thread* thread = Thread::Current();
592 Isolate* isolate = thread->isolate();
593 ASSERT(isolate != NULL);
594 ObjectStore* object_store = isolate->object_store();
595 ASSERT(object_store != NULL);
596
597 // First read the version string, and check that it matches.
598 RawApiError* error = VerifyVersionAndFeatures();
599 if (error != ApiError::null()) {
600 return error;
601 }
602
603 // The version string matches. Read the rest of the snapshot.
604
605 // TODO(asiva): Add a check here to ensure we have the right heap
606 // size for the full snapshot being read.
607 {
608 NoSafepointScope no_safepoint;
609 HeapLocker hl(thread, old_space());
610
611 // Read in all the objects stored in the object store.
612 intptr_t num_flds =
613 (object_store->to_snapshot(kind_) - object_store->from());
614 for (intptr_t i = 0; i <= num_flds; i++) {
615 *(object_store->from() + i) = ReadObjectImpl(kAsInlinedObject);
616 }
617 for (intptr_t i = 0; i < backward_references_->length(); i++) {
618 if (!(*backward_references_)[i].is_deserialized()) {
619 ReadObjectImpl(kAsInlinedObject);
620 (*backward_references_)[i].set_state(kIsDeserialized);
621 }
622 }
623
624 if (kind_ == Snapshot::kAppNoJIT) {
625 ICData& ic = ICData::Handle(thread->zone());
626 Object& funcOrCode = Object::Handle(thread->zone());
627 Code& code = Code::Handle(thread->zone());
628 Smi& entry_point = Smi::Handle(thread->zone());
629 for (intptr_t i = 0; i < backward_references_->length(); i++) {
630 if ((*backward_references_)[i].reference()->IsICData()) {
631 ic ^= (*backward_references_)[i].reference()->raw();
632 for (intptr_t j = 0; j < ic.NumberOfChecks(); j++) {
633 funcOrCode = ic.GetTargetOrCodeAt(j);
634 if (funcOrCode.IsCode()) {
635 code ^= funcOrCode.raw();
636 entry_point = Smi::FromAlignedAddress(code.EntryPoint());
637 ic.SetEntryPointAt(j, entry_point);
638 }
639 }
640 }
641 }
642 }
643
644 // Validate the class table.
645 #if defined(DEBUG)
646 isolate->ValidateClassTable();
647 #endif
648
649 // Setup native resolver for bootstrap impl.
650 Bootstrap::SetupNativeResolver();
651 }
652
653 Class& cls = Class::Handle(thread->zone());
654 for (intptr_t i = 0; i < backward_references_->length(); i++) {
655 if ((*backward_references_)[i].reference()->IsClass()) {
656 cls ^= (*backward_references_)[i].reference()->raw();
657 cls.RehashConstants(thread->zone());
658 }
659 }
660
661 return ApiError::null();
662 }
663
664
665 RawObject* SnapshotReader::ReadScriptSnapshot() { 587 RawObject* SnapshotReader::ReadScriptSnapshot() {
666 ASSERT(kind_ == Snapshot::kScript); 588 ASSERT(kind_ == Snapshot::kScript);
667 589
668 // First read the version string, and check that it matches. 590 // First read the version string, and check that it matches.
669 RawApiError* error = VerifyVersionAndFeatures(); 591 RawApiError* error = VerifyVersionAndFeatures();
670 if (error != ApiError::null()) { 592 if (error != ApiError::null()) {
671 return error; 593 return error;
672 } 594 }
673 595
674 // The version string matches. Read the rest of the snapshot. 596 // The version string matches. Read the rest of the snapshot.
(...skipping 1020 matching lines...) Expand 10 before | Expand all | Expand 10 after
1695 reinterpret_cast<RawObject**>(result.raw()->ptr()); 1617 reinterpret_cast<RawObject**>(result.raw()->ptr());
1696 for (intptr_t i = 0; i < len; i++) { 1618 for (intptr_t i = 0; i < len; i++) {
1697 *PassiveObjectHandle() = ReadObjectImpl(as_reference, 1619 *PassiveObjectHandle() = ReadObjectImpl(as_reference,
1698 object_id, 1620 object_id,
1699 (i + offset)); 1621 (i + offset));
1700 result.SetAt(i, *PassiveObjectHandle()); 1622 result.SetAt(i, *PassiveObjectHandle());
1701 } 1623 }
1702 } 1624 }
1703 1625
1704 1626
1705 VmIsolateSnapshotReader::VmIsolateSnapshotReader(
1706 Snapshot::Kind kind,
1707 const uint8_t* buffer,
1708 intptr_t size,
1709 const uint8_t* instructions_buffer,
1710 const uint8_t* data_buffer,
1711 Thread* thread)
1712 : SnapshotReader(buffer,
1713 size,
1714 instructions_buffer,
1715 data_buffer,
1716 kind,
1717 new ZoneGrowableArray<BackRefNode>(
1718 kNumVmIsolateSnapshotReferences),
1719 thread) {
1720 ASSERT(Snapshot::IsFull(kind));
1721 }
1722
1723
1724 VmIsolateSnapshotReader::~VmIsolateSnapshotReader() {
1725 intptr_t len = GetBackwardReferenceTable()->length();
1726 Object::InitVmIsolateSnapshotObjectTable(len);
1727 ZoneGrowableArray<BackRefNode>* backrefs = GetBackwardReferenceTable();
1728 for (intptr_t i = 0; i < len; i++) {
1729 Object::vm_isolate_snapshot_object_table().SetAt(
1730 i, *(backrefs->At(i).reference()));
1731 }
1732 ResetBackwardReferenceTable();
1733 Dart::set_instructions_snapshot_buffer(instructions_buffer_);
1734 Dart::set_data_snapshot_buffer(data_buffer_);
1735 }
1736
1737
1738 RawApiError* VmIsolateSnapshotReader::ReadVmIsolateSnapshot() {
1739 ASSERT(Snapshot::IsFull(kind()));
1740 Thread* thread = Thread::Current();
1741 Isolate* isolate = thread->isolate();
1742 ASSERT(isolate != NULL);
1743 ASSERT(isolate == Dart::vm_isolate());
1744 ObjectStore* object_store = isolate->object_store();
1745 ASSERT(object_store != NULL);
1746
1747 // First read the version string, and check that it matches.
1748 RawApiError* error = VerifyVersionAndFeatures();
1749 if (error != ApiError::null()) {
1750 return error;
1751 }
1752
1753 // The version string matches. Read the rest of the snapshot.
1754
1755 {
1756 NoSafepointScope no_safepoint;
1757 HeapLocker hl(thread, old_space());
1758
1759 // Read in the symbol table.
1760 object_store->symbol_table_ = reinterpret_cast<RawArray*>(ReadObject());
1761
1762 Symbols::InitOnceFromSnapshot(isolate);
1763
1764 // Read in all the script objects and the accompanying token streams
1765 // for bootstrap libraries so that they are in the VM isolate's read
1766 // only memory.
1767 *(ArrayHandle()) ^= ReadObject();
1768
1769 if (Snapshot::IncludesCode(kind())) {
1770 StubCode::ReadFrom(this);
1771 }
1772
1773 // Validate the class table.
1774 #if defined(DEBUG)
1775 isolate->ValidateClassTable();
1776 #endif
1777
1778 return ApiError::null();
1779 }
1780 }
1781
1782
1783 IsolateSnapshotReader::IsolateSnapshotReader(Snapshot::Kind kind,
1784 const uint8_t* buffer,
1785 intptr_t size,
1786 const uint8_t* instructions_buffer,
1787 const uint8_t* data_buffer,
1788 Thread* thread)
1789 : SnapshotReader(buffer,
1790 size,
1791 instructions_buffer,
1792 data_buffer,
1793 kind,
1794 new ZoneGrowableArray<BackRefNode>(
1795 kNumInitialReferencesInFullSnapshot),
1796 thread) {
1797 isolate()->set_compilation_allowed(kind != Snapshot::kAppNoJIT);
1798 ASSERT(Snapshot::IsFull(kind));
1799 }
1800
1801
1802 IsolateSnapshotReader::~IsolateSnapshotReader() {
1803 ResetBackwardReferenceTable();
1804 }
1805
1806
1807 ScriptSnapshotReader::ScriptSnapshotReader(const uint8_t* buffer, 1627 ScriptSnapshotReader::ScriptSnapshotReader(const uint8_t* buffer,
1808 intptr_t size, 1628 intptr_t size,
1809 Thread* thread) 1629 Thread* thread)
1810 : SnapshotReader(buffer, 1630 : SnapshotReader(buffer,
1811 size, 1631 size,
1812 NULL, /* instructions_buffer */ 1632 NULL, /* instructions_buffer */
1813 NULL, /* data_buffer */ 1633 NULL, /* data_buffer */
1814 Snapshot::kScript, 1634 Snapshot::kScript,
1815 new ZoneGrowableArray<BackRefNode>(kNumInitialReferences), 1635 new ZoneGrowableArray<BackRefNode>(kNumInitialReferences),
1816 thread) { 1636 thread) {
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after
2032 1852
2033 intptr_t count() const { return count_; } 1853 intptr_t count() const { return count_; }
2034 1854
2035 private: 1855 private:
2036 Object& objHandle_; 1856 Object& objHandle_;
2037 intptr_t count_; 1857 intptr_t count_;
2038 const Array* scripts_; 1858 const Array* scripts_;
2039 }; 1859 };
2040 1860
2041 1861
2042 FullSnapshotWriter::FullSnapshotWriter(Snapshot::Kind kind,
2043 uint8_t** vm_isolate_snapshot_buffer,
2044 uint8_t** isolate_snapshot_buffer,
2045 ReAlloc alloc,
2046 InstructionsWriter* instructions_writer)
2047 : thread_(Thread::Current()),
2048 kind_(kind),
2049 vm_isolate_snapshot_buffer_(vm_isolate_snapshot_buffer),
2050 isolate_snapshot_buffer_(isolate_snapshot_buffer),
2051 alloc_(alloc),
2052 vm_isolate_snapshot_size_(0),
2053 isolate_snapshot_size_(0),
2054 forward_list_(NULL),
2055 instructions_writer_(instructions_writer),
2056 scripts_(Array::Handle(zone())),
2057 saved_symbol_table_(Array::Handle(zone())),
2058 new_vm_symbol_table_(Array::Handle(zone())) {
2059 ASSERT(isolate_snapshot_buffer_ != NULL);
2060 ASSERT(alloc_ != NULL);
2061 ASSERT(isolate() != NULL);
2062 ASSERT(ClassFinalizer::AllClassesFinalized());
2063 ASSERT(isolate() != NULL);
2064 ASSERT(heap() != NULL);
2065 ObjectStore* object_store = isolate()->object_store();
2066 ASSERT(object_store != NULL);
2067
2068 #if defined(DEBUG)
2069 // Ensure the class table is valid.
2070 isolate()->ValidateClassTable();
2071 #endif
2072 // Can't have any mutation happening while we're serializing.
2073 ASSERT(isolate()->background_compiler() == NULL);
2074
2075 intptr_t first_object_id = -1;
2076 if (vm_isolate_snapshot_buffer != NULL) {
2077 NOT_IN_PRODUCT(TimelineDurationScope tds(thread(),
2078 Timeline::GetIsolateStream(), "PrepareNewVMIsolate"));
2079
2080 // Collect all the script objects and their accompanying token stream
2081 // objects into an array so that we can write it out as part of the VM
2082 // isolate snapshot. We first count the number of script objects, allocate
2083 // an array and then fill it up with the script objects.
2084 ScriptVisitor scripts_counter(thread());
2085 heap()->IterateOldObjects(&scripts_counter);
2086 Dart::vm_isolate()->heap()->IterateOldObjects(&scripts_counter);
2087 intptr_t count = scripts_counter.count();
2088 scripts_ = Array::New(count, Heap::kOld);
2089 ScriptVisitor script_visitor(thread(), &scripts_);
2090 heap()->IterateOldObjects(&script_visitor);
2091 Dart::vm_isolate()->heap()->IterateOldObjects(&script_visitor);
2092 ASSERT(script_visitor.count() == count);
2093
2094 // Tuck away the current symbol table.
2095 saved_symbol_table_ = object_store->symbol_table();
2096
2097 // Create a unified symbol table that will be written as the vm isolate's
2098 // symbol table.
2099 new_vm_symbol_table_ = Symbols::UnifiedSymbolTable();
2100
2101 // Create an empty symbol table that will be written as the isolate's symbol
2102 // table.
2103 Symbols::SetupSymbolTable(isolate());
2104
2105 first_object_id = kMaxPredefinedObjectIds;
2106 } else {
2107 intptr_t max_vm_isolate_object_id =
2108 Object::vm_isolate_snapshot_object_table().Length();
2109 first_object_id = kMaxPredefinedObjectIds + max_vm_isolate_object_id;
2110 }
2111
2112 forward_list_ = new ForwardList(thread(), first_object_id);
2113 ASSERT(forward_list_ != NULL);
2114 }
2115
2116
2117 FullSnapshotWriter::~FullSnapshotWriter() {
2118 delete forward_list_;
2119 // We may run Dart code afterwards, restore the symbol table if needed.
2120 if (!saved_symbol_table_.IsNull()) {
2121 isolate()->object_store()->set_symbol_table(saved_symbol_table_);
2122 saved_symbol_table_ = Array::null();
2123 }
2124 new_vm_symbol_table_ = Array::null();
2125 scripts_ = Array::null();
2126 }
2127
2128
2129 void FullSnapshotWriter::WriteVmIsolateSnapshot() {
2130 NOT_IN_PRODUCT(TimelineDurationScope tds(thread(),
2131 Timeline::GetIsolateStream(), "WriteVmIsolateSnapshot"));
2132
2133 ASSERT(vm_isolate_snapshot_buffer_ != NULL);
2134 SnapshotWriter writer(thread(),
2135 kind_,
2136 vm_isolate_snapshot_buffer_,
2137 alloc_,
2138 kInitialSize,
2139 forward_list_,
2140 instructions_writer_,
2141 true, /* can_send_any_object */
2142 true /* writing_vm_isolate */);
2143 // Write full snapshot for the VM isolate.
2144 // Setup for long jump in case there is an exception while writing
2145 // the snapshot.
2146 LongJumpScope jump;
2147 if (setjmp(*jump.Set()) == 0) {
2148 // Reserve space in the output buffer for a snapshot header.
2149 writer.ReserveHeader();
2150
2151 // Write out the version string.
2152 writer.WriteVersionAndFeatures();
2153
2154 /*
2155 * Now Write out the following
2156 * - the symbol table
2157 * - all the scripts and token streams for these scripts
2158 * - the stub code (precompiled snapshots only)
2159 **/
2160 // Write out the symbol table.
2161 writer.WriteObject(new_vm_symbol_table_.raw());
2162
2163 // Write out all the script objects and the accompanying token streams
2164 // for the bootstrap libraries so that they are in the VM isolate
2165 // read only memory.
2166 writer.WriteObject(scripts_.raw());
2167
2168 if (Snapshot::IncludesCode(kind_)) {
2169 StubCode::WriteTo(&writer);
2170 }
2171
2172 writer.FillHeader(writer.kind());
2173
2174 vm_isolate_snapshot_size_ = writer.BytesWritten();
2175 } else {
2176 writer.ThrowException(writer.exception_type(), writer.exception_msg());
2177 }
2178 }
2179
2180
2181 void FullSnapshotWriter::WriteIsolateFullSnapshot() {
2182 NOT_IN_PRODUCT(TimelineDurationScope tds(thread(),
2183 Timeline::GetIsolateStream(), "WriteIsolateFullSnapshot"));
2184
2185 SnapshotWriter writer(thread(),
2186 kind_,
2187 isolate_snapshot_buffer_,
2188 alloc_,
2189 kInitialSize,
2190 forward_list_,
2191 instructions_writer_,
2192 true, /* can_send_any_object */
2193 false /* writing_vm_isolate */);
2194 ObjectStore* object_store = isolate()->object_store();
2195 ASSERT(object_store != NULL);
2196
2197 // Write full snapshot for a regular isolate.
2198 // Setup for long jump in case there is an exception while writing
2199 // the snapshot.
2200 LongJumpScope jump;
2201 if (setjmp(*jump.Set()) == 0) {
2202 // Reserve space in the output buffer for a snapshot header.
2203 writer.ReserveHeader();
2204
2205 // Write out the version string.
2206 writer.WriteVersionAndFeatures();
2207
2208 // Write out the full snapshot.
2209
2210 // Write out all the objects in the object store of the isolate which
2211 // is the root set for all dart allocated objects at this point.
2212 SnapshotWriterVisitor visitor(&writer, false);
2213 visitor.VisitPointers(object_store->from(),
2214 object_store->to_snapshot(kind_));
2215
2216 // Write out all forwarded objects.
2217 writer.WriteForwardedObjects();
2218
2219 writer.FillHeader(writer.kind());
2220
2221 isolate_snapshot_size_ = writer.BytesWritten();
2222 } else {
2223 writer.ThrowException(writer.exception_type(), writer.exception_msg());
2224 }
2225 }
2226
2227
2228 void FullSnapshotWriter::WriteFullSnapshot() {
2229 if (vm_isolate_snapshot_buffer() != NULL) {
2230 WriteVmIsolateSnapshot();
2231 }
2232 WriteIsolateFullSnapshot();
2233 if (Snapshot::IncludesCode(kind_)) {
2234 instructions_writer_->Write();
2235
2236 OS::Print("VMIsolate(CodeSize): %" Pd "\n", VmIsolateSnapshotSize());
2237 OS::Print("Isolate(CodeSize): %" Pd "\n", IsolateSnapshotSize());
2238 OS::Print("Instructions(CodeSize): %" Pd "\n",
2239 instructions_writer_->binary_size());
2240 intptr_t total = VmIsolateSnapshotSize() +
2241 IsolateSnapshotSize() +
2242 instructions_writer_->binary_size();
2243 OS::Print("Total(CodeSize): %" Pd "\n", total);
2244 }
2245 }
2246
2247
2248 ForwardList::ForwardList(Thread* thread, intptr_t first_object_id) 1862 ForwardList::ForwardList(Thread* thread, intptr_t first_object_id)
2249 : thread_(thread), 1863 : thread_(thread),
2250 first_object_id_(first_object_id), 1864 first_object_id_(first_object_id),
2251 nodes_(), 1865 nodes_(),
2252 first_unprocessed_object_id_(first_object_id) { 1866 first_unprocessed_object_id_(first_object_id) {
2253 ASSERT(first_object_id > 0); 1867 ASSERT(first_object_id > 0);
2254 } 1868 }
2255 1869
2256 1870
2257 ForwardList::~ForwardList() { 1871 ForwardList::~ForwardList() {
(...skipping 567 matching lines...) Expand 10 before | Expand all | Expand 10 after
2825 if (setjmp(*jump.Set()) == 0) { 2439 if (setjmp(*jump.Set()) == 0) {
2826 NoSafepointScope no_safepoint; 2440 NoSafepointScope no_safepoint;
2827 WriteObject(obj.raw()); 2441 WriteObject(obj.raw());
2828 } else { 2442 } else {
2829 ThrowException(exception_type(), exception_msg()); 2443 ThrowException(exception_type(), exception_msg());
2830 } 2444 }
2831 } 2445 }
2832 2446
2833 2447
2834 } // namespace dart 2448 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/snapshot.h ('k') | runtime/vm/snapshot_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698