1// Copyright 2018 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/read-only-serializer.h"
6
7#include "src/api/api.h"
8#include "src/diagnostics/code-tracer.h"
9#include "src/execution/v8threads.h"
10#include "src/handles/global-handles.h"
11#include "src/heap/read-only-heap.h"
12#include "src/objects/objects-inl.h"
13#include "src/objects/slots.h"
14#include "src/snapshot/serializer-inl.h"
15#include "src/snapshot/startup-serializer.h"
16
17namespace v8 {
18namespace internal {
19
20ReadOnlySerializer::ReadOnlySerializer(Isolate* isolate,
21                                       Snapshot::SerializerFlags flags)
22    : RootsSerializer(isolate, flags, RootIndex::kFirstReadOnlyRoot)
23#ifdef DEBUG
24      ,
25      serialized_objects_(isolate->heap()),
26      did_serialize_not_mapped_symbol_(false)
27#endif
28{
29  STATIC_ASSERT(RootIndex::kFirstReadOnlyRoot == RootIndex::kFirstRoot);
30}
31
32ReadOnlySerializer::~ReadOnlySerializer() {
33  OutputStatistics("ReadOnlySerializer");
34}
35
36void ReadOnlySerializer::SerializeObjectImpl(Handle<HeapObject> obj) {
37  CHECK(ReadOnlyHeap::Contains(*obj));
38  CHECK_IMPLIES(obj->IsString(), obj->IsInternalizedString());
39
40  // There should be no references to the not_mapped_symbol except for the entry
41  // in the root table, so don't try to serialize a reference and rely on the
42  // below CHECK(!did_serialize_not_mapped_symbol_) to make sure it doesn't
43  // serialize twice.
44  {
45    DisallowGarbageCollection no_gc;
46    HeapObject raw = *obj;
47    if (!IsNotMappedSymbol(raw)) {
48      if (SerializeHotObject(raw)) return;
49      if (IsRootAndHasBeenSerialized(raw) && SerializeRoot(raw)) return;
50      if (SerializeBackReference(raw)) return;
51    }
52
53    CheckRehashability(raw);
54  }
55
56  // Object has not yet been serialized.  Serialize it here.
57  ObjectSerializer object_serializer(this, obj, &sink_);
58  object_serializer.Serialize();
59#ifdef DEBUG
60  if (IsNotMappedSymbol(*obj)) {
61    CHECK(!did_serialize_not_mapped_symbol_);
62    did_serialize_not_mapped_symbol_ = true;
63  } else {
64    CHECK_NULL(serialized_objects_.Find(obj));
65    // There's no "IdentitySet", so use an IdentityMap with a value that is
66    // later ignored.
67    serialized_objects_.Insert(obj, 0);
68  }
69#endif
70}
71
72void ReadOnlySerializer::SerializeReadOnlyRoots() {
73  // No active threads.
74  CHECK_NULL(isolate()->thread_manager()->FirstThreadStateInUse());
75  // No active or weak handles.
76  CHECK_IMPLIES(!allow_active_isolate_for_testing(),
77                isolate()->handle_scope_implementer()->blocks()->empty());
78
79  ReadOnlyRoots(isolate()).Iterate(this);
80
81  if (reconstruct_read_only_and_shared_object_caches_for_testing()) {
82    ReconstructReadOnlyObjectCacheForTesting();
83  }
84}
85
86void ReadOnlySerializer::FinalizeSerialization() {
87  // This comes right after serialization of the other snapshots, where we
88  // add entries to the read-only object cache. Add one entry with 'undefined'
89  // to terminate the read-only object cache.
90  Object undefined = ReadOnlyRoots(isolate()).undefined_value();
91  VisitRootPointer(Root::kReadOnlyObjectCache, nullptr,
92                   FullObjectSlot(&undefined));
93  SerializeDeferredObjects();
94  Pad();
95
96#ifdef DEBUG
97  // Check that every object on read-only heap is reachable (and was
98  // serialized).
99  ReadOnlyHeapObjectIterator iterator(isolate()->read_only_heap());
100  for (HeapObject object = iterator.Next(); !object.is_null();
101       object = iterator.Next()) {
102    if (IsNotMappedSymbol(object)) {
103      CHECK(did_serialize_not_mapped_symbol_);
104    } else {
105      CHECK_NOT_NULL(serialized_objects_.Find(object));
106    }
107  }
108#endif
109}
110
111bool ReadOnlySerializer::MustBeDeferred(HeapObject object) {
112  if (root_has_been_serialized(RootIndex::kFreeSpaceMap) &&
113      root_has_been_serialized(RootIndex::kOnePointerFillerMap) &&
114      root_has_been_serialized(RootIndex::kTwoPointerFillerMap)) {
115    // All required root objects are serialized, so any aligned objects can
116    // be saved without problems.
117    return false;
118  }
119  // Defer objects with special alignment requirements until the filler roots
120  // are serialized.
121  return HeapObject::RequiredAlignment(object.map()) != kTaggedAligned;
122}
123
124bool ReadOnlySerializer::SerializeUsingReadOnlyObjectCache(
125    SnapshotByteSink* sink, Handle<HeapObject> obj) {
126  if (!ReadOnlyHeap::Contains(*obj)) return false;
127
128  // Get the cache index and serialize it into the read-only snapshot if
129  // necessary.
130  int cache_index = SerializeInObjectCache(obj);
131
132  // Writing out the cache entry into the calling serializer's sink.
133  sink->Put(kReadOnlyObjectCache, "ReadOnlyObjectCache");
134  sink->PutInt(cache_index, "read_only_object_cache_index");
135
136  return true;
137}
138
139void ReadOnlySerializer::ReconstructReadOnlyObjectCacheForTesting() {
140  ReadOnlyHeap* ro_heap = isolate()->read_only_heap();
141  DCHECK(ro_heap->read_only_object_cache_is_initialized());
142  for (size_t i = 0, size = ro_heap->read_only_object_cache_size(); i < size;
143       i++) {
144    Handle<HeapObject> obj(
145        HeapObject::cast(ro_heap->cached_read_only_object(i)), isolate());
146    int cache_index = SerializeInObjectCache(obj);
147    USE(cache_index);
148    DCHECK_EQ(cache_index, i);
149  }
150}
151
152}  // namespace internal
153}  // namespace v8
154