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/external-reference-table.h"
6
7#include "src/accessors.h"
8#include "src/counters.h"
9#include "src/external-reference.h"
10#include "src/ic/stub-cache.h"
11
12#if defined(DEBUG) && defined(V8_OS_LINUX) && !defined(V8_OS_ANDROID)
13#define SYMBOLIZE_FUNCTION
14#include <execinfo.h>
15#include <vector>
16#endif // DEBUG && V8_OS_LINUX && !V8_OS_ANDROID
17
18namespace v8 {
19namespace internal {
20
21#define ADD_EXT_REF_NAME(name, desc) desc,
22#define ADD_BUILTIN_NAME(Name, ...) "Builtin_" #Name,
23#define ADD_RUNTIME_FUNCTION(name, ...) "Runtime::" #name,
24#define ADD_ISOLATE_ADDR(Name, name) "Isolate::" #name "_address",
25#define ADD_ACCESSOR_INFO_NAME(_, __, AccessorName, ...) \
26 "Accessors::" #AccessorName "Getter",
27#define ADD_ACCESSOR_SETTER_NAME(name) "Accessors::" #name,
28#define ADD_STATS_COUNTER_NAME(name, ...) "StatsCounter::" #name,
29// static
30// clang-format off
31const char* const
32 ExternalReferenceTable::ref_name_[ExternalReferenceTable::kSize] = {
33 // Special references:
34 "nullptr",
35 // External references:
36 EXTERNAL_REFERENCE_LIST(ADD_EXT_REF_NAME)
37 EXTERNAL_REFERENCE_LIST_WITH_ISOLATE(ADD_EXT_REF_NAME)
38 // Builtins:
39 BUILTIN_LIST_C(ADD_BUILTIN_NAME)
40 // Runtime functions:
41 FOR_EACH_INTRINSIC(ADD_RUNTIME_FUNCTION)
42 // Isolate addresses:
43 FOR_EACH_ISOLATE_ADDRESS_NAME(ADD_ISOLATE_ADDR)
44 // Accessors:
45 ACCESSOR_INFO_LIST_GENERATOR(ADD_ACCESSOR_INFO_NAME, /* not used */)
46 ACCESSOR_SETTER_LIST(ADD_ACCESSOR_SETTER_NAME)
47 // Stub cache:
48 "Load StubCache::primary_->key",
49 "Load StubCache::primary_->value",
50 "Load StubCache::primary_->map",
51 "Load StubCache::secondary_->key",
52 "Load StubCache::secondary_->value",
53 "Load StubCache::secondary_->map",
54 "Store StubCache::primary_->key",
55 "Store StubCache::primary_->value",
56 "Store StubCache::primary_->map",
57 "Store StubCache::secondary_->key",
58 "Store StubCache::secondary_->value",
59 "Store StubCache::secondary_->map",
60 // Native code counters:
61 STATS_COUNTER_NATIVE_CODE_LIST(ADD_STATS_COUNTER_NAME)
62};
63// clang-format on
64#undef ADD_EXT_REF_NAME
65#undef ADD_BUILTIN_NAME
66#undef ADD_RUNTIME_FUNCTION
67#undef ADD_ISOLATE_ADDR
68#undef ADD_ACCESSOR_INFO_NAME
69#undef ADD_ACCESSOR_SETTER_NAME
70#undef ADD_STATS_COUNTER_NAME
71
72// Forward declarations for C++ builtins.
73#define FORWARD_DECLARE(Name) \
74 Address Builtin_##Name(int argc, Address* args, Isolate* isolate);
75BUILTIN_LIST_C(FORWARD_DECLARE)
76#undef FORWARD_DECLARE
77
78void ExternalReferenceTable::Init(Isolate* isolate) {
79 int index = 0;
80
81 // kNullAddress is preserved through serialization/deserialization.
82 Add(kNullAddress, &index);
83 AddReferences(isolate, &index);
84 AddBuiltins(&index);
85 AddRuntimeFunctions(&index);
86 AddIsolateAddresses(isolate, &index);
87 AddAccessors(&index);
88 AddStubCache(isolate, &index);
89 AddNativeCodeStatsCounters(isolate, &index);
90 is_initialized_ = static_cast<uint32_t>(true);
91
92 CHECK_EQ(kSize, index);
93}
94
95const char* ExternalReferenceTable::ResolveSymbol(void* address) {
96#ifdef SYMBOLIZE_FUNCTION
97 char** names = backtrace_symbols(&address, 1);
98 const char* name = names[0];
99 // The array of names is malloc'ed. However, each name string is static
100 // and do not need to be freed.
101 free(names);
102 return name;
103#else
104 return "<unresolved>";
105#endif // SYMBOLIZE_FUNCTION
106}
107
108void ExternalReferenceTable::Add(Address address, int* index) {
109 ref_addr_[(*index)++] = address;
110}
111
112void ExternalReferenceTable::AddReferences(Isolate* isolate, int* index) {
113 CHECK_EQ(kSpecialReferenceCount, *index);
114
115#define ADD_EXTERNAL_REFERENCE(name, desc) \
116 Add(ExternalReference::name().address(), index);
117 EXTERNAL_REFERENCE_LIST(ADD_EXTERNAL_REFERENCE)
118#undef ADD_EXTERNAL_REFERENCE
119
120#define ADD_EXTERNAL_REFERENCE(name, desc) \
121 Add(ExternalReference::name(isolate).address(), index);
122 EXTERNAL_REFERENCE_LIST_WITH_ISOLATE(ADD_EXTERNAL_REFERENCE)
123#undef ADD_EXTERNAL_REFERENCE
124
125 CHECK_EQ(kSpecialReferenceCount + kExternalReferenceCount, *index);
126}
127
128void ExternalReferenceTable::AddBuiltins(int* index) {
129 CHECK_EQ(kSpecialReferenceCount + kExternalReferenceCount, *index);
130
131 static const Address c_builtins[] = {
132#define DEF_ENTRY(Name, ...) FUNCTION_ADDR(&Builtin_##Name),
133 BUILTIN_LIST_C(DEF_ENTRY)
134#undef DEF_ENTRY
135 };
136 for (Address addr : c_builtins) {
137 Add(ExternalReference::Create(addr).address(), index);
138 }
139
140 CHECK_EQ(kSpecialReferenceCount + kExternalReferenceCount +
141 kBuiltinsReferenceCount,
142 *index);
143}
144
145void ExternalReferenceTable::AddRuntimeFunctions(int* index) {
146 CHECK_EQ(kSpecialReferenceCount + kExternalReferenceCount +
147 kBuiltinsReferenceCount,
148 *index);
149
150 static constexpr Runtime::FunctionId runtime_functions[] = {
151#define RUNTIME_ENTRY(name, ...) Runtime::k##name,
152 FOR_EACH_INTRINSIC(RUNTIME_ENTRY)
153#undef RUNTIME_ENTRY
154 };
155
156 for (Runtime::FunctionId fId : runtime_functions) {
157 Add(ExternalReference::Create(fId).address(), index);
158 }
159
160 CHECK_EQ(kSpecialReferenceCount + kExternalReferenceCount +
161 kBuiltinsReferenceCount + kRuntimeReferenceCount,
162 *index);
163}
164
165void ExternalReferenceTable::AddIsolateAddresses(Isolate* isolate, int* index) {
166 CHECK_EQ(kSpecialReferenceCount + kExternalReferenceCount +
167 kBuiltinsReferenceCount + kRuntimeReferenceCount,
168 *index);
169
170 for (int i = 0; i < IsolateAddressId::kIsolateAddressCount; ++i) {
171 Add(isolate->get_address_from_id(static_cast<IsolateAddressId>(i)), index);
172 }
173
174 CHECK_EQ(kSpecialReferenceCount + kExternalReferenceCount +
175 kBuiltinsReferenceCount + kRuntimeReferenceCount +
176 kIsolateAddressReferenceCount,
177 *index);
178}
179
180void ExternalReferenceTable::AddAccessors(int* index) {
181 CHECK_EQ(kSpecialReferenceCount + kExternalReferenceCount +
182 kBuiltinsReferenceCount + kRuntimeReferenceCount +
183 kIsolateAddressReferenceCount,
184 *index);
185
186 static const Address accessors[] = {
187 // Getters:
188#define ACCESSOR_INFO_DECLARATION(_, __, AccessorName, ...) \
189 FUNCTION_ADDR(&Accessors::AccessorName##Getter),
190 ACCESSOR_INFO_LIST_GENERATOR(ACCESSOR_INFO_DECLARATION, /* not used */)
191#undef ACCESSOR_INFO_DECLARATION
192 // Setters:
193#define ACCESSOR_SETTER_DECLARATION(name) FUNCTION_ADDR(&Accessors::name),
194 ACCESSOR_SETTER_LIST(ACCESSOR_SETTER_DECLARATION)
195#undef ACCESSOR_SETTER_DECLARATION
196 };
197
198 for (Address addr : accessors) {
199 Add(addr, index);
200 }
201
202 CHECK_EQ(kSpecialReferenceCount + kExternalReferenceCount +
203 kBuiltinsReferenceCount + kRuntimeReferenceCount +
204 kIsolateAddressReferenceCount + kAccessorReferenceCount,
205 *index);
206}
207
208void ExternalReferenceTable::AddStubCache(Isolate* isolate, int* index) {
209 CHECK_EQ(kSpecialReferenceCount + kExternalReferenceCount +
210 kBuiltinsReferenceCount + kRuntimeReferenceCount +
211 kIsolateAddressReferenceCount + kAccessorReferenceCount,
212 *index);
213
214 StubCache* load_stub_cache = isolate->load_stub_cache();
215
216 // Stub cache tables
217 Add(load_stub_cache->key_reference(StubCache::kPrimary).address(), index);
218 Add(load_stub_cache->value_reference(StubCache::kPrimary).address(), index);
219 Add(load_stub_cache->map_reference(StubCache::kPrimary).address(), index);
220 Add(load_stub_cache->key_reference(StubCache::kSecondary).address(), index);
221 Add(load_stub_cache->value_reference(StubCache::kSecondary).address(), index);
222 Add(load_stub_cache->map_reference(StubCache::kSecondary).address(), index);
223
224 StubCache* store_stub_cache = isolate->store_stub_cache();
225
226 // Stub cache tables
227 Add(store_stub_cache->key_reference(StubCache::kPrimary).address(), index);
228 Add(store_stub_cache->value_reference(StubCache::kPrimary).address(), index);
229 Add(store_stub_cache->map_reference(StubCache::kPrimary).address(), index);
230 Add(store_stub_cache->key_reference(StubCache::kSecondary).address(), index);
231 Add(store_stub_cache->value_reference(StubCache::kSecondary).address(),
232 index);
233 Add(store_stub_cache->map_reference(StubCache::kSecondary).address(), index);
234
235 CHECK_EQ(kSpecialReferenceCount + kExternalReferenceCount +
236 kBuiltinsReferenceCount + kRuntimeReferenceCount +
237 kIsolateAddressReferenceCount + kAccessorReferenceCount +
238 kStubCacheReferenceCount,
239 *index);
240}
241
242Address ExternalReferenceTable::GetStatsCounterAddress(StatsCounter* counter) {
243 int* address = counter->Enabled()
244 ? counter->GetInternalPointer()
245 : reinterpret_cast<int*>(&dummy_stats_counter_);
246 return reinterpret_cast<Address>(address);
247}
248
249void ExternalReferenceTable::AddNativeCodeStatsCounters(Isolate* isolate,
250 int* index) {
251 CHECK_EQ(kSpecialReferenceCount + kExternalReferenceCount +
252 kBuiltinsReferenceCount + kRuntimeReferenceCount +
253 kIsolateAddressReferenceCount + kAccessorReferenceCount +
254 kStubCacheReferenceCount,
255 *index);
256
257 Counters* counters = isolate->counters();
258
259#define SC(name, caption) Add(GetStatsCounterAddress(counters->name()), index);
260 STATS_COUNTER_NATIVE_CODE_LIST(SC)
261#undef SC
262
263 CHECK_EQ(kSpecialReferenceCount + kExternalReferenceCount +
264 kBuiltinsReferenceCount + kRuntimeReferenceCount +
265 kIsolateAddressReferenceCount + kAccessorReferenceCount +
266 kStubCacheReferenceCount + kStatsCountersReferenceCount,
267 *index);
268 CHECK_EQ(kSize, *index);
269}
270
271} // namespace internal
272} // namespace v8
273
274#undef SYMBOLIZE_FUNCTION
275