Line data Source code
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/serializer-common.h"
6 :
7 : #include "src/external-reference-table.h"
8 : #include "src/objects-inl.h"
9 : #include "src/objects/foreign-inl.h"
10 : #include "src/objects/slots.h"
11 :
12 : namespace v8 {
13 : namespace internal {
14 :
15 806963 : ExternalReferenceEncoder::ExternalReferenceEncoder(Isolate* isolate) {
16 : #ifdef DEBUG
17 : api_references_ = isolate->api_external_references();
18 : if (api_references_ != nullptr) {
19 : for (uint32_t i = 0; api_references_[i] != 0; ++i) count_.push_back(0);
20 : }
21 : #endif // DEBUG
22 806456 : map_ = isolate->external_reference_map();
23 806456 : if (map_ != nullptr) return;
24 1014 : map_ = new AddressToIndexHashMap();
25 : isolate->set_external_reference_map(map_);
26 : // Add V8's external references.
27 : ExternalReferenceTable* table = isolate->external_reference_table();
28 473538 : for (uint32_t i = 0; i < ExternalReferenceTable::kSize; ++i) {
29 : Address addr = table->address(i);
30 : // Ignore duplicate references.
31 : // This can happen due to ICF. See http://crbug.com/726896.
32 473031 : if (map_->Get(addr).IsNothing()) map_->Set(addr, Value::Encode(i, false));
33 : DCHECK(map_->Get(addr).IsJust());
34 : }
35 : // Add external references provided by the embedder.
36 : const intptr_t* api_references = isolate->api_external_references();
37 507 : if (api_references == nullptr) return;
38 175 : for (uint32_t i = 0; api_references[i] != 0; ++i) {
39 175 : Address addr = static_cast<Address>(api_references[i]);
40 : // Ignore duplicate references.
41 : // This can happen due to ICF. See http://crbug.com/726896.
42 325 : if (map_->Get(addr).IsNothing()) map_->Set(addr, Value::Encode(i, true));
43 : DCHECK(map_->Get(addr).IsJust());
44 : }
45 : }
46 :
47 806456 : ExternalReferenceEncoder::~ExternalReferenceEncoder() {
48 : #ifdef DEBUG
49 : if (!i::FLAG_external_reference_stats) return;
50 : if (api_references_ == nullptr) return;
51 : for (uint32_t i = 0; api_references_[i] != 0; ++i) {
52 : Address addr = static_cast<Address>(api_references_[i]);
53 : DCHECK(map_->Get(addr).IsJust());
54 : v8::base::OS::Print(
55 : "index=%5d count=%5d %-60s\n", i, count_[i],
56 : ExternalReferenceTable::ResolveSymbol(reinterpret_cast<void*>(addr)));
57 : }
58 : #endif // DEBUG
59 806456 : }
60 :
61 30 : Maybe<ExternalReferenceEncoder::Value> ExternalReferenceEncoder::TryEncode(
62 : Address address) {
63 30 : Maybe<uint32_t> maybe_index = map_->Get(address);
64 30 : if (maybe_index.IsNothing()) return Nothing<Value>();
65 : Value result(maybe_index.FromJust());
66 : #ifdef DEBUG
67 : if (result.is_from_api()) count_[result.index()]++;
68 : #endif // DEBUG
69 : return Just<Value>(result);
70 : }
71 :
72 813860 : ExternalReferenceEncoder::Value ExternalReferenceEncoder::Encode(
73 : Address address) {
74 813860 : Maybe<uint32_t> maybe_index = map_->Get(address);
75 813860 : if (maybe_index.IsNothing()) {
76 0 : void* addr = reinterpret_cast<void*>(address);
77 0 : v8::base::OS::PrintError("Unknown external reference %p.\n", addr);
78 0 : v8::base::OS::PrintError("%s", ExternalReferenceTable::ResolveSymbol(addr));
79 0 : v8::base::OS::Abort();
80 : }
81 : Value result(maybe_index.FromJust());
82 : #ifdef DEBUG
83 : if (result.is_from_api()) count_[result.index()]++;
84 : #endif // DEBUG
85 813860 : return result;
86 : }
87 :
88 0 : const char* ExternalReferenceEncoder::NameOfAddress(Isolate* isolate,
89 : Address address) const {
90 0 : Maybe<uint32_t> maybe_index = map_->Get(address);
91 0 : if (maybe_index.IsNothing()) return "<unknown>";
92 : Value value(maybe_index.FromJust());
93 0 : if (value.is_from_api()) return "<from api>";
94 0 : return isolate->external_reference_table()->name(value.index());
95 : }
96 :
97 1112 : void SerializedData::AllocateData(uint32_t size) {
98 : DCHECK(!owns_data_);
99 1112 : data_ = NewArray<byte>(size);
100 1112 : size_ = size;
101 1112 : owns_data_ = true;
102 : DCHECK(IsAligned(reinterpret_cast<intptr_t>(data_), kPointerAlignment));
103 1112 : }
104 :
105 : // static
106 : constexpr uint32_t SerializedData::kMagicNumber;
107 :
108 : // The partial snapshot cache is terminated by undefined. We visit the
109 : // partial snapshot...
110 : // - during deserialization to populate it.
111 : // - during normal GC to keep its content alive.
112 : // - not during serialization. The partial serializer adds to it explicitly.
113 : DISABLE_CFI_PERF
114 306999 : void SerializerDeserializer::Iterate(Isolate* isolate, RootVisitor* visitor) {
115 306999 : std::vector<Object>* cache = isolate->partial_snapshot_cache();
116 455180340 : for (size_t i = 0;; ++i) {
117 : // Extend the array ready to get a value when deserializing.
118 455487339 : if (cache->size() <= i) cache->push_back(Smi::kZero);
119 : // During deserialization, the visitor populates the partial snapshot cache
120 : // and eventually terminates the cache with undefined.
121 : visitor->VisitRootPointer(Root::kPartialSnapshotCache, nullptr,
122 910974270 : FullObjectSlot(&cache->at(i)));
123 455487339 : if (cache->at(i)->IsUndefined(isolate)) break;
124 455180340 : }
125 306999 : }
126 :
127 3143 : bool SerializerDeserializer::CanBeDeferred(HeapObject o) {
128 9429 : return !o->IsString() && !o->IsScript() && !o->IsJSTypedArray();
129 : }
130 :
131 63078 : void SerializerDeserializer::RestoreExternalReferenceRedirectors(
132 : const std::vector<AccessorInfo>& accessor_infos) {
133 : // Restore wiped accessor infos.
134 126156 : for (AccessorInfo info : accessor_infos) {
135 0 : Foreign::cast(info->js_getter())
136 0 : ->set_foreign_address(info->redirected_getter());
137 : }
138 63078 : }
139 :
140 63078 : void SerializerDeserializer::RestoreExternalReferenceRedirectors(
141 : const std::vector<CallHandlerInfo>& call_handler_infos) {
142 126156 : for (CallHandlerInfo info : call_handler_infos) {
143 0 : Foreign::cast(info->js_callback())
144 0 : ->set_foreign_address(info->redirected_callback());
145 : }
146 63078 : }
147 :
148 : } // namespace internal
149 183867 : } // namespace v8
|