Commit bebaffb9 authored by Yang Guo's avatar Yang Guo Committed by Commit Bot

[serialize] explicitly serialize code content upfront.

The serializer performs two passes over the code. The first pass copies out the
code content verbatim, the second pass visits references recorded in the reloc
info.

So far the first pass is implicit and happens as part of the second pass, when
we encounter a non-HeapObject reference when iterating the code object.  That
however does not work for internal references. So we hit an assertion if the
first non-HeapObject reference we see is an internal reference.

This change explicitly triggers the first pass.

R=petermarshall@chromium.org

Bug: v8:6817
Change-Id: I1ee9949e10b7d9409986da83be22ac6287785f9f
Reviewed-on: https://chromium-review.googlesource.com/663867Reviewed-by: 's avatarPeter Marshall <petermarshall@chromium.org>
Reviewed-by: 's avatarYang Guo <yangguo@chromium.org>
Commit-Queue: Yang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48010}
parent b45a2737
......@@ -373,6 +373,9 @@ class Code::BodyDescriptor final : public BodyDescriptorBase {
v->VisitNextCodeLink(Code::cast(obj),
HeapObject::RawField(obj, kNextCodeLinkOffset));
// GC does not visit data/code in the header and in the body directly.
STATIC_ASSERT(Code::kNextCodeLinkOffset + kPointerSize == kDataStart);
RelocIterator it(Code::cast(obj), mode_mask);
Isolate* isolate = obj->GetIsolate();
for (; !it.done(); it.next()) {
......
......@@ -4011,6 +4011,11 @@ class Code: public HeapObject {
static const int kHeaderSize =
(kHeaderPaddingStart + kCodeAlignmentMask) & ~kCodeAlignmentMask;
// Data or code not directly visited by GC directly starts here.
// The serializer needs to copy bytes starting from here verbatim.
// Objects embedded into code is visited via reloc info.
static const int kDataStart = kInstructionSizeOffset;
inline int GetUnwindingInfoSizeOffset() const;
class BodyDescriptor;
......
......@@ -653,6 +653,17 @@ bool Deserializer::ReadData(Object** current, Object** limit, int source_space,
int size_in_bytes = source_.GetInt();
byte* raw_data_out = reinterpret_cast<byte*>(current);
source_.CopyRaw(raw_data_out, size_in_bytes);
current = reinterpret_cast<Object**>(
reinterpret_cast<intptr_t>(current) + size_in_bytes);
break;
}
// Deserialize raw code directly into the body of the code object.
// Do not move current.
case kVariableRawCode: {
int size_in_bytes = source_.GetInt();
source_.CopyRaw(current_object_address + Code::kDataStart,
size_in_bytes);
break;
}
......
......@@ -186,21 +186,24 @@ class SerializerDeserializer : public RootVisitor {
// Repeats of variable length.
static const int kVariableRepeat = 0x19;
// Raw data of variable length.
static const int kVariableRawData = 0x1a;
// Internal reference encoded as offsets of pc and target from code entry.
static const int kInternalReference = 0x1b;
static const int kInternalReferenceEncoded = 0x1c;
static const int kVariableRawCode = 0x1a;
static const int kVariableRawData = 0x1b;
// Used for embedder-allocated backing stores for TypedArrays.
static const int kOffHeapBackingStore = 0x1c;
// Used to encode deoptimizer entry code.
static const int kDeoptimizerEntryPlain = 0x1d;
static const int kDeoptimizerEntryFromCode = 0x1e;
// Used for embedder-provided serialization data for embedder fields.
static const int kEmbedderFieldsData = 0x1f;
// Used for embedder-allocated backing stores for TypedArrays.
static const int kOffHeapBackingStore = 0x35;
// Internal reference encoded as offsets of pc and target from code entry.
static const int kInternalReference = 0x35;
static const int kInternalReferenceEncoded = 0x36;
// Used to encode external referenced provided through the API.
static const int kApiReference = 0x36;
static const int kApiReference = 0x37;
// 8 hot (recently seen or back-referenced) objects with optional skip.
static const int kNumberOfHotObjects = 8;
......@@ -211,7 +214,7 @@ class SerializerDeserializer : public RootVisitor {
static const int kHotObjectWithSkip = 0x58;
static const int kHotObjectMask = 0x07;
// 0x37, 0x55..0x57, 0x75..0x7f unused.
// 0x55..0x57, 0x75..0x7f unused.
// ---------- byte code range 0x80..0xff ----------
// First 32 root array items.
......
This diff is collapsed.
......@@ -310,8 +310,7 @@ class Serializer::ObjectSerializer : public ObjectVisitor {
object_(obj),
sink_(sink),
reference_representation_(how_to_code + where_to_point),
bytes_processed_so_far_(0),
code_has_been_output_(false) {
bytes_processed_so_far_(0) {
#ifdef DEBUG
serializer_->PushStack(obj);
#endif // DEBUG
......@@ -322,7 +321,7 @@ class Serializer::ObjectSerializer : public ObjectVisitor {
#endif // DEBUG
}
void Serialize();
void SerializeContent();
void SerializeObject();
void SerializeDeferred();
void VisitPointers(HeapObject* host, Object** start, Object** end) override;
void VisitEmbeddedPointer(Code* host, RelocInfo* target) override;
......@@ -335,13 +334,12 @@ class Serializer::ObjectSerializer : public ObjectVisitor {
private:
void SerializePrologue(AllocationSpace space, int size, Map* map);
enum ReturnSkip { kCanReturnSkipInsteadOfSkipping, kIgnoringReturn };
// This function outputs or skips the raw data between the last pointer and
// up to the current position. It optionally can just return the number of
// bytes to skip instead of performing a skip instruction, in case the skip
// can be merged into the next instruction.
int OutputRawData(Address up_to, ReturnSkip return_skip = kIgnoringReturn);
// up to the current position.
void SerializeContent(Map* map, int size);
void OutputRawData(Address up_to);
void OutputCode(int size);
int SkipTo(Address to);
int32_t SerializeBackingStore(void* backing_store, int32_t byte_length);
void FixupIfNeutered();
void SerializeJSArrayBuffer();
......@@ -349,15 +347,12 @@ class Serializer::ObjectSerializer : public ObjectVisitor {
void SerializeExternalString();
void SerializeExternalStringAsSequentialString();
Address PrepareCode();
Serializer* serializer_;
HeapObject* object_;
SnapshotByteSink* sink_;
std::map<void*, Smi*> backing_stores;
int reference_representation_;
int bytes_processed_so_far_;
bool code_has_been_output_;
};
} // namespace internal
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment