// 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/context-deserializer.h" #include "src/api/api-inl.h" #include "src/common/assert-scope.h" #include "src/heap/heap-inl.h" #include "src/objects/js-array-buffer-inl.h" #include "src/objects/slots.h" #include "src/snapshot/snapshot.h" namespace v8 { namespace internal { MaybeHandle ContextDeserializer::DeserializeContext( Isolate* isolate, const SnapshotData* data, bool can_rehash, Handle global_proxy, v8::DeserializeEmbedderFieldsCallback embedder_fields_deserializer) { ContextDeserializer d(isolate, data, can_rehash); MaybeHandle maybe_result = d.Deserialize(isolate, global_proxy, embedder_fields_deserializer); Handle result; return maybe_result.ToHandle(&result) ? Handle::cast(result) : MaybeHandle(); } MaybeHandle ContextDeserializer::Deserialize( Isolate* isolate, Handle global_proxy, v8::DeserializeEmbedderFieldsCallback embedder_fields_deserializer) { // Replace serialized references to the global proxy and its map with the // given global proxy and its map. AddAttachedObject(global_proxy); AddAttachedObject(handle(global_proxy->map(), isolate)); Handle result; { // There's no code deserialized here. If this assert fires then that's // changed and logging should be added to notify the profiler et al. of // the new code, which also has to be flushed from instruction cache. DisallowCodeAllocation no_code_allocation; result = ReadObject(); DeserializeDeferredObjects(); DeserializeEmbedderFields(embedder_fields_deserializer); LogNewMapEvents(); WeakenDescriptorArrays(); } if (should_rehash()) Rehash(); SetupOffHeapArrayBufferBackingStores(); return result; } void ContextDeserializer::SetupOffHeapArrayBufferBackingStores() { for (Handle buffer : new_off_heap_array_buffers()) { uint32_t store_index = buffer->GetBackingStoreRefForDeserialization(); auto bs = backing_store(store_index); SharedFlag shared = bs && bs->is_shared() ? SharedFlag::kShared : SharedFlag::kNotShared; DCHECK_IMPLIES(bs, buffer->is_resizable() == bs->is_resizable()); ResizableFlag resizable = bs && bs->is_resizable() ? ResizableFlag::kResizable : ResizableFlag::kNotResizable; buffer->Setup(shared, resizable, bs); } } void ContextDeserializer::DeserializeEmbedderFields( v8::DeserializeEmbedderFieldsCallback embedder_fields_deserializer) { if (!source()->HasMore() || source()->Get() != kEmbedderFieldsData) return; DisallowGarbageCollection no_gc; DisallowJavascriptExecution no_js(isolate()); DisallowCompilation no_compile(isolate()); DCHECK_NOT_NULL(embedder_fields_deserializer.callback); for (int code = source()->Get(); code != kSynchronize; code = source()->Get()) { HandleScope scope(isolate()); Handle obj = Handle::cast(GetBackReferencedObject()); int index = source()->GetInt(); int size = source()->GetInt(); // TODO(yangguo,jgruber): Turn this into a reusable shared buffer. byte* data = new byte[size]; source()->CopyRaw(data, size); embedder_fields_deserializer.callback(v8::Utils::ToLocal(obj), index, {reinterpret_cast(data), size}, embedder_fields_deserializer.data); delete[] data; } } } // namespace internal } // namespace v8