• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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