@@ -46,7 +46,42 @@ struct AccessibleFunctionsSection {
46
46
const AccessibleFunctionRecord *end () const { return End; }
47
47
};
48
48
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
+
49
83
struct AccessibleFunctionsState {
84
+ ConcurrentReadableHashMap<AccessibleFunctionCacheEntry> Cache;
50
85
ConcurrentReadableArray<AccessibleFunctionsSection> SectionsToScan;
51
86
52
87
AccessibleFunctionsState () {
@@ -78,3 +113,43 @@ void swift::addImageAccessibleFunctionsBlockCallback(const void *functions,
78
113
Functions.get ();
79
114
addImageAccessibleFunctionsBlockCallbackUnsafe (functions, size);
80
115
}
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