���� JFIF �� � ( %"1"%)+...383,7(-.-
![]() Server : Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips PHP/7.4.20 System : Linux st2.domain.com 3.10.0-1127.10.1.el7.x86_64 #1 SMP Wed Jun 3 14:28:03 UTC 2020 x86_64 User : apache ( 48) PHP Version : 7.4.20 Disable Function : NONE Directory : /home/real/node-v13.0.1/deps/v8/src/snapshot/ |
// Copyright 2016 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-serializer.h" #include "src/api/api.h" #include "src/deoptimizer/deoptimizer.h" #include "src/execution/v8threads.h" #include "src/handles/global-handles.h" #include "src/heap/heap-inl.h" #include "src/heap/read-only-heap.h" #include "src/objects/contexts.h" #include "src/objects/foreign-inl.h" #include "src/objects/objects-inl.h" #include "src/objects/slots.h" #include "src/snapshot/read-only-serializer.h" namespace v8 { namespace internal { StartupSerializer::StartupSerializer(Isolate* isolate, ReadOnlySerializer* read_only_serializer) : RootsSerializer(isolate, RootIndex::kFirstStrongRoot), read_only_serializer_(read_only_serializer) { InitializeCodeAddressMap(); } StartupSerializer::~StartupSerializer() { RestoreExternalReferenceRedirectors(accessor_infos_); RestoreExternalReferenceRedirectors(call_handler_infos_); OutputStatistics("StartupSerializer"); } #ifdef DEBUG namespace { bool IsUnexpectedCodeObject(Isolate* isolate, HeapObject obj) { if (!obj.IsCode()) return false; Code code = Code::cast(obj); // TODO(v8:8768): Deopt entry code should not be serialized. if (code.kind() == Code::STUB && isolate->deoptimizer_data() != nullptr) { if (isolate->deoptimizer_data()->IsDeoptEntryCode(code)) return false; } if (code.kind() == Code::REGEXP) return false; if (!code.is_builtin()) return true; if (!FLAG_embedded_builtins) return false; if (code.is_off_heap_trampoline()) return false; // An on-heap builtin. We only expect this for the interpreter entry // trampoline copy stored on the root list and transitively called builtins. // See Heap::interpreter_entry_trampoline_for_profiling. switch (code.builtin_index()) { case Builtins::kAbort: case Builtins::kCEntry_Return1_DontSaveFPRegs_ArgvOnStack_NoBuiltinExit: case Builtins::kInterpreterEntryTrampoline: case Builtins::kRecordWrite: return false; default: return true; } UNREACHABLE(); } } // namespace #endif // DEBUG void StartupSerializer::SerializeObject(HeapObject obj) { #ifdef DEBUG if (obj.IsJSFunction()) { v8::base::OS::PrintError("Reference stack:\n"); PrintStack(std::cerr); obj.Print(std::cerr); FATAL( "JSFunction should be added through the context snapshot instead of " "the isolate snapshot"); } #endif // DEBUG DCHECK(!IsUnexpectedCodeObject(isolate(), obj)); if (SerializeHotObject(obj)) return; if (IsRootAndHasBeenSerialized(obj) && SerializeRoot(obj)) return; if (SerializeUsingReadOnlyObjectCache(&sink_, obj)) return; if (SerializeBackReference(obj)) return; bool use_simulator = false; #ifdef USE_SIMULATOR use_simulator = true; #endif if (use_simulator && obj.IsAccessorInfo()) { // Wipe external reference redirects in the accessor info. AccessorInfo info = AccessorInfo::cast(obj); Address original_address = Foreign::cast(info.getter()).foreign_address(); Foreign::cast(info.js_getter()).set_foreign_address(original_address); accessor_infos_.push_back(info); } else if (use_simulator && obj.IsCallHandlerInfo()) { CallHandlerInfo info = CallHandlerInfo::cast(obj); Address original_address = Foreign::cast(info.callback()).foreign_address(); Foreign::cast(info.js_callback()).set_foreign_address(original_address); call_handler_infos_.push_back(info); } else if (obj.IsScript() && Script::cast(obj).IsUserJavaScript()) { Script::cast(obj).set_context_data( ReadOnlyRoots(isolate()).uninitialized_symbol()); } else if (obj.IsSharedFunctionInfo()) { // Clear inferred name for native functions. SharedFunctionInfo shared = SharedFunctionInfo::cast(obj); if (!shared.IsSubjectToDebugging() && shared.HasUncompiledData()) { shared.uncompiled_data().set_inferred_name( ReadOnlyRoots(isolate()).empty_string()); } } CheckRehashability(obj); // Object has not yet been serialized. Serialize it here. DCHECK(!ReadOnlyHeap::Contains(obj)); ObjectSerializer object_serializer(this, obj, &sink_); object_serializer.Serialize(); } void StartupSerializer::SerializeWeakReferencesAndDeferred() { // This comes right after serialization of the partial snapshot, where we // add entries to the partial snapshot cache of the startup snapshot. Add // one entry with 'undefined' to terminate the partial snapshot cache. Object undefined = ReadOnlyRoots(isolate()).undefined_value(); VisitRootPointer(Root::kPartialSnapshotCache, nullptr, FullObjectSlot(&undefined)); isolate()->heap()->IterateWeakRoots(this, VISIT_FOR_SERIALIZATION); SerializeDeferredObjects(); Pad(); } void StartupSerializer::SerializeStrongReferences() { Isolate* isolate = this->isolate(); // No active threads. CHECK_NULL(isolate->thread_manager()->FirstThreadStateInUse()); // No active or weak handles. CHECK(isolate->handle_scope_implementer()->blocks()->empty()); // Visit smi roots and immortal immovables first to make sure they end up in // the first page. isolate->heap()->IterateSmiRoots(this); isolate->heap()->IterateStrongRoots(this, VISIT_FOR_SERIALIZATION); } SerializedHandleChecker::SerializedHandleChecker(Isolate* isolate, std::vector<Context>* contexts) : isolate_(isolate) { AddToSet(isolate->heap()->serialized_objects()); for (auto const& context : *contexts) { AddToSet(context.serialized_objects()); } } bool StartupSerializer::SerializeUsingReadOnlyObjectCache( SnapshotByteSink* sink, HeapObject obj) { return read_only_serializer_->SerializeUsingReadOnlyObjectCache(sink, obj); } void StartupSerializer::SerializeUsingPartialSnapshotCache( SnapshotByteSink* sink, HeapObject obj) { int cache_index = SerializeInObjectCache(obj); sink->Put(kPartialSnapshotCache, "PartialSnapshotCache"); sink->PutInt(cache_index, "partial_snapshot_cache_index"); } void SerializedHandleChecker::AddToSet(FixedArray serialized) { int length = serialized.length(); for (int i = 0; i < length; i++) serialized_.insert(serialized.get(i)); } void SerializedHandleChecker::VisitRootPointers(Root root, const char* description, FullObjectSlot start, FullObjectSlot end) { for (FullObjectSlot p = start; p < end; ++p) { if (serialized_.find(*p) != serialized_.end()) continue; PrintF("%s handle not serialized: ", root == Root::kGlobalHandles ? "global" : "eternal"); (*p).Print(); ok_ = false; } } bool SerializedHandleChecker::CheckGlobalAndEternalHandles() { isolate_->global_handles()->IterateAllRoots(this); isolate_->eternal_handles()->IterateAllRoots(this); return ok_; } } // namespace internal } // namespace v8