[snapshot][ptr-compr] Simplify deserialization of references embedded in code
... and use RelocInfo iteration instead of skip-and-unaligned-write sequences. This is a step towards avoiding unaligned stores via UnalignedSlot. Various cleanup CLs will follow. Bug: v8:8794 Change-Id: I62faedfa1c1ababe4b185fa8d7f2c6c1baa5cf79 Reviewed-on: https://chromium-review.googlesource.com/c/1456579 Commit-Queue: Igor Sheludko <ishell@chromium.org> Reviewed-by: Jakob Gruber <jgruber@chromium.org> Cr-Commit-Position: refs/heads/master@{#59443}
This commit is contained in:
parent
7a8cd55146
commit
7e914db539
@ -589,22 +589,22 @@ class Code::BodyDescriptor final : public BodyDescriptorBase {
|
||||
return true;
|
||||
}
|
||||
|
||||
static constexpr int kRelocModeMask =
|
||||
RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
|
||||
RelocInfo::ModeMask(RelocInfo::RELATIVE_CODE_TARGET) |
|
||||
RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
|
||||
RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
|
||||
RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
|
||||
RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED) |
|
||||
RelocInfo::ModeMask(RelocInfo::OFF_HEAP_TARGET) |
|
||||
RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY);
|
||||
|
||||
template <typename ObjectVisitor>
|
||||
static inline void IterateBody(Map map, HeapObject obj, ObjectVisitor* v) {
|
||||
static constexpr int kModeMask =
|
||||
RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
|
||||
RelocInfo::ModeMask(RelocInfo::RELATIVE_CODE_TARGET) |
|
||||
RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
|
||||
RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
|
||||
RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
|
||||
RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED) |
|
||||
RelocInfo::ModeMask(RelocInfo::OFF_HEAP_TARGET) |
|
||||
RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY);
|
||||
|
||||
// GC does not visit data/code in the header and in the body directly.
|
||||
IteratePointers(obj, kRelocationInfoOffset, kDataStart, v);
|
||||
|
||||
RelocIterator it(Code::cast(obj), kModeMask);
|
||||
RelocIterator it(Code::cast(obj), kRelocModeMask);
|
||||
v->VisitRelocInfo(&it);
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "src/interpreter/interpreter.h"
|
||||
#include "src/isolate.h"
|
||||
#include "src/log.h"
|
||||
#include "src/objects-body-descriptors-inl.h"
|
||||
#include "src/objects/api-callbacks.h"
|
||||
#include "src/objects/cell-inl.h"
|
||||
#include "src/objects/hash-table.h"
|
||||
@ -367,6 +368,16 @@ HeapObject Deserializer::GetBackReferencedObject(int space) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
HeapObject Deserializer::ReadObject() {
|
||||
MaybeObject object;
|
||||
// We are reading to a location outside of JS heap, so pass NEW_SPACE to
|
||||
// avoid triggering write barriers.
|
||||
bool filled = ReadData(UnalignedSlot(&object), UnalignedSlot(&object + 1),
|
||||
NEW_SPACE, kNullAddress);
|
||||
CHECK(filled);
|
||||
return object.GetHeapObjectAssumeStrong();
|
||||
}
|
||||
|
||||
HeapObject Deserializer::ReadObject(int space_number) {
|
||||
const int size = source_.GetInt() << kObjectAlignmentBits;
|
||||
|
||||
@ -393,21 +404,114 @@ HeapObject Deserializer::ReadObject(int space_number) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
void Deserializer::ReadCodeObjectBody(int space_number,
|
||||
Address code_object_address) {
|
||||
// At this point the code object is already allocated, its map field is
|
||||
// initialized and its raw data fields and code stream are also read.
|
||||
// Now we read the rest of code header's fields.
|
||||
UnalignedSlot current(code_object_address + HeapObject::kHeaderSize);
|
||||
UnalignedSlot limit(code_object_address + Code::kDataStart);
|
||||
bool filled = ReadData(current, limit, space_number, code_object_address);
|
||||
CHECK(filled);
|
||||
|
||||
// Now iterate RelocInfos the same way it was done by the serialzier and
|
||||
// deserialize respective data into RelocInfos.
|
||||
Code code = Code::cast(HeapObject::FromAddress(code_object_address));
|
||||
RelocIterator it(code, Code::BodyDescriptor::kRelocModeMask);
|
||||
for (; !it.done(); it.next()) {
|
||||
RelocInfo rinfo = *it.rinfo();
|
||||
rinfo.Visit(this);
|
||||
}
|
||||
}
|
||||
|
||||
void Deserializer::VisitCodeTarget(Code host, RelocInfo* rinfo) {
|
||||
HeapObject object = ReadObject();
|
||||
rinfo->set_target_address(Code::cast(object)->raw_instruction_start());
|
||||
}
|
||||
|
||||
void Deserializer::VisitEmbeddedPointer(Code host, RelocInfo* rinfo) {
|
||||
HeapObject object = ReadObject();
|
||||
// Embedded object reference must be a strong one.
|
||||
rinfo->set_target_object(isolate_->heap(), object);
|
||||
}
|
||||
|
||||
void Deserializer::VisitRuntimeEntry(Code host, RelocInfo* rinfo) {
|
||||
// We no longer serialize code that contains runtime entries.
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
void Deserializer::VisitExternalReference(Code host, RelocInfo* rinfo) {
|
||||
byte data = source_.Get();
|
||||
CHECK(data == kExternalReference + kPlain + kStartOfObject ||
|
||||
data == kExternalReference + kFromCode + kStartOfObject);
|
||||
|
||||
uint32_t reference_id = static_cast<uint32_t>(source_.GetInt());
|
||||
Address address = external_reference_table_->address(reference_id);
|
||||
|
||||
DCHECK_EQ(rinfo->IsCodedSpecially(),
|
||||
data == kExternalReference + kFromCode + kStartOfObject);
|
||||
if (data == kExternalReference + kFromCode + kStartOfObject) {
|
||||
Address location_of_branch_data = rinfo->pc();
|
||||
Assembler::deserialization_set_special_target_at(location_of_branch_data,
|
||||
host, address);
|
||||
} else {
|
||||
WriteUnalignedValue(rinfo->target_address_address(), address);
|
||||
}
|
||||
}
|
||||
|
||||
void Deserializer::VisitInternalReference(Code host, RelocInfo* rinfo) {
|
||||
byte data = source_.Get();
|
||||
CHECK(data == kInternalReference || data == kInternalReferenceEncoded);
|
||||
|
||||
// Internal reference address is not encoded via skip, but by offset
|
||||
// from code entry.
|
||||
int pc_offset = source_.GetInt();
|
||||
int target_offset = source_.GetInt();
|
||||
DCHECK(0 <= pc_offset && pc_offset <= host->raw_instruction_size());
|
||||
DCHECK(0 <= target_offset && target_offset <= host->raw_instruction_size());
|
||||
Address pc = host->entry() + pc_offset;
|
||||
// TODO(ishell): don't encode pc_offset as it can be taken from the rinfo.
|
||||
DCHECK_EQ(pc, rinfo->pc());
|
||||
Address target = host->entry() + target_offset;
|
||||
Assembler::deserialization_set_target_internal_reference_at(
|
||||
pc, target,
|
||||
data == kInternalReference ? RelocInfo::INTERNAL_REFERENCE
|
||||
: RelocInfo::INTERNAL_REFERENCE_ENCODED);
|
||||
}
|
||||
|
||||
void Deserializer::VisitOffHeapTarget(Code host, RelocInfo* rinfo) {
|
||||
DCHECK(FLAG_embedded_builtins);
|
||||
byte data = source_.Get();
|
||||
CHECK_EQ(data, kOffHeapTarget);
|
||||
|
||||
int builtin_index = source_.GetInt();
|
||||
DCHECK(Builtins::IsBuiltinId(builtin_index));
|
||||
|
||||
CHECK_NOT_NULL(isolate_->embedded_blob());
|
||||
EmbeddedData d = EmbeddedData::FromBlob();
|
||||
Address address = d.InstructionStartOfBuiltin(builtin_index);
|
||||
CHECK_NE(kNullAddress, address);
|
||||
|
||||
// TODO(ishell): implement RelocInfo::set_target_off_heap_target()
|
||||
if (RelocInfo::OffHeapTargetIsCodedSpecially()) {
|
||||
Address location_of_branch_data = rinfo->pc();
|
||||
Assembler::deserialization_set_special_target_at(location_of_branch_data,
|
||||
host, address);
|
||||
} else {
|
||||
WriteUnalignedValue(rinfo->target_address_address(), address);
|
||||
}
|
||||
}
|
||||
|
||||
UnalignedSlot Deserializer::ReadRepeatedObject(UnalignedSlot current,
|
||||
int repeat_count) {
|
||||
CHECK_LE(2, repeat_count);
|
||||
MaybeObject object;
|
||||
// We are reading to a location outside of JS heap, so pass NEW_SPACE to
|
||||
// avoid triggering write barriers.
|
||||
bool filled = ReadData(UnalignedSlot(&object), UnalignedSlot(&object + 1),
|
||||
NEW_SPACE, kNullAddress);
|
||||
CHECK(filled);
|
||||
DCHECK(HAS_HEAP_OBJECT_TAG(object.ptr()));
|
||||
|
||||
HeapObject object = ReadObject();
|
||||
DCHECK(!Heap::InYoungGeneration(object));
|
||||
for (int i = 0; i < repeat_count; i++) {
|
||||
// Repeated values are not subject to the write barrier so we don't need
|
||||
// to trigger it.
|
||||
UnalignedCopy(current, object);
|
||||
UnalignedCopy(current, object.ptr());
|
||||
current.Advance();
|
||||
}
|
||||
return current;
|
||||
@ -549,55 +653,17 @@ bool Deserializer::ReadData(UnalignedSlot current, UnalignedSlot limit,
|
||||
// Find an external reference and write a pointer to it in the current
|
||||
// code object.
|
||||
case kExternalReference + kFromCode + kStartOfObject:
|
||||
current = ReadExternalReferenceCase(kFromCode, current,
|
||||
current_object_address);
|
||||
UNREACHABLE();
|
||||
break;
|
||||
|
||||
case kInternalReferenceEncoded:
|
||||
case kInternalReference: {
|
||||
// Internal reference address is not encoded via skip, but by offset
|
||||
// from code entry.
|
||||
int pc_offset = source_.GetInt();
|
||||
int target_offset = source_.GetInt();
|
||||
Code code = Code::cast(HeapObject::FromAddress(current_object_address));
|
||||
DCHECK(0 <= pc_offset && pc_offset <= code->raw_instruction_size());
|
||||
DCHECK(0 <= target_offset &&
|
||||
target_offset <= code->raw_instruction_size());
|
||||
Address pc = code->entry() + pc_offset;
|
||||
Address target = code->entry() + target_offset;
|
||||
Assembler::deserialization_set_target_internal_reference_at(
|
||||
pc, target,
|
||||
data == kInternalReference ? RelocInfo::INTERNAL_REFERENCE
|
||||
: RelocInfo::INTERNAL_REFERENCE_ENCODED);
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
|
||||
case kOffHeapTarget: {
|
||||
DCHECK(FLAG_embedded_builtins);
|
||||
int skip = source_.GetInt();
|
||||
int builtin_index = source_.GetInt();
|
||||
DCHECK(Builtins::IsBuiltinId(builtin_index));
|
||||
|
||||
current.Advance(skip);
|
||||
|
||||
CHECK_NOT_NULL(isolate->embedded_blob());
|
||||
EmbeddedData d = EmbeddedData::FromBlob();
|
||||
Address address = d.InstructionStartOfBuiltin(builtin_index);
|
||||
CHECK_NE(kNullAddress, address);
|
||||
|
||||
if (RelocInfo::OffHeapTargetIsCodedSpecially()) {
|
||||
Address location_of_branch_data = current.address();
|
||||
int skip = Assembler::deserialization_special_target_size(
|
||||
location_of_branch_data);
|
||||
Assembler::deserialization_set_special_target_at(
|
||||
location_of_branch_data,
|
||||
Code::cast(HeapObject::FromAddress(current_object_address)),
|
||||
address);
|
||||
current.Advance(skip);
|
||||
} else {
|
||||
UnalignedCopy(current, address);
|
||||
current.Advance();
|
||||
}
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
|
||||
@ -612,7 +678,7 @@ bool Deserializer::ReadData(UnalignedSlot current, UnalignedSlot limit,
|
||||
|
||||
case kDeferred: {
|
||||
// Deferred can only occur right after the heap object header.
|
||||
DCHECK_EQ(current.address(), current_object_address + kPointerSize);
|
||||
DCHECK_EQ(current.address(), current_object_address + kTaggedSize);
|
||||
HeapObject obj = HeapObject::FromAddress(current_object_address);
|
||||
// If the deferred object is a map, its instance type may be used
|
||||
// during deserialization. Initialize it with a temporary value.
|
||||
@ -638,10 +704,17 @@ bool Deserializer::ReadData(UnalignedSlot current, UnalignedSlot limit,
|
||||
// Deserialize raw code directly into the body of the code object.
|
||||
// Do not move current.
|
||||
case kVariableRawCode: {
|
||||
// VariableRawCode can only occur right after the heap object header.
|
||||
DCHECK_EQ(current.address(), current_object_address + kTaggedSize);
|
||||
int size_in_bytes = source_.GetInt();
|
||||
source_.CopyRaw(
|
||||
reinterpret_cast<byte*>(current_object_address + Code::kDataStart),
|
||||
size_in_bytes);
|
||||
ReadCodeObjectBody(source_space, current_object_address);
|
||||
// Set current to the code object end.
|
||||
current.Advance(Code::kDataStart - HeapObject::kHeaderSize +
|
||||
size_in_bytes);
|
||||
CHECK_EQ(current, limit);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -663,8 +736,6 @@ bool Deserializer::ReadData(UnalignedSlot current, UnalignedSlot limit,
|
||||
}
|
||||
|
||||
case kApiReference: {
|
||||
int skip = source_.GetInt();
|
||||
current.Advance(skip);
|
||||
uint32_t reference_id = static_cast<uint32_t>(source_.GetInt());
|
||||
Address address;
|
||||
if (isolate->api_external_references()) {
|
||||
@ -790,23 +861,12 @@ bool Deserializer::ReadData(UnalignedSlot current, UnalignedSlot limit,
|
||||
|
||||
UnalignedSlot Deserializer::ReadExternalReferenceCase(
|
||||
HowToCode how, UnalignedSlot current, Address current_object_address) {
|
||||
int skip = source_.GetInt();
|
||||
current.Advance(skip);
|
||||
uint32_t reference_id = static_cast<uint32_t>(source_.GetInt());
|
||||
Address address = external_reference_table_->address(reference_id);
|
||||
|
||||
if (how == kFromCode) {
|
||||
Address location_of_branch_data = current.address();
|
||||
int skip =
|
||||
Assembler::deserialization_special_target_size(location_of_branch_data);
|
||||
Assembler::deserialization_set_special_target_at(
|
||||
location_of_branch_data,
|
||||
Code::cast(HeapObject::FromAddress(current_object_address)), address);
|
||||
current.Advance(skip);
|
||||
} else {
|
||||
UnalignedCopy(current, address);
|
||||
current.Advance();
|
||||
}
|
||||
DCHECK_EQ(how, kPlain);
|
||||
UnalignedCopy(current, address);
|
||||
current.Advance();
|
||||
return current;
|
||||
}
|
||||
|
||||
@ -824,71 +884,39 @@ UnalignedSlot Deserializer::ReadDataCase(Isolate* isolate,
|
||||
? HeapObjectReferenceType::WEAK
|
||||
: HeapObjectReferenceType::STRONG;
|
||||
|
||||
if (where == kNewObject && how == kPlain && within == kStartOfObject) {
|
||||
if (where == kNewObject) {
|
||||
heap_object = ReadObject(space_number);
|
||||
emit_write_barrier = (space_number == NEW_SPACE);
|
||||
} else if (where == kBackref) {
|
||||
emit_write_barrier = (space_number == NEW_SPACE);
|
||||
heap_object = GetBackReferencedObject(data & kSpaceMask);
|
||||
} else if (where == kBackrefWithSkip) {
|
||||
int skip = source_.GetInt();
|
||||
current.Advance(skip);
|
||||
emit_write_barrier = (space_number == NEW_SPACE);
|
||||
heap_object = GetBackReferencedObject(data & kSpaceMask);
|
||||
} else if (where == kRootArray) {
|
||||
int id = source_.GetInt();
|
||||
RootIndex root_index = static_cast<RootIndex>(id);
|
||||
heap_object = HeapObject::cast(isolate->root(root_index));
|
||||
emit_write_barrier = Heap::InYoungGeneration(heap_object);
|
||||
hot_objects_.Add(heap_object);
|
||||
} else if (where == kReadOnlyObjectCache) {
|
||||
int cache_index = source_.GetInt();
|
||||
heap_object =
|
||||
HeapObject::cast(isolate->read_only_object_cache()->at(cache_index));
|
||||
DCHECK(!Heap::InYoungGeneration(heap_object));
|
||||
emit_write_barrier = false;
|
||||
} else if (where == kPartialSnapshotCache) {
|
||||
int cache_index = source_.GetInt();
|
||||
heap_object =
|
||||
HeapObject::cast(isolate->partial_snapshot_cache()->at(cache_index));
|
||||
emit_write_barrier = Heap::InYoungGeneration(heap_object);
|
||||
} else {
|
||||
if (where == kNewObject) {
|
||||
heap_object = ReadObject(space_number);
|
||||
emit_write_barrier = (space_number == NEW_SPACE);
|
||||
} else if (where == kBackref) {
|
||||
emit_write_barrier = (space_number == NEW_SPACE);
|
||||
heap_object = GetBackReferencedObject(data & kSpaceMask);
|
||||
} else if (where == kBackrefWithSkip) {
|
||||
int skip = source_.GetInt();
|
||||
current.Advance(skip);
|
||||
emit_write_barrier = (space_number == NEW_SPACE);
|
||||
heap_object = GetBackReferencedObject(data & kSpaceMask);
|
||||
} else if (where == kRootArray) {
|
||||
int id = source_.GetInt();
|
||||
RootIndex root_index = static_cast<RootIndex>(id);
|
||||
heap_object = HeapObject::cast(isolate->root(root_index));
|
||||
emit_write_barrier = Heap::InYoungGeneration(heap_object);
|
||||
hot_objects_.Add(heap_object);
|
||||
} else if (where == kReadOnlyObjectCache) {
|
||||
int cache_index = source_.GetInt();
|
||||
heap_object =
|
||||
HeapObject::cast(isolate->read_only_object_cache()->at(cache_index));
|
||||
DCHECK(!Heap::InYoungGeneration(heap_object));
|
||||
emit_write_barrier = false;
|
||||
} else if (where == kPartialSnapshotCache) {
|
||||
int cache_index = source_.GetInt();
|
||||
heap_object =
|
||||
HeapObject::cast(isolate->partial_snapshot_cache()->at(cache_index));
|
||||
emit_write_barrier = Heap::InYoungGeneration(heap_object);
|
||||
} else {
|
||||
DCHECK_EQ(where, kAttachedReference);
|
||||
int index = source_.GetInt();
|
||||
heap_object = *attached_objects_[index];
|
||||
emit_write_barrier = Heap::InYoungGeneration(heap_object);
|
||||
}
|
||||
if (how == kFromCode) {
|
||||
Address value;
|
||||
if (within == kInnerPointer) {
|
||||
if (heap_object->IsCode()) {
|
||||
value = Code::cast(heap_object)->raw_instruction_start();
|
||||
} else {
|
||||
value = Cell::cast(heap_object)->ValueAddress();
|
||||
}
|
||||
} else {
|
||||
value = heap_object->ptr();
|
||||
}
|
||||
DCHECK_EQ(reference_type, HeapObjectReferenceType::STRONG);
|
||||
Address location_of_branch_data = current.address();
|
||||
int skip = Assembler::deserialization_special_target_size(
|
||||
location_of_branch_data);
|
||||
Assembler::deserialization_set_special_target_at(
|
||||
location_of_branch_data,
|
||||
Code::cast(HeapObject::FromAddress(current_object_address)), value);
|
||||
current.Advance(skip);
|
||||
// Nothing else to be done in this case.
|
||||
DCHECK(!write_barrier_needed);
|
||||
return current;
|
||||
|
||||
} else {
|
||||
DCHECK_EQ(how, kPlain);
|
||||
DCHECK_EQ(within, kStartOfObject);
|
||||
}
|
||||
DCHECK_EQ(where, kAttachedReference);
|
||||
int index = source_.GetInt();
|
||||
heap_object = *attached_objects_[index];
|
||||
emit_write_barrier = Heap::InYoungGeneration(heap_object);
|
||||
}
|
||||
HeapObjectReference heap_object_ref =
|
||||
reference_type == HeapObjectReferenceType::STRONG
|
||||
|
@ -136,8 +136,19 @@ class Deserializer : public SerializerDeserializer {
|
||||
inline UnalignedSlot ReadExternalReferenceCase(
|
||||
HowToCode how, UnalignedSlot current, Address current_object_address);
|
||||
|
||||
HeapObject ReadObject();
|
||||
HeapObject ReadObject(int space_number);
|
||||
void ReadCodeObjectBody(int space_number, Address code_object_address);
|
||||
|
||||
public:
|
||||
void VisitCodeTarget(Code host, RelocInfo* rinfo);
|
||||
void VisitEmbeddedPointer(Code host, RelocInfo* rinfo);
|
||||
void VisitRuntimeEntry(Code host, RelocInfo* rinfo);
|
||||
void VisitExternalReference(Code host, RelocInfo* rinfo);
|
||||
void VisitInternalReference(Code host, RelocInfo* rinfo);
|
||||
void VisitOffHeapTarget(Code host, RelocInfo* rinfo);
|
||||
|
||||
private:
|
||||
UnalignedSlot ReadRepeatedObject(UnalignedSlot current, int repeat_count);
|
||||
|
||||
// Special handling for serialized code like hooking up internalized strings.
|
||||
|
@ -147,12 +147,8 @@ bool Serializer::SerializeHotObject(HeapObject obj, HowToCode how_to_code,
|
||||
obj->ShortPrint();
|
||||
PrintF("\n");
|
||||
}
|
||||
if (skip != 0) {
|
||||
sink_.Put(kHotObjectWithSkip + index, "HotObjectWithSkip");
|
||||
sink_.PutInt(skip, "HotObjectSkipDistance");
|
||||
} else {
|
||||
sink_.Put(kHotObject + index, "HotObject");
|
||||
}
|
||||
// TODO(ishell): remove kHotObjectWithSkip
|
||||
sink_.Put(kHotObject + index, "HotObject");
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -182,13 +178,8 @@ bool Serializer::SerializeBackReference(HeapObject obj, HowToCode how_to_code,
|
||||
|
||||
PutAlignmentPrefix(obj);
|
||||
AllocationSpace space = reference.space();
|
||||
if (skip == 0) {
|
||||
sink_.Put(kBackref + how_to_code + where_to_point + space, "BackRef");
|
||||
} else {
|
||||
sink_.Put(kBackrefWithSkip + how_to_code + where_to_point + space,
|
||||
"BackRefWithSkip");
|
||||
sink_.PutInt(skip, "BackRefSkipDistance");
|
||||
}
|
||||
// TODO(ishell): remove kBackrefWithSkip
|
||||
sink_.Put(kBackref + how_to_code + where_to_point + space, "BackRef");
|
||||
PutBackReference(obj, reference);
|
||||
}
|
||||
return true;
|
||||
@ -219,12 +210,8 @@ void Serializer::PutRoot(RootIndex root, HeapObject object,
|
||||
if (how_to_code == kPlain && where_to_point == kStartOfObject &&
|
||||
root_index < kNumberOfRootArrayConstants &&
|
||||
!Heap::InYoungGeneration(object)) {
|
||||
if (skip == 0) {
|
||||
sink_.Put(kRootArrayConstants + root_index, "RootConstant");
|
||||
} else {
|
||||
sink_.Put(kRootArrayConstantsWithSkip + root_index, "RootConstant");
|
||||
sink_.PutInt(skip, "SkipInPutRoot");
|
||||
}
|
||||
// TODO(ishell): remove kRootArrayConstantsWithSkip
|
||||
sink_.Put(kRootArrayConstants + root_index, "RootConstant");
|
||||
} else {
|
||||
FlushSkip(skip);
|
||||
sink_.Put(kRootArray + how_to_code + where_to_point, "RootSerialization");
|
||||
@ -735,7 +722,8 @@ void Serializer::ObjectSerializer::VisitPointers(HeapObject host,
|
||||
|
||||
void Serializer::ObjectSerializer::VisitEmbeddedPointer(Code host,
|
||||
RelocInfo* rinfo) {
|
||||
int skip = SkipTo(rinfo->target_address_address());
|
||||
// TODO(ishell): remove skip parameter from bytecode.
|
||||
int skip = 0;
|
||||
HowToCode how_to_code = rinfo->IsCodedSpecially() ? kFromCode : kPlain;
|
||||
Object object = rinfo->target_object();
|
||||
serializer_->SerializeObject(HeapObject::cast(object), how_to_code,
|
||||
@ -745,7 +733,12 @@ void Serializer::ObjectSerializer::VisitEmbeddedPointer(Code host,
|
||||
|
||||
void Serializer::ObjectSerializer::VisitExternalReference(Foreign host,
|
||||
Address* p) {
|
||||
int skip = SkipTo(reinterpret_cast<Address>(p));
|
||||
// TODO(ishell): handle gap between map field and payload field
|
||||
// once we shrink kTaggedSize.
|
||||
STATIC_ASSERT(static_cast<int>(Foreign::kForeignAddressOffset) ==
|
||||
static_cast<int>(HeapObject::kHeaderSize));
|
||||
DCHECK_EQ(0, SkipTo(reinterpret_cast<Address>(p)));
|
||||
|
||||
Address target = *p;
|
||||
auto encoded_reference = serializer_->EncodeExternalReference(target);
|
||||
if (encoded_reference.is_from_api()) {
|
||||
@ -753,14 +746,12 @@ void Serializer::ObjectSerializer::VisitExternalReference(Foreign host,
|
||||
} else {
|
||||
sink_->Put(kExternalReference + kPlain + kStartOfObject, "ExternalRef");
|
||||
}
|
||||
sink_->PutInt(skip, "SkipB4ExternalRef");
|
||||
sink_->PutInt(encoded_reference.index(), "reference index");
|
||||
bytes_processed_so_far_ += kSystemPointerSize;
|
||||
}
|
||||
|
||||
void Serializer::ObjectSerializer::VisitExternalReference(Code host,
|
||||
RelocInfo* rinfo) {
|
||||
int skip = SkipTo(rinfo->target_address_address());
|
||||
Address target = rinfo->target_external_reference();
|
||||
auto encoded_reference = serializer_->EncodeExternalReference(target);
|
||||
if (encoded_reference.is_from_api()) {
|
||||
@ -771,7 +762,6 @@ void Serializer::ObjectSerializer::VisitExternalReference(Code host,
|
||||
sink_->Put(kExternalReference + how_to_code + kStartOfObject,
|
||||
"ExternalRef");
|
||||
}
|
||||
sink_->PutInt(skip, "SkipB4ExternalRef");
|
||||
DCHECK_NE(target, kNullAddress); // Code does not reference null.
|
||||
sink_->PutInt(encoded_reference.index(), "reference index");
|
||||
bytes_processed_so_far_ += rinfo->target_address_size();
|
||||
@ -802,15 +792,8 @@ void Serializer::ObjectSerializer::VisitInternalReference(Code host,
|
||||
|
||||
void Serializer::ObjectSerializer::VisitRuntimeEntry(Code host,
|
||||
RelocInfo* rinfo) {
|
||||
int skip = SkipTo(rinfo->target_address_address());
|
||||
HowToCode how_to_code = rinfo->IsCodedSpecially() ? kFromCode : kPlain;
|
||||
Address target = rinfo->target_address();
|
||||
auto encoded_reference = serializer_->EncodeExternalReference(target);
|
||||
DCHECK(!encoded_reference.is_from_api());
|
||||
sink_->Put(kExternalReference + how_to_code + kStartOfObject, "ExternalRef");
|
||||
sink_->PutInt(skip, "SkipB4ExternalRef");
|
||||
sink_->PutInt(encoded_reference.index(), "reference index");
|
||||
bytes_processed_so_far_ += rinfo->target_address_size();
|
||||
// We no longer serialize code that contains runtime entries.
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
void Serializer::ObjectSerializer::VisitOffHeapTarget(Code host,
|
||||
@ -824,48 +807,18 @@ void Serializer::ObjectSerializer::VisitOffHeapTarget(Code host,
|
||||
Code target = InstructionStream::TryLookupCode(serializer_->isolate(), addr);
|
||||
CHECK(Builtins::IsIsolateIndependentBuiltin(target));
|
||||
|
||||
int skip = SkipTo(rinfo->target_address_address());
|
||||
sink_->Put(kOffHeapTarget, "OffHeapTarget");
|
||||
sink_->PutInt(skip, "SkipB4OffHeapTarget");
|
||||
sink_->PutInt(target->builtin_index(), "builtin index");
|
||||
bytes_processed_so_far_ += rinfo->target_address_size();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class CompareRelocInfo {
|
||||
public:
|
||||
bool operator()(RelocInfo x, RelocInfo y) {
|
||||
// Everything that does not use target_address_address will compare equal.
|
||||
Address x_num = 0;
|
||||
Address y_num = 0;
|
||||
if (x.HasTargetAddressAddress()) x_num = x.target_address_address();
|
||||
if (y.HasTargetAddressAddress()) y_num = y.target_address_address();
|
||||
return x_num > y_num;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
void Serializer::ObjectSerializer::VisitRelocInfo(RelocIterator* it) {
|
||||
std::priority_queue<RelocInfo, std::vector<RelocInfo>, CompareRelocInfo>
|
||||
reloc_queue;
|
||||
for (; !it->done(); it->next()) {
|
||||
reloc_queue.push(*it->rinfo());
|
||||
}
|
||||
while (!reloc_queue.empty()) {
|
||||
RelocInfo rinfo = reloc_queue.top();
|
||||
reloc_queue.pop();
|
||||
rinfo.Visit(this);
|
||||
}
|
||||
}
|
||||
|
||||
void Serializer::ObjectSerializer::VisitCodeTarget(Code host,
|
||||
RelocInfo* rinfo) {
|
||||
#ifdef V8_TARGET_ARCH_ARM
|
||||
DCHECK(!RelocInfo::IsRelativeCodeTarget(rinfo->rmode()));
|
||||
#endif
|
||||
int skip = SkipTo(rinfo->target_address_address());
|
||||
// TODO(ishell): remove skip parameter from bytecode.
|
||||
int skip = 0;
|
||||
Code object = Code::GetCodeFromTargetAddress(rinfo->target_address());
|
||||
serializer_->SerializeObject(object, kFromCode, kInnerPointer, skip);
|
||||
bytes_processed_so_far_ += rinfo->target_address_size();
|
||||
|
@ -227,10 +227,7 @@ class Serializer : public SerializerDeserializer {
|
||||
bool ObjectIsBytecodeHandler(HeapObject obj) const;
|
||||
|
||||
static inline void FlushSkip(SnapshotByteSink* sink, int skip) {
|
||||
if (skip != 0) {
|
||||
sink->Put(kSkip, "SkipFromSerializeObject");
|
||||
sink->PutInt(skip, "SkipDistanceFromSerializeObject");
|
||||
}
|
||||
// TODO(ishell): remove kSkip and friends as they are no longer needed.
|
||||
}
|
||||
|
||||
inline void FlushSkip(int skip) { FlushSkip(&sink_, skip); }
|
||||
@ -335,8 +332,6 @@ class Serializer::ObjectSerializer : public ObjectVisitor {
|
||||
void VisitCodeTarget(Code host, RelocInfo* target) override;
|
||||
void VisitRuntimeEntry(Code host, RelocInfo* reloc) override;
|
||||
void VisitOffHeapTarget(Code host, RelocInfo* target) override;
|
||||
// Relocation info needs to be visited sorted by target_address_address.
|
||||
void VisitRelocInfo(RelocIterator* it) override;
|
||||
|
||||
private:
|
||||
void SerializePrologue(AllocationSpace space, int size, Map map);
|
||||
|
Loading…
Reference in New Issue
Block a user