1 // Copyright 2016 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "src/snapshot/startup-serializer.h" 6 7 #include "src/api.h" 8 #include "src/code-tracer.h" 9 #include "src/global-handles.h" 10 #include "src/objects-inl.h" 11 #include "src/v8threads.h" 12 13 namespace v8 { 14 namespace internal { 15 16 StartupSerializer::StartupSerializer(Isolate* isolate) 17 : Serializer(isolate), can_be_rehashed_(true) { 18 InitializeCodeAddressMap(); 19 } 20 21 StartupSerializer::~StartupSerializer() { 22 RestoreExternalReferenceRedirectors(accessor_infos_); 23 RestoreExternalReferenceRedirectors(call_handler_infos_); 24 OutputStatistics("StartupSerializer"); 25 } 26 27 void StartupSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code, 28 WhereToPoint where_to_point, int skip) { 29 DCHECK(!ObjectIsBytecodeHandler(obj)); // Only referenced in dispatch table. 30 DCHECK(!obj->IsJSFunction()); 31 32 if (SerializeBuiltinReference(obj, how_to_code, where_to_point, skip)) { 33 return; 34 } 35 if (SerializeHotObject(obj, how_to_code, where_to_point, skip)) return; 36 37 int root_index = root_index_map()->Lookup(obj); 38 // We can only encode roots as such if it has already been serialized. 39 // That applies to root indices below the wave front. 40 if (root_index != RootIndexMap::kInvalidRootIndex) { 41 if (root_has_been_serialized(root_index)) { 42 PutRoot(root_index, obj, how_to_code, where_to_point, skip); 43 return; 44 } 45 } 46 47 if (SerializeBackReference(obj, how_to_code, where_to_point, skip)) return; 48 49 FlushSkip(skip); 50 bool use_simulator = false; 51 #ifdef USE_SIMULATOR 52 use_simulator = true; 53 #endif 54 55 if (use_simulator && obj->IsAccessorInfo()) { 56 // Wipe external reference redirects in the accessor info. 57 AccessorInfo* info = AccessorInfo::cast(obj); 58 Address original_address = Foreign::cast(info->getter())->foreign_address(); 59 Foreign::cast(info->js_getter())->set_foreign_address(original_address); 60 accessor_infos_.push_back(info); 61 } else if (use_simulator && obj->IsCallHandlerInfo()) { 62 CallHandlerInfo* info = CallHandlerInfo::cast(obj); 63 Address original_address = 64 Foreign::cast(info->callback())->foreign_address(); 65 Foreign::cast(info->js_callback())->set_foreign_address(original_address); 66 call_handler_infos_.push_back(info); 67 } else if (obj->IsScript() && Script::cast(obj)->IsUserJavaScript()) { 68 Script::cast(obj)->set_context_data( 69 ReadOnlyRoots(isolate()).uninitialized_symbol()); 70 } else if (obj->IsSharedFunctionInfo()) { 71 // Clear inferred name for native functions. 72 SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj); 73 if (!shared->IsSubjectToDebugging() && shared->HasUncompiledData()) { 74 shared->uncompiled_data()->set_inferred_name( 75 ReadOnlyRoots(isolate()).empty_string()); 76 } 77 } 78 79 CheckRehashability(obj); 80 81 // Object has not yet been serialized. Serialize it here. 82 ObjectSerializer object_serializer(this, obj, &sink_, how_to_code, 83 where_to_point); 84 object_serializer.Serialize(); 85 } 86 87 void StartupSerializer::SerializeWeakReferencesAndDeferred() { 88 // This comes right after serialization of the partial snapshot, where we 89 // add entries to the partial snapshot cache of the startup snapshot. Add 90 // one entry with 'undefined' to terminate the partial snapshot cache. 91 Object* undefined = ReadOnlyRoots(isolate()).undefined_value(); 92 VisitRootPointer(Root::kPartialSnapshotCache, nullptr, &undefined); 93 isolate()->heap()->IterateWeakRoots(this, VISIT_FOR_SERIALIZATION); 94 SerializeDeferredObjects(); 95 Pad(); 96 } 97 98 int StartupSerializer::PartialSnapshotCacheIndex(HeapObject* heap_object) { 99 int index; 100 if (!partial_cache_index_map_.LookupOrInsert(heap_object, &index)) { 101 // This object is not part of the partial snapshot cache yet. Add it to the 102 // startup snapshot so we can refer to it via partial snapshot index from 103 // the partial snapshot. 104 VisitRootPointer(Root::kPartialSnapshotCache, nullptr, 105 reinterpret_cast<Object**>(&heap_object)); 106 } 107 return index; 108 } 109 110 void StartupSerializer::Synchronize(VisitorSynchronization::SyncTag tag) { 111 sink_.Put(kSynchronize, "Synchronize"); 112 } 113 114 void StartupSerializer::SerializeStrongReferences() { 115 Isolate* isolate = this->isolate(); 116 // No active threads. 117 CHECK_NULL(isolate->thread_manager()->FirstThreadStateInUse()); 118 // No active or weak handles. 119 CHECK(isolate->handle_scope_implementer()->blocks()->empty()); 120 121 // Visit smi roots. 122 // Clear the stack limits to make the snapshot reproducible. 123 // Reset it again afterwards. 124 isolate->heap()->ClearStackLimits(); 125 isolate->heap()->IterateSmiRoots(this); 126 isolate->heap()->SetStackLimits(); 127 // First visit immortal immovables to make sure they end up in the first page. 128 isolate->heap()->IterateStrongRoots(this, VISIT_FOR_SERIALIZATION); 129 } 130 131 void StartupSerializer::VisitRootPointers(Root root, const char* description, 132 Object** start, Object** end) { 133 if (start == isolate()->heap()->roots_array_start()) { 134 // Serializing the root list needs special handling: 135 // - Only root list elements that have been fully serialized can be 136 // referenced using kRootArray bytecodes. 137 for (Object** current = start; current < end; current++) { 138 SerializeRootObject(*current); 139 int root_index = static_cast<int>(current - start); 140 root_has_been_serialized_.set(root_index); 141 } 142 } else { 143 Serializer::VisitRootPointers(root, description, start, end); 144 } 145 } 146 147 void StartupSerializer::CheckRehashability(HeapObject* obj) { 148 if (!can_be_rehashed_) return; 149 if (!obj->NeedsRehashing()) return; 150 if (obj->CanBeRehashed()) return; 151 can_be_rehashed_ = false; 152 } 153 154 bool StartupSerializer::MustBeDeferred(HeapObject* object) { 155 if (root_has_been_serialized_.test(Heap::kFreeSpaceMapRootIndex) && 156 root_has_been_serialized_.test(Heap::kOnePointerFillerMapRootIndex) && 157 root_has_been_serialized_.test(Heap::kTwoPointerFillerMapRootIndex)) { 158 // All required root objects are serialized, so any aligned objects can 159 // be saved without problems. 160 return false; 161 } 162 // Just defer everything except of Map objects until all required roots are 163 // serialized. Some objects may have special alignment requirements, that may 164 // not be fulfilled during deserialization until few first root objects are 165 // serialized. But we must serialize Map objects since deserializer checks 166 // that these root objects are indeed Maps. 167 return !object->IsMap(); 168 } 169 170 SerializedHandleChecker::SerializedHandleChecker( 171 Isolate* isolate, std::vector<Context*>* contexts) 172 : isolate_(isolate) { 173 AddToSet(isolate->heap()->serialized_objects()); 174 for (auto const& context : *contexts) { 175 AddToSet(context->serialized_objects()); 176 } 177 } 178 179 void SerializedHandleChecker::AddToSet(FixedArray* serialized) { 180 int length = serialized->length(); 181 for (int i = 0; i < length; i++) serialized_.insert(serialized->get(i)); 182 } 183 184 void SerializedHandleChecker::VisitRootPointers(Root root, 185 const char* description, 186 Object** start, Object** end) { 187 for (Object** p = start; p < end; p++) { 188 if (serialized_.find(*p) != serialized_.end()) continue; 189 PrintF("%s handle not serialized: ", 190 root == Root::kGlobalHandles ? "global" : "eternal"); 191 (*p)->Print(); 192 ok_ = false; 193 } 194 } 195 196 bool SerializedHandleChecker::CheckGlobalAndEternalHandles() { 197 isolate_->global_handles()->IterateAllRoots(this); 198 isolate_->eternal_handles()->IterateAllRoots(this); 199 return ok_; 200 } 201 202 } // namespace internal 203 } // namespace v8 204