blob: 34defb4dced93d73c02de17747165946c48f47bb [file] [log] [blame]
Ben Murdochda12d292016-06-02 14:46:10 +01001// 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
7#include "src/objects-inl.h"
8
9namespace v8 {
10namespace internal {
11
12PartialSerializer::PartialSerializer(Isolate* isolate,
13 Serializer* startup_snapshot_serializer,
14 SnapshotByteSink* sink)
15 : Serializer(isolate, sink),
16 startup_serializer_(startup_snapshot_serializer),
Ben Murdochda12d292016-06-02 14:46:10 +010017 next_partial_cache_index_(0) {
18 InitializeCodeAddressMap();
19}
20
21PartialSerializer::~PartialSerializer() {
22 OutputStatistics("PartialSerializer");
23}
24
25void PartialSerializer::Serialize(Object** o) {
26 if ((*o)->IsContext()) {
27 Context* context = Context::cast(*o);
Ben Murdochc5610432016-08-08 18:44:38 +010028 reference_map()->AddAttachedReference(context->global_proxy());
Ben Murdochda12d292016-06-02 14:46:10 +010029 // The bootstrap snapshot has a code-stub context. When serializing the
30 // partial snapshot, it is chained into the weak context list on the isolate
31 // and it's next context pointer may point to the code-stub context. Clear
32 // it before serializing, it will get re-added to the context list
33 // explicitly when it's loaded.
34 if (context->IsNativeContext()) {
35 context->set(Context::NEXT_CONTEXT_LINK,
36 isolate_->heap()->undefined_value());
37 DCHECK(!context->global_object()->IsUndefined());
38 }
39 }
40 VisitPointer(o);
41 SerializeDeferredObjects();
42 Pad();
43}
44
45void PartialSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code,
46 WhereToPoint where_to_point, int skip) {
47 if (obj->IsMap()) {
48 // The code-caches link to context-specific code objects, which
49 // the startup and context serializes cannot currently handle.
50 DCHECK(Map::cast(obj)->code_cache() == obj->GetHeap()->empty_fixed_array());
51 }
52
53 // Replace typed arrays by undefined.
54 if (obj->IsJSTypedArray()) obj = isolate_->heap()->undefined_value();
55
56 int root_index = root_index_map_.Lookup(obj);
57 if (root_index != RootIndexMap::kInvalidRootIndex) {
58 PutRoot(root_index, obj, how_to_code, where_to_point, skip);
59 return;
60 }
61
62 if (ShouldBeInThePartialSnapshotCache(obj)) {
63 FlushSkip(skip);
64
65 int cache_index = PartialSnapshotCacheIndex(obj);
66 sink_->Put(kPartialSnapshotCache + how_to_code + where_to_point,
67 "PartialSnapshotCache");
68 sink_->PutInt(cache_index, "partial_snapshot_cache_index");
69 return;
70 }
71
72 // Pointers from the partial snapshot to the objects in the startup snapshot
73 // should go through the root array or through the partial snapshot cache.
74 // If this is not the case you may have to add something to the root array.
Ben Murdochc5610432016-08-08 18:44:38 +010075 DCHECK(!startup_serializer_->reference_map()->Lookup(obj).is_valid());
Ben Murdochda12d292016-06-02 14:46:10 +010076 // All the internalized strings that the partial snapshot needs should be
77 // either in the root table or in the partial snapshot cache.
78 DCHECK(!obj->IsInternalizedString());
79
80 if (SerializeKnownObject(obj, how_to_code, where_to_point, skip)) return;
81
82 FlushSkip(skip);
83
84 // Clear literal boilerplates.
85 if (obj->IsJSFunction()) {
86 FixedArray* literals = JSFunction::cast(obj)->literals();
87 for (int i = 0; i < literals->length(); i++) literals->set_undefined(i);
88 }
89
90 // Object has not yet been serialized. Serialize it here.
91 ObjectSerializer serializer(this, obj, sink_, how_to_code, where_to_point);
92 serializer.Serialize();
93}
94
95int PartialSerializer::PartialSnapshotCacheIndex(HeapObject* heap_object) {
96 int index = partial_cache_index_map_.LookupOrInsert(
97 heap_object, next_partial_cache_index_);
98 if (index == PartialCacheIndexMap::kInvalidIndex) {
99 // This object is not part of the partial snapshot cache yet. Add it to the
100 // startup snapshot so we can refer to it via partial snapshot index from
101 // the partial snapshot.
102 startup_serializer_->VisitPointer(reinterpret_cast<Object**>(&heap_object));
103 return next_partial_cache_index_++;
104 }
105 return index;
106}
107
108bool PartialSerializer::ShouldBeInThePartialSnapshotCache(HeapObject* o) {
109 // Scripts should be referred only through shared function infos. We can't
110 // allow them to be part of the partial snapshot because they contain a
111 // unique ID, and deserializing several partial snapshots containing script
112 // would cause dupes.
113 DCHECK(!o->IsScript());
114 return o->IsName() || o->IsSharedFunctionInfo() || o->IsHeapNumber() ||
115 o->IsCode() || o->IsScopeInfo() || o->IsAccessorInfo() ||
116 o->map() ==
117 startup_serializer_->isolate()->heap()->fixed_cow_array_map();
118}
119
120} // namespace internal
121} // namespace v8