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(ReadOnlyHeap* ro_heap);
151   explicit ReadOnlyHeapObjectIterator(ReadOnlySpace* ro_space);
152 
153   HeapObject Next();
154 
155  private:
156   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