1 // Copyright 2019 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_HEAP_READ_ONLY_HEAP_H_ 6 #define V8_HEAP_READ_ONLY_HEAP_H_ 7 8 #include <memory> 9 #include <utility> 10 #include <vector> 11 12 #include "src/base/macros.h" 13 #include "src/base/optional.h" 14 #include "src/objects/heap-object.h" 15 #include "src/objects/objects.h" 16 #include "src/roots/roots.h" 17 18 namespace v8 { 19 20 class SharedMemoryStatistics; 21 22 namespace internal { 23 24 class BasicMemoryChunk; 25 class Isolate; 26 class Page; 27 class ReadOnlyArtifacts; 28 class ReadOnlyPage; 29 class ReadOnlySpace; 30 class SharedReadOnlySpace; 31 class SnapshotData; 32 33 // This class transparently manages read-only space, roots and cache creation 34 // and destruction. 35 class ReadOnlyHeap { 36 public: 37 static constexpr size_t kEntriesCount = 38 static_cast<size_t>(RootIndex::kReadOnlyRootsCount); 39 40 virtual ~ReadOnlyHeap() = default; 41 42 ReadOnlyHeap(const ReadOnlyHeap&) = delete; 43 ReadOnlyHeap& operator=(const ReadOnlyHeap&) = delete; 44 45 // If necessary creates read-only heap and initializes its artifacts (if the 46 // deserializer is provided). Then attaches the read-only heap to the isolate. 47 // If the deserializer is not provided, then the read-only heap will be only 48 // finish initializing when initial heap object creation in the Isolate is 49 // completed, which is signalled by calling OnCreateHeapObjectsComplete. When 50 // V8_SHARED_RO_HEAP is enabled, a lock will be held until that method is 51 // called. 52 // TODO(v8:7464): Ideally we'd create this without needing a heap. 53 static void SetUp(Isolate* isolate, SnapshotData* read_only_snapshot_data, 54 bool can_rehash); 55 // Indicates that the isolate has been set up and all read-only space objects 56 // have been created and will not be written to. This should only be called if 57 // a deserializer was not previously provided to Setup. When V8_SHARED_RO_HEAP 58 // is enabled, this releases the ReadOnlyHeap creation lock. 59 void OnCreateHeapObjectsComplete(Isolate* isolate); 60 // Indicates that the current isolate no longer requires the read-only heap 61 // and it may be safely disposed of. 62 virtual void OnHeapTearDown(Heap* heap); 63 // If the read-only heap is shared, then populate |statistics| with its stats, 64 // otherwise the read-only heap stats are set to 0. 65 static void PopulateReadOnlySpaceStatistics( 66 SharedMemoryStatistics* statistics); 67 68 // Returns whether the address is within the read-only space. 69 V8_EXPORT_PRIVATE static bool Contains(Address address); 70 // Returns whether the object resides in the read-only space. 71 V8_EXPORT_PRIVATE static bool Contains(HeapObject object); 72 // Gets read-only roots from an appropriate root list: shared read-only root 73 // list if the shared read-only heap has been initialized or the isolate 74 // specific roots table. 75 V8_EXPORT_PRIVATE inline static ReadOnlyRoots GetReadOnlyRoots( 76 HeapObject object); 77 78 // Extends the read-only object cache with new zero smi and returns a 79 // reference to it. 80 Object* ExtendReadOnlyObjectCache(); 81 // Returns a read-only cache entry at a particular index. 82 Object cached_read_only_object(size_t i) const; 83 bool read_only_object_cache_is_initialized() const; 84 size_t read_only_object_cache_size() const; 85 read_only_space()86 ReadOnlySpace* read_only_space() const { return read_only_space_; } 87 88 // Returns whether the ReadOnlySpace will actually be shared taking into 89 // account whether shared memory is available with pointer compression. IsReadOnlySpaceShared()90 static bool IsReadOnlySpaceShared() { 91 return V8_SHARED_RO_HEAP_BOOL && 92 (!COMPRESS_POINTERS_BOOL || COMPRESS_POINTERS_IN_SHARED_CAGE_BOOL); 93 } 94 InitializeIsolateRoots(Isolate * isolate)95 virtual void InitializeIsolateRoots(Isolate* isolate) {} InitializeFromIsolateRoots(Isolate * isolate)96 virtual void InitializeFromIsolateRoots(Isolate* isolate) {} IsOwnedByIsolate()97 virtual bool IsOwnedByIsolate() { return true; } 98 99 protected: 100 friend class ReadOnlyArtifacts; 101 friend class PointerCompressedReadOnlyArtifacts; 102 103 // Creates a new read-only heap and attaches it to the provided isolate. Only 104 // used the first time when creating a ReadOnlyHeap for sharing. 105 static ReadOnlyHeap* CreateInitalHeapForBootstrapping( 106 Isolate* isolate, std::shared_ptr<ReadOnlyArtifacts> artifacts); 107 // Runs the read-only deserializer and calls InitFromIsolate to complete 108 // read-only heap initialization. 109 void DeseralizeIntoIsolate(Isolate* isolate, 110 SnapshotData* read_only_snapshot_data, 111 bool can_rehash); 112 // Initializes read-only heap from an already set-up isolate, copying 113 // read-only roots from the isolate. This then seals the space off from 114 // further writes, marks it as read-only and detaches it from the heap 115 // (unless sharing is disabled). 116 void InitFromIsolate(Isolate* isolate); 117 118 bool init_complete_ = false; 119 ReadOnlySpace* read_only_space_ = nullptr; 120 std::vector<Object> read_only_object_cache_; 121 122 // Returns whether shared memory can be allocated and then remapped to 123 // additional addresses. 124 static bool IsSharedMemoryAvailable(); 125 ReadOnlyHeap(ReadOnlySpace * ro_space)126 explicit ReadOnlyHeap(ReadOnlySpace* ro_space) : read_only_space_(ro_space) {} 127 ReadOnlyHeap(ReadOnlyHeap* ro_heap, ReadOnlySpace* ro_space); 128 }; 129 130 // This is used without pointer compression when there is just a single 131 // ReadOnlyHeap object shared between all Isolates. 132 class SoleReadOnlyHeap : public ReadOnlyHeap { 133 public: 134 void InitializeIsolateRoots(Isolate* isolate) override; 135 void InitializeFromIsolateRoots(Isolate* isolate) override; 136 void OnHeapTearDown(Heap* heap) override; IsOwnedByIsolate()137 bool IsOwnedByIsolate() override { return false; } 138 139 private: 140 friend class ReadOnlyHeap; 141 SoleReadOnlyHeap(ReadOnlySpace * ro_space)142 explicit SoleReadOnlyHeap(ReadOnlySpace* ro_space) : ReadOnlyHeap(ro_space) {} 143 Address read_only_roots_[kEntriesCount]; 144 V8_EXPORT_PRIVATE static SoleReadOnlyHeap* shared_ro_heap_; 145 }; 146 147 // This class enables iterating over all read-only heap objects. 148 class V8_EXPORT_PRIVATE ReadOnlyHeapObjectIterator { 149 public: 150 explicit ReadOnlyHeapObjectIterator(const ReadOnlyHeap* ro_heap); 151 explicit ReadOnlyHeapObjectIterator(const ReadOnlySpace* ro_space); 152 153 HeapObject Next(); 154 155 private: 156 const ReadOnlySpace* const ro_space_; 157 std::vector<ReadOnlyPage*>::const_iterator current_page_; 158 Address current_addr_; 159 }; 160 161 } // namespace internal 162 } // namespace v8 163 164 #endif // V8_HEAP_READ_ONLY_HEAP_H_ 165