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 
18 namespace v8 {
19 namespace internal {
20 
21 // Forward declarations for C++ builtins.
22 #define FORWARD_DECLARE(Name) \
23   Object* Builtin_##Name(int argc, Object** args, Isolate* isolate);
BUILTIN_LIST_C(FORWARD_DECLARE)24 BUILTIN_LIST_C(FORWARD_DECLARE)
25 #undef FORWARD_DECLARE
26 
27 void ExternalReferenceTable::Init(Isolate* isolate) {
28   int index = 0;
29 
30   // kNullAddress is preserved through serialization/deserialization.
31   Add(kNullAddress, "nullptr", &index);
32   AddReferences(isolate, &index);
33   AddBuiltins(&index);
34   AddRuntimeFunctions(&index);
35   AddIsolateAddresses(isolate, &index);
36   AddAccessors(&index);
37   AddStubCache(isolate, &index);
38   is_initialized_ = static_cast<uint32_t>(true);
39   USE(unused_padding_);
40 
41   CHECK_EQ(kSize, index);
42 }
43 
ResolveSymbol(void * address)44 const char* ExternalReferenceTable::ResolveSymbol(void* address) {
45 #ifdef SYMBOLIZE_FUNCTION
46   char** names = backtrace_symbols(&address, 1);
47   const char* name = names[0];
48   // The array of names is malloc'ed. However, each name string is static
49   // and do not need to be freed.
50   free(names);
51   return name;
52 #else
53   return "<unresolved>";
54 #endif  // SYMBOLIZE_FUNCTION
55 }
56 
Add(Address address,const char * name,int * index)57 void ExternalReferenceTable::Add(Address address, const char* name,
58                                  int* index) {
59   refs_[(*index)++] = {address, name};
60 }
61 
AddReferences(Isolate * isolate,int * index)62 void ExternalReferenceTable::AddReferences(Isolate* isolate, int* index) {
63   CHECK_EQ(kSpecialReferenceCount, *index);
64 
65 #define ADD_EXTERNAL_REFERENCE(name, desc) \
66   Add(ExternalReference::name().address(), desc, index);
67   EXTERNAL_REFERENCE_LIST(ADD_EXTERNAL_REFERENCE)
68 #undef ADD_EXTERNAL_REFERENCE
69 
70 #define ADD_EXTERNAL_REFERENCE(name, desc) \
71   Add(ExternalReference::name(isolate).address(), desc, index);
72   EXTERNAL_REFERENCE_LIST_WITH_ISOLATE(ADD_EXTERNAL_REFERENCE)
73 #undef ADD_EXTERNAL_REFERENCE
74 
75   CHECK_EQ(kSpecialReferenceCount + kExternalReferenceCount, *index);
76 }
77 
AddBuiltins(int * index)78 void ExternalReferenceTable::AddBuiltins(int* index) {
79   CHECK_EQ(kSpecialReferenceCount + kExternalReferenceCount, *index);
80 
81   struct CBuiltinEntry {
82     Address address;
83     const char* name;
84   };
85   static const CBuiltinEntry c_builtins[] = {
86 #define DEF_ENTRY(Name, ...) {FUNCTION_ADDR(&Builtin_##Name), "Builtin_" #Name},
87       BUILTIN_LIST_C(DEF_ENTRY)
88 #undef DEF_ENTRY
89   };
90   for (unsigned i = 0; i < arraysize(c_builtins); ++i) {
91     Add(ExternalReference::Create(c_builtins[i].address).address(),
92         c_builtins[i].name, index);
93   }
94 
95   CHECK_EQ(kSpecialReferenceCount + kExternalReferenceCount +
96                kBuiltinsReferenceCount,
97            *index);
98 }
99 
AddRuntimeFunctions(int * index)100 void ExternalReferenceTable::AddRuntimeFunctions(int* index) {
101   CHECK_EQ(kSpecialReferenceCount + kExternalReferenceCount +
102                kBuiltinsReferenceCount,
103            *index);
104 
105   struct RuntimeEntry {
106     Runtime::FunctionId id;
107     const char* name;
108   };
109 
110   static const RuntimeEntry runtime_functions[] = {
111 #define RUNTIME_ENTRY(name, i1, i2) {Runtime::k##name, "Runtime::" #name},
112       FOR_EACH_INTRINSIC(RUNTIME_ENTRY)
113 #undef RUNTIME_ENTRY
114   };
115 
116   for (unsigned i = 0; i < arraysize(runtime_functions); ++i) {
117     ExternalReference ref = ExternalReference::Create(runtime_functions[i].id);
118     Add(ref.address(), runtime_functions[i].name, index);
119   }
120 
121   CHECK_EQ(kSpecialReferenceCount + kExternalReferenceCount +
122                kBuiltinsReferenceCount + kRuntimeReferenceCount,
123            *index);
124 }
125 
AddIsolateAddresses(Isolate * isolate,int * index)126 void ExternalReferenceTable::AddIsolateAddresses(Isolate* isolate, int* index) {
127   CHECK_EQ(kSpecialReferenceCount + kExternalReferenceCount +
128                kBuiltinsReferenceCount + kRuntimeReferenceCount,
129            *index);
130 
131   // Top addresses
132   static const char* address_names[] = {
133 #define BUILD_NAME_LITERAL(Name, name) "Isolate::" #name "_address",
134       FOR_EACH_ISOLATE_ADDRESS_NAME(BUILD_NAME_LITERAL) nullptr
135 #undef BUILD_NAME_LITERAL
136   };
137 
138   for (int i = 0; i < IsolateAddressId::kIsolateAddressCount; ++i) {
139     Add(isolate->get_address_from_id(static_cast<IsolateAddressId>(i)),
140         address_names[i], index);
141   }
142 
143   CHECK_EQ(kSpecialReferenceCount + kExternalReferenceCount +
144                kBuiltinsReferenceCount + kRuntimeReferenceCount +
145                kIsolateAddressReferenceCount,
146            *index);
147 }
148 
AddAccessors(int * index)149 void ExternalReferenceTable::AddAccessors(int* index) {
150   CHECK_EQ(kSpecialReferenceCount + kExternalReferenceCount +
151                kBuiltinsReferenceCount + kRuntimeReferenceCount +
152                kIsolateAddressReferenceCount,
153            *index);
154 
155   // Accessors
156   struct AccessorRefTable {
157     Address address;
158     const char* name;
159   };
160 
161   static const AccessorRefTable getters[] = {
162 #define ACCESSOR_INFO_DECLARATION(accessor_name, AccessorName) \
163   {FUNCTION_ADDR(&Accessors::AccessorName##Getter),            \
164    "Accessors::" #AccessorName "Getter"}, /* NOLINT(whitespace/indent) */
165       ACCESSOR_INFO_LIST(ACCESSOR_INFO_DECLARATION)
166 #undef ACCESSOR_INFO_DECLARATION
167   };
168   static const AccessorRefTable setters[] = {
169 #define ACCESSOR_SETTER_DECLARATION(name) \
170   { FUNCTION_ADDR(&Accessors::name), "Accessors::" #name},
171       ACCESSOR_SETTER_LIST(ACCESSOR_SETTER_DECLARATION)
172 #undef ACCESSOR_SETTER_DECLARATION
173   };
174 
175   for (unsigned i = 0; i < arraysize(getters); ++i) {
176     Add(getters[i].address, getters[i].name, index);
177   }
178 
179   for (unsigned i = 0; i < arraysize(setters); ++i) {
180     Add(setters[i].address, setters[i].name, index);
181   }
182 
183   CHECK_EQ(kSpecialReferenceCount + kExternalReferenceCount +
184                kBuiltinsReferenceCount + kRuntimeReferenceCount +
185                kIsolateAddressReferenceCount + kAccessorReferenceCount,
186            *index);
187 }
188 
AddStubCache(Isolate * isolate,int * index)189 void ExternalReferenceTable::AddStubCache(Isolate* isolate, int* index) {
190   CHECK_EQ(kSpecialReferenceCount + kExternalReferenceCount +
191                kBuiltinsReferenceCount + kRuntimeReferenceCount +
192                kIsolateAddressReferenceCount + kAccessorReferenceCount,
193            *index);
194 
195   StubCache* load_stub_cache = isolate->load_stub_cache();
196 
197   // Stub cache tables
198   Add(load_stub_cache->key_reference(StubCache::kPrimary).address(),
199       "Load StubCache::primary_->key", index);
200   Add(load_stub_cache->value_reference(StubCache::kPrimary).address(),
201       "Load StubCache::primary_->value", index);
202   Add(load_stub_cache->map_reference(StubCache::kPrimary).address(),
203       "Load StubCache::primary_->map", index);
204   Add(load_stub_cache->key_reference(StubCache::kSecondary).address(),
205       "Load StubCache::secondary_->key", index);
206   Add(load_stub_cache->value_reference(StubCache::kSecondary).address(),
207       "Load StubCache::secondary_->value", index);
208   Add(load_stub_cache->map_reference(StubCache::kSecondary).address(),
209       "Load StubCache::secondary_->map", index);
210 
211   StubCache* store_stub_cache = isolate->store_stub_cache();
212 
213   // Stub cache tables
214   Add(store_stub_cache->key_reference(StubCache::kPrimary).address(),
215       "Store StubCache::primary_->key", index);
216   Add(store_stub_cache->value_reference(StubCache::kPrimary).address(),
217       "Store StubCache::primary_->value", index);
218   Add(store_stub_cache->map_reference(StubCache::kPrimary).address(),
219       "Store StubCache::primary_->map", index);
220   Add(store_stub_cache->key_reference(StubCache::kSecondary).address(),
221       "Store StubCache::secondary_->key", index);
222   Add(store_stub_cache->value_reference(StubCache::kSecondary).address(),
223       "Store StubCache::secondary_->value", index);
224   Add(store_stub_cache->map_reference(StubCache::kSecondary).address(),
225       "Store StubCache::secondary_->map", index);
226 
227   CHECK_EQ(kSpecialReferenceCount + kExternalReferenceCount +
228                kBuiltinsReferenceCount + kRuntimeReferenceCount +
229                kIsolateAddressReferenceCount + kAccessorReferenceCount +
230                kStubCacheReferenceCount,
231            *index);
232   CHECK_EQ(kSize, *index);
233 }
234 
235 }  // namespace internal
236 }  // namespace v8
237 
238 #undef SYMBOLIZE_FUNCTION
239