36#if V8_COMPRESS_POINTERS
39 hot_objects_(isolate->
heap()),
40 reference_map_(isolate),
41 external_reference_encoder_(isolate),
42 root_index_map_(isolate),
43 deferred_objects_(isolate->
heap()),
44 forward_refs_per_pending_object_(isolate->
heap()),
48 back_refs_(isolate->
heap()),
49 stack_(isolate->
heap())
52#ifdef VERBOSE_SERIALIZATION_STATISTICS
53 if (
v8_flags.serialization_statistics) {
54 for (int space = 0; space < kNumberOfSnapshotSpaces; ++space) {
56 instance_type_count_[space] = std::make_unique<int[]>(kInstanceTypes);
57 instance_type_size_[space] = std::make_unique<size_t[]>(kInstanceTypes);
64void Serializer::PopStack() { stack_.Pop(); }
71 const int space_number =
static_cast<int>(
space);
72 allocation_size_[space_number] +=
size;
73#ifdef VERBOSE_SERIALIZATION_STATISTICS
74 int instance_type = map->instance_type();
75 instance_type_count_[space_number][instance_type]++;
76 instance_type_size_[space_number][instance_type] +=
size;
80int Serializer::TotalAllocationSize()
const {
82 for (
int space = 0; space < kNumberOfSnapshotSpaces; space++) {
83 sum += allocation_size_[
space];
92 case SnapshotSpace::kReadOnlyHeap:
93 return "ReadOnlyHeap";
94 case SnapshotSpace::kOld:
96 case SnapshotSpace::kCode:
98 case SnapshotSpace::kTrusted:
105void Serializer::OutputStatistics(
const char* name) {
106 if (!
v8_flags.serialization_statistics)
return;
109 if (!serializer_tracks_serialization_statistics()) {
110 PrintF(
" <serialization statistics are not tracked>\n");
114 PrintF(
" Spaces (bytes):\n");
117 SnapshotSpace::kReadOnlyHeap,
119 SnapshotSpace::kCode,
128 PrintF(
"%16zu", allocation_size_[
static_cast<int>(space)]);
132#ifdef VERBOSE_SERIALIZATION_STATISTICS
133 PrintF(
" Instance types (count and bytes):\n");
134#define PRINT_INSTANCE_TYPE(Name) \
135 for (SnapshotSpace space : kAllSnapshotSpaces) { \
136 const int space_i = static_cast<int>(space); \
137 if (instance_type_count_[space_i][Name]) { \
138 PrintF("%10d %10zu %-10s %s\n", instance_type_count_[space_i][Name], \
139 instance_type_size_[space_i][Name], ToString(space), #Name); \
143#undef PRINT_INSTANCE_TYPE
148void Serializer::SerializeDeferredObjects() {
150 PrintF(
"Serializing deferred objects\n");
153 Handle<HeapObject> obj = handle(deferred_objects_.Pop(), isolate());
155 ObjectSerializer obj_serializer(this, obj, &sink_);
156 obj_serializer.SerializeDeferred();
158 sink_.Put(kSynchronize,
"Finished with deferred objects");
164 if (IsThinString(*obj,
isolate())) {
165 obj =
handle(Cast<ThinString>(*obj)->actual(), isolate());
166 }
else if (IsCode(*obj,
isolate())) {
169 if (code->kind() == CodeKind::BASELINE) {
173 obj =
handle(code->bytecode_or_interpreter_data(), isolate());
175 CHECK(code->is_builtin());
178 SerializeObjectImpl(obj, slot_type);
183void Serializer::VisitRootPointers(
Root root,
const char* description,
186 SerializeRootObject(current);
200void Serializer::PrintStack() { PrintStack(std::cout); }
202void Serializer::PrintStack(std::ostream& out) {
203 for (
const auto o : stack_) {
214 if (root_index_map()->Lookup(obj, &root_index)) {
224 int index = hot_objects_.Find(obj);
225 if (index == HotObjectsList::kNotFound)
return false;
226 DCHECK(index >= 0 && index < kHotObjectCount);
228 PrintF(
" Encoding hot object %d:", index);
232 sink_.Put(HotObject::Encode(index),
"HotObject");
239 if (reference ==
nullptr)
return false;
246 PrintF(
" Encoding attached reference %d\n",
249 PutAttachedReference(*reference);
253 PrintF(
" Encoding back reference to: ");
258 sink_.Put(kBackref,
"Backref");
259 PutBackReference(obj, *reference);
266 forward_refs_per_pending_object_.Find(obj);
267 if (refs_to_object ==
nullptr) {
270 PutPendingForwardReference(*refs_to_object);
275 if (!IsCode(obj))
return false;
276 return (Cast<Code>(obj)->
kind() == CodeKind::BYTECODE_HANDLER);
281 int root_index =
static_cast<int>(root);
284 PrintF(
" Encoding root %d:", root_index);
291 static_assert(
static_cast<int>(RootIndex::kArgumentsMarker) ==
292 kRootArrayConstantsCount - 1);
295 if (root_index < kRootArrayConstantsCount &&
296 !HeapLayout::InYoungGeneration(
object)) {
297 sink_.Put(RootArrayConstant::Encode(root),
"RootConstant");
299 sink_.Put(kRootArray,
"RootSerialization");
300 sink_.PutUint30(root_index,
"root_index");
301 hot_objects_.Add(
object);
309 static_assert(
decltype(slot)::kSlotDataSize ==
sizeof(Address));
311 static constexpr int bytes_to_output =
decltype(slot)::kSlotDataSize;
312 static constexpr int size_in_tagged = bytes_to_output >>
kTaggedSizeLog2;
313 sink_.Put(FixedRawDataWithSize::Encode(size_in_tagged),
"Smi");
315 Address raw_value = Cast<Smi>(*slot).ptr();
316 const uint8_t* raw_value_as_bytes =
317 reinterpret_cast<const uint8_t*
>(&raw_value);
318 sink_.PutRaw(raw_value_as_bytes, bytes_to_output,
"Bytes");
325 hot_objects_.Add(
object);
330 sink_.Put(kAttachedReference,
"AttachedRef");
334void Serializer::PutRepeatRoot(
int repeat_count,
RootIndex root_index) {
335 if (repeat_count <= kLastEncodableFixedRepeatRootCount) {
336 sink_.Put(FixedRepeatRootWithCount::Encode(repeat_count),
339 sink_.Put(kVariableRepeatRoot,
"VariableRepeatRoot");
340 sink_.PutUint30(VariableRepeatRootCount::Encode(repeat_count),
343 DCHECK_LE(
static_cast<uint32_t
>(root_index), UINT8_MAX);
344 sink_.Put(
static_cast<uint8_t
>(root_index),
"root index");
348 sink_.Put(kRegisterPendingForwardRef,
"RegisterPendingForwardRef");
349 unresolved_forward_refs_++;
351 int forward_ref_id = next_forward_ref_id_++;
352 if (refs ==
nullptr) {
357 refs =
new std::vector<int>();
359 refs->push_back(forward_ref_id);
362void Serializer::ResolvePendingForwardReference(
int forward_reference_id) {
363 sink_.Put(kResolvePendingForwardRef,
"ResolvePendingForwardRef");
364 sink_.PutUint30(forward_reference_id,
"with this index");
365 unresolved_forward_refs_--;
369 if (unresolved_forward_refs_ == 0) {
370 next_forward_ref_id_ = 0;
377 external_reference_encoder_.TryEncode(addr);
380 PrintStack(std::cerr);
382 void* addr_ptr =
reinterpret_cast<void*
>(addr);
383 v8::base::OS::PrintError(
"Unknown external reference %p.\n", addr_ptr);
384 v8::base::OS::PrintError(
"%s\n",
385 ExternalReferenceTable::ResolveSymbol(addr_ptr));
393 if (IsNotMappedSymbol(obj))
return;
396 auto find_result = forward_refs_per_pending_object_.FindOrInsert(obj);
403 DCHECK_IMPLIES(find_result.already_exists, *find_result.entry !=
nullptr);
405 CanBeDeferred(obj, SlotType::kAnySlot));
410 if (IsNotMappedSymbol(obj))
return;
412 std::vector<int>* refs;
413 CHECK(forward_refs_per_pending_object_.Delete(obj, &refs));
415 for (
int index : *refs) {
416 ResolvePendingForwardReference(index);
424void Serializer::Pad(
int padding_offset) {
427 for (
unsigned i = 0;
i <
sizeof(int32_t) - 1;
i++) {
428 sink_.Put(kNop,
"Padding");
432 sink_.Put(kNop,
"Padding");
436void Serializer::InitializeCodeAddressMap() {
437 isolate_->InitializeLoggingAndCounters();
438 code_address_map_ = std::make_unique<CodeAddressMap>(
isolate_);
443 code_buffer_.clear();
447 code_buffer_.resize(InstructionStream::kCodeAlignmentMinusCodeHeader);
448 int size = istream->Size();
449 code_buffer_.insert(code_buffer_.end(),
450 reinterpret_cast<uint8_t*
>(istream.
address()),
451 reinterpret_cast<uint8_t*
>(istream.
address() + size));
454 return UncheckedCast<InstructionStream>(
455 HeapObject::FromAddress(
reinterpret_cast<Address
>(
456 &code_buffer_[InstructionStream::kCodeAlignmentMinusCodeHeader])));
462 if (serializer_->code_address_map_) {
463 const char* code_name =
464 serializer_->code_address_map_->Lookup(
object_->address());
465 LOG(serializer_->isolate_,
466 CodeNameEvent(
object_->address(),
sink_->Position(), code_name));
469 if (map.SafeEquals(*
object_)) {
471 DCHECK_EQ(space, SnapshotSpace::kReadOnlyHeap);
472 sink_->Put(kNewContextlessMetaMap,
"NewContextlessMetaMap");
475 DCHECK(IsContext(map->native_context_or_null()));
476 sink_->Put(kNewContextfulMetaMap,
"NewContextfulMetaMap");
492 if (!serializer_->forward_refs_per_pending_object_.Find(
native_context)) {
499 sink_->Put(NewObject::Encode(space),
"NewObject");
505 serializer_->RegisterObjectIsPending(*
object_);
512 serializer_->SerializeObject(
handle(map,
isolate()), SlotType::kMapSlot);
517 !serializer_->IsNotMappedSymbol(*
object_),
518 serializer_->reference_map()->LookupReference(
object_) ==
nullptr);
525 sink_->Put(kInitializeSelfIndirectPointer,
526 "InitializeSelfIndirectPointer");
531 serializer_->ResolvePendingObject(*
object_);
534 if (
v8_flags.serialization_statistics) {
535 serializer_->CountAllocation(
object_->map(), size, space);
548 serializer_->num_back_refs_++;
550 serializer_->back_refs_.Push(*
object_);
551 DCHECK_EQ(serializer_->back_refs_.size(), serializer_->num_back_refs_);
553 if (!serializer_->IsNotMappedSymbol(*
object_)) {
558 SerializerReference::BackReference(serializer_->num_back_refs_ - 1);
559 serializer_->reference_map()->Add(*
object_, back_reference);
568uint32_t Serializer::ObjectSerializer::SerializeBackingStore(
569 void* backing_store, uint32_t byte_length,
573 serializer_->reference_map()->LookupBackingStore(backing_store);
579 if (max_byte_length.
IsJust()) {
580 sink_->Put(kOffHeapResizableBackingStore,
581 "Off-heap resizable backing store");
583 sink_->Put(kOffHeapBackingStore,
"Off-heap backing store");
585 sink_->PutUint32(byte_length,
"length");
586 if (max_byte_length.
IsJust()) {
589 sink_->PutRaw(
static_cast<uint8_t*
>(backing_store), byte_length,
591 DCHECK_NE(0, serializer_->seen_backing_stores_index_);
593 SerializerReference::OffHeapBackingStoreReference(
594 serializer_->seen_backing_stores_index_++);
596 serializer_->reference_map()->AddBackingStore(backing_store, reference);
600void Serializer::ObjectSerializer::SerializeJSTypedArray() {
604 if (typed_array->is_on_heap()) {
605 typed_array->RemoveExternalPointerCompensationForSerialization(
isolate());
607 if (!typed_array->IsDetachedOrOutOfBounds()) {
610 Cast<JSArrayBuffer>(typed_array->buffer());
613 size_t byte_length_size = buffer->GetByteLength();
615 size_t{std::numeric_limits<uint32_t>::max()});
616 uint32_t byte_length =
static_cast<uint32_t
>(byte_length_size);
618 if (buffer->is_resizable_by_js()) {
620 std::numeric_limits<uint32_t>::max());
622 Just(
static_cast<uint32_t
>(buffer->max_byte_length()));
624 size_t byte_offset = typed_array->byte_offset();
628 void* backing_store =
reinterpret_cast<void*
>(
629 reinterpret_cast<Address
>(typed_array->DataPtr()) - byte_offset);
632 SerializeBackingStore(backing_store, byte_length, max_byte_length);
633 typed_array->SetExternalBackingStoreRefForSerialization(ref);
635 typed_array->SetExternalBackingStoreRefForSerialization(0);
642void Serializer::ObjectSerializer::SerializeJSArrayBuffer() {
648 backing_store = buffer->backing_store();
651 size_t byte_length_size = buffer->GetByteLength();
652 CHECK_LE(byte_length_size, std::numeric_limits<uint32_t>::max());
653 uint32_t byte_length =
static_cast<uint32_t
>(byte_length_size);
655 if (buffer->is_resizable_by_js()) {
656 CHECK_LE(buffer->max_byte_length(), std::numeric_limits<uint32_t>::max());
657 max_byte_length =
Just(
static_cast<uint32_t
>(buffer->max_byte_length()));
662 if (buffer->IsEmpty()) {
663 buffer->SetBackingStoreRefForSerialization(kEmptyBackingStoreRefSentinel);
666 SerializeBackingStore(backing_store, byte_length, max_byte_length);
667 buffer->SetBackingStoreRefForSerialization(ref);
672 buffer->set_extension(
nullptr);
677 buffer->set_backing_store(
isolate(), backing_store);
682void Serializer::ObjectSerializer::SerializeExternalString() {
686 auto string = Cast<ExternalString>(
object_);
687 Address resource =
string->resource_as_address();
689 if (serializer_->external_reference_encoder_.TryEncode(resource).To(
692#ifdef V8_ENABLE_SANDBOX
693 uint32_t external_pointer_entry =
694 string->GetResourceRefForDeserialization();
696 string->SetResourceRefForSerialization(reference.
index());
698#ifdef V8_ENABLE_SANDBOX
699 string->SetResourceRefForSerialization(external_pointer_entry);
701 string->set_address_as_resource(
isolate(), resource);
704 SerializeExternalStringAsSequentialString();
708void Serializer::ObjectSerializer::SerializeExternalStringAsSequentialString() {
715 uint32_t length =
string->length();
719 const uint8_t* resource;
721 bool internalized = IsInternalizedString(*
object_, cage_base);
722 if (IsExternalOneByteString(*
object_, cage_base)) {
723 map = internalized ? roots.internalized_one_byte_string_map()
724 : roots.seq_one_byte_string_map();
725 allocation_size = SeqOneByteString::SizeFor(length);
727 resource =
reinterpret_cast<const uint8_t*
>(
728 Cast<ExternalOneByteString>(
string)->resource()->data());
730 map = internalized ? roots.internalized_two_byte_string_map()
731 : roots.seq_two_byte_string_map();
732 allocation_size = SeqTwoByteString::SizeFor(length);
734 resource =
reinterpret_cast<const uint8_t*
>(
735 Cast<ExternalTwoByteString>(
string)->resource()->data());
739 SerializePrologue(space, allocation_size, map);
742 int bytes_to_output = allocation_size - HeapObject::kHeaderSize;
747 sink_->Put(kVariableRawData,
"RawDataForString");
748 sink_->PutUint30(slots_to_output,
"length");
751 uint8_t* string_start =
reinterpret_cast<uint8_t*
>(
string->address());
753 sink_->Put(string_start[
i],
"StringHeader");
757 sink_->PutRaw(resource, content_size,
"StringContent");
761 size_t padding_size = allocation_size -
sizeof(
SeqString) - content_size;
763 for (
size_t i = 0;
i < padding_size;
i++) {
764 sink_->Put(
static_cast<uint8_t
>(0),
"StringPadding");
774 if (TryCast<AllocationSiteWithWeakNext>(
object, &
object_)) {
781 if (next_ == Smi::zero())
return;
794void Serializer::ObjectSerializer::Serialize(
SlotType slot_type) {
804 if (should_defer && CanBeDeferred(raw, slot_type)) {
806 PrintF(
" Deferring heap object: ");
811 serializer_->RegisterObjectIsPending(raw);
812 serializer_->PutPendingForwardReference(
813 *serializer_->forward_refs_per_pending_object_.Find(raw));
814 serializer_->QueueDeferredObject(raw);
818 PrintF(
" Exceeding max recursion depth by %d for: ",
826 PrintF(
" Encoding heap object: ");
834 if (InstanceTypeChecker::IsExternalString(instance_type)) {
835 SerializeExternalString();
838 if (InstanceTypeChecker::IsJSTypedArray(instance_type)) {
839 SerializeJSTypedArray();
842 if (InstanceTypeChecker::IsJSArrayBuffer(instance_type)) {
843 SerializeJSArrayBuffer();
846 if (InstanceTypeChecker::IsScript(instance_type)) {
848 Cast<Script>(
object_)->set_line_ends(Smi::zero());
849 Cast<Script>(
object_)->set_compiled_lazy_function_positions(
853#if V8_ENABLE_WEBASSEMBLY
859 !IsFreeSpaceOrFiller(*
object_, cage_base));
869 if (ReadOnlyHeap::Contains(
object)) {
870 return SnapshotSpace::kReadOnlyHeap;
873 MutablePageMetadata::FromHeapObject(
object)->owner_identity();
877 switch (heap_space) {
891 return SnapshotSpace::kOld;
893 return SnapshotSpace::kCode;
896 return SnapshotSpace::kTrusted;
902 return SnapshotSpace::kTrusted;
911void Serializer::ObjectSerializer::SerializeObject() {
913 int size =
object_->SizeFromMap(map);
927 SerializePrologue(space, size, map);
930 CHECK_EQ(0, bytes_processed_so_far_);
933 SerializeContent(map, size);
936void Serializer::ObjectSerializer::SerializeDeferred() {
938 serializer_->reference_map()->LookupReference(
object_);
940 if (back_reference !=
nullptr) {
942 PrintF(
" Deferred heap object ");
944 PrintF(
" was already serialized\n");
950 PrintF(
" Encoding deferred heap object\n");
952 Serialize(SlotType::kAnySlot);
955void Serializer::ObjectSerializer::SerializeContent(
Tagged<Map> map,
int size) {
961 OutputRawData(raw.
address() + size);
978 while (current <
end) {
979 while (current <
end && current.load(cage_base).IsSmi()) {
983 OutputRawData(current.address());
987 while (current <
end && current.load(cage_base).IsCleared()) {
988 sink_->Put(kClearedWeakReference,
"ClearedWeakReference");
993 HeapObjectReferenceType reference_type;
994 while (current <
end && current.load(cage_base).GetHeapObject(
995 ¤t_contents, &reference_type)) {
998 if (reference_type == HeapObjectReferenceType::WEAK) {
999 sink_->Put(kWeakPrefix,
"WeakReference");
1003 if (serializer_->SerializePendingObject(*obj)) {
1015 static_assert(UINT8_MAX <=
1016 static_cast<int>(RootIndex::kLastImmortalImmovableRoot));
1018 if (repeat_end <
end &&
1019 serializer_->root_index_map()->Lookup(*obj, &root_index) &&
1020 static_cast<uint32_t
>(root_index) <= UINT8_MAX &&
1021 current.
load(cage_base) == repeat_end.
load(cage_base) &&
1022 reference_type == HeapObjectReferenceType::STRONG) {
1023 DCHECK(!HeapLayout::InYoungGeneration(*obj));
1024 while (repeat_end <
end &&
1025 repeat_end.
load(cage_base) == current.load(cage_base)) {
1028 int repeat_count =
static_cast<int>(repeat_end -
current);
1029 current = repeat_end;
1030 bytes_processed_so_far_ += repeat_count *
kTaggedSize;
1031 serializer_->PutRepeatRoot(repeat_count, root_index);
1035 serializer_->SerializeObject(obj, SlotType::kAnySlot);
1041void Serializer::ObjectSerializer::VisitInstructionStreamPointer(
1043 DCHECK(!host->has_instruction_stream());
1048void Serializer::ObjectSerializer::VisitEmbeddedPointer(
1053void Serializer::ObjectSerializer::VisitExternalReference(
1058void Serializer::ObjectSerializer::VisitInternalReference(
1063void Serializer::ObjectSerializer::VisitOffHeapTarget(
1068void Serializer::ObjectSerializer::VisitCodeTarget(
1073void Serializer::ObjectSerializer::OutputExternalReference(
1079 bool encoded_successfully;
1081 if (serializer_->allow_unknown_external_references_for_testing()) {
1082 encoded_successfully =
1083 serializer_->TryEncodeExternalReference(target).To(&encoded_reference);
1085 encoded_reference = serializer_->EncodeExternalReference(target);
1086 encoded_successfully =
true;
1089 if (!encoded_successfully) {
1094 CHECK(serializer_->allow_unknown_external_references_for_testing());
1099 sink_->Put(kSandboxedRawExternalReference,
"SandboxedRawReference");
1100 sink_->PutRaw(
reinterpret_cast<uint8_t*
>(&target), target_size,
1106 sink_->Put(FixedRawDataWithSize::Encode(size_in_tagged),
"FixedRawData");
1107 sink_->PutRaw(
reinterpret_cast<uint8_t*
>(&target), target_size,
1112 sink_->Put(kSandboxedApiReference,
"SandboxedApiRef");
1114 sink_->Put(kApiReference,
"ApiRef");
1116 sink_->PutUint30(encoded_reference.
index(),
"reference index");
1119 sink_->Put(kSandboxedExternalReference,
"SandboxedExternalRef");
1121 sink_->Put(kExternalReference,
"ExternalRef");
1123 sink_->PutUint30(encoded_reference.
index(),
"reference index");
1126 sink_->PutUint30(tag,
"external pointer tag");
1130void Serializer::ObjectSerializer::VisitCppHeapPointer(
1149void Serializer::ObjectSerializer::VisitExternalPointer(
1153 if (InstanceTypeChecker::IsForeign(instance_type) ||
1154 InstanceTypeChecker::IsJSExternalObject(instance_type) ||
1155 InstanceTypeChecker::IsAccessorInfo(instance_type) ||
1156 InstanceTypeChecker::IsFunctionTemplateInfo(instance_type)) {
1158 OutputRawData(slot.
address());
1160#ifdef V8_ENABLE_SANDBOX
1178 InstanceTypeChecker::IsEmbedderDataArray(instance_type) ||
1180 InstanceTypeChecker::IsJSTypedArray(instance_type) ||
1182 InstanceTypeChecker::IsJSArrayBuffer(instance_type) ||
1184 InstanceTypeChecker::IsExternalString(instance_type) ||
1186 InstanceTypeChecker::IsNativeContext(instance_type) ||
1191 InstanceTypeChecker::IsJSSynchronizationPrimitive(instance_type) ||
1193 (InstanceTypeChecker::IsJSObject(instance_type) &&
1194 Cast<JSObject>(host)->GetEmbedderFieldCount() > 0));
1198void Serializer::ObjectSerializer::VisitIndirectPointer(
1201#ifdef V8_ENABLE_SANDBOX
1208 OutputRawData(slot.
address());
1214 CHECK(IsHeapObject(*slot_value));
1219 CHECK(!serializer_->SerializePendingObject(*slot_value));
1220 sink_->Put(kIndirectPointerPrefix,
"IndirectPointer");
1221 serializer_->SerializeObject(slot_value, SlotType::kAnySlot);
1227void Serializer::ObjectSerializer::VisitTrustedPointerTableEntry(
1229#ifdef V8_ENABLE_SANDBOX
1233 ExposedTrustedObject::kSelfIndirectPointerOffset);
1243void Serializer::ObjectSerializer::VisitProtectedPointer(
1249 if (content == Smi::zero())
return;
1253 OutputRawData(slot.
address());
1260 CHECK(!serializer_->SerializePendingObject(*
object));
1261 sink_->Put(kProtectedPointerPrefix,
"ProtectedPointer");
1262 serializer_->SerializeObject(
object, SlotType::kAnySlot);
1265void Serializer::ObjectSerializer::VisitProtectedPointer(
1269 if (maybe_content.
IsSmi())
return;
1272 OutputRawData(slot.
address());
1275 sink_->Put(kClearedWeakReference,
"ClearedWeakReference");
1281 HeapObjectReferenceType reference_type;
1282 if (maybe_content.
GetHeapObject(&content, &reference_type)) {
1283 if (reference_type == HeapObjectReferenceType::WEAK) {
1284 sink_->Put(kWeakPrefix,
"WeakReference");
1289 CHECK(!serializer_->SerializePendingObject(*
object));
1290 sink_->Put(kProtectedPointerPrefix,
"ProtectedPointer");
1291 serializer_->SerializeObject(
object, SlotType::kAnySlot);
1295void Serializer::ObjectSerializer::VisitJSDispatchTableEntry(
1297#ifdef V8_ENABLE_LEAPTIERING
1298 JSDispatchTable* jdt = IsolateGroup::current()->js_dispatch_table();
1306#if !defined(V8_COMPRESS_POINTERS) && defined(V8_TARGET_ARCH_64_BIT)
1308 JSFunction::kPaddingOffset ==
1313 auto it = serializer_->dispatch_handle_map_.find(
handle);
1314 if (it == serializer_->dispatch_handle_map_.end()) {
1315 auto id =
static_cast<uint32_t
>(serializer_->dispatch_handle_map_.size());
1316 serializer_->dispatch_handle_map_[
handle] = id;
1317 sink_->Put(kAllocateJSDispatchEntry,
"AllocateJSDispatchEntry");
1318 sink_->PutUint30(jdt->GetParameterCount(
handle),
"ParameterCount");
1323 CHECK(!serializer_->SerializePendingObject(*code));
1324 serializer_->SerializeObject(code, SlotType::kAnySlot);
1326 sink_->Put(kJSDispatchEntry,
"JSDispatchEntry");
1327 sink_->PutUint30(it->second,
"EntryID");
1339 int written_so_far,
int bytes_to_write,
1340 int field_offset,
int field_size,
1341 const uint8_t* field_value) {
1342 int offset = field_offset - written_so_far;
1345 sink->
PutRaw(
reinterpret_cast<uint8_t*
>(object_start + written_so_far),
1347 sink->
PutRaw(field_value, field_size,
"Bytes");
1348 written_so_far +=
offset + field_size;
1349 bytes_to_write -=
offset + field_size;
1350 sink->
PutRaw(
reinterpret_cast<uint8_t*
>(object_start + written_so_far),
1351 bytes_to_write,
"Bytes");
1353 sink->
PutRaw(
reinterpret_cast<uint8_t*
>(object_start + written_so_far),
1354 bytes_to_write,
"Bytes");
1359void Serializer::ObjectSerializer::OutputRawData(Address up_to) {
1360 Address object_start =
object_->address();
1361 int base = bytes_processed_so_far_;
1362 int up_to_offset =
static_cast<int>(up_to - object_start);
1363 int to_skip = up_to_offset - bytes_processed_so_far_;
1364 int bytes_to_output = to_skip;
1366 int tagged_to_output = bytes_to_output /
kTaggedSize;
1367 bytes_processed_so_far_ += to_skip;
1369 if (bytes_to_output != 0) {
1370 DCHECK(to_skip == bytes_to_output);
1371 if (tagged_to_output <= kFixedRawDataCount) {
1372 sink_->Put(FixedRawDataWithSize::Encode(tagged_to_output),
1375 sink_->Put(kVariableRawData,
"VariableRawData");
1376 sink_->PutUint30(tagged_to_output,
"length");
1378#ifdef MEMORY_SANITIZER
1380 __msan_check_mem_is_initialized(
1381 reinterpret_cast<void*
>(object_start +
base), bytes_to_output);
1384 if (IsSharedFunctionInfo(*
object_, cage_base)) {
1386 static_assert(SharedFunctionInfo::kAgeSize ==
kUInt16Size);
1387 uint16_t field_value = 0;
1388 OutputRawWithCustomField(
sink_, object_start,
base, bytes_to_output,
1389 SharedFunctionInfo::kAgeOffset,
1390 sizeof(field_value),
1391 reinterpret_cast<uint8_t*
>(&field_value));
1392 }
else if (IsDescriptorArray(*
object_, cage_base)) {
1395 const auto field_value = DescriptorArrayMarkingState::kInitialGCState;
1396 static_assert(
sizeof(field_value) == DescriptorArray::kSizeOfRawGcState);
1397 OutputRawWithCustomField(
sink_, object_start,
base, bytes_to_output,
1398 DescriptorArray::kRawGcStateOffset,
1399 sizeof(field_value),
1400 reinterpret_cast<const uint8_t*
>(&field_value));
1401 }
else if (IsCode(*
object_, cage_base)) {
1402#ifdef V8_ENABLE_SANDBOX
1407 OutputRawWithCustomField(
sink_, object_start,
base, bytes_to_output,
1408 Code::kSelfIndirectPointerOffset,
1409 sizeof(field_value), field_value);
1415 OutputRawWithCustomField(
sink_, object_start,
base, bytes_to_output,
1416 Code::kInstructionStartOffset,
1417 sizeof(field_value), field_value);
1419 }
else if (IsSeqString(*
object_)) {
1423 Cast<SeqString>(*object_)->GetDataAndPaddingSizes();
1426 sink_->PutRaw(
reinterpret_cast<uint8_t*
>(object_start +
base),
1427 data_bytes_to_output,
"SeqStringData");
1430 sink_->PutRaw(
reinterpret_cast<uint8_t*
>(object_start +
base),
1431 bytes_to_output,
"Bytes");
1442 heap_->UnregisterStrongRoots(strong_roots_entry_);
1447 return isolate->factory()->empty_fixed_array();
1450 isolate->factory()->NewFixedArray(
size());
1455 for (
auto it = it_scope.
begin(); it != it_scope.
end(); ++it) {
1456 raw->set(*it.entry(), it.key());
1471 uint32_t chunk_index = 0;
1475 if (chunk == page)
break;
1478 uint32_t chunk_offset =
static_cast<uint32_t
>(chunk->
Offset(address));
1480 sink->
PutUint30(chunk_index,
"ReadOnlyHeapRefChunkIndex");
1481 sink->
PutUint30(chunk_offset,
"ReadOnlyHeapRefChunkOffset");
#define DISALLOW_GARBAGE_COLLECTION(name)
V8_INLINE bool IsJust() const
V8_INLINE T FromJust() const &
Address load(IsolateForSandbox isolate)
Tagged< MaybeObject > load() const
Tagged< Object > load() const
ReadOnlySpace * read_only_space() const
Tagged< Object > load(IsolateForSandbox isolate) const
DirectHandle< FixedArray > Values(Isolate *isolate)
static V8_EXPORT_PRIVATE bool Contains(Address address)
const std::vector< ReadOnlyPageMetadata * > & pages() const
uint32_t attached_reference_index() const
uint32_t off_heap_backing_store_index() const
bool is_attached_reference() const
bool is_back_reference() const
uint32_t back_ref_index() const
StrongRootsEntry * strong_roots_entry_
Address circular_queue_[kSize]
int ExceedsMaximumBy() const
bool ExceedsMaximum() const
Isolate * isolate() const
bool SerializeReadOnlyObjectReference(Tagged< HeapObject > obj, SnapshotByteSink *sink)
Serializer(Isolate *isolate, Snapshot::SerializerFlags flags)
std::vector< int > * PendingObjectReferences
void PutUint30(uint32_t integer, const char *description)
void PutRaw(const uint8_t *data, int number_of_bytes, const char *description)
void Put(uint8_t b, const char *description)
constexpr bool IsCleared() const
bool GetHeapObject(Tagged< HeapObject > *result) const
constexpr V8_INLINE bool IsSmi() const
UnlinkWeakNextScope(Heap *heap, Tagged< HeapObject > object)
Tagged< AllocationSiteWithWeakNext > object_
#define V8_ENABLE_SANDBOX_BOOL
constexpr const char * ToString(DataViewOp op)
#define WHILE_WITH_HANDLE_SCOPE(isolate, limit_check, body)
DisallowGarbageCollection no_gc_
too high values may cause the compiler to set high thresholds for inlining to as much as possible avoid inlined allocation of objects that cannot escape trace load stores from virtual maglev objects use TurboFan fast string builder analyze liveness of environment slots and zap dead values trace TurboFan load elimination emit data about basic block usage in builtins to this enable builtin reordering when run mksnapshot flag for emit warnings when applying builtin profile data verify register allocation in TurboFan randomly schedule instructions to stress dependency tracking enable store store elimination in TurboFan rewrite far to near simulate GC compiler thread race related to allow float parameters to be passed in simulator mode JS Wasm Run additional turbo_optimize_inlined_js_wasm_wrappers enable experimental feedback collection in generic lowering enable Turboshaft s WasmLoadElimination enable Turboshaft s low level load elimination for JS enable Turboshaft s escape analysis for string concatenation use enable Turbolev features that we want to ship in the not too far future trace individual Turboshaft reduction steps trace intermediate Turboshaft reduction steps invocation count threshold for early optimization Enables optimizations which favor memory size over execution speed Enables sampling allocation profiler with X as a sample interval min size of a semi the new space consists of two semi spaces max size of the Collect garbage after Collect garbage after keeps maps alive for< n > old space garbage collections print one detailed trace line in allocation gc speed threshold for starting incremental marking via a task in percent of available space
ZoneVector< RpoNumber > & result
#define LOG(isolate, Call)
V8_INLINE IndirectHandle< T > handle(Tagged< T > object, Isolate *isolate)
constexpr intptr_t kPointerAlignment
constexpr int kTaggedSize
void VisitObjectBody(Isolate *isolate, Tagged< HeapObject > object, ObjectVisitor *visitor)
constexpr intptr_t kObjectAlignment
void PrintF(const char *format,...)
constexpr int kJSDispatchHandleSize
V8_INLINE constexpr bool IsSmi(TaggedImpl< kRefType, StorageType > obj)
constexpr CppHeapPointer_t kNullCppHeapPointer
constexpr int kSystemPointerSize
constexpr int kTaggedSizeLog2
constexpr JSDispatchHandle kNullJSDispatchHandle(0)
void ShortPrint(Tagged< Object > obj, FILE *out)
typename detail::FlattenUnionHelper< Union<>, Ts... >::type UnionOf
constexpr int kExternalPointerSlotSize
constexpr int kIndirectPointerSize
@ SHARED_TRUSTED_LO_SPACE
@ kExternalPointerNullTag
V8_EXPORT_PRIVATE FlagValues v8_flags
constexpr int kCppHeapPointerSlotSize
uint32_t ExternalPointerHandle
constexpr int kUInt16Size
bool IsJSApiWrapperObject(Tagged< Map > map)
constexpr int kObjectAlignmentBits
!IsContextMap !IsContextMap native_context
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Maybe< T > Just(const T &t)
#define INSTANCE_TYPE_LIST(V)
SnapshotByteSink *const sink_
#define DCHECK_LE(v1, v2)
#define CHECK_LE(lhs, rhs)
#define DCHECK_IMPLIES(v1, v2)
#define DCHECK_NE(v1, v2)
#define DCHECK_GE(v1, v2)
#define CHECK_EQ(lhs, rhs)
#define DCHECK(condition)
#define DCHECK_EQ(v1, v2)
constexpr T RoundUp(T x, intptr_t m)
constexpr bool IsAligned(T value, U alignment)