v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
read-only-heap.cc
Go to the documentation of this file.
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
6
7#include <cstddef>
8#include <cstring>
9
10#include "src/common/globals.h"
19#include "src/objects/smi.h"
23
24namespace v8 {
25namespace internal {
26
28#ifdef V8_ENABLE_SANDBOX
29 IsolateGroup::current()->code_pointer_table()->TearDownSpace(
30 &code_pointer_space_);
31#endif
32#ifdef V8_ENABLE_LEAPTIERING
33 JSDispatchTable* jdt = IsolateGroup::current()->js_dispatch_table();
34#if V8_STATIC_DISPATCH_HANDLES_BOOL
35 jdt->DetachSpaceFromReadOnlySegment(&js_dispatch_table_space_);
36#endif // V8_STATIC_DISPATCH_HANDLES_BOOL
37 jdt->TearDownSpace(&js_dispatch_table_space_);
38#endif
39}
40
41// static
43 SnapshotData* read_only_snapshot_data,
44 bool can_rehash) {
45 DCHECK_NOT_NULL(isolate);
46 IsolateGroup* group = isolate->isolate_group();
47 group->mutex()->AssertHeld();
48 if (read_only_snapshot_data != nullptr) {
49 bool read_only_heap_created = false;
50 ReadOnlyArtifacts* artifacts = group->read_only_artifacts();
51 if (!artifacts) {
52 artifacts = group->InitializeReadOnlyArtifacts();
53 artifacts->InitializeChecksum(read_only_snapshot_data);
54 CreateInitialHeapForBootstrapping(isolate, artifacts);
56 isolate, read_only_snapshot_data, can_rehash);
57 artifacts->set_initial_next_unique_sfi_id(isolate->next_unique_sfi_id());
58 read_only_heap_created = true;
59 } else {
60 isolate->SetUpFromReadOnlyArtifacts(artifacts);
61#ifdef V8_COMPRESS_POINTERS
62 isolate->external_pointer_table().SetUpFromReadOnlyArtifacts(
63 isolate->heap()->read_only_external_pointer_space(), artifacts);
64#endif // V8_COMPRESS_POINTERS
65 }
66 artifacts->VerifyChecksum(read_only_snapshot_data, read_only_heap_created);
67 artifacts->read_only_heap()->InitializeIsolateRoots(isolate);
68 } else {
69 // This path should only be taken in mksnapshot, should only be run once
70 // before tearing down the Isolate that holds this ReadOnlyArtifacts and
71 // is not thread-safe.
72 ReadOnlyArtifacts* artifacts = group->read_only_artifacts();
73 CHECK(!artifacts);
74 artifacts = group->InitializeReadOnlyArtifacts();
75 CreateInitialHeapForBootstrapping(isolate, artifacts);
76
77 // Ensure the first read-only page ends up first in the cage.
78 artifacts->read_only_heap()->read_only_space()->EnsurePage();
79 artifacts->VerifyChecksum(read_only_snapshot_data, true);
80 }
81}
82
84 SnapshotData* read_only_snapshot_data,
85 bool can_rehash) {
86 DCHECK_NOT_NULL(read_only_snapshot_data);
87
88 ReadOnlyDeserializer des(isolate, read_only_snapshot_data, can_rehash);
90 OnCreateRootsComplete(isolate);
91
92 if (V8_UNLIKELY(v8_flags.extensible_ro_snapshot &&
93 isolate->serializer_enabled())) {
94 // If this isolate will be serialized, leave RO space unfinalized and
95 // allocatable s.t. it can be extended (e.g. by future Context::New calls).
96 // We reach this scenario when creating custom snapshots - these initially
97 // create the isolate from the default V8 snapshot, create new customized
98 // contexts, and finally reserialize.
99 } else {
100 InitFromIsolate(isolate);
101 }
102}
103
110
112 DCHECK_NOT_NULL(isolate);
113
114 // InitFromIsolate mutates MemoryChunk flags which would race with any
115 // concurrently-running sweeper tasks. Ensure that sweeping has been
116 // completed, i.e. no sweeper tasks are currently running.
117 isolate->heap()->EnsureSweepingCompleted(
118 Heap::SweepingForcedFinalizationMode::kV8Only);
119
120 InitFromIsolate(isolate);
121
122#ifdef VERIFY_HEAP
123 if (v8_flags.verify_heap) {
124 HeapVerifier::VerifyReadOnlyHeap(isolate->heap());
125 HeapVerifier::VerifyHeap(isolate->heap());
126 }
127#endif
128}
129
130// static
132 Isolate* isolate, ReadOnlyArtifacts* artifacts) {
133 ReadOnlySpace* ro_space = new ReadOnlySpace(isolate->heap());
134 std::unique_ptr<ReadOnlyHeap> shared_ro_heap(new ReadOnlyHeap(ro_space));
135 isolate->isolate_group()->set_shared_read_only_heap(shared_ro_heap.get());
136 artifacts->set_read_only_heap(std::move(shared_ro_heap));
137 isolate->SetUpFromReadOnlyArtifacts(artifacts);
138}
139
141 void* const isolate_ro_roots =
142 isolate->roots_table().read_only_roots_begin().location();
143 std::memcpy(isolate_ro_roots, read_only_roots_,
144 kEntriesCount * sizeof(Address));
145}
146
148 void* const isolate_ro_roots =
149 isolate->roots_table().read_only_roots_begin().location();
150 std::memcpy(read_only_roots_, isolate_ro_roots,
151 kEntriesCount * sizeof(Address));
152}
153
157 ReadOnlyArtifacts* artifacts =
158 isolate->isolate_group()->read_only_artifacts();
160 artifacts->ReinstallReadOnlySpace(isolate);
161
163
164#ifdef DEBUG
165 artifacts->VerifyHeapAndSpaceRelationships(isolate);
166#endif
167}
168
170 : read_only_space_(ro_space) {
171#ifdef V8_ENABLE_SANDBOX
172 IsolateGroup::current()->code_pointer_table()->InitializeSpace(
173 &code_pointer_space_);
174#endif // V8_ENABLE_SANDBOX
175#ifdef V8_ENABLE_LEAPTIERING
176 JSDispatchTable* jdt = IsolateGroup::current()->js_dispatch_table();
177 jdt->InitializeSpace(&js_dispatch_table_space_);
178 // To avoid marking trying to write to these read-only cells they are
179 // allocated black. Target code objects in the read-only dispatch table are
180 // read-only code objects.
181 js_dispatch_table_space_.set_allocate_black(true);
182#if V8_STATIC_DISPATCH_HANDLES_BOOL
183 jdt->AttachSpaceToReadOnlySegment(&js_dispatch_table_space_);
184 jdt->PreAllocateEntries(&js_dispatch_table_space_,
185 JSBuiltinDispatchHandleRoot::kCount, true);
186#endif // V8_STATIC_DISPATCH_HANDLES_BOOL
187#endif // V8_ENABLE_LEAPTIERING
188}
189
190// static
192 SharedMemoryStatistics* statistics) {
193 statistics->read_only_space_size_ = 0;
194 statistics->read_only_space_used_size_ = 0;
195 statistics->read_only_space_physical_size_ = 0;
197 if (artifacts) {
198 SharedReadOnlySpace* ro_space = artifacts->shared_read_only_space();
199 statistics->read_only_space_size_ = ro_space->CommittedMemory();
200 statistics->read_only_space_used_size_ = ro_space->Size();
201 statistics->read_only_space_physical_size_ =
202 ro_space->CommittedPhysicalMemory();
203 }
204}
205
206// static
208 return MemoryChunk::FromAddress(address)->InReadOnlySpace();
209}
210
211// static
213 return Contains(object.address());
214}
215
216// static
218#ifdef V8_ENABLE_SANDBOX
219 return MemoryChunk::FromHeapObject(object)->SandboxSafeInReadOnlySpace();
220#else
221 return Contains(object);
222#endif
223}
224
228
230 const ReadOnlySpace* ro_space)
231 : ro_space_(ro_space),
232 current_page_(ro_space->pages().begin()),
233 page_iterator_(
234 current_page_ == ro_space->pages().end() ? nullptr : *current_page_) {
235}
236
238 while (current_page_ != ro_space_->pages().end()) {
240 if (!obj.is_null()) return obj;
241
243 if (current_page_ == ro_space_->pages().end()) return Tagged<HeapObject>();
245 }
246
247 DCHECK_EQ(current_page_, ro_space_->pages().end());
248 return Tagged<HeapObject>();
249}
250
252 const ReadOnlyPageMetadata* page,
253 SkipFreeSpaceOrFiller skip_free_space_or_filler)
255 page, page == nullptr ? kNullAddress : page->GetAreaStart(),
256 skip_free_space_or_filler) {}
257
259 const ReadOnlyPageMetadata* page, Address current_addr,
260 SkipFreeSpaceOrFiller skip_free_space_or_filler)
261 : page_(page),
262 current_addr_(current_addr),
263 skip_free_space_or_filler_(skip_free_space_or_filler) {
264 DCHECK_GE(current_addr, page->GetAreaStart());
265 DCHECK_LT(current_addr, page->GetAreaStart() + page->area_size());
266}
267
269 if (page_ == nullptr) return HeapObject();
270
271 Address end = page_->GetAreaStart() + page_->area_size();
272 for (;;) {
274 if (current_addr_ == end) return HeapObject();
275
277 const int object_size = object->Size();
279
281 IsFreeSpaceOrFiller(object)) {
282 continue;
283 }
284
285 DCHECK_OBJECT_SIZE(object_size);
286 return object;
287 }
288}
289
291 page_ = page;
292 current_addr_ = page->GetAreaStart();
293}
294
295} // namespace internal
296} // namespace v8
V8_INLINE void AssertHeld() const
Definition mutex.h:58
virtual size_t CommittedMemory() const
Definition base-space.h:36
static Tagged< HeapObject > FromAddress(Address address)
static void VerifyReadOnlyHeap(Heap *heap)
static void VerifyHeap(Heap *heap)
static IsolateGroup * current()
ReadOnlyArtifacts * read_only_artifacts()
ReadOnlyArtifacts * InitializeReadOnlyArtifacts()
static V8_INLINE MemoryChunk * FromAddress(Address addr)
static V8_INLINE MemoryChunk * FromHeapObject(Tagged< HeapObject > object)
V8_INLINE bool InReadOnlySpace() const
ReadOnlyHeap * read_only_heap() const
void ReinstallReadOnlySpace(Isolate *isolate)
void InitializeChecksum(SnapshotData *read_only_snapshot_data)
void VerifyChecksum(SnapshotData *read_only_snapshot_data, bool read_only_heap_created)
void set_initial_next_unique_sfi_id(uint32_t id)
void set_read_only_heap(std::unique_ptr< ReadOnlyHeap > read_only_heap)
void VerifyHeapAndSpaceRelationships(Isolate *isolate)
SharedReadOnlySpace * shared_read_only_space()
std::vector< ReadOnlyPageMetadata * >::const_iterator current_page_
ReadOnlyPageObjectIterator page_iterator_
ReadOnlyHeapObjectIterator(const ReadOnlyHeap *ro_heap)
static void PopulateReadOnlySpaceStatistics(SharedMemoryStatistics *statistics)
void DeserializeIntoIsolate(Isolate *isolate, SnapshotData *read_only_snapshot_data, bool can_rehash)
static V8_EXPORT_PRIVATE bool Contains(Address address)
void InitializeFromIsolateRoots(Isolate *isolate)
Address read_only_roots_[kEntriesCount]
static constexpr size_t kEntriesCount
static V8_EXPORT_PRIVATE bool SandboxSafeContains(Tagged< HeapObject > object)
static void SetUp(Isolate *isolate, SnapshotData *read_only_snapshot_data, bool can_rehash)
V8_EXPORT_PRIVATE void OnCreateHeapObjectsComplete(Isolate *isolate)
ReadOnlySpace * read_only_space_
void InitFromIsolate(Isolate *isolate)
void InitializeIsolateRoots(Isolate *isolate)
ReadOnlyHeap(ReadOnlySpace *ro_space)
static void CreateInitialHeapForBootstrapping(Isolate *isolate, ReadOnlyArtifacts *artifacts)
void OnCreateRootsComplete(Isolate *isolate)
ReadOnlySpace * read_only_space() const
const SkipFreeSpaceOrFiller skip_free_space_or_filler_
const ReadOnlyPageMetadata * page_
ReadOnlyPageObjectIterator(const ReadOnlyPageMetadata *page, SkipFreeSpaceOrFiller skip_free_space_or_filler=SkipFreeSpaceOrFiller::kYes)
void Reset(const ReadOnlyPageMetadata *page)
V8_EXPORT_PRIVATE void ShrinkPages()
size_t Size() const override
V8_EXPORT_PRIVATE size_t CommittedPhysicalMemory() const override
void DetachPagesAndAddToArtifacts(ReadOnlyArtifacts *artifacts)
V8_INLINE constexpr bool is_null() const
Definition tagged.h:502
#define ALIGN_TO_ALLOCATION_ALIGNMENT(value)
Definition globals.h:1796
NormalPage * current_page_
Definition compactor.cc:327
BasePage * page
Definition sweeper.cc:218
BasePage & page_
Definition sweeper.cc:157
int end
kInterpreterTrampolineOffset Tagged< HeapObject >
V8_EXPORT_PRIVATE FlagValues v8_flags
static constexpr Address kNullAddress
Definition v8-internal.h:53
#define DCHECK_OBJECT_SIZE(size)
Definition spaces.h:51
#define DCHECK_LE(v1, v2)
Definition logging.h:490
#define CHECK(condition)
Definition logging.h:124
#define DCHECK_NOT_NULL(val)
Definition logging.h:492
#define DCHECK_GE(v1, v2)
Definition logging.h:488
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_LT(v1, v2)
Definition logging.h:489
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define V8_UNLIKELY(condition)
Definition v8config.h:660