v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
snapshot.cc
Go to the documentation of this file.
1// Copyright 2006-2008 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// The common functionality when building with or without snapshots.
6
8
9#include "src/api/api-inl.h" // For OpenHandle.
16#include "src/heap/safepoint.h"
27#include "src/utils/memcopy.h"
28#include "src/utils/version.h"
29
30#ifdef V8_SNAPSHOT_COMPRESSION
32#endif
33
34namespace v8 {
35namespace internal {
36
37namespace {
38
39class SnapshotImpl : public AllStatic {
40 public:
41 static v8::StartupData CreateSnapshotBlob(
42 const SnapshotData* startup_snapshot_in,
43 const SnapshotData* read_only_snapshot_in,
44 const SnapshotData* shared_heap_snapshot_in,
45 const std::vector<SnapshotData*>& context_snapshots_in,
46 bool can_be_rehashed);
47
48 static uint32_t ExtractNumContexts(const v8::StartupData* data);
49 static uint32_t ExtractContextOffset(const v8::StartupData* data,
50 uint32_t index);
51 static base::Vector<const uint8_t> ExtractStartupData(
52 const v8::StartupData* data);
53 static base::Vector<const uint8_t> ExtractReadOnlyData(
54 const v8::StartupData* data);
55 static base::Vector<const uint8_t> ExtractSharedHeapData(
56 const v8::StartupData* data);
57 static base::Vector<const uint8_t> ExtractContextData(
58 const v8::StartupData* data, uint32_t index);
59
60 static uint32_t GetHeaderValue(const v8::StartupData* data, uint32_t offset) {
61 DCHECK_NOT_NULL(data);
62 DCHECK_LT(offset, static_cast<uint32_t>(data->raw_size));
64 reinterpret_cast<Address>(data->data) + offset);
65 }
66 static void SetHeaderValue(char* data, uint32_t offset, uint32_t value) {
67 base::WriteLittleEndianValue(reinterpret_cast<Address>(data) + offset,
68 value);
69 }
70
71 static void CheckVersion(const v8::StartupData* data);
72
73 // Snapshot blob layout:
74 // [0] number of contexts N
75 // [1] rehashability
76 // [2] checksum
77 // [3] read-only snapshot checksum
78 // [4] (64 bytes) version string
79 // [5] offset to readonly
80 // [6] offset to shared heap
81 // [7] offset to context 0
82 // [8] offset to context 1
83 // ...
84 // ... offset to context N - 1
85 // ... startup snapshot data
86 // ... read-only snapshot data
87 // ... shared heap snapshot data
88 // ... context 0 snapshot data
89 // ... context 1 snapshot data
90
91 static const uint32_t kNumberOfContextsOffset = 0;
92 // TODO(yangguo): generalize rehashing, and remove this flag.
93 static const uint32_t kRehashabilityOffset =
96 static const uint32_t kReadOnlySnapshotChecksumOffset =
98 static const uint32_t kVersionStringOffset =
100 static const uint32_t kVersionStringLength = 64;
101 static const uint32_t kReadOnlyOffsetOffset =
103 static const uint32_t kSharedHeapOffsetOffset =
105 static const uint32_t kFirstContextOffsetOffset =
107
108 static base::Vector<const uint8_t> ChecksummedContent(
109 const v8::StartupData* data) {
110 // The hashed region is everything but the header slots up-to-and-including
111 // the checksum slot itself.
112 // TODO(jgruber): We currently exclude #contexts and rehashability. This
113 // seems arbitrary and I think we could shuffle header slot order around to
114 // include them, just for consistency.
115 static_assert(kReadOnlySnapshotChecksumOffset ==
117 const uint32_t kChecksumStart = kReadOnlySnapshotChecksumOffset;
118 return base::Vector<const uint8_t>(
119 reinterpret_cast<const uint8_t*>(data->data + kChecksumStart),
120 data->raw_size - kChecksumStart);
121 }
122
123 static uint32_t StartupSnapshotOffset(int num_contexts) {
124 return POINTER_SIZE_ALIGN(kFirstContextOffsetOffset +
125 num_contexts * kInt32Size);
126 }
127
128 static uint32_t ContextSnapshotOffsetOffset(int index) {
129 return kFirstContextOffsetOffset + index * kInt32Size;
130 }
131};
132
133} // namespace
134
136 base::Vector<const uint8_t> snapshot_data) {
137#ifdef V8_SNAPSHOT_COMPRESSION
138 TRACE_EVENT0("v8", "V8.SnapshotDecompress");
139 RCS_SCOPE(isolate, RuntimeCallCounterId::kSnapshotDecompress);
140 NestedTimedHistogramScope histogram_timer(
141 isolate->counters()->snapshot_decompress());
142 return SnapshotCompression::Decompress(snapshot_data);
143#else
144 return SnapshotData(snapshot_data);
145#endif
146}
147
148#ifdef DEBUG
149bool Snapshot::SnapshotIsValid(const v8::StartupData* snapshot_blob) {
150 return SnapshotImpl::ExtractNumContexts(snapshot_blob) > 0;
151}
152#endif // DEBUG
153
154bool Snapshot::HasContextSnapshot(Isolate* isolate, size_t index) {
155 // Do not use snapshots if the isolate is used to create snapshots.
156 const v8::StartupData* blob = isolate->snapshot_blob();
157 if (blob == nullptr) return false;
158 if (blob->data == nullptr) return false;
159 size_t num_contexts =
160 static_cast<size_t>(SnapshotImpl::ExtractNumContexts(blob));
161 return index < num_contexts;
162}
163
165 char version[SnapshotImpl::kVersionStringLength];
166 memset(version, 0, SnapshotImpl::kVersionStringLength);
167 CHECK_LT(
168 SnapshotImpl::kVersionStringOffset + SnapshotImpl::kVersionStringLength,
169 static_cast<uint32_t>(data->raw_size));
171 base::Vector<char>(version, SnapshotImpl::kVersionStringLength));
172 return strncmp(version, data->data + SnapshotImpl::kVersionStringOffset,
173 SnapshotImpl::kVersionStringLength) == 0;
174}
175
177 if (!isolate->snapshot_available()) return false;
178
179 const v8::StartupData* blob = isolate->snapshot_blob();
180 SnapshotImpl::CheckVersion(blob);
182 CHECK(VerifyChecksum(blob));
183 }
184
185 base::Vector<const uint8_t> startup_data =
186 SnapshotImpl::ExtractStartupData(blob);
187 base::Vector<const uint8_t> read_only_data =
188 SnapshotImpl::ExtractReadOnlyData(blob);
189 base::Vector<const uint8_t> shared_heap_data =
190 SnapshotImpl::ExtractSharedHeapData(blob);
191
192 SnapshotData startup_snapshot_data(MaybeDecompress(isolate, startup_data));
193 SnapshotData read_only_snapshot_data(
194 MaybeDecompress(isolate, read_only_data));
195 SnapshotData shared_heap_snapshot_data(
196 MaybeDecompress(isolate, shared_heap_data));
197
198 return isolate->InitWithSnapshot(
199 &startup_snapshot_data, &read_only_snapshot_data,
200 &shared_heap_snapshot_data, ExtractRehashability(blob));
201}
202
204 Isolate* isolate, DirectHandle<JSGlobalProxy> global_proxy,
205 size_t context_index,
206 DeserializeEmbedderFieldsCallback embedder_fields_deserializer) {
207 if (!isolate->snapshot_available()) return DirectHandle<Context>();
208
209 const v8::StartupData* blob = isolate->snapshot_blob();
210 bool can_rehash = ExtractRehashability(blob);
211 base::Vector<const uint8_t> context_data = SnapshotImpl::ExtractContextData(
212 blob, static_cast<uint32_t>(context_index));
213 SnapshotData snapshot_data(MaybeDecompress(isolate, context_data));
214
216 isolate, &snapshot_data, context_index, can_rehash, global_proxy,
217 embedder_fields_deserializer);
218}
219
220// static
222 Isolate* isolate, bool clear_recompilable_data) {
223 // Clear SFIs and JSRegExps.
224 PtrComprCageBase cage_base(isolate);
225
226 {
227 HandleScope scope(isolate);
228 std::vector<i::Handle<i::SharedFunctionInfo>> sfis_to_clear;
229 {
230 i::HeapObjectIterator it(isolate->heap());
231 for (i::Tagged<i::HeapObject> o = it.Next(); !o.is_null();
232 o = it.Next()) {
233 if (clear_recompilable_data && IsSharedFunctionInfo(o, cage_base)) {
236 if (IsScript(shared->script(cage_base), cage_base) &&
237 Cast<Script>(shared->script(cage_base))->type() ==
239 continue; // Don't clear extensions, they cannot be recompiled.
240 }
241 if (shared->CanDiscardCompiled()) {
242 sfis_to_clear.emplace_back(shared, isolate);
243 }
244 } else if (IsJSRegExp(o, cage_base)) {
246 if (regexp->has_data()) {
247 i::Tagged<i::RegExpData> data = regexp->data(isolate);
248 if (data->HasCompiledCode()) {
249 DCHECK(Is<IrRegExpData>(regexp->data(isolate)));
250 Cast<IrRegExpData>(data)->DiscardCompiledCodeForSerialization();
251 }
252 }
253 }
254 }
255 }
256
257#if V8_ENABLE_WEBASSEMBLY
258 // Clear the cached js-to-wasm wrappers.
260 isolate->heap()->js_to_wasm_wrappers(), isolate);
261 MemsetTagged(wrappers->RawFieldOfFirstElement(), ClearedValue(isolate),
262 wrappers->length());
263#endif // V8_ENABLE_WEBASSEMBLY
264
265 // Must happen after heap iteration since SFI::DiscardCompiled may allocate.
266 for (i::DirectHandle<i::SharedFunctionInfo> shared : sfis_to_clear) {
267 if (shared->CanDiscardCompiled()) {
268 i::SharedFunctionInfo::DiscardCompiled(isolate, shared);
269 }
270 }
271 }
272
273 // Clear JSFunctions.
274 {
275 i::HeapObjectIterator it(isolate->heap());
276 for (i::Tagged<i::HeapObject> o = it.Next(); !o.is_null(); o = it.Next()) {
277 if (!IsJSFunction(o, cage_base)) continue;
278
280 fun->CompleteInobjectSlackTrackingIfActive();
281
282 i::Tagged<i::SharedFunctionInfo> shared = fun->shared();
283 if (IsScript(shared->script(cage_base), cage_base) &&
284 Cast<Script>(shared->script(cage_base))->type() ==
286 continue; // Don't clear extensions, they cannot be recompiled.
287 }
288
289 // Also, clear out feedback vectors and recompilable code.
290 if (fun->CanDiscardCompiled(isolate)) {
291 fun->UpdateCode(*BUILTIN_CODE(isolate, CompileLazy));
292 }
293 if (!IsUndefined(fun->raw_feedback_cell(cage_base)->value(cage_base))) {
294 fun->raw_feedback_cell(cage_base)->set_value(
295 i::ReadOnlyRoots(isolate).undefined_value());
296 }
297#ifdef DEBUG
298 if (clear_recompilable_data) {
299#if V8_ENABLE_WEBASSEMBLY
300 DCHECK(fun->shared()->HasWasmExportedFunctionData() ||
301 fun->shared()->HasBuiltinId() ||
302 fun->shared()->IsApiFunction() ||
303 fun->shared()->HasUncompiledDataWithoutPreparseData());
304#else
305 DCHECK(fun->shared()->HasBuiltinId() ||
306 fun->shared()->IsApiFunction() ||
307 fun->shared()->HasUncompiledDataWithoutPreparseData());
308#endif // V8_ENABLE_WEBASSEMBLY
309 }
310#endif // DEBUG
311 }
312 }
313
314 // PendingOptimizeTable also contains BytecodeArray, we need to clear the
315 // recompilable code same as above.
316 ReadOnlyRoots roots(isolate);
317 isolate->heap()->SetFunctionsMarkedForManualOptimization(
318 roots.undefined_value());
319
320#if V8_ENABLE_WEBASSEMBLY
321 {
322 // Check if there are any asm.js / wasm functions on the heap.
323 // These cannot be serialized due to restrictions with the js-to-wasm
324 // wrapper. A tiered-up wrapper would have to be replaced with a generic
325 // wrapper which isn't supported. For asm.js there also isn't any support
326 // for the generic wrapper at all.
327 i::HeapObjectIterator it(isolate->heap(),
329 for (i::Tagged<i::HeapObject> o = it.Next(); !o.is_null(); o = it.Next()) {
330 if (IsJSFunction(o)) {
332 if (fun->shared()->HasAsmWasmData()) {
333 FATAL("asm.js functions are not supported in snapshots");
334 }
335 if (fun->shared()->HasWasmExportedFunctionData()) {
336 FATAL(
337 "Exported WebAssembly functions are not supported in snapshots");
338 }
339 }
340 }
341 }
342#endif // V8_ENABLE_WEBASSEMBLY
343}
344
345// static
347 Isolate* isolate, DirectHandle<Context> default_context) {
348 StartupData serialized_data;
349 std::unique_ptr<const char[]> auto_delete_serialized_data;
350
351 isolate->heap()->CollectAllAvailableGarbage(
352 i::GarbageCollectionReason::kSnapshotCreator);
353
354 // Test serialization.
355 {
356 SafepointKind safepoint_kind = isolate->has_shared_space()
359 SafepointScope safepoint_scope(isolate, safepoint_kind);
361
366 std::vector<Tagged<Context>> contexts{*default_context};
367 std::vector<SerializeEmbedderFieldsCallback> callbacks{
369 serialized_data = Snapshot::Create(isolate, &contexts, callbacks,
370 safepoint_scope, no_gc, flags);
371 auto_delete_serialized_data.reset(serialized_data.data);
372 }
373
374 // The shared heap is verified on Heap teardown, which performs a global
375 // safepoint. Both isolate and new_isolate are running in the same thread, so
376 // park isolate before running new_isolate to avoid deadlock.
377 isolate->main_thread_local_isolate()->ExecuteMainThreadWhileParked(
378 [&serialized_data]() {
379 // Test deserialization.
380 Isolate* new_isolate = Isolate::New();
381 std::unique_ptr<v8::ArrayBuffer::Allocator> array_buffer_allocator(
383 {
384 // Set serializer_enabled() to not install extensions and experimental
385 // natives on the new isolate.
386 // TODO(v8:10416): This should be a separate setting on the isolate.
387 new_isolate->enable_serializer();
388 new_isolate->Enter();
389 new_isolate->set_snapshot_blob(&serialized_data);
390 new_isolate->set_array_buffer_allocator(array_buffer_allocator.get());
391 CHECK(Snapshot::Initialize(new_isolate));
392
393 HandleScope scope(new_isolate);
394 DirectHandle<Context> new_native_context =
396 CHECK(IsNativeContext(*new_native_context));
397
398#ifdef VERIFY_HEAP
399 if (v8_flags.verify_heap)
400 HeapVerifier::VerifyHeap(new_isolate->heap());
401#endif // VERIFY_HEAP
402 }
403 new_isolate->Exit();
404 Isolate::Delete(new_isolate);
405 });
406}
407
408// static
410 Isolate* isolate, std::vector<Tagged<Context>>* contexts,
411 const std::vector<SerializeEmbedderFieldsCallback>&
412 embedder_fields_serializers,
413 const SafepointScope& safepoint_scope,
414 const DisallowGarbageCollection& no_gc, SerializerFlags flags) {
415 TRACE_EVENT0("v8", "V8.SnapshotCreate");
416 DCHECK_EQ(contexts->size(), embedder_fields_serializers.size());
417 DCHECK_GT(contexts->size(), 0);
418 HandleScope scope(isolate);
419
420 ReadOnlySerializer read_only_serializer(isolate, flags);
421 read_only_serializer.Serialize();
422
423 // TODO(v8:6593): generalize rehashing, and remove this flag.
424 bool can_be_rehashed = read_only_serializer.can_be_rehashed();
425
426 SharedHeapSerializer shared_heap_serializer(isolate, flags);
427 StartupSerializer startup_serializer(isolate, flags, &shared_heap_serializer);
428 startup_serializer.SerializeStrongReferences(no_gc);
429
430 // Serialize each context with a new serializer.
431 const int num_contexts = static_cast<int>(contexts->size());
432 std::vector<SnapshotData*> context_snapshots;
433 context_snapshots.reserve(num_contexts);
434
435 std::vector<int> context_allocation_sizes;
436 for (int i = 0; i < num_contexts; i++) {
437 ContextSerializer context_serializer(isolate, flags, &startup_serializer,
438 embedder_fields_serializers[i]);
439 context_serializer.Serialize(&contexts->at(i), no_gc);
440 can_be_rehashed = can_be_rehashed && context_serializer.can_be_rehashed();
441 context_snapshots.push_back(new SnapshotData(&context_serializer));
442 if (v8_flags.serialization_statistics) {
443 context_allocation_sizes.push_back(
444 context_serializer.TotalAllocationSize());
445 }
446 }
447
448 startup_serializer.SerializeWeakReferencesAndDeferred();
449 can_be_rehashed = can_be_rehashed && startup_serializer.can_be_rehashed();
450
451 startup_serializer.CheckNoDirtyFinalizationRegistries();
452
453 shared_heap_serializer.FinalizeSerialization();
454 can_be_rehashed = can_be_rehashed && shared_heap_serializer.can_be_rehashed();
455
456 if (v8_flags.serialization_statistics) {
457 DCHECK_NE(read_only_serializer.TotalAllocationSize(), 0);
458 DCHECK_NE(startup_serializer.TotalAllocationSize(), 0);
459 // The shared heap snapshot can be empty, no problem.
460 // DCHECK_NE(shared_heap_serializer.TotalAllocationSize(), 0);
461 int per_isolate_allocation_size = startup_serializer.TotalAllocationSize();
462 int per_process_allocation_size =
463 read_only_serializer.TotalAllocationSize();
464 // TODO(jgruber): At snapshot-generation time we don't know whether the
465 // shared heap snapshot will actually be shared at runtime, or if it will
466 // be deserialized into each isolate. Conservatively account to per-isolate
467 // memory here.
468 per_isolate_allocation_size += shared_heap_serializer.TotalAllocationSize();
469 // These prints must match the regexp in test/memory/Memory.json
470 PrintF("Deserialization will allocate:\n");
471 PrintF("%10d bytes per process\n", per_process_allocation_size);
472 PrintF("%10d bytes per isolate\n", per_isolate_allocation_size);
473 for (int i = 0; i < num_contexts; i++) {
474 DCHECK_NE(context_allocation_sizes[i], 0);
475 PrintF("%10d bytes per context #%d\n", context_allocation_sizes[i], i);
476 }
477 PrintF("\n");
478 }
479
480 SnapshotData read_only_snapshot(&read_only_serializer);
481 SnapshotData shared_heap_snapshot(&shared_heap_serializer);
482 SnapshotData startup_snapshot(&startup_serializer);
483 v8::StartupData result = SnapshotImpl::CreateSnapshotBlob(
484 &startup_snapshot, &read_only_snapshot, &shared_heap_snapshot,
485 context_snapshots, can_be_rehashed);
486
487 for (const SnapshotData* ptr : context_snapshots) delete ptr;
488
490 return result;
491}
492
493v8::StartupData SnapshotImpl::CreateSnapshotBlob(
494 const SnapshotData* startup_snapshot_in,
495 const SnapshotData* read_only_snapshot_in,
496 const SnapshotData* shared_heap_snapshot_in,
497 const std::vector<SnapshotData*>& context_snapshots_in,
498 bool can_be_rehashed) {
499 TRACE_EVENT0("v8", "V8.SnapshotCompress");
500 // Have these separate from snapshot_in for compression, since we need to
501 // access the compressed data as well as the uncompressed reservations.
502 const SnapshotData* startup_snapshot;
503 const SnapshotData* read_only_snapshot;
504 const SnapshotData* shared_heap_snapshot;
505 const std::vector<SnapshotData*>* context_snapshots;
506#ifdef V8_SNAPSHOT_COMPRESSION
507 SnapshotData startup_compressed(
508 SnapshotCompression::Compress(startup_snapshot_in));
509 SnapshotData read_only_compressed(
510 SnapshotCompression::Compress(read_only_snapshot_in));
511 SnapshotData shared_heap_compressed(
512 SnapshotCompression::Compress(shared_heap_snapshot_in));
513 startup_snapshot = &startup_compressed;
514 read_only_snapshot = &read_only_compressed;
515 shared_heap_snapshot = &shared_heap_compressed;
516 std::vector<SnapshotData> context_snapshots_compressed;
517 context_snapshots_compressed.reserve(context_snapshots_in.size());
518 std::vector<SnapshotData*> context_snapshots_compressed_ptrs;
519 for (unsigned int i = 0; i < context_snapshots_in.size(); ++i) {
520 context_snapshots_compressed.push_back(
521 SnapshotCompression::Compress(context_snapshots_in[i]));
522 context_snapshots_compressed_ptrs.push_back(
523 &context_snapshots_compressed[i]);
524 }
525 context_snapshots = &context_snapshots_compressed_ptrs;
526#else
527 startup_snapshot = startup_snapshot_in;
528 read_only_snapshot = read_only_snapshot_in;
529 shared_heap_snapshot = shared_heap_snapshot_in;
530 context_snapshots = &context_snapshots_in;
531#endif
532
533 uint32_t num_contexts = static_cast<uint32_t>(context_snapshots->size());
534 uint32_t startup_snapshot_offset =
535 SnapshotImpl::StartupSnapshotOffset(num_contexts);
536 uint32_t total_length = startup_snapshot_offset;
537 total_length += static_cast<uint32_t>(startup_snapshot->RawData().length());
538 total_length += static_cast<uint32_t>(read_only_snapshot->RawData().length());
539 total_length +=
540 static_cast<uint32_t>(shared_heap_snapshot->RawData().length());
541 for (const auto context_snapshot : *context_snapshots) {
542 total_length += static_cast<uint32_t>(context_snapshot->RawData().length());
543 }
544
545 char* data = new char[total_length];
546 // Zero out pre-payload data. Part of that is only used for padding.
547 memset(data, 0, SnapshotImpl::StartupSnapshotOffset(num_contexts));
548
549 SnapshotImpl::SetHeaderValue(data, SnapshotImpl::kNumberOfContextsOffset,
550 num_contexts);
551 SnapshotImpl::SetHeaderValue(data, SnapshotImpl::kRehashabilityOffset,
552 can_be_rehashed ? 1 : 0);
553
554 // Write version string into snapshot data.
555 memset(data + SnapshotImpl::kVersionStringOffset, 0,
556 SnapshotImpl::kVersionStringLength);
557 Version::GetString(
558 base::Vector<char>(data + SnapshotImpl::kVersionStringOffset,
559 SnapshotImpl::kVersionStringLength));
560
561 // Startup snapshot (isolate-specific data).
562 uint32_t payload_offset = startup_snapshot_offset;
563 uint32_t payload_length =
564 static_cast<uint32_t>(startup_snapshot->RawData().length());
565 CopyBytes(data + payload_offset,
566 reinterpret_cast<const char*>(startup_snapshot->RawData().begin()),
567 payload_length);
568 if (v8_flags.serialization_statistics) {
569 // These prints must match the regexp in test/memory/Memory.json
570 PrintF("Snapshot blob consists of:\n");
571 PrintF("%10d bytes for startup\n", payload_length);
572 }
573 payload_offset += payload_length;
574
575 // Read-only.
576 SnapshotImpl::SetHeaderValue(data, SnapshotImpl::kReadOnlyOffsetOffset,
577 payload_offset);
578 payload_length = read_only_snapshot->RawData().length();
579 CopyBytes(
580 data + payload_offset,
581 reinterpret_cast<const char*>(read_only_snapshot->RawData().begin()),
582 payload_length);
583 SnapshotImpl::SetHeaderValue(
584 data, SnapshotImpl::kReadOnlySnapshotChecksumOffset,
585 Checksum(base::VectorOf(
586 reinterpret_cast<const uint8_t*>(data + payload_offset),
587 payload_length)));
588 if (v8_flags.serialization_statistics) {
589 // These prints must match the regexp in test/memory/Memory.json
590 PrintF("%10d bytes for read-only\n", payload_length);
591 }
592 payload_offset += payload_length;
593
594 // Shared heap.
595 SnapshotImpl::SetHeaderValue(data, SnapshotImpl::kSharedHeapOffsetOffset,
596 payload_offset);
597 payload_length = shared_heap_snapshot->RawData().length();
598 CopyBytes(
599 data + payload_offset,
600 reinterpret_cast<const char*>(shared_heap_snapshot->RawData().begin()),
601 payload_length);
602 if (v8_flags.serialization_statistics) {
603 // These prints must match the regexp in test/memory/Memory.json
604 PrintF("%10d bytes for shared heap\n", payload_length);
605 }
606 payload_offset += payload_length;
607
608 // Context snapshots (context-specific data).
609 for (uint32_t i = 0; i < num_contexts; i++) {
610 SnapshotImpl::SetHeaderValue(
611 data, SnapshotImpl::ContextSnapshotOffsetOffset(i), payload_offset);
612 SnapshotData* context_snapshot = (*context_snapshots)[i];
613 payload_length = context_snapshot->RawData().length();
614 CopyBytes(
615 data + payload_offset,
616 reinterpret_cast<const char*>(context_snapshot->RawData().begin()),
617 payload_length);
618 if (v8_flags.serialization_statistics) {
619 // These prints must match the regexp in test/memory/Memory.json
620 PrintF("%10d bytes for context #%d\n", payload_length, i);
621 }
622 payload_offset += payload_length;
623 }
624 if (v8_flags.serialization_statistics) PrintF("\n");
625
626 DCHECK_EQ(total_length, payload_offset);
627 v8::StartupData result = {data, static_cast<int>(total_length)};
628
629 SnapshotImpl::SetHeaderValue(
630 data, SnapshotImpl::kChecksumOffset,
631 Checksum(SnapshotImpl::ChecksummedContent(&result)));
632
633 return result;
634}
635
636uint32_t SnapshotImpl::ExtractNumContexts(const v8::StartupData* data) {
637 return GetHeaderValue(data, kNumberOfContextsOffset);
638}
639
641 return SnapshotImpl::GetHeaderValue(data, SnapshotImpl::kChecksumOffset);
642}
644 return Checksum(SnapshotImpl::ChecksummedContent(data));
645}
646
648 base::ElapsedTimer timer;
649 if (v8_flags.profile_deserialization) timer.Start();
650 uint32_t expected = GetExpectedChecksum(data);
651 uint32_t result = CalculateChecksum(data);
652 if (v8_flags.profile_deserialization) {
653 double ms = timer.Elapsed().InMillisecondsF();
654 PrintF("[Verifying snapshot checksum took %0.3f ms]\n", ms);
655 }
656 return result == expected;
657}
658
659uint32_t SnapshotImpl::ExtractContextOffset(const v8::StartupData* data,
660 uint32_t index) {
661 // Extract the offset of the context at a given index from the StartupData,
662 // and check that it is within bounds.
663 uint32_t context_offset =
664 GetHeaderValue(data, ContextSnapshotOffsetOffset(index));
665 CHECK_LT(context_offset, static_cast<uint32_t>(data->raw_size));
666 return context_offset;
667}
668
670 uint32_t rehashability =
671 SnapshotImpl::GetHeaderValue(data, SnapshotImpl::kRehashabilityOffset);
672 CHECK_IMPLIES(rehashability != 0, rehashability == 1);
673 return rehashability != 0;
674}
675
676// static
678 const v8::StartupData* data) {
679 return SnapshotImpl::GetHeaderValue(
680 data, SnapshotImpl::kReadOnlySnapshotChecksumOffset);
681}
682
683namespace {
684base::Vector<const uint8_t> ExtractData(const v8::StartupData* snapshot,
685 uint32_t start_offset,
686 uint32_t end_offset) {
687 CHECK_LT(start_offset, end_offset);
688 CHECK_LT(end_offset, snapshot->raw_size);
689 uint32_t length = end_offset - start_offset;
690 const uint8_t* data =
691 reinterpret_cast<const uint8_t*>(snapshot->data + start_offset);
692 return base::Vector<const uint8_t>(data, length);
693}
694} // namespace
695
696base::Vector<const uint8_t> SnapshotImpl::ExtractStartupData(
697 const v8::StartupData* data) {
698 DCHECK(Snapshot::SnapshotIsValid(data));
699
700 uint32_t num_contexts = ExtractNumContexts(data);
701 return ExtractData(data, StartupSnapshotOffset(num_contexts),
702 GetHeaderValue(data, kReadOnlyOffsetOffset));
703}
704
705base::Vector<const uint8_t> SnapshotImpl::ExtractReadOnlyData(
706 const v8::StartupData* data) {
707 DCHECK(Snapshot::SnapshotIsValid(data));
708
709 return ExtractData(data, GetHeaderValue(data, kReadOnlyOffsetOffset),
710 GetHeaderValue(data, kSharedHeapOffsetOffset));
711}
712
713base::Vector<const uint8_t> SnapshotImpl::ExtractSharedHeapData(
714 const v8::StartupData* data) {
715 DCHECK(Snapshot::SnapshotIsValid(data));
716
717 return ExtractData(data, GetHeaderValue(data, kSharedHeapOffsetOffset),
718 GetHeaderValue(data, ContextSnapshotOffsetOffset(0)));
719}
720
721base::Vector<const uint8_t> SnapshotImpl::ExtractContextData(
722 const v8::StartupData* data, uint32_t index) {
723 uint32_t num_contexts = ExtractNumContexts(data);
724 CHECK_LT(index, num_contexts);
725
726 uint32_t context_offset = ExtractContextOffset(data, index);
727 uint32_t next_context_offset;
728 if (index == num_contexts - 1) {
729 next_context_offset = data->raw_size;
730 } else {
731 next_context_offset = ExtractContextOffset(data, index + 1);
732 CHECK_LT(next_context_offset, data->raw_size);
733 }
734
735 const uint8_t* context_data =
736 reinterpret_cast<const uint8_t*>(data->data + context_offset);
737 uint32_t context_length = next_context_offset - context_offset;
738 return base::Vector<const uint8_t>(context_data, context_length);
739}
740
741void SnapshotImpl::CheckVersion(const v8::StartupData* data) {
742 if (!Snapshot::VersionIsValid(data)) {
743 char version[kVersionStringLength];
744 memset(version, 0, kVersionStringLength);
746 static_cast<uint32_t>(data->raw_size));
747 Version::GetString(base::Vector<char>(version, kVersionStringLength));
748 FATAL(
749 "Version mismatch between V8 binary and snapshot.\n"
750 "# V8 binary version: %.*s\n"
751 "# Snapshot version: %.*s\n"
752 "# The snapshot consists of %d bytes and contains %d context(s).",
754 data->data + kVersionStringOffset, data->raw_size,
755 ExtractNumContexts(data));
756 }
757}
758
759namespace {
760
761bool RunExtraCode(v8::Isolate* isolate, v8::Local<v8::Context> context,
762 const char* utf8_source, const char* name) {
763 v8::Context::Scope context_scope(context);
764 v8::TryCatch try_catch(isolate);
765 v8::Local<v8::String> source_string;
766 if (!v8::String::NewFromUtf8(isolate, utf8_source).ToLocal(&source_string)) {
767 return false;
768 }
769 v8::Local<v8::String> resource_name =
770 v8::String::NewFromUtf8(isolate, name).ToLocalChecked();
771 v8::ScriptOrigin origin(resource_name);
772 v8::ScriptCompiler::Source source(source_string, origin);
774 if (!v8::ScriptCompiler::Compile(context, &source).ToLocal(&script)) {
775 return false;
776 }
777 if (script->Run(context).IsEmpty()) return false;
778 CHECK(!try_catch.HasCaught());
779 return true;
780}
781
782} // namespace
783
785 v8::SnapshotCreator::FunctionCodeHandling function_code_handling,
786 const char* embedded_source, SnapshotCreator& snapshot_creator,
787 Snapshot::SerializerFlags serializer_flags) {
788 SnapshotCreatorImpl* creator =
790 {
791 auto v8_isolate = reinterpret_cast<v8::Isolate*>(creator->isolate());
792 v8::HandleScope scope(v8_isolate);
793 v8::Local<v8::Context> context = v8::Context::New(v8_isolate);
794 if (embedded_source != nullptr &&
795 !RunExtraCode(v8_isolate, context, embedded_source, "<embedded>")) {
796 return {};
797 }
800 }
801 return creator->CreateBlob(function_code_handling, serializer_flags);
802}
803
805 v8::SnapshotCreator::FunctionCodeHandling function_code_handling,
806 const char* embedded_source, Snapshot::SerializerFlags serializer_flags) {
807 std::unique_ptr<v8::ArrayBuffer::Allocator> array_buffer_allocator(
809 v8::Isolate::CreateParams create_params;
810 create_params.array_buffer_allocator = array_buffer_allocator.get();
811 v8::SnapshotCreator creator(create_params);
812 return CreateSnapshotDataBlobInternal(function_code_handling, embedded_source,
813 creator, serializer_flags);
814}
815
817 v8::SnapshotCreator::FunctionCodeHandling function_code_handling,
818 const char* embedded_source) {
819 return CreateSnapshotDataBlobInternal(function_code_handling,
820 embedded_source);
821}
822
824 v8::StartupData cold_snapshot_blob, const char* warmup_source) {
825 CHECK(cold_snapshot_blob.raw_size > 0 && cold_snapshot_blob.data != nullptr);
826 CHECK_NOT_NULL(warmup_source);
827
828 // Use following steps to create a warmed up snapshot blob from a cold one:
829 // - Create a new isolate from the cold snapshot.
830 // - Create a new context to run the warmup script. This will trigger
831 // compilation of executed functions.
832 // - Create a new context. This context will be unpolluted.
833 // - Serialize the isolate and the second context into a new snapshot blob.
834
835 std::unique_ptr<v8::ArrayBuffer::Allocator> allocator(
838 params.snapshot_blob = &cold_snapshot_blob;
839 params.array_buffer_allocator = allocator.get();
840 v8::SnapshotCreator snapshot_creator(params);
841 v8::Isolate* isolate = snapshot_creator.GetIsolate();
842 {
843 v8::HandleScope scope(isolate);
844 v8::Local<v8::Context> context = v8::Context::New(isolate);
845 if (!RunExtraCode(isolate, context, warmup_source, "<warm-up>")) {
846 return {};
847 }
848 }
849 {
850 v8::HandleScope handle_scope(isolate);
851 isolate->ContextDisposedNotification(v8::ContextDependants::kNoDependants);
852 v8::Local<v8::Context> context = v8::Context::New(isolate);
853 snapshot_creator.SetDefaultContext(context);
854 }
855
856 return snapshot_creator.CreateBlob(
858}
859
861 isolate_->enable_serializer();
862 isolate_->Enter();
863
864 if (blob != nullptr && blob->raw_size > 0) {
865 isolate_->set_snapshot_blob(blob);
867 } else {
868 isolate_->InitWithoutSnapshot();
869 }
870
871#ifdef V8_ENABLE_SPARKPLUG
872 isolate_->baseline_batch_compiler()->set_enabled(false);
873#endif // V8_ENABLE_SPARKPLUG
874
875 // Reserve a spot for the default context s.t. the call sequence of
876 // SetDefaultContext / AddContext remains independent.
877 contexts_.push_back(SerializableContext{});
878 DCHECK_EQ(contexts_.size(), kDefaultContextIndex + 1);
879}
880
882 Isolate* isolate, const intptr_t* api_external_references,
883 const StartupData* existing_blob, bool owns_isolate)
884 : owns_isolate_(owns_isolate),
885 isolate_(isolate == nullptr ? Isolate::New() : isolate),
886 array_buffer_allocator_(ArrayBuffer::Allocator::NewDefaultAllocator()) {
888
890 isolate_->set_api_external_references(api_external_references);
891
892 InitInternal(existing_blob ? existing_blob : Snapshot::DefaultSnapshotBlob());
893}
894
896 const v8::Isolate::CreateParams& params)
897 : owns_isolate_(true), isolate_(Isolate::New()) {
898 if (auto allocator = params.array_buffer_allocator_shared) {
899 CHECK(params.array_buffer_allocator == nullptr ||
900 params.array_buffer_allocator == allocator.get());
901 isolate_->set_array_buffer_allocator(allocator.get());
902 isolate_->set_array_buffer_allocator_shared(std::move(allocator));
903 } else {
904 CHECK_NOT_NULL(params.array_buffer_allocator);
905 isolate_->set_array_buffer_allocator(params.array_buffer_allocator);
906 }
907 isolate_->set_api_external_references(params.external_references);
908 isolate_->heap()->ConfigureHeap(params.constraints, params.cpp_heap);
909
910 InitInternal(params.snapshot_blob ? params.snapshot_blob
912}
913
915 Isolate* isolate, const v8::Isolate::CreateParams& params)
916 : owns_isolate_(false), isolate_(isolate) {
917 if (auto allocator = params.array_buffer_allocator_shared) {
918 CHECK(params.array_buffer_allocator == nullptr ||
919 params.array_buffer_allocator == allocator.get());
920 isolate_->set_array_buffer_allocator(allocator.get());
921 isolate_->set_array_buffer_allocator_shared(std::move(allocator));
922 } else {
923 CHECK_NOT_NULL(params.array_buffer_allocator);
924 isolate_->set_array_buffer_allocator(params.array_buffer_allocator);
925 }
926 isolate_->set_api_external_references(params.external_references);
927 isolate_->heap()->ConfigureHeap(params.constraints, params.cpp_heap);
928
929 InitInternal(params.snapshot_blob ? params.snapshot_blob
931}
932
934 if (isolate_->heap()->read_only_space()->writable()) {
935 // Finalize the RO heap in order to leave the Isolate in a consistent state.
937 }
938 // Destroy leftover global handles (i.e. if CreateBlob was never called).
939 for (size_t i = 0; i < contexts_.size(); i++) {
940 DCHECK(!created());
941 GlobalHandles::Destroy(contexts_[i].handle_location);
942 contexts_[i].handle_location = nullptr;
943 }
944 isolate_->Exit();
946}
947
951 DCHECK(contexts_[kDefaultContextIndex].handle_location == nullptr);
952 DCHECK(!context.is_null());
953 DCHECK(!created());
954 CHECK_EQ(isolate_, context->GetIsolate());
955 contexts_[kDefaultContextIndex].handle_location =
956 isolate_->global_handles()->Create(*context).location();
958}
959
963 DCHECK(!context.is_null());
964 DCHECK(!created());
965 CHECK_EQ(isolate_, context->GetIsolate());
966 size_t index = contexts_.size() - kFirstAddtlContextIndex;
967 contexts_.emplace_back(
968 isolate_->global_handles()->Create(*context).location(), callback);
969 return index;
970}
971
973 Address object) {
974 CHECK_EQ(isolate_, context->GetIsolate());
975 DCHECK_NE(object, kNullAddress);
976 DCHECK(!created());
977 HandleScope scope(isolate_);
980 if (!IsArrayList(context->serialized_objects())) {
981 list = ArrayList::New(isolate_, 1);
982 } else {
983 list =
984 direct_handle(Cast<ArrayList>(context->serialized_objects()), isolate_);
985 }
986 size_t index = static_cast<size_t>(list->length());
987 list = ArrayList::Add(isolate_, list, obj);
988 context->set_serialized_objects(*list);
989 return index;
990}
991
993 DCHECK_NE(object, kNullAddress);
994 DCHECK(!created());
995 HandleScope scope(isolate_);
998 if (!IsArrayList(isolate_->heap()->serialized_objects())) {
999 list = ArrayList::New(isolate_, 1);
1000 } else {
1001 list = direct_handle(
1002 Cast<ArrayList>(isolate_->heap()->serialized_objects()), isolate_);
1003 }
1004 size_t index = static_cast<size_t>(list->length());
1005 list = ArrayList::Add(isolate_, list, obj);
1007 return index;
1008}
1009
1013
1014namespace {
1015
1016void ConvertSerializedObjectsToFixedArray(Isolate* isolate) {
1017 if (!IsArrayList(isolate->heap()->serialized_objects())) {
1018 isolate->heap()->SetSerializedObjects(
1019 ReadOnlyRoots(isolate).empty_fixed_array());
1020 } else {
1021 DirectHandle<ArrayList> list(
1022 Cast<ArrayList>(isolate->heap()->serialized_objects()), isolate);
1023 DirectHandle<FixedArray> elements = ArrayList::ToFixedArray(isolate, list);
1024 isolate->heap()->SetSerializedObjects(*elements);
1025 }
1026}
1027
1028void ConvertSerializedObjectsToFixedArray(Isolate* isolate,
1029 DirectHandle<NativeContext> context) {
1030 if (!IsArrayList(context->serialized_objects())) {
1031 context->set_serialized_objects(ReadOnlyRoots(isolate).empty_fixed_array());
1032 } else {
1033 DirectHandle<ArrayList> list(Cast<ArrayList>(context->serialized_objects()),
1034 isolate);
1035 DirectHandle<FixedArray> elements = ArrayList::ToFixedArray(isolate, list);
1036 context->set_serialized_objects(*elements);
1037 }
1038}
1039
1040} // anonymous namespace
1041
1042// static
1044 SnapshotCreator::FunctionCodeHandling function_code_handling,
1045 Snapshot::SerializerFlags serializer_flags) {
1046 CHECK(!created());
1047 CHECK(contexts_[kDefaultContextIndex].handle_location != nullptr);
1048
1049 const size_t num_contexts = contexts_.size();
1050 const size_t num_additional_contexts = num_contexts - 1;
1051
1052 // Create and store lists of embedder-provided data needed during
1053 // serialization.
1054 {
1055 HandleScope scope(isolate_);
1056
1057 // Convert list of context-independent data to FixedArray.
1058 ConvertSerializedObjectsToFixedArray(isolate_);
1059
1060 // Convert lists of context-dependent data to FixedArray.
1061 for (size_t i = 0; i < num_contexts; i++) {
1062 ConvertSerializedObjectsToFixedArray(isolate_, context_at(i));
1063 }
1064
1065 // We need to store the global proxy size upfront in case we need the
1066 // bootstrapper to create a global proxy before we deserialize the context.
1067 DirectHandle<FixedArray> global_proxy_sizes =
1069 static_cast<int>(num_additional_contexts), AllocationType::kOld);
1070 for (size_t i = kFirstAddtlContextIndex; i < num_contexts; i++) {
1071 global_proxy_sizes->set(
1072 static_cast<int>(i - kFirstAddtlContextIndex),
1073 Smi::FromInt(context_at(i)->global_proxy()->Size()));
1074 }
1075 isolate_->heap()->SetSerializedGlobalProxySizes(*global_proxy_sizes);
1076 }
1077
1078 // We might rehash strings and re-sort descriptors. Clear the lookup cache.
1080
1081 // If we don't do this then we end up with a stray root pointing at the
1082 // context even after we have disposed of the context.
1083 {
1084 // Note that we need to run a garbage collection without stack at this
1085 // point, so that all dead objects are reclaimed. This is required to avoid
1086 // conservative stack scanning and guarantee deterministic behaviour.
1087 EmbedderStackStateScope stack_scope(
1089 StackState::kNoHeapPointers);
1092 }
1093 {
1094 HandleScope scope(isolate_);
1096 }
1097
1099 isolate_,
1100 function_code_handling == SnapshotCreator::FunctionCodeHandling::kClear);
1101
1102 SafepointKind safepoint_kind = isolate_->has_shared_space()
1105 SafepointScope safepoint_scope(isolate_, safepoint_kind);
1106 DisallowGarbageCollection no_gc_from_here_on;
1107
1108 // RO space is usually writable when serializing a snapshot s.t. preceding
1109 // heap initialization can also extend RO space. There are notable exceptions
1110 // though, including --stress-snapshot and serializer cctests.
1111 if (isolate_->heap()->read_only_space()->writable()) {
1112 // Promote objects from mutable heap spaces to read-only space prior to
1113 // serialization. Objects can be promoted if a) they are themselves
1114 // immutable-after-deserialization and b) all objects in the transitive
1115 // object graph also satisfy condition a).
1116 ReadOnlyPromotion::Promote(isolate_, safepoint_scope, no_gc_from_here_on);
1117 // When creating the snapshot from scratch, we are responsible for sealing
1118 // the RO heap here. Note we cannot delegate the responsibility e.g. to
1119 // Isolate::Init since it should still be possible to allocate into RO
1120 // space after the Isolate has been initialized, for example as part of
1121 // Context creation.
1123 }
1124
1125 // Create a vector with all contexts and destroy associated global handles.
1126 // This is important because serialization visits active global handles as
1127 // roots, which we don't want for our internal SnapshotCreatorImpl-related
1128 // data.
1129 // Note these contexts may be dead after calling Clear(), but will not be
1130 // collected until serialization completes and the DisallowGarbageCollection
1131 // scope above goes out of scope.
1132 std::vector<Tagged<Context>> raw_contexts;
1133 raw_contexts.reserve(num_contexts);
1134 {
1135 HandleScope scope(isolate_);
1136 for (size_t i = 0; i < num_contexts; i++) {
1137 raw_contexts.push_back(*context_at(i));
1138 GlobalHandles::Destroy(contexts_[i].handle_location);
1139 contexts_[i].handle_location = nullptr;
1140 }
1141 }
1142
1143 // Check that values referenced by global/eternal handles are accounted for.
1144 SerializedHandleChecker handle_checker(isolate_, &raw_contexts);
1145 if (!handle_checker.CheckGlobalAndEternalHandles()) {
1146 GRACEFUL_FATAL("CheckGlobalAndEternalHandles failed");
1147 }
1148
1149 // Create a vector with all embedder fields serializers.
1150 std::vector<SerializeEmbedderFieldsCallback> raw_callbacks;
1151 raw_callbacks.reserve(num_contexts);
1152 for (size_t i = 0; i < num_contexts; i++) {
1153 raw_callbacks.push_back(contexts_[i].callback);
1154 }
1155
1156 contexts_.clear();
1157 return Snapshot::Create(isolate_, &raw_contexts, raw_callbacks,
1158 safepoint_scope, no_gc_from_here_on,
1159 serializer_flags);
1160}
1161
1163 v8::SnapshotCreator* snapshot_creator) {
1164 return snapshot_creator->impl_;
1165}
1166
1167} // namespace internal
1168} // namespace v8
Isolate * isolate_
union v8::internal::@341::BuiltinMetadata::KindSpecificData data
#define BUILTIN_CODE(isolate, name)
Definition builtins.h:45
static Allocator * NewDefaultAllocator()
Definition api.cc:8923
static Local< Context > New(Isolate *isolate, ExtensionConfiguration *extensions=nullptr, MaybeLocal< ObjectTemplate > global_template=MaybeLocal< ObjectTemplate >(), MaybeLocal< Value > global_object=MaybeLocal< Value >(), DeserializeInternalFieldsCallback internal_fields_deserializer=DeserializeInternalFieldsCallback(), MicrotaskQueue *microtask_queue=nullptr, DeserializeContextDataCallback context_data_deserializer=DeserializeContextDataCallback(), DeserializeAPIWrapperCallback api_wrapper_deserializer=DeserializeAPIWrapperCallback())
Definition api.cc:6778
static V8_WARN_UNUSED_RESULT MaybeLocal< Script > Compile(Local< Context > context, Source *source, CompileOptions options=kNoCompileOptions, NoCacheReason no_cache_reason=kNoCacheNoReason)
Definition api.cc:2438
Isolate * GetIsolate()
Definition api.cc:376
void SetDefaultContext(Local< Context > context, SerializeInternalFieldsCallback internal_fields_serializer=SerializeInternalFieldsCallback(), SerializeContextDataCallback context_data_serializer=SerializeContextDataCallback(), SerializeAPIWrapperCallback api_wrapper_serializer=SerializeAPIWrapperCallback())
Definition api.cc:380
StartupData CreateBlob(FunctionCodeHandling function_code_handling)
Definition api.cc:412
internal::SnapshotCreatorImpl * impl_
const char * data
Definition v8-snapshot.h:35
static V8_WARN_UNUSED_RESULT MaybeLocal< String > NewFromUtf8(Isolate *isolate, const char *data, NewStringType type=NewStringType::kNormal, int length=-1)
Definition api.cc:7593
static v8::internal::DirectHandle< To > OpenDirectHandle(v8::Local< From > handle)
Definition api.h:279
int length() const
Definition vector.h:64
constexpr T * begin() const
Definition vector.h:96
static V8_EXPORT_PRIVATE DirectHandle< ArrayList > Add(Isolate *isolate, DirectHandle< ArrayList > array, Tagged< Smi > obj, AllocationType allocation=AllocationType::kYoung)
static V8_EXPORT_PRIVATE DirectHandle< FixedArray > ToFixedArray(Isolate *isolate, DirectHandle< ArrayList > array, AllocationType allocation=AllocationType::kYoung)
static DirectHandle< ArrayList > New(IsolateT *isolate, int capacity, AllocationType allocation=AllocationType::kYoung)
DirectHandle< NativeContext > CreateEnvironmentForTesting()
static MaybeDirectHandle< Context > DeserializeContext(Isolate *isolate, const SnapshotData *data, size_t context_index, bool can_rehash, DirectHandle< JSGlobalProxy > global_proxy, DeserializeEmbedderFieldsCallback embedder_fields_deserializer)
void Serialize(Tagged< Context > *o, const DisallowGarbageCollection &no_gc)
static V8_INLINE DirectHandle FromSlot(Address *slot)
Definition handles.h:687
Handle< FixedArray > NewFixedArray(int length, AllocationType allocation=AllocationType::kYoung)
static void Destroy(Address *location)
IndirectHandle< Object > Create(Tagged< Object > value)
static void VerifyHeap(Heap *heap)
void CompactWeakArrayLists()
Definition heap.cc:6289
void ConfigureHeap(const v8::ResourceConstraints &constraints, v8::CppHeap *cpp_heap)
Definition heap.cc:4917
V8_EXPORT_PRIVATE void CollectAllAvailableGarbage(GarbageCollectionReason gc_reason)
Definition heap.cc:1327
void SetSerializedObjects(Tagged< HeapObject > objects)
Definition heap.cc:166
ReadOnlySpace * read_only_space() const
Definition heap.h:738
void SetSerializedGlobalProxySizes(Tagged< FixedArray > sizes)
Definition heap.cc:171
GlobalHandles * global_handles() const
Definition isolate.h:1416
ReadOnlyHeap * read_only_heap() const
Definition isolate.h:1201
Bootstrapper * bootstrapper()
Definition isolate.h:1178
static Isolate * New()
Definition isolate.cc:4093
static void Delete(Isolate *isolate)
Definition isolate.cc:4115
bool has_shared_space() const
Definition isolate.h:2303
DescriptorLookupCache * descriptor_lookup_cache() const
Definition isolate.h:1389
v8::internal::Factory * factory()
Definition isolate.h:1527
void set_array_buffer_allocator(v8::ArrayBuffer::Allocator *allocator)
Definition isolate.h:1935
V8_EXPORT_PRIVATE void OnCreateHeapObjectsComplete(Isolate *isolate)
static V8_EXPORT_PRIVATE void Promote(Isolate *isolate, const SafepointScope &safepoint_scope, const DisallowGarbageCollection &no_gc)
int TotalAllocationSize() const
Definition serializer.cc:80
static constexpr Tagged< Smi > FromInt(int value)
Definition smi.h:38
static V8_EXPORT_PRIVATE SnapshotData Decompress(base::Vector< const uint8_t > compressed_data)
static constexpr size_t kFirstAddtlContextIndex
Definition snapshot.h:188
void SetDefaultContext(DirectHandle< NativeContext > context, SerializeEmbedderFieldsCallback callback)
Definition snapshot.cc:948
size_t AddContext(DirectHandle< NativeContext > context, SerializeEmbedderFieldsCallback callback)
Definition snapshot.cc:960
static constexpr size_t kDefaultContextIndex
Definition snapshot.h:187
std::vector< SerializableContext > contexts_
Definition snapshot.h:208
SnapshotCreatorImpl(Isolate *isolate, const intptr_t *api_external_references, const StartupData *existing_blob, bool owns_isolate)
Definition snapshot.cc:881
size_t AddData(DirectHandle< NativeContext > context, Address object)
Definition snapshot.cc:972
static SnapshotCreatorImpl * FromSnapshotCreator(v8::SnapshotCreator *snapshot_creator)
Definition snapshot.cc:1162
DirectHandle< NativeContext > context_at(size_t i) const
Definition snapshot.cc:1010
void InitInternal(const StartupData *)
Definition snapshot.cc:860
StartupData CreateBlob(SnapshotCreator::FunctionCodeHandling function_code_handling, Snapshot::SerializerFlags serializer_flags=Snapshot::kDefaultSerializerFlags)
Definition snapshot.cc:1043
std::unique_ptr< v8::ArrayBuffer::Allocator > array_buffer_allocator_
Definition snapshot.h:207
base::Vector< const uint8_t > RawData() const
static bool VersionIsValid(const v8::StartupData *data)
Definition snapshot.cc:164
static V8_EXPORT_PRIVATE void ClearReconstructableDataForSerialization(Isolate *isolate, bool clear_recompilable_data)
Definition snapshot.cc:221
static V8_EXPORT_PRIVATE void SerializeDeserializeAndVerifyForTesting(Isolate *isolate, DirectHandle< Context > default_context)
Definition snapshot.cc:346
static v8::StartupData Create(Isolate *isolate, std::vector< Tagged< Context > > *contexts, const std::vector< SerializeEmbedderFieldsCallback > &embedder_fields_serializers, const SafepointScope &safepoint_scope, const DisallowGarbageCollection &no_gc, SerializerFlags flags=kDefaultSerializerFlags)
Definition snapshot.cc:409
static bool ExtractRehashability(const v8::StartupData *data)
Definition snapshot.cc:669
static bool Initialize(Isolate *isolate)
Definition snapshot.cc:176
static const v8::StartupData * DefaultSnapshotBlob()
static V8_EXPORT_PRIVATE uint32_t GetExpectedChecksum(const v8::StartupData *data)
Definition snapshot.cc:640
@ kReconstructReadOnlyAndSharedObjectCachesForTesting
Definition snapshot.h:54
@ kAllowUnknownExternalReferencesForTesting
Definition snapshot.h:34
static bool HasContextSnapshot(Isolate *isolate, size_t index)
Definition snapshot.cc:154
static V8_EXPORT_PRIVATE uint32_t CalculateChecksum(const v8::StartupData *data)
Definition snapshot.cc:643
static MaybeDirectHandle< Context > NewContextFromSnapshot(Isolate *isolate, DirectHandle< JSGlobalProxy > global_proxy, size_t context_index, DeserializeEmbedderFieldsCallback embedder_fields_deserializer)
Definition snapshot.cc:203
static bool ShouldVerifyChecksum(const v8::StartupData *data)
static V8_EXPORT_PRIVATE bool VerifyChecksum(const v8::StartupData *data)
Definition snapshot.cc:647
static V8_EXPORT_PRIVATE uint32_t ExtractReadOnlySnapshotChecksum(const v8::StartupData *data)
Definition snapshot.cc:677
void SerializeStrongReferences(const DisallowGarbageCollection &no_gc)
V8_INLINE constexpr bool is_null() const
Definition tagged.h:502
static void GetString(base::Vector< char > str)
Definition version.cc:29
#define POINTER_SIZE_ALIGN(value)
Definition globals.h:1804
int32_t offset
TNode< Object > callback
ZoneVector< RpoNumber > & result
InstructionOperand source
static void WriteLittleEndianValue(Address p, V value)
Definition memory.h:67
static V ReadLittleEndianValue(Address p)
Definition memory.h:52
void CopyBytes(T *dst, const T *src, size_t num_bytes)
Definition memcopy.h:261
v8::StartupData CreateSnapshotDataBlobInternalForInspectorTest(v8::SnapshotCreator::FunctionCodeHandling function_code_handling, const char *embedded_source)
Definition snapshot.cc:816
SnapshotData MaybeDecompress(Isolate *isolate, base::Vector< const uint8_t > snapshot_data)
Definition snapshot.cc:135
bool Is(IndirectHandle< U > value)
Definition handles-inl.h:51
void PrintF(const char *format,...)
Definition utils.cc:39
void MemsetTagged(Tagged_t *start, Tagged< MaybeObject > value, size_t counter)
Definition slots-inl.h:486
V8_INLINE DirectHandle< T > direct_handle(Tagged< T > object, Isolate *isolate)
Flag flags[]
Definition flags.cc:3797
constexpr int kInt32Size
Definition globals.h:401
Tagged< ClearedWeakValue > ClearedValue(PtrComprCageBase cage_base)
V8_EXPORT_PRIVATE FlagValues v8_flags
v8::StartupData WarmUpSnapshotDataBlobInternal(v8::StartupData cold_snapshot_blob, const char *warmup_source)
Definition snapshot.cc:823
constexpr int kUInt32Size
Definition globals.h:403
static constexpr Address kNullAddress
Definition v8-internal.h:53
v8::StartupData CreateSnapshotDataBlobInternal(v8::SnapshotCreator::FunctionCodeHandling function_code_handling, const char *embedded_source, SnapshotCreator &snapshot_creator, Snapshot::SerializerFlags serializer_flags)
Definition snapshot.cc:784
uint32_t Checksum(base::Vector< const uint8_t > payload)
kInterpreterTrampolineOffset script
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Definition casting.h:150
bool ToLocal(v8::internal::MaybeDirectHandle< v8::internal::Object > maybe, Local< T > *local)
Definition api.h:303
#define RCS_SCOPE(...)
static const uint32_t kRehashabilityOffset
Definition snapshot.cc:93
static const uint32_t kFirstContextOffsetOffset
Definition snapshot.cc:105
static const uint32_t kReadOnlySnapshotChecksumOffset
Definition snapshot.cc:96
static const uint32_t kSharedHeapOffsetOffset
Definition snapshot.cc:103
static const uint32_t kVersionStringLength
Definition snapshot.cc:100
static const uint32_t kNumberOfContextsOffset
Definition snapshot.cc:91
static const uint32_t kReadOnlyOffsetOffset
Definition snapshot.cc:101
static const uint32_t kVersionStringOffset
Definition snapshot.cc:98
static const uint32_t kChecksumOffset
Definition snapshot.cc:95
#define FATAL(...)
Definition logging.h:47
#define GRACEFUL_FATAL(...)
Definition logging.h:41
#define CHECK_IMPLIES(lhs, rhs)
#define CHECK(condition)
Definition logging.h:124
#define CHECK_LT(lhs, rhs)
#define DCHECK_NOT_NULL(val)
Definition logging.h:492
#define CHECK_NOT_NULL(val)
#define DCHECK_NE(v1, v2)
Definition logging.h:486
#define CHECK_EQ(lhs, rhs)
#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 DCHECK_GT(v1, v2)
Definition logging.h:487
ArrayBuffer::Allocator * array_buffer_allocator
Definition v8-isolate.h:326
const StartupData * snapshot_blob
Definition v8-isolate.h:300
#define TRACE_EVENT0(category_group, name)