Commit 899f0af7 authored by Camillo Bruni's avatar Camillo Bruni Committed by V8 LUCI CQ

[serializer] Dehandlify more De-/Serializer code

Bug: v8:11263
Change-Id: I6f9f43125e5a1b27d8f8595bbbebdff2665968da
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3471635Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Commit-Queue: Camillo Bruni <cbruni@chromium.org>
Cr-Commit-Position: refs/heads/main@{#79771}
parent cfa49d26
...@@ -109,13 +109,14 @@ AlignedCachedData* CodeSerializer::SerializeSharedFunctionInfo( ...@@ -109,13 +109,14 @@ AlignedCachedData* CodeSerializer::SerializeSharedFunctionInfo(
return data.GetScriptData(); return data.GetScriptData();
} }
bool CodeSerializer::SerializeReadOnlyObject(Handle<HeapObject> obj) { bool CodeSerializer::SerializeReadOnlyObject(
if (!ReadOnlyHeap::Contains(*obj)) return false; HeapObject obj, const DisallowGarbageCollection& no_gc) {
if (!ReadOnlyHeap::Contains(obj)) return false;
// For objects on the read-only heap, never serialize the object, but instead // For objects on the read-only heap, never serialize the object, but instead
// create a back reference that encodes the page number as the chunk_index and // create a back reference that encodes the page number as the chunk_index and
// the offset within the page as the chunk_offset. // the offset within the page as the chunk_offset.
Address address = obj->address(); Address address = obj.address();
BasicMemoryChunk* chunk = BasicMemoryChunk::FromAddress(address); BasicMemoryChunk* chunk = BasicMemoryChunk::FromAddress(address);
uint32_t chunk_index = 0; uint32_t chunk_index = 0;
ReadOnlySpace* const read_only_space = isolate()->heap()->read_only_space(); ReadOnlySpace* const read_only_space = isolate()->heap()->read_only_space();
...@@ -131,77 +132,93 @@ bool CodeSerializer::SerializeReadOnlyObject(Handle<HeapObject> obj) { ...@@ -131,77 +132,93 @@ bool CodeSerializer::SerializeReadOnlyObject(Handle<HeapObject> obj) {
} }
void CodeSerializer::SerializeObjectImpl(Handle<HeapObject> obj) { void CodeSerializer::SerializeObjectImpl(Handle<HeapObject> obj) {
if (SerializeHotObject(obj)) return;
if (SerializeRoot(obj)) return;
if (SerializeBackReference(obj)) return;
if (SerializeReadOnlyObject(obj)) return;
CHECK(!obj->IsCode(cage_base()));
ReadOnlyRoots roots(isolate()); ReadOnlyRoots roots(isolate());
if (ElideObject(*obj)) { InstanceType instance_type;
return SerializeObject(roots.undefined_value_handle()); {
} DisallowGarbageCollection no_gc;
HeapObject raw = *obj;
if (obj->IsScript()) { if (SerializeHotObject(raw)) return;
Handle<Script> script_obj = Handle<Script>::cast(obj); if (SerializeRoot(raw)) return;
DCHECK_NE(script_obj->compilation_type(), Script::COMPILATION_TYPE_EVAL); if (SerializeBackReference(raw)) return;
// We want to differentiate between undefined and uninitialized_symbol for if (SerializeReadOnlyObject(raw, no_gc)) return;
// context_data for now. It is hack to allow debugging for scripts that are
// included as a part of custom snapshot. (see debug::Script::IsEmbedded()) instance_type = raw.map().instance_type();
Object context_data = script_obj->context_data(); CHECK(!InstanceTypeChecker::IsCode(instance_type));
if (context_data != roots.undefined_value() &&
context_data != roots.uninitialized_symbol()) { if (ElideObject(raw)) {
script_obj->set_context_data(roots.undefined_value()); AllowGarbageCollection allow_gc;
return SerializeObject(roots.undefined_value_handle());
} }
// We don't want to serialize host options to avoid serializing unnecessary
// object graph.
FixedArray host_options = script_obj->host_defined_options();
script_obj->set_host_defined_options(roots.empty_fixed_array());
SerializeGeneric(obj);
script_obj->set_host_defined_options(host_options);
script_obj->set_context_data(context_data);
return;
} }
if (obj->IsSharedFunctionInfo()) { if (InstanceTypeChecker::IsScript(instance_type)) {
Handle<SharedFunctionInfo> sfi = Handle<SharedFunctionInfo>::cast(obj); Handle<FixedArray> host_options;
DCHECK(!sfi->IsApiFunction()); Handle<Object> context_data;
{
DisallowGarbageCollection no_gc;
Script script_obj = Script::cast(*obj);
DCHECK_NE(script_obj.compilation_type(), Script::COMPILATION_TYPE_EVAL);
// We want to differentiate between undefined and uninitialized_symbol for
// context_data for now. It is hack to allow debugging for scripts that
// are included as a part of custom snapshot. (see
// debug::Script::IsEmbedded())
Object raw_context_data = script_obj.context_data();
if (raw_context_data != roots.undefined_value() &&
raw_context_data != roots.uninitialized_symbol()) {
script_obj.set_context_data(roots.undefined_value());
}
context_data = handle(raw_context_data, isolate());
// We don't want to serialize host options to avoid serializing
// unnecessary object graph.
host_options = handle(script_obj.host_defined_options(), isolate());
script_obj.set_host_defined_options(roots.empty_fixed_array());
}
SerializeGeneric(obj);
{
DisallowGarbageCollection no_gc;
Script script_obj = Script::cast(*obj);
script_obj.set_host_defined_options(*host_options);
script_obj.set_context_data(*context_data);
}
return;
} else if (InstanceTypeChecker::IsSharedFunctionInfo(instance_type)) {
Handle<DebugInfo> debug_info;
bool restore_bytecode = false;
{
DisallowGarbageCollection no_gc;
SharedFunctionInfo sfi = SharedFunctionInfo::cast(*obj);
DCHECK(!sfi.IsApiFunction());
#if V8_ENABLE_WEBASSEMBLY #if V8_ENABLE_WEBASSEMBLY
// TODO(7110): Enable serializing of Asm modules once the AsmWasmData // TODO(7110): Enable serializing of Asm modules once the AsmWasmData
// is context independent. // is context independent.
DCHECK(!sfi->HasAsmWasmData()); DCHECK(!sfi.HasAsmWasmData());
#endif // V8_ENABLE_WEBASSEMBLY #endif // V8_ENABLE_WEBASSEMBLY
DebugInfo debug_info; if (sfi.HasDebugInfo()) {
BytecodeArray debug_bytecode_array; // Clear debug info.
if (sfi->HasDebugInfo()) { DebugInfo raw_debug_info = sfi.GetDebugInfo();
// Clear debug info. if (raw_debug_info.HasInstrumentedBytecodeArray()) {
debug_info = sfi->GetDebugInfo(); restore_bytecode = true;
if (debug_info.HasInstrumentedBytecodeArray()) { sfi.SetActiveBytecodeArray(raw_debug_info.OriginalBytecodeArray());
debug_bytecode_array = debug_info.DebugBytecodeArray(); }
sfi->SetActiveBytecodeArray(debug_info.OriginalBytecodeArray()); sfi.set_script_or_debug_info(raw_debug_info.script(), kReleaseStore);
debug_info = handle(raw_debug_info, isolate());
} }
sfi->set_script_or_debug_info(debug_info.script(), kReleaseStore); DCHECK(!sfi.HasDebugInfo());
} }
DCHECK(!sfi->HasDebugInfo());
SerializeGeneric(obj); SerializeGeneric(obj);
// Restore debug info // Restore debug info
if (!debug_info.is_null()) { if (!debug_info.is_null()) {
sfi->set_script_or_debug_info(debug_info, kReleaseStore); DisallowGarbageCollection no_gc;
if (!debug_bytecode_array.is_null()) { SharedFunctionInfo sfi = SharedFunctionInfo::cast(*obj);
sfi->SetActiveBytecodeArray(debug_bytecode_array); sfi.set_script_or_debug_info(*debug_info, kReleaseStore);
if (restore_bytecode) {
sfi.SetActiveBytecodeArray(debug_info->DebugBytecodeArray());
} }
} }
return; return;
} } else if (InstanceTypeChecker::IsUncompiledDataWithoutPreparseDataWithJob(
instance_type)) {
if (obj->IsUncompiledDataWithoutPreparseDataWithJob()) {
Handle<UncompiledDataWithoutPreparseDataWithJob> data = Handle<UncompiledDataWithoutPreparseDataWithJob> data =
Handle<UncompiledDataWithoutPreparseDataWithJob>::cast(obj); Handle<UncompiledDataWithoutPreparseDataWithJob>::cast(obj);
Address job = data->job(); Address job = data->job();
...@@ -209,8 +226,8 @@ void CodeSerializer::SerializeObjectImpl(Handle<HeapObject> obj) { ...@@ -209,8 +226,8 @@ void CodeSerializer::SerializeObjectImpl(Handle<HeapObject> obj) {
SerializeGeneric(data); SerializeGeneric(data);
data->set_job(job); data->set_job(job);
return; return;
} } else if (InstanceTypeChecker::IsUncompiledDataWithPreparseDataAndJob(
if (obj->IsUncompiledDataWithPreparseDataAndJob()) { instance_type)) {
Handle<UncompiledDataWithPreparseDataAndJob> data = Handle<UncompiledDataWithPreparseDataAndJob> data =
Handle<UncompiledDataWithPreparseDataAndJob>::cast(obj); Handle<UncompiledDataWithPreparseDataAndJob>::cast(obj);
Address job = data->job(); Address job = data->job();
...@@ -233,14 +250,16 @@ void CodeSerializer::SerializeObjectImpl(Handle<HeapObject> obj) { ...@@ -233,14 +250,16 @@ void CodeSerializer::SerializeObjectImpl(Handle<HeapObject> obj) {
#endif // V8_TARGET_ARCH_ARM #endif // V8_TARGET_ARCH_ARM
// Past this point we should not see any (context-specific) maps anymore. // Past this point we should not see any (context-specific) maps anymore.
CHECK(!obj->IsMap()); CHECK(!InstanceTypeChecker::IsMap(instance_type));
// There should be no references to the global object embedded. // There should be no references to the global object embedded.
CHECK(!obj->IsJSGlobalProxy() && !obj->IsJSGlobalObject()); CHECK(!InstanceTypeChecker::IsJSGlobalProxy(instance_type) &&
!InstanceTypeChecker::IsJSGlobalObject(instance_type));
// Embedded FixedArrays that need rehashing must support rehashing. // Embedded FixedArrays that need rehashing must support rehashing.
CHECK_IMPLIES(obj->NeedsRehashing(cage_base()), CHECK_IMPLIES(obj->NeedsRehashing(cage_base()),
obj->CanBeRehashed(cage_base())); obj->CanBeRehashed(cage_base()));
// We expect no instantiated function objects or contexts. // We expect no instantiated function objects or contexts.
CHECK(!obj->IsJSFunction() && !obj->IsContext()); CHECK(!InstanceTypeChecker::IsJSFunction(instance_type) &&
!InstanceTypeChecker::IsContext(instance_type));
SerializeGeneric(obj); SerializeGeneric(obj);
} }
......
...@@ -104,7 +104,8 @@ class CodeSerializer : public Serializer { ...@@ -104,7 +104,8 @@ class CodeSerializer : public Serializer {
private: private:
void SerializeObjectImpl(Handle<HeapObject> o) override; void SerializeObjectImpl(Handle<HeapObject> o) override;
bool SerializeReadOnlyObject(Handle<HeapObject> obj); bool SerializeReadOnlyObject(HeapObject obj,
const DisallowGarbageCollection& no_gc);
DISALLOW_GARBAGE_COLLECTION(no_gc_) DISALLOW_GARBAGE_COLLECTION(no_gc_)
uint32_t source_hash_; uint32_t source_hash_;
......
...@@ -121,7 +121,7 @@ void ContextSerializer::Serialize(Context* o, ...@@ -121,7 +121,7 @@ void ContextSerializer::Serialize(Context* o,
} }
void ContextSerializer::SerializeObjectImpl(Handle<HeapObject> obj) { void ContextSerializer::SerializeObjectImpl(Handle<HeapObject> obj) {
DCHECK(!ObjectIsBytecodeHandler(obj)); // Only referenced in dispatch table. DCHECK(!ObjectIsBytecodeHandler(*obj)); // Only referenced in dispatch table.
if (!allow_active_isolate_for_testing()) { if (!allow_active_isolate_for_testing()) {
// When serializing a snapshot intended for real use, we should not end up // When serializing a snapshot intended for real use, we should not end up
...@@ -132,11 +132,13 @@ void ContextSerializer::SerializeObjectImpl(Handle<HeapObject> obj) { ...@@ -132,11 +132,13 @@ void ContextSerializer::SerializeObjectImpl(Handle<HeapObject> obj) {
DCHECK_IMPLIES(obj->IsNativeContext(), *obj == context_); DCHECK_IMPLIES(obj->IsNativeContext(), *obj == context_);
} }
if (SerializeHotObject(obj)) return; {
DisallowGarbageCollection no_gc;
if (SerializeRoot(obj)) return; HeapObject raw = *obj;
if (SerializeHotObject(raw)) return;
if (SerializeBackReference(obj)) return; if (SerializeRoot(raw)) return;
if (SerializeBackReference(raw)) return;
}
if (startup_serializer_->SerializeUsingReadOnlyObjectCache(&sink_, obj)) { if (startup_serializer_->SerializeUsingReadOnlyObjectCache(&sink_, obj)) {
return; return;
...@@ -161,30 +163,29 @@ void ContextSerializer::SerializeObjectImpl(Handle<HeapObject> obj) { ...@@ -161,30 +163,29 @@ void ContextSerializer::SerializeObjectImpl(Handle<HeapObject> obj) {
// Function and object templates are not context specific. // Function and object templates are not context specific.
DCHECK(!obj->IsTemplateInfo()); DCHECK(!obj->IsTemplateInfo());
// Clear literal boilerplates and feedback. InstanceType instance_type = obj->map().instance_type();
if (obj->IsFeedbackVector()) { if (InstanceTypeChecker::IsFeedbackVector(instance_type)) {
// Clear literal boilerplates and feedback.
Handle<FeedbackVector>::cast(obj)->ClearSlots(isolate()); Handle<FeedbackVector>::cast(obj)->ClearSlots(isolate());
} } else if (InstanceTypeChecker::IsFeedbackCell(instance_type)) {
// Clear InterruptBudget when serializing FeedbackCell.
// Clear InterruptBudget when serializing FeedbackCell.
if (obj->IsFeedbackCell()) {
Handle<FeedbackCell>::cast(obj)->SetInitialInterruptBudget(); Handle<FeedbackCell>::cast(obj)->SetInitialInterruptBudget();
} } else if (InstanceTypeChecker::IsJSObject(instance_type)) {
if (SerializeJSObjectWithEmbedderFields(Handle<JSObject>::cast(obj))) {
if (SerializeJSObjectWithEmbedderFields(obj)) { return;
return; }
} if (InstanceTypeChecker::IsJSFunction(instance_type)) {
DisallowGarbageCollection no_gc;
if (obj->IsJSFunction()) { // Unconditionally reset the JSFunction to its SFI's code, since we can't
// Unconditionally reset the JSFunction to its SFI's code, since we can't // serialize optimized code anyway.
// serialize optimized code anyway. JSFunction closure = JSFunction::cast(*obj);
Handle<JSFunction> closure = Handle<JSFunction>::cast(obj); closure.ResetIfCodeFlushed();
closure->ResetIfCodeFlushed(); if (closure.is_compiled()) {
if (closure->is_compiled()) { if (closure.shared().HasBaselineCode()) {
if (closure->shared().HasBaselineCode()) { closure.shared().FlushBaselineCode();
closure->shared().FlushBaselineCode(); }
closure.set_code(closure.shared().GetCode(), kReleaseStore);
} }
closure->set_code(closure->shared().GetCode(), kReleaseStore);
} }
} }
...@@ -219,19 +220,18 @@ bool DataIsEmpty(const StartupData& data) { return data.raw_size == 0; } ...@@ -219,19 +220,18 @@ bool DataIsEmpty(const StartupData& data) { return data.raw_size == 0; }
} // anonymous namespace } // anonymous namespace
bool ContextSerializer::SerializeJSObjectWithEmbedderFields( bool ContextSerializer::SerializeJSObjectWithEmbedderFields(
Handle<HeapObject> obj) { Handle<JSObject> obj) {
if (!obj->IsJSObject()) return false; DisallowGarbageCollection no_gc;
Handle<JSObject> js_obj = Handle<JSObject>::cast(obj); JSObject js_obj = *obj;
int embedder_fields_count = js_obj->GetEmbedderFieldCount(); int embedder_fields_count = js_obj.GetEmbedderFieldCount();
if (embedder_fields_count == 0) return false; if (embedder_fields_count == 0) return false;
CHECK_GT(embedder_fields_count, 0); CHECK_GT(embedder_fields_count, 0);
DCHECK(!js_obj->NeedsRehashing(cage_base())); DCHECK(!js_obj.NeedsRehashing(cage_base()));
DisallowGarbageCollection no_gc;
DisallowJavascriptExecution no_js(isolate()); DisallowJavascriptExecution no_js(isolate());
DisallowCompilation no_compile(isolate()); DisallowCompilation no_compile(isolate());
v8::Local<v8::Object> api_obj = v8::Utils::ToLocal(js_obj); v8::Local<v8::Object> api_obj = v8::Utils::ToLocal(obj);
std::vector<EmbedderDataSlot::RawData> original_embedder_values; std::vector<EmbedderDataSlot::RawData> original_embedder_values;
std::vector<StartupData> serialized_data; std::vector<StartupData> serialized_data;
...@@ -241,7 +241,7 @@ bool ContextSerializer::SerializeJSObjectWithEmbedderFields( ...@@ -241,7 +241,7 @@ bool ContextSerializer::SerializeJSObjectWithEmbedderFields(
// serializer. For aligned pointers, call the serialize callback. Hold // serializer. For aligned pointers, call the serialize callback. Hold
// onto the result. // onto the result.
for (int i = 0; i < embedder_fields_count; i++) { for (int i = 0; i < embedder_fields_count; i++) {
EmbedderDataSlot embedder_data_slot(*js_obj, i); EmbedderDataSlot embedder_data_slot(js_obj, i);
original_embedder_values.emplace_back( original_embedder_values.emplace_back(
embedder_data_slot.load_raw(isolate(), no_gc)); embedder_data_slot.load_raw(isolate(), no_gc));
Object object = embedder_data_slot.load_tagged(); Object object = embedder_data_slot.load_tagged();
...@@ -270,13 +270,18 @@ bool ContextSerializer::SerializeJSObjectWithEmbedderFields( ...@@ -270,13 +270,18 @@ bool ContextSerializer::SerializeJSObjectWithEmbedderFields(
// with embedder callbacks. // with embedder callbacks.
for (int i = 0; i < embedder_fields_count; i++) { for (int i = 0; i < embedder_fields_count; i++) {
if (!DataIsEmpty(serialized_data[i])) { if (!DataIsEmpty(serialized_data[i])) {
EmbedderDataSlot(*js_obj, i).store_raw(isolate(), kNullAddress, no_gc); EmbedderDataSlot(js_obj, i).store_raw(isolate(), kNullAddress, no_gc);
} }
} }
// 3) Serialize the object. References from embedder fields to heap objects or // 3) Serialize the object. References from embedder fields to heap objects or
// smis are serialized regularly. // smis are serialized regularly.
ObjectSerializer(this, js_obj, &sink_).Serialize(); {
AllowGarbageCollection allow_gc;
ObjectSerializer(this, obj, &sink_).Serialize();
// Reload raw pointer.
js_obj = *obj;
}
// 4) Obtain back reference for the serialized object. // 4) Obtain back reference for the serialized object.
const SerializerReference* reference = const SerializerReference* reference =
...@@ -290,8 +295,8 @@ bool ContextSerializer::SerializeJSObjectWithEmbedderFields( ...@@ -290,8 +295,8 @@ bool ContextSerializer::SerializeJSObjectWithEmbedderFields(
StartupData data = serialized_data[i]; StartupData data = serialized_data[i];
if (DataIsEmpty(data)) continue; if (DataIsEmpty(data)) continue;
// Restore original values from cleared fields. // Restore original values from cleared fields.
EmbedderDataSlot(*js_obj, i) EmbedderDataSlot(js_obj, i).store_raw(isolate(),
.store_raw(isolate(), original_embedder_values[i], no_gc); original_embedder_values[i], no_gc);
embedder_fields_sink_.Put(kNewObject, "embedder field holder"); embedder_fields_sink_.Put(kNewObject, "embedder field holder");
embedder_fields_sink_.PutInt(reference->back_ref_index(), "BackRefIndex"); embedder_fields_sink_.PutInt(reference->back_ref_index(), "BackRefIndex");
embedder_fields_sink_.PutInt(i, "embedder field index"); embedder_fields_sink_.PutInt(i, "embedder field index");
......
...@@ -33,7 +33,7 @@ class V8_EXPORT_PRIVATE ContextSerializer : public Serializer { ...@@ -33,7 +33,7 @@ class V8_EXPORT_PRIVATE ContextSerializer : public Serializer {
void SerializeObjectImpl(Handle<HeapObject> o) override; void SerializeObjectImpl(Handle<HeapObject> o) override;
bool ShouldBeInTheStartupObjectCache(HeapObject o); bool ShouldBeInTheStartupObjectCache(HeapObject o);
bool ShouldBeInTheSharedObjectCache(HeapObject o); bool ShouldBeInTheSharedObjectCache(HeapObject o);
bool SerializeJSObjectWithEmbedderFields(Handle<HeapObject> obj); bool SerializeJSObjectWithEmbedderFields(Handle<JSObject> obj);
void CheckRehashability(HeapObject obj); void CheckRehashability(HeapObject obj);
StartupSerializer* startup_serializer_; StartupSerializer* startup_serializer_;
......
...@@ -41,13 +41,17 @@ void ReadOnlySerializer::SerializeObjectImpl(Handle<HeapObject> obj) { ...@@ -41,13 +41,17 @@ void ReadOnlySerializer::SerializeObjectImpl(Handle<HeapObject> obj) {
// in the root table, so don't try to serialize a reference and rely on the // in the root table, so don't try to serialize a reference and rely on the
// below CHECK(!did_serialize_not_mapped_symbol_) to make sure it doesn't // below CHECK(!did_serialize_not_mapped_symbol_) to make sure it doesn't
// serialize twice. // serialize twice.
if (!IsNotMappedSymbol(*obj)) { {
if (SerializeHotObject(obj)) return; DisallowGarbageCollection no_gc;
if (IsRootAndHasBeenSerialized(*obj) && SerializeRoot(obj)) return; HeapObject raw = *obj;
if (SerializeBackReference(obj)) return; if (!IsNotMappedSymbol(raw)) {
} if (SerializeHotObject(raw)) return;
if (IsRootAndHasBeenSerialized(raw) && SerializeRoot(raw)) return;
if (SerializeBackReference(raw)) return;
}
CheckRehashability(*obj); CheckRehashability(raw);
}
// Object has not yet been serialized. Serialize it here. // Object has not yet been serialized. Serialize it here.
ObjectSerializer object_serializer(this, obj, &sink_); ObjectSerializer object_serializer(this, obj, &sink_);
......
...@@ -27,7 +27,7 @@ RootsSerializer::RootsSerializer(Isolate* isolate, ...@@ -27,7 +27,7 @@ RootsSerializer::RootsSerializer(Isolate* isolate,
int RootsSerializer::SerializeInObjectCache(Handle<HeapObject> heap_object) { int RootsSerializer::SerializeInObjectCache(Handle<HeapObject> heap_object) {
int index; int index;
if (!object_cache_index_map_.LookupOrInsert(heap_object, &index)) { if (!object_cache_index_map_.LookupOrInsert(*heap_object, &index)) {
// This object is not part of the object cache yet. Add it to the cache so // This object is not part of the object cache yet. Add it to the cache so
// we can refer to it via cache index from the delegating snapshot. // we can refer to it via cache index from the delegating snapshot.
SerializeObject(heap_object); SerializeObject(heap_object);
......
This diff is collapsed.
...@@ -233,8 +233,7 @@ class Serializer : public SerializerDeserializer { ...@@ -233,8 +233,7 @@ class Serializer : public SerializerDeserializer {
void PutRoot(RootIndex root_index); void PutRoot(RootIndex root_index);
void PutSmiRoot(FullObjectSlot slot); void PutSmiRoot(FullObjectSlot slot);
void PutBackReference(Handle<HeapObject> object, void PutBackReference(HeapObject object, SerializerReference reference);
SerializerReference reference);
void PutAttachedReference(SerializerReference reference); void PutAttachedReference(SerializerReference reference);
void PutNextChunk(SnapshotSpace space); void PutNextChunk(SnapshotSpace space);
void PutRepeat(int repeat_count); void PutRepeat(int repeat_count);
...@@ -247,19 +246,19 @@ class Serializer : public SerializerDeserializer { ...@@ -247,19 +246,19 @@ class Serializer : public SerializerDeserializer {
void ResolvePendingForwardReference(int obj); void ResolvePendingForwardReference(int obj);
// Returns true if the object was successfully serialized as a root. // Returns true if the object was successfully serialized as a root.
bool SerializeRoot(Handle<HeapObject> obj); bool SerializeRoot(HeapObject obj);
// Returns true if the object was successfully serialized as hot object. // Returns true if the object was successfully serialized as hot object.
bool SerializeHotObject(Handle<HeapObject> obj); bool SerializeHotObject(HeapObject obj);
// Returns true if the object was successfully serialized as back reference. // Returns true if the object was successfully serialized as back reference.
bool SerializeBackReference(Handle<HeapObject> obj); bool SerializeBackReference(HeapObject obj);
// Returns true if the object was successfully serialized as pending object. // Returns true if the object was successfully serialized as pending object.
bool SerializePendingObject(Handle<HeapObject> obj); bool SerializePendingObject(HeapObject obj);
// Returns true if the given heap object is a bytecode handler code object. // Returns true if the given heap object is a bytecode handler code object.
bool ObjectIsBytecodeHandler(Handle<HeapObject> obj) const; bool ObjectIsBytecodeHandler(HeapObject obj) const;
ExternalReferenceEncoder::Value EncodeExternalReference(Address addr); ExternalReferenceEncoder::Value EncodeExternalReference(Address addr);
...@@ -278,18 +277,18 @@ class Serializer : public SerializerDeserializer { ...@@ -278,18 +277,18 @@ class Serializer : public SerializerDeserializer {
Code CopyCode(Code code); Code CopyCode(Code code);
void QueueDeferredObject(Handle<HeapObject> obj) { void QueueDeferredObject(HeapObject obj) {
DCHECK_NULL(reference_map_.LookupReference(obj)); DCHECK_NULL(reference_map_.LookupReference(obj));
deferred_objects_.Push(*obj); deferred_objects_.Push(obj);
} }
// Register that the the given object shouldn't be immediately serialized, but // Register that the the given object shouldn't be immediately serialized, but
// will be serialized later and any references to it should be pending forward // will be serialized later and any references to it should be pending forward
// references. // references.
void RegisterObjectIsPending(Handle<HeapObject> obj); void RegisterObjectIsPending(HeapObject obj);
// Resolve the given pending object reference with the current object. // Resolve the given pending object reference with the current object.
void ResolvePendingObject(Handle<HeapObject> obj); void ResolvePendingObject(HeapObject obj);
void OutputStatistics(const char* name); void OutputStatistics(const char* name);
......
...@@ -169,15 +169,22 @@ void SharedHeapSerializer::SerializeObjectImpl(Handle<HeapObject> obj) { ...@@ -169,15 +169,22 @@ void SharedHeapSerializer::SerializeObjectImpl(Handle<HeapObject> obj) {
// Objects in the shared heap cannot depend on per-Isolate roots but can // Objects in the shared heap cannot depend on per-Isolate roots but can
// depend on RO roots since sharing objects requires sharing the RO space. // depend on RO roots since sharing objects requires sharing the RO space.
DCHECK(CanBeInSharedOldSpace(*obj) || ReadOnlyHeap::Contains(*obj)); DCHECK(CanBeInSharedOldSpace(*obj) || ReadOnlyHeap::Contains(*obj));
{
if (SerializeHotObject(obj)) return; DisallowGarbageCollection no_gc;
if (IsRootAndHasBeenSerialized(*obj) && SerializeRoot(obj)) return; HeapObject raw = *obj;
if (SerializeHotObject(raw)) return;
if (IsRootAndHasBeenSerialized(raw) && SerializeRoot(raw)) return;
}
if (SerializeUsingReadOnlyObjectCache(&sink_, obj)) return; if (SerializeUsingReadOnlyObjectCache(&sink_, obj)) return;
if (SerializeBackReference(obj)) return; {
DisallowGarbageCollection no_gc;
HeapObject raw = *obj;
if (SerializeBackReference(raw)) return;
CheckRehashability(raw);
CheckRehashability(*obj); DCHECK(!ReadOnlyHeap::Contains(raw));
}
DCHECK(!ReadOnlyHeap::Contains(*obj));
ObjectSerializer object_serializer(this, obj, &sink_); ObjectSerializer object_serializer(this, obj, &sink_);
object_serializer.Serialize(); object_serializer.Serialize();
......
...@@ -144,13 +144,17 @@ void StartupSerializer::SerializeObjectImpl(Handle<HeapObject> obj) { ...@@ -144,13 +144,17 @@ void StartupSerializer::SerializeObjectImpl(Handle<HeapObject> obj) {
"the isolate snapshot"); "the isolate snapshot");
} }
#endif // DEBUG #endif // DEBUG
DCHECK(!IsUnexpectedCodeObject(isolate(), *obj)); {
DisallowGarbageCollection no_gc;
HeapObject raw = *obj;
DCHECK(!IsUnexpectedCodeObject(isolate(), raw));
if (SerializeHotObject(raw)) return;
if (IsRootAndHasBeenSerialized(raw) && SerializeRoot(raw)) return;
}
if (SerializeHotObject(obj)) return;
if (IsRootAndHasBeenSerialized(*obj) && SerializeRoot(obj)) return;
if (SerializeUsingReadOnlyObjectCache(&sink_, obj)) return; if (SerializeUsingReadOnlyObjectCache(&sink_, obj)) return;
if (SerializeUsingSharedHeapObjectCache(&sink_, obj)) return; if (SerializeUsingSharedHeapObjectCache(&sink_, obj)) return;
if (SerializeBackReference(obj)) return; if (SerializeBackReference(*obj)) return;
bool use_simulator = false; bool use_simulator = false;
#ifdef USE_SIMULATOR #ifdef USE_SIMULATOR
......
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