// Copyright 2017 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "src/snapshot/object-deserializer.h" #include "src/assembler-inl.h" #include "src/code-stubs.h" #include "src/isolate.h" #include "src/objects.h" #include "src/snapshot/code-serializer.h" #include "src/wasm/wasm-objects.h" namespace v8 { namespace internal { MaybeHandle ObjectDeserializer::DeserializeSharedFunctionInfo( Isolate* isolate, const SerializedCodeData* data, Handle source) { ObjectDeserializer d(data); d.AddAttachedObject(source); Vector code_stub_keys = data->CodeStubKeys(); for (int i = 0; i < code_stub_keys.length(); i++) { d.AddAttachedObject( CodeStub::GetCode(isolate, code_stub_keys[i]).ToHandleChecked()); } Handle result; return d.Deserialize(isolate).ToHandle(&result) ? Handle::cast(result) : MaybeHandle(); } MaybeHandle ObjectDeserializer::DeserializeWasmCompiledModule( Isolate* isolate, const SerializedCodeData* data, Vector wire_bytes) { ObjectDeserializer d(data); d.AddAttachedObject(isolate->native_context()); MaybeHandle maybe_wire_bytes_as_string = isolate->factory()->NewStringFromOneByte(wire_bytes, TENURED); Handle wire_bytes_as_string; if (!maybe_wire_bytes_as_string.ToHandle(&wire_bytes_as_string)) { return MaybeHandle(); } d.AddAttachedObject(wire_bytes_as_string); Vector code_stub_keys = data->CodeStubKeys(); for (int i = 0; i < code_stub_keys.length(); i++) { d.AddAttachedObject( CodeStub::GetCode(isolate, code_stub_keys[i]).ToHandleChecked()); } Handle result; if (!d.Deserialize(isolate).ToHandle(&result)) return MaybeHandle(); if (!result->IsWasmCompiledModule()) return MaybeHandle(); // Cast without type checks, as the module wrapper is not there yet. return handle(static_cast(*result), isolate); } MaybeHandle ObjectDeserializer::Deserialize(Isolate* isolate) { Initialize(isolate); if (!allocator()->ReserveSpace()) return MaybeHandle(); DCHECK(deserializing_user_code()); HandleScope scope(isolate); Handle result; { DisallowHeapAllocation no_gc; Object* root; VisitRootPointer(Root::kPartialSnapshotCache, nullptr, &root); DeserializeDeferredObjects(); FlushICacheForNewCodeObjectsAndRecordEmbeddedObjects(); result = Handle(HeapObject::cast(root)); Rehash(); allocator()->RegisterDeserializedObjectsForBlackAllocation(); } CommitPostProcessedObjects(); return scope.CloseAndEscape(result); } void ObjectDeserializer:: FlushICacheForNewCodeObjectsAndRecordEmbeddedObjects() { DCHECK(deserializing_user_code()); for (Code* code : new_code_objects()) { // Record all references to embedded objects in the new code object. isolate()->heap()->RecordWritesIntoCode(code); Assembler::FlushICache(code->raw_instruction_start(), code->raw_instruction_size()); } } void ObjectDeserializer::CommitPostProcessedObjects() { CHECK_LE(new_internalized_strings().size(), kMaxInt); StringTable::EnsureCapacityForDeserialization( isolate(), static_cast(new_internalized_strings().size())); for (Handle string : new_internalized_strings()) { DisallowHeapAllocation no_gc; StringTableInsertionKey key(*string); DCHECK_NULL(StringTable::ForwardStringIfExists(isolate(), &key, *string)); StringTable::AddKeyNoResize(isolate(), &key); } Heap* heap = isolate()->heap(); Factory* factory = isolate()->factory(); for (Handle