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