| // 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/startup-deserializer.h" |
| |
| #include "src/api/api.h" |
| #include "src/codegen/assembler-inl.h" |
| #include "src/execution/v8threads.h" |
| #include "src/heap/heap-inl.h" |
| #include "src/logging/log.h" |
| #include "src/snapshot/snapshot.h" |
| |
| namespace v8 { |
| namespace internal { |
| |
| void StartupDeserializer::DeserializeIntoIsolate() { |
| HandleScope scope(isolate()); |
| |
| // No active threads. |
| DCHECK_NULL(isolate()->thread_manager()->FirstThreadStateInUse()); |
| // No active handles. |
| DCHECK(isolate()->handle_scope_implementer()->blocks()->empty()); |
| // Startup object cache is not yet populated. |
| DCHECK(isolate()->startup_object_cache()->empty()); |
| // Builtins are not yet created. |
| DCHECK(!isolate()->builtins()->is_initialized()); |
| |
| { |
| isolate()->heap()->IterateSmiRoots(this); |
| isolate()->heap()->IterateRoots( |
| this, |
| base::EnumSet<SkipRoot>{SkipRoot::kUnserializable, SkipRoot::kWeak}); |
| Iterate(isolate(), this); |
| DeserializeStringTable(); |
| |
| isolate()->heap()->IterateWeakRoots( |
| this, base::EnumSet<SkipRoot>{SkipRoot::kUnserializable}); |
| DeserializeDeferredObjects(); |
| for (Handle<AccessorInfo> info : accessor_infos()) { |
| RestoreExternalReferenceRedirector(isolate(), info); |
| } |
| for (Handle<CallHandlerInfo> info : call_handler_infos()) { |
| RestoreExternalReferenceRedirector(isolate(), info); |
| } |
| |
| // Flush the instruction cache for the entire code-space. Must happen after |
| // builtins deserialization. |
| FlushICache(); |
| } |
| |
| CheckNoArrayBufferBackingStores(); |
| |
| isolate()->heap()->set_native_contexts_list( |
| ReadOnlyRoots(isolate()).undefined_value()); |
| // The allocation site list is build during root iteration, but if no sites |
| // were encountered then it needs to be initialized to undefined. |
| if (isolate()->heap()->allocation_sites_list() == Smi::zero()) { |
| isolate()->heap()->set_allocation_sites_list( |
| ReadOnlyRoots(isolate()).undefined_value()); |
| } |
| isolate()->heap()->set_dirty_js_finalization_registries_list( |
| ReadOnlyRoots(isolate()).undefined_value()); |
| isolate()->heap()->set_dirty_js_finalization_registries_list_tail( |
| ReadOnlyRoots(isolate()).undefined_value()); |
| |
| isolate()->builtins()->MarkInitialized(); |
| |
| LogNewMapEvents(); |
| WeakenDescriptorArrays(); |
| |
| if (FLAG_rehash_snapshot && can_rehash()) { |
| // Hash seed was initalized in ReadOnlyDeserializer. |
| Rehash(); |
| } |
| } |
| |
| void StartupDeserializer::DeserializeStringTable() { |
| // See StartupSerializer::SerializeStringTable. |
| |
| // Get the string table size. |
| int string_table_size = source()->GetInt(); |
| |
| // Add each string to the Isolate's string table. |
| // TODO(leszeks): Consider pre-sizing the string table. |
| for (int i = 0; i < string_table_size; ++i) { |
| Handle<String> string = Handle<String>::cast(ReadObject()); |
| StringTableInsertionKey key(string); |
| Handle<String> result = |
| isolate()->string_table()->LookupKey(isolate(), &key); |
| USE(result); |
| |
| // This is startup, so there should be no duplicate entries in the string |
| // table, and the lookup should unconditionally add the given string. |
| DCHECK_EQ(*result, *string); |
| } |
| |
| DCHECK_EQ(string_table_size, isolate()->string_table()->NumberOfElements()); |
| } |
| |
| void StartupDeserializer::LogNewMapEvents() { |
| if (FLAG_trace_maps) LOG(isolate(), LogAllMaps()); |
| } |
| |
| void StartupDeserializer::FlushICache() { |
| DCHECK(!deserializing_user_code()); |
| // The entire isolate is newly deserialized. Simply flush all code pages. |
| for (Page* p : *isolate()->heap()->code_space()) { |
| FlushInstructionCache(p->area_start(), p->area_end() - p->area_start()); |
| } |
| } |
| |
| } // namespace internal |
| } // namespace v8 |