Bug Summary

File:out/../deps/v8/src/heap/read-only-heap.cc
Warning:line 100, column 7
Value stored to 'ro_heap' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name read-only-heap.cc -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/home/maurizio/node-v18.6.0/out -resource-dir /usr/local/lib/clang/16.0.0 -D _GLIBCXX_USE_CXX11_ABI=1 -D NODE_OPENSSL_CONF_NAME=nodejs_conf -D NODE_OPENSSL_HAS_QUIC -D V8_GYP_BUILD -D V8_TYPED_ARRAY_MAX_SIZE_IN_HEAP=64 -D __STDC_FORMAT_MACROS -D OPENSSL_NO_PINSHARED -D OPENSSL_THREADS -D V8_TARGET_ARCH_X64 -D V8_HAVE_TARGET_OS -D V8_TARGET_OS_LINUX -D V8_EMBEDDER_STRING="-node.8" -D ENABLE_DISASSEMBLER -D V8_PROMISE_INTERNAL_FIELD_COUNT=1 -D V8_SHORT_BUILTIN_CALLS -D OBJECT_PRINT -D V8_INTL_SUPPORT -D V8_ATOMIC_OBJECT_FIELD_WRITES -D V8_ENABLE_LAZY_SOURCE_POSITIONS -D V8_USE_SIPHASH -D V8_SHARED_RO_HEAP -D V8_WIN64_UNWINDING_INFO -D V8_ENABLE_REGEXP_INTERPRETER_THREADED_DISPATCH -D V8_SNAPSHOT_COMPRESSION -D V8_ENABLE_WEBASSEMBLY -D V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS -D V8_ALLOCATION_FOLDING -D V8_ALLOCATION_SITE_TRACKING -D V8_SCRIPTORMODULE_LEGACY_LIFETIME -D V8_ADVANCED_BIGINT_ALGORITHMS -D ICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_STATIC -D UCONFIG_NO_SERVICE=1 -D U_ENABLE_DYLOAD=0 -D U_STATIC_IMPLEMENTATION=1 -D U_HAVE_STD_STRING=1 -D UCONFIG_NO_BREAK_ITERATION=0 -I ../deps/v8 -I ../deps/v8/include -I /home/maurizio/node-v18.6.0/out/Release/obj/gen/inspector-generated-output-root -I ../deps/v8/third_party/inspector_protocol -I /home/maurizio/node-v18.6.0/out/Release/obj/gen -I /home/maurizio/node-v18.6.0/out/Release/obj/gen/generate-bytecode-output-root -I ../deps/icu-small/source/i18n -I ../deps/icu-small/source/common -I ../deps/v8/third_party/zlib -I ../deps/v8/third_party/zlib/google -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8 -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8/x86_64-redhat-linux -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8/backward -internal-isystem /usr/local/lib/clang/16.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wno-unused-parameter -Wno-return-type -std=gnu++17 -fdeprecated-macro -fdebug-compilation-dir=/home/maurizio/node-v18.6.0/out -ferror-limit 19 -fno-rtti -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-08-22-142216-507842-1 -x c++ ../deps/v8/src/heap/read-only-heap.cc
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#include "src/heap/read-only-heap.h"
6
7#include <cstddef>
8#include <cstring>
9
10#include "src/base/lazy-instance.h"
11#include "src/base/platform/mutex.h"
12#include "src/common/ptr-compr-inl.h"
13#include "src/heap/basic-memory-chunk.h"
14#include "src/heap/heap-write-barrier-inl.h"
15#include "src/heap/memory-chunk.h"
16#include "src/heap/read-only-spaces.h"
17#include "src/heap/third-party/heap-api.h"
18#include "src/objects/heap-object-inl.h"
19#include "src/objects/objects-inl.h"
20#include "src/objects/smi.h"
21#include "src/snapshot/read-only-deserializer.h"
22#include "src/utils/allocation.h"
23
24namespace v8 {
25namespace internal {
26
27namespace {
28// Mutex used to ensure that ReadOnlyArtifacts creation is only done once.
29base::LazyMutex read_only_heap_creation_mutex_ = LAZY_MUTEX_INITIALIZER{ { 0 }, { {} } };
30
31// Weak pointer holding ReadOnlyArtifacts. ReadOnlyHeap::SetUp creates a
32// std::shared_ptr from this when it attempts to reuse it. Since all Isolates
33// hold a std::shared_ptr to this, the object is destroyed when no Isolates
34// remain.
35base::LazyInstance<std::weak_ptr<ReadOnlyArtifacts>>::type
36 read_only_artifacts_ = LAZY_INSTANCE_INITIALIZER{ { 0 }, { {} } };
37
38std::shared_ptr<ReadOnlyArtifacts> InitializeSharedReadOnlyArtifacts() {
39 std::shared_ptr<ReadOnlyArtifacts> artifacts;
40 if (COMPRESS_POINTERS_IN_ISOLATE_CAGE_BOOLfalse) {
41 artifacts = std::make_shared<PointerCompressedReadOnlyArtifacts>();
42 } else {
43 artifacts = std::make_shared<SingleCopyReadOnlyArtifacts>();
44 }
45 *read_only_artifacts_.Pointer() = artifacts;
46 return artifacts;
47}
48} // namespace
49
50bool ReadOnlyHeap::IsSharedMemoryAvailable() {
51 static bool shared_memory_allocation_supported =
52 GetPlatformPageAllocator()->CanAllocateSharedPages();
53 return shared_memory_allocation_supported;
54}
55
56// This ReadOnlyHeap instance will only be accessed by Isolates that are already
57// set up. As such it doesn't need to be guarded by a mutex or shared_ptrs,
58// since an already set up Isolate will hold a shared_ptr to
59// read_only_artifacts_.
60SoleReadOnlyHeap* SoleReadOnlyHeap::shared_ro_heap_ = nullptr;
61
62// static
63void ReadOnlyHeap::SetUp(Isolate* isolate,
64 SnapshotData* read_only_snapshot_data,
65 bool can_rehash) {
66 DCHECK_NOT_NULL(isolate)((void) 0);
67
68 if (IsReadOnlySpaceShared()) {
69 ReadOnlyHeap* ro_heap;
70 if (read_only_snapshot_data != nullptr) {
71 bool read_only_heap_created = false;
72 base::MutexGuard guard(read_only_heap_creation_mutex_.Pointer());
73 std::shared_ptr<ReadOnlyArtifacts> artifacts =
74 read_only_artifacts_.Get().lock();
75 if (!artifacts) {
76 artifacts = InitializeSharedReadOnlyArtifacts();
77 artifacts->InitializeChecksum(read_only_snapshot_data);
78 ro_heap = CreateInitalHeapForBootstrapping(isolate, artifacts);
79 ro_heap->DeseralizeIntoIsolate(isolate, read_only_snapshot_data,
80 can_rehash);
81 read_only_heap_created = true;
82 } else {
83 // With pointer compression, there is one ReadOnlyHeap per Isolate.
84 // Without PC, there is only one shared between all Isolates.
85 ro_heap = artifacts->GetReadOnlyHeapForIsolate(isolate);
86 isolate->SetUpFromReadOnlyArtifacts(artifacts, ro_heap);
87 }
88 artifacts->VerifyChecksum(read_only_snapshot_data,
89 read_only_heap_created);
90 ro_heap->InitializeIsolateRoots(isolate);
91 } else {
92 // This path should only be taken in mksnapshot, should only be run once
93 // before tearing down the Isolate that holds this ReadOnlyArtifacts and
94 // is not thread-safe.
95 std::shared_ptr<ReadOnlyArtifacts> artifacts =
96 read_only_artifacts_.Get().lock();
97 CHECK(!artifacts)do { if ((__builtin_expect(!!(!(!artifacts)), 0))) { V8_Fatal
("Check failed: %s.", "!artifacts"); } } while (false)
;
98 artifacts = InitializeSharedReadOnlyArtifacts();
99
100 ro_heap = CreateInitalHeapForBootstrapping(isolate, artifacts);
Value stored to 'ro_heap' is never read
101 artifacts->VerifyChecksum(read_only_snapshot_data, true);
102 }
103 } else {
104 auto* ro_heap = new ReadOnlyHeap(new ReadOnlySpace(isolate->heap()));
105 isolate->SetUpFromReadOnlyArtifacts(nullptr, ro_heap);
106 if (read_only_snapshot_data != nullptr) {
107 ro_heap->DeseralizeIntoIsolate(isolate, read_only_snapshot_data,
108 can_rehash);
109 }
110 }
111}
112
113void ReadOnlyHeap::DeseralizeIntoIsolate(Isolate* isolate,
114 SnapshotData* read_only_snapshot_data,
115 bool can_rehash) {
116 DCHECK_NOT_NULL(read_only_snapshot_data)((void) 0);
117 ReadOnlyDeserializer des(isolate, read_only_snapshot_data, can_rehash);
118 des.DeserializeIntoIsolate();
119 InitFromIsolate(isolate);
120}
121
122void ReadOnlyHeap::OnCreateHeapObjectsComplete(Isolate* isolate) {
123 DCHECK_NOT_NULL(isolate)((void) 0);
124 InitFromIsolate(isolate);
125}
126
127// Only for compressed spaces
128ReadOnlyHeap::ReadOnlyHeap(ReadOnlyHeap* ro_heap, ReadOnlySpace* ro_space)
129 : read_only_space_(ro_space),
130 read_only_object_cache_(ro_heap->read_only_object_cache_) {
131 DCHECK(ReadOnlyHeap::IsReadOnlySpaceShared())((void) 0);
132 DCHECK(COMPRESS_POINTERS_IN_ISOLATE_CAGE_BOOL)((void) 0);
133}
134
135// static
136ReadOnlyHeap* ReadOnlyHeap::CreateInitalHeapForBootstrapping(
137 Isolate* isolate, std::shared_ptr<ReadOnlyArtifacts> artifacts) {
138 DCHECK(IsReadOnlySpaceShared())((void) 0);
139
140 std::unique_ptr<ReadOnlyHeap> ro_heap;
141 auto* ro_space = new ReadOnlySpace(isolate->heap());
142 if (COMPRESS_POINTERS_IN_ISOLATE_CAGE_BOOLfalse) {
143 ro_heap.reset(new ReadOnlyHeap(ro_space));
144 } else {
145 std::unique_ptr<SoleReadOnlyHeap> sole_ro_heap(
146 new SoleReadOnlyHeap(ro_space));
147 // The global shared ReadOnlyHeap is only used without pointer compression.
148 SoleReadOnlyHeap::shared_ro_heap_ = sole_ro_heap.get();
149 ro_heap = std::move(sole_ro_heap);
150 }
151 artifacts->set_read_only_heap(std::move(ro_heap));
152 isolate->SetUpFromReadOnlyArtifacts(artifacts, artifacts->read_only_heap());
153 return artifacts->read_only_heap();
154}
155
156void SoleReadOnlyHeap::InitializeIsolateRoots(Isolate* isolate) {
157 void* const isolate_ro_roots =
158 isolate->roots_table().read_only_roots_begin().location();
159 std::memcpy(isolate_ro_roots, read_only_roots_,
160 kEntriesCount * sizeof(Address));
161}
162
163void SoleReadOnlyHeap::InitializeFromIsolateRoots(Isolate* isolate) {
164 void* const isolate_ro_roots =
165 isolate->roots_table().read_only_roots_begin().location();
166 std::memcpy(read_only_roots_, isolate_ro_roots,
167 kEntriesCount * sizeof(Address));
168}
169
170void ReadOnlyHeap::InitFromIsolate(Isolate* isolate) {
171 DCHECK(!init_complete_)((void) 0);
172 read_only_space_->ShrinkPages();
173 if (IsReadOnlySpaceShared()) {
174 InitializeFromIsolateRoots(isolate);
175 std::shared_ptr<ReadOnlyArtifacts> artifacts(
176 *read_only_artifacts_.Pointer());
177
178 read_only_space()->DetachPagesAndAddToArtifacts(artifacts);
179 artifacts->ReinstallReadOnlySpace(isolate);
180
181 read_only_space_ = artifacts->shared_read_only_space();
182
183#ifdef DEBUG
184 artifacts->VerifyHeapAndSpaceRelationships(isolate);
185#endif
186 } else {
187 read_only_space_->Seal(ReadOnlySpace::SealMode::kDoNotDetachFromHeap);
188 }
189 init_complete_ = true;
190}
191
192void ReadOnlyHeap::OnHeapTearDown(Heap* heap) {
193 read_only_space_->TearDown(heap->memory_allocator());
194 delete read_only_space_;
195}
196
197void SoleReadOnlyHeap::OnHeapTearDown(Heap* heap) {
198 // Do nothing as ReadOnlyHeap is shared between all Isolates.
199}
200
201// static
202void ReadOnlyHeap::PopulateReadOnlySpaceStatistics(
203 SharedMemoryStatistics* statistics) {
204 statistics->read_only_space_size_ = 0;
205 statistics->read_only_space_used_size_ = 0;
206 statistics->read_only_space_physical_size_ = 0;
207 if (IsReadOnlySpaceShared()) {
208 std::shared_ptr<ReadOnlyArtifacts> artifacts =
209 read_only_artifacts_.Get().lock();
210 if (artifacts) {
211 auto* ro_space = artifacts->shared_read_only_space();
212 statistics->read_only_space_size_ = ro_space->CommittedMemory();
213 statistics->read_only_space_used_size_ = ro_space->Size();
214 statistics->read_only_space_physical_size_ =
215 ro_space->CommittedPhysicalMemory();
216 }
217 }
218}
219
220// static
221bool ReadOnlyHeap::Contains(Address address) {
222 if (V8_ENABLE_THIRD_PARTY_HEAP_BOOLfalse) {
223 return third_party_heap::Heap::InReadOnlySpace(address);
224 } else {
225 return BasicMemoryChunk::FromAddress(address)->InReadOnlySpace();
226 }
227}
228
229// static
230bool ReadOnlyHeap::Contains(HeapObject object) {
231 if (V8_ENABLE_THIRD_PARTY_HEAP_BOOLfalse) {
232 return third_party_heap::Heap::InReadOnlySpace(object.address());
233 } else {
234 return BasicMemoryChunk::FromHeapObject(object)->InReadOnlySpace();
235 }
236}
237
238Object* ReadOnlyHeap::ExtendReadOnlyObjectCache() {
239 read_only_object_cache_.push_back(Smi::zero());
240 return &read_only_object_cache_.back();
241}
242
243Object ReadOnlyHeap::cached_read_only_object(size_t i) const {
244 DCHECK_LE(i, read_only_object_cache_.size())((void) 0);
245 return read_only_object_cache_[i];
246}
247
248bool ReadOnlyHeap::read_only_object_cache_is_initialized() const {
249 return read_only_object_cache_.size() > 0;
250}
251
252size_t ReadOnlyHeap::read_only_object_cache_size() const {
253 return read_only_object_cache_.size();
254}
255
256ReadOnlyHeapObjectIterator::ReadOnlyHeapObjectIterator(
257 const ReadOnlyHeap* ro_heap)
258 : ReadOnlyHeapObjectIterator(ro_heap->read_only_space()) {}
259
260ReadOnlyHeapObjectIterator::ReadOnlyHeapObjectIterator(
261 const ReadOnlySpace* ro_space)
262 : ro_space_(ro_space),
263 current_page_(V8_ENABLE_THIRD_PARTY_HEAP_BOOLfalse
264 ? std::vector<ReadOnlyPage*>::iterator()
265 : ro_space->pages().begin()),
266 current_addr_(V8_ENABLE_THIRD_PARTY_HEAP_BOOLfalse
267 ? Address()
268 : (*current_page_)->GetAreaStart()) {}
269
270HeapObject ReadOnlyHeapObjectIterator::Next() {
271 if (V8_ENABLE_THIRD_PARTY_HEAP_BOOLfalse) {
272 return HeapObject(); // Unsupported
273 }
274
275 if (current_page_ == ro_space_->pages().end()) {
276 return HeapObject();
277 }
278
279 ReadOnlyPage* current_page = *current_page_;
280 for (;;) {
281 Address end = current_page->address() + current_page->area_size() +
282 MemoryChunkLayout::ObjectStartOffsetInMemoryChunk(RO_SPACE);
283 DCHECK_LE(current_addr_, end)((void) 0);
284 if (current_addr_ == end) {
285 // Progress to the next page.
286 ++current_page_;
287 if (current_page_ == ro_space_->pages().end()) {
288 return HeapObject();
289 }
290 current_page = *current_page_;
291 current_addr_ = current_page->GetAreaStart();
292 }
293
294 if (current_addr_ == ro_space_->top() &&
295 current_addr_ != ro_space_->limit()) {
296 current_addr_ = ro_space_->limit();
297 continue;
298 }
299 HeapObject object = HeapObject::FromAddress(current_addr_);
300 const int object_size = object.Size();
301 current_addr_ += object_size;
302
303 if (object.IsFreeSpaceOrFiller()) {
304 continue;
305 }
306
307 DCHECK_OBJECT_SIZE(object_size)((void) 0);
308 return object;
309 }
310}
311
312} // namespace internal
313} // namespace v8