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