• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
PartialSerializer(Isolate * isolate,StartupSerializer * startup_serializer,v8::SerializeInternalFieldsCallback callback)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 
~PartialSerializer()22 PartialSerializer::~PartialSerializer() {
23   OutputStatistics("PartialSerializer");
24 }
25 
Serialize(Object ** o)26 void PartialSerializer::Serialize(Object** o) {
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 
SerializeObject(HeapObject * obj,HowToCode how_to_code,WhereToPoint where_to_point,int skip)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     LiteralsArray* literals = function->literals();
97     for (int i = 0; i < literals->literals_count(); i++) {
98       literals->set_literal_undefined(i);
99     }
100     function->ClearTypeFeedbackInfo();
101   }
102 
103   if (obj->IsJSObject()) {
104     JSObject* jsobj = JSObject::cast(obj);
105     if (jsobj->GetInternalFieldCount() > 0) internal_field_holders_.Add(jsobj);
106   }
107 
108   // Object has not yet been serialized.  Serialize it here.
109   ObjectSerializer serializer(this, obj, &sink_, how_to_code, where_to_point);
110   serializer.Serialize();
111 }
112 
ShouldBeInThePartialSnapshotCache(HeapObject * o)113 bool PartialSerializer::ShouldBeInThePartialSnapshotCache(HeapObject* o) {
114   // Scripts should be referred only through shared function infos.  We can't
115   // allow them to be part of the partial snapshot because they contain a
116   // unique ID, and deserializing several partial snapshots containing script
117   // would cause dupes.
118   DCHECK(!o->IsScript());
119   return o->IsName() || o->IsSharedFunctionInfo() || o->IsHeapNumber() ||
120          o->IsCode() || o->IsScopeInfo() || o->IsAccessorInfo() ||
121          o->IsTemplateInfo() ||
122          o->map() ==
123              startup_serializer_->isolate()->heap()->fixed_cow_array_map();
124 }
125 
SerializeInternalFields()126 void PartialSerializer::SerializeInternalFields() {
127   int count = internal_field_holders_.length();
128   if (count == 0) return;
129   DisallowHeapAllocation no_gc;
130   DisallowJavascriptExecution no_js(isolate());
131   DisallowCompilation no_compile(isolate());
132   DCHECK_NOT_NULL(serialize_internal_fields_);
133   sink_.Put(kInternalFieldsData, "internal fields data");
134   while (internal_field_holders_.length() > 0) {
135     HandleScope scope(isolate());
136     Handle<JSObject> obj(internal_field_holders_.RemoveLast(), isolate());
137     SerializerReference reference = reference_map_.Lookup(*obj);
138     DCHECK(reference.is_back_reference());
139     int internal_fields_count = obj->GetInternalFieldCount();
140     for (int i = 0; i < internal_fields_count; i++) {
141       if (obj->GetInternalField(i)->IsHeapObject()) continue;
142       StartupData data = serialize_internal_fields_(v8::Utils::ToLocal(obj), i);
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