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 22namespace v8 { 23namespace 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 35const 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 80namespace { 81static 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); 88BUILTIN_LIST_C(FORWARD_DECLARE) 89#undef FORWARD_DECLARE 90 91void 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 105const 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 118void 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 131const 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 141void ExternalReferenceTable::Add(Address address, int* index) { 142 ref_addr_[(*index)++] = address; 143} 144 145void ExternalReferenceTable::AddIsolateIndependent(Address address, 146 int* index) { 147 ref_addr_isolate_independent_[(*index)++] = address; 148} 149 150void 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 162void 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 175void 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 193void 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 213void 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 221void 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 234void 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 261void 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 292Address 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 301void 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