@@ -46,7 +46,42 @@ struct AccessibleFunctionsSection {
4646 const AccessibleFunctionRecord *end () const { return End; }
4747};
4848
49+ struct AccessibleFunctionCacheEntry {
50+ private:
51+ const char *Name;
52+ size_t NameLength;
53+
54+ const AccessibleFunctionRecord *Func;
55+
56+ public:
57+ AccessibleFunctionCacheEntry (llvm::StringRef name,
58+ const AccessibleFunctionRecord *func)
59+ : Func(func) {
60+ char *Name = reinterpret_cast <char *>(malloc (name.size ()));
61+ memcpy (Name, name.data (), name.size ());
62+
63+ this ->Name = Name;
64+ this ->NameLength = name.size ();
65+ }
66+
67+ const AccessibleFunctionRecord *getFunction () const { return Func; }
68+
69+ bool matchesKey (llvm::StringRef name) {
70+ return name == llvm::StringRef{Name, NameLength};
71+ }
72+
73+ friend llvm::hash_code hash_value (const AccessibleFunctionCacheEntry &value) {
74+ return hash_value (llvm::StringRef{value.Name , value.NameLength });
75+ }
76+
77+ template <class ... T>
78+ static size_t getExtraAllocationSize (T &&...ignored) {
79+ return 0 ;
80+ }
81+ };
82+
4983struct AccessibleFunctionsState {
84+ ConcurrentReadableHashMap<AccessibleFunctionCacheEntry> Cache;
5085 ConcurrentReadableArray<AccessibleFunctionsSection> SectionsToScan;
5186
5287 AccessibleFunctionsState () {
@@ -78,3 +113,43 @@ void swift::addImageAccessibleFunctionsBlockCallback(const void *functions,
78113 Functions.get ();
79114 addImageAccessibleFunctionsBlockCallbackUnsafe (functions, size);
80115}
116+
117+ static const AccessibleFunctionRecord *
118+ _searchForFunctionRecord (AccessibleFunctionsState &S, llvm::StringRef name) {
119+ for (const auto §ion : S.SectionsToScan .snapshot ()) {
120+ for (auto &record : section) {
121+ auto recordName =
122+ swift::Demangle::makeSymbolicMangledNameStringRef (record.Name .get ());
123+ if (recordName == name)
124+ return &record;
125+ }
126+ }
127+ return nullptr ;
128+ }
129+
130+ static const AccessibleFunctionRecord *
131+ _findAccessibleFunction (llvm::StringRef name) {
132+ auto &S = Functions.get ();
133+
134+ // Look for an existing entry.
135+ {
136+ auto snapshot = S.Cache .snapshot ();
137+ if (auto E = snapshot.find (name))
138+ return E->getFunction ();
139+ }
140+
141+ // If entry doesn't exist (either record doesn't exist, hasn't been loaded, or
142+ // requested yet), let's try to find it and add to the cache.
143+
144+ auto *function = _searchForFunctionRecord (S, name);
145+ if (function) {
146+ S.Cache .getOrInsert (
147+ name, [&](AccessibleFunctionCacheEntry *entry, bool created) {
148+ if (created)
149+ new (entry) AccessibleFunctionCacheEntry{name, function};
150+ return true ;
151+ });
152+ }
153+
154+ return function;
155+ }
0 commit comments