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/ic/stub-cache.h"
10 #include "src/logging/counters.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
18 namespace v8 {
19 namespace 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
31 const 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);
BUILTIN_LIST_C(FORWARD_DECLARE)75 BUILTIN_LIST_C(FORWARD_DECLARE)
76 #undef FORWARD_DECLARE
77
78 void 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
ResolveSymbol(void * address)95 const 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
Add(Address address,int * index)108 void ExternalReferenceTable::Add(Address address, int* index) {
109 ref_addr_[(*index)++] = address;
110 }
111
AddReferences(Isolate * isolate,int * index)112 void 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
AddBuiltins(int * index)128 void 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
AddRuntimeFunctions(int * index)145 void 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
AddIsolateAddresses(Isolate * isolate,int * index)165 void 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
AddAccessors(int * index)180 void 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
AddStubCache(Isolate * isolate,int * index)208 void 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
GetStatsCounterAddress(StatsCounter * counter)242 Address 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
AddNativeCodeStatsCounters(Isolate * isolate,int * index)249 void 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