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/partial-serializer.h" 6 #include "src/snapshot/startup-serializer.h" 7 8 #include "src/objects-inl.h" 9 10 namespace v8 { 11 namespace internal { 12 13 PartialSerializer::PartialSerializer( 14 Isolate* isolate, StartupSerializer* startup_serializer, 15 v8::SerializeInternalFieldsCallback callback) 16 : Serializer(isolate), 17 startup_serializer_(startup_serializer), 18 serialize_internal_fields_(callback) { 19 InitializeCodeAddressMap(); 20 } 21 22 PartialSerializer::~PartialSerializer() { 23 OutputStatistics("PartialSerializer"); 24 } 25 26 void PartialSerializer::Serialize(Object** o, bool include_global_proxy) { 27 if ((*o)->IsContext()) { 28 Context* context = Context::cast(*o); 29 reference_map()->AddAttachedReference(context->global_proxy()); 30 // The bootstrap snapshot has a code-stub context. When serializing the 31 // partial snapshot, it is chained into the weak context list on the isolate 32 // and it's next context pointer may point to the code-stub context. Clear 33 // it before serializing, it will get re-added to the context list 34 // explicitly when it's loaded. 35 if (context->IsNativeContext()) { 36 context->set(Context::NEXT_CONTEXT_LINK, 37 isolate_->heap()->undefined_value()); 38 DCHECK(!context->global_object()->IsUndefined(context->GetIsolate())); 39 // Reset math random cache to get fresh random numbers. 40 context->set_math_random_index(Smi::kZero); 41 context->set_math_random_cache(isolate_->heap()->undefined_value()); 42 } 43 } 44 VisitPointer(o); 45 SerializeDeferredObjects(); 46 SerializeInternalFields(); 47 Pad(); 48 } 49 50 void PartialSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code, 51 WhereToPoint where_to_point, int skip) { 52 if (obj->IsMap()) { 53 // The code-caches link to context-specific code objects, which 54 // the startup and context serializes cannot currently handle. 55 DCHECK(Map::cast(obj)->code_cache() == obj->GetHeap()->empty_fixed_array()); 56 } 57 58 // Replace typed arrays by undefined. 59 if (obj->IsJSTypedArray()) obj = isolate_->heap()->undefined_value(); 60 61 if (SerializeHotObject(obj, how_to_code, where_to_point, skip)) return; 62 63 int root_index = root_index_map_.Lookup(obj); 64 if (root_index != RootIndexMap::kInvalidRootIndex) { 65 PutRoot(root_index, obj, how_to_code, where_to_point, skip); 66 return; 67 } 68 69 if (SerializeBackReference(obj, how_to_code, where_to_point, skip)) return; 70 71 if (ShouldBeInThePartialSnapshotCache(obj)) { 72 FlushSkip(skip); 73 74 int cache_index = startup_serializer_->PartialSnapshotCacheIndex(obj); 75 sink_.Put(kPartialSnapshotCache + how_to_code + where_to_point, 76 "PartialSnapshotCache"); 77 sink_.PutInt(cache_index, "partial_snapshot_cache_index"); 78 return; 79 } 80 81 // Pointers from the partial snapshot to the objects in the startup snapshot 82 // should go through the root array or through the partial snapshot cache. 83 // If this is not the case you may have to add something to the root array. 84 DCHECK(!startup_serializer_->reference_map()->Lookup(obj).is_valid()); 85 // All the internalized strings that the partial snapshot needs should be 86 // either in the root table or in the partial snapshot cache. 87 DCHECK(!obj->IsInternalizedString()); 88 // Function and object templates are not context specific. 89 DCHECK(!obj->IsTemplateInfo()); 90 91 FlushSkip(skip); 92 93 // Clear literal boilerplates. 94 if (obj->IsJSFunction()) { 95 JSFunction* function = JSFunction::cast(obj); 96 function->ClearTypeFeedbackInfo(); 97 } 98 99 if (obj->IsJSObject()) { 100 JSObject* jsobj = JSObject::cast(obj); 101 if (jsobj->GetInternalFieldCount() > 0) { 102 DCHECK_NOT_NULL(serialize_internal_fields_.callback); 103 internal_field_holders_.Add(jsobj); 104 } 105 } 106 107 // Object has not yet been serialized. Serialize it here. 108 ObjectSerializer serializer(this, obj, &sink_, how_to_code, where_to_point); 109 serializer.Serialize(); 110 } 111 112 bool PartialSerializer::ShouldBeInThePartialSnapshotCache(HeapObject* o) { 113 // Scripts should be referred only through shared function infos. We can't 114 // allow them to be part of the partial snapshot because they contain a 115 // unique ID, and deserializing several partial snapshots containing script 116 // would cause dupes. 117 DCHECK(!o->IsScript()); 118 return o->IsName() || o->IsSharedFunctionInfo() || o->IsHeapNumber() || 119 o->IsCode() || o->IsScopeInfo() || o->IsAccessorInfo() || 120 o->IsTemplateInfo() || 121 o->map() == 122 startup_serializer_->isolate()->heap()->fixed_cow_array_map(); 123 } 124 125 void PartialSerializer::SerializeInternalFields() { 126 int count = internal_field_holders_.length(); 127 if (count == 0) return; 128 DisallowHeapAllocation no_gc; 129 DisallowJavascriptExecution no_js(isolate()); 130 DisallowCompilation no_compile(isolate()); 131 DCHECK_NOT_NULL(serialize_internal_fields_.callback); 132 sink_.Put(kInternalFieldsData, "internal fields data"); 133 while (internal_field_holders_.length() > 0) { 134 HandleScope scope(isolate()); 135 Handle<JSObject> obj(internal_field_holders_.RemoveLast(), isolate()); 136 SerializerReference reference = reference_map_.Lookup(*obj); 137 DCHECK(reference.is_back_reference()); 138 int internal_fields_count = obj->GetInternalFieldCount(); 139 for (int i = 0; i < internal_fields_count; i++) { 140 if (obj->GetInternalField(i)->IsHeapObject()) continue; 141 StartupData data = serialize_internal_fields_.callback( 142 v8::Utils::ToLocal(obj), i, serialize_internal_fields_.data); 143 sink_.Put(kNewObject + reference.space(), "internal field holder"); 144 PutBackReference(*obj, reference); 145 sink_.PutInt(i, "internal field index"); 146 sink_.PutInt(data.raw_size, "internal fields data size"); 147 sink_.PutRaw(reinterpret_cast<const byte*>(data.data), data.raw_size, 148 "internal fields data"); 149 delete[] data.data; 150 } 151 } 152 sink_.Put(kSynchronize, "Finished with internal fields data"); 153 } 154 155 } // namespace internal 156 } // namespace v8 157