summaryrefslogtreecommitdiff
path: root/deps/v8/src/heap/read-only-heap.h
blob: 33a6c4a09ee6eb8d27497ecca003d28f6b06c625 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_HEAP_READ_ONLY_HEAP_H_
#define V8_HEAP_READ_ONLY_HEAP_H_

#include <memory>
#include <utility>
#include <vector>

#include "src/base/macros.h"
#include "src/base/optional.h"
#include "src/objects/heap-object.h"
#include "src/objects/objects.h"
#include "src/roots/roots.h"

namespace v8 {

class SharedMemoryStatistics;

namespace internal {

class BasicMemoryChunk;
class Isolate;
class Page;
class ReadOnlyArtifacts;
class ReadOnlyPage;
class ReadOnlySpace;
class SharedReadOnlySpace;
class SnapshotData;

// This class transparently manages read-only space, roots and cache creation
// and destruction.
class ReadOnlyHeap {
 public:
  static constexpr size_t kEntriesCount =
      static_cast<size_t>(RootIndex::kReadOnlyRootsCount);

  virtual ~ReadOnlyHeap() = default;

  ReadOnlyHeap(const ReadOnlyHeap&) = delete;
  ReadOnlyHeap& operator=(const ReadOnlyHeap&) = delete;

  // If necessary creates read-only heap and initializes its artifacts (if the
  // deserializer is provided). Then attaches the read-only heap to the isolate.
  // If the deserializer is not provided, then the read-only heap will be only
  // finish initializing when initial heap object creation in the Isolate is
  // completed, which is signalled by calling OnCreateHeapObjectsComplete. When
  // V8_SHARED_RO_HEAP is enabled, a lock will be held until that method is
  // called.
  // TODO(v8:7464): Ideally we'd create this without needing a heap.
  static void SetUp(Isolate* isolate, SnapshotData* read_only_snapshot_data,
                    bool can_rehash);
  // Indicates that the isolate has been set up and all read-only space objects
  // have been created and will not be written to. This should only be called if
  // a deserializer was not previously provided to Setup. When V8_SHARED_RO_HEAP
  // is enabled, this releases the ReadOnlyHeap creation lock.
  void OnCreateHeapObjectsComplete(Isolate* isolate);
  // Indicates that all objects reachable by the read only roots table have been
  // set up.
  void OnCreateRootsComplete(Isolate* isolate);
  // Indicates that the current isolate no longer requires the read-only heap
  // and it may be safely disposed of.
  virtual void OnHeapTearDown(Heap* heap);
  // If the read-only heap is shared, then populate |statistics| with its stats,
  // otherwise the read-only heap stats are set to 0.
  static void PopulateReadOnlySpaceStatistics(
      SharedMemoryStatistics* statistics);

  // Returns whether the address is within the read-only space.
  V8_EXPORT_PRIVATE static bool Contains(Address address);
  // Returns whether the object resides in the read-only space.
  V8_EXPORT_PRIVATE static bool Contains(HeapObject object);
  // Gets read-only roots from an appropriate root list. Shared read only root
  // must be initialized
  V8_EXPORT_PRIVATE inline static ReadOnlyRoots GetReadOnlyRoots(
      HeapObject object);
  // Returns the current isolates roots table during initialization as opposed
  // to the shared one in case the latter is not initialized yet.
  V8_EXPORT_PRIVATE inline static ReadOnlyRoots EarlyGetReadOnlyRoots(
      HeapObject object);

  // Extends the read-only object cache with new zero smi and returns a
  // reference to it.
  Object* ExtendReadOnlyObjectCache();
  // Returns a read-only cache entry at a particular index.
  Object cached_read_only_object(size_t i) const;
  bool read_only_object_cache_is_initialized() const;
  size_t read_only_object_cache_size() const;

  ReadOnlySpace* read_only_space() const { return read_only_space_; }

  // Returns whether the ReadOnlySpace will actually be shared taking into
  // account whether shared memory is available with pointer compression.
  static constexpr bool IsReadOnlySpaceShared() {
    return V8_SHARED_RO_HEAP_BOOL &&
           (!COMPRESS_POINTERS_BOOL || COMPRESS_POINTERS_IN_SHARED_CAGE_BOOL);
  }

  virtual void InitializeIsolateRoots(Isolate* isolate) {}
  virtual void InitializeFromIsolateRoots(Isolate* isolate) {}
  virtual bool IsOwnedByIsolate() { return true; }

  bool roots_init_complete() const { return roots_init_complete_; }

 protected:
  friend class ReadOnlyArtifacts;
  friend class PointerCompressedReadOnlyArtifacts;

  // Creates a new read-only heap and attaches it to the provided isolate. Only
  // used the first time when creating a ReadOnlyHeap for sharing.
  static ReadOnlyHeap* CreateInitalHeapForBootstrapping(
      Isolate* isolate, std::shared_ptr<ReadOnlyArtifacts> artifacts);
  // Runs the read-only deserializer and calls InitFromIsolate to complete
  // read-only heap initialization.
  void DeserializeIntoIsolate(Isolate* isolate,
                              SnapshotData* read_only_snapshot_data,
                              bool can_rehash);
  // Initializes read-only heap from an already set-up isolate, copying
  // read-only roots from the isolate. This then seals the space off from
  // further writes, marks it as read-only and detaches it from the heap
  // (unless sharing is disabled).
  void InitFromIsolate(Isolate* isolate);

  bool roots_init_complete_ = false;
  ReadOnlySpace* read_only_space_ = nullptr;
  std::vector<Object> read_only_object_cache_;

  // Returns whether shared memory can be allocated and then remapped to
  // additional addresses.
  static bool IsSharedMemoryAvailable();

  explicit ReadOnlyHeap(ReadOnlySpace* ro_space) : read_only_space_(ro_space) {}
  ReadOnlyHeap(ReadOnlyHeap* ro_heap, ReadOnlySpace* ro_space);
};

// This is used without pointer compression when there is just a single
// ReadOnlyHeap object shared between all Isolates.
class SoleReadOnlyHeap : public ReadOnlyHeap {
 public:
  void InitializeIsolateRoots(Isolate* isolate) override;
  void InitializeFromIsolateRoots(Isolate* isolate) override;
  void OnHeapTearDown(Heap* heap) override;
  bool IsOwnedByIsolate() override { return false; }

 private:
  friend class ReadOnlyHeap;

  explicit SoleReadOnlyHeap(ReadOnlySpace* ro_space) : ReadOnlyHeap(ro_space) {}
  Address read_only_roots_[kEntriesCount];
  V8_EXPORT_PRIVATE static SoleReadOnlyHeap* shared_ro_heap_;
};

// This class enables iterating over all read-only heap objects.
class V8_EXPORT_PRIVATE ReadOnlyHeapObjectIterator {
 public:
  explicit ReadOnlyHeapObjectIterator(const ReadOnlyHeap* ro_heap);
  explicit ReadOnlyHeapObjectIterator(const ReadOnlySpace* ro_space);

  HeapObject Next();

 private:
  const ReadOnlySpace* const ro_space_;
  std::vector<ReadOnlyPage*>::const_iterator current_page_;
  Address current_addr_;
};

}  // namespace internal
}  // namespace v8

#endif  // V8_HEAP_READ_ONLY_HEAP_H_