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