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 :
10 : namespace v8 {
11 : namespace internal {
12 :
13 1409 : ExternalReferenceEncoder::ExternalReferenceEncoder(Isolate* isolate) {
14 : #ifdef DEBUG
15 : api_references_ = isolate->api_external_references();
16 : if (api_references_ != nullptr) {
17 : for (uint32_t i = 0; api_references_[i] != 0; ++i) count_.push_back(0);
18 : }
19 : #endif // DEBUG
20 891 : map_ = isolate->external_reference_map();
21 891 : if (map_ != nullptr) return;
22 1036 : map_ = new AddressToIndexHashMap();
23 : isolate->set_external_reference_map(map_);
24 : // Add V8's external references.
25 518 : ExternalReferenceTable* table = ExternalReferenceTable::instance(isolate);
26 1005956 : for (uint32_t i = 0; i < table->size(); ++i) {
27 : Address addr = table->address(i);
28 : // Ignore duplicate references.
29 : // This can happen due to ICF. See http://crbug.com/726896.
30 502460 : if (map_->Get(addr).IsNothing()) map_->Set(addr, Value::Encode(i, false));
31 : DCHECK(map_->Get(addr).IsJust());
32 : }
33 : // Add external references provided by the embedder.
34 : const intptr_t* api_references = isolate->api_external_references();
35 518 : if (api_references == nullptr) return;
36 120 : for (uint32_t i = 0; api_references[i] != 0; ++i) {
37 120 : Address addr = reinterpret_cast<Address>(api_references[i]);
38 : // Ignore duplicate references.
39 : // This can happen due to ICF. See http://crbug.com/726896.
40 220 : if (map_->Get(addr).IsNothing()) map_->Set(addr, Value::Encode(i, true));
41 : DCHECK(map_->Get(addr).IsJust());
42 : }
43 : }
44 :
45 891 : ExternalReferenceEncoder::~ExternalReferenceEncoder() {
46 : #ifdef DEBUG
47 : if (!i::FLAG_external_reference_stats) return;
48 : if (api_references_ == nullptr) return;
49 : for (uint32_t i = 0; api_references_[i] != 0; ++i) {
50 : Address addr = reinterpret_cast<Address>(api_references_[i]);
51 : DCHECK(map_->Get(addr).IsJust());
52 : v8::base::OS::Print("index=%5d count=%5d %-60s\n", i, count_[i],
53 : ExternalReferenceTable::ResolveSymbol(addr));
54 : }
55 : #endif // DEBUG
56 891 : }
57 :
58 845893 : ExternalReferenceEncoder::Value ExternalReferenceEncoder::Encode(
59 : Address address) {
60 845893 : Maybe<uint32_t> maybe_index = map_->Get(address);
61 845893 : if (maybe_index.IsNothing()) {
62 : void* addr = address;
63 0 : v8::base::OS::PrintError("Unknown external reference %p.\n", addr);
64 0 : v8::base::OS::PrintError("%s", ExternalReferenceTable::ResolveSymbol(addr));
65 0 : v8::base::OS::Abort();
66 : }
67 : Value result(maybe_index.FromJust());
68 : #ifdef DEBUG
69 : if (result.is_from_api()) count_[result.index()]++;
70 : #endif // DEBUG
71 845893 : return result;
72 : }
73 :
74 0 : const char* ExternalReferenceEncoder::NameOfAddress(Isolate* isolate,
75 : Address address) const {
76 0 : Maybe<uint32_t> maybe_index = map_->Get(address);
77 0 : if (maybe_index.IsNothing()) return "<unknown>";
78 : return ExternalReferenceTable::instance(isolate)->name(
79 0 : maybe_index.FromJust());
80 : }
81 :
82 891 : void SerializedData::AllocateData(uint32_t size) {
83 : DCHECK(!owns_data_);
84 891 : data_ = NewArray<byte>(size);
85 891 : size_ = size;
86 891 : owns_data_ = true;
87 : DCHECK(IsAligned(reinterpret_cast<intptr_t>(data_), kPointerAlignment));
88 891 : }
89 :
90 : // The partial snapshot cache is terminated by undefined. We visit the
91 : // partial snapshot...
92 : // - during deserialization to populate it.
93 : // - during normal GC to keep its content alive.
94 : // - not during serialization. The partial serializer adds to it explicitly.
95 : DISABLE_CFI_PERF
96 232096 : void SerializerDeserializer::Iterate(Isolate* isolate, RootVisitor* visitor) {
97 232096 : std::vector<Object*>* cache = isolate->partial_snapshot_cache();
98 503217601 : for (size_t i = 0;; ++i) {
99 : // Extend the array ready to get a value when deserializing.
100 622698608 : if (cache->size() <= i) cache->push_back(Smi::kZero);
101 : // During deserialization, the visitor populates the partial snapshot cache
102 : // and eventually terminates the cache with undefined.
103 1006899156 : visitor->VisitRootPointer(Root::kPartialSnapshotCache, &cache->at(i));
104 1006899522 : if (cache->at(i)->IsUndefined(isolate)) break;
105 503217601 : }
106 232262 : }
107 :
108 3145 : bool SerializerDeserializer::CanBeDeferred(HeapObject* o) {
109 6290 : return !o->IsString() && !o->IsScript();
110 : }
111 :
112 55129 : void SerializerDeserializer::RestoreExternalReferenceRedirectors(
113 : const std::vector<AccessorInfo*>& accessor_infos) {
114 : // Restore wiped accessor infos.
115 110258 : for (AccessorInfo* info : accessor_infos) {
116 : Foreign::cast(info->js_getter())
117 0 : ->set_foreign_address(info->redirected_getter());
118 : }
119 55129 : }
120 :
121 : } // namespace internal
122 : } // namespace v8
|