11
11
// ===----------------------------------------------------------------------===//
12
12
13
13
#include " swift/Runtime/LibPrespecialized.h"
14
+ #include " MetadataCache.h"
14
15
#include " Private.h"
15
16
#include " swift/Basic/Lazy.h"
16
17
#include " swift/Runtime/EnvironmentVariables.h"
@@ -75,24 +76,89 @@ static const LibPrespecializedData<InProcess> *findLibPrespecialized() {
75
76
return data;
76
77
}
77
78
79
+ struct LibPrespecializedState {
80
+ struct AddressRange {
81
+ uintptr_t start, end;
82
+
83
+ bool contains (const void *ptr) {
84
+ return start <= (uintptr_t )ptr && (uintptr_t )ptr < end;
85
+ }
86
+ };
87
+
88
+ bool loggingEnabled;
89
+ const LibPrespecializedData<InProcess> *data;
90
+ AddressRange sharedCacheRange{0 , 0 };
91
+ AddressRange metadataAllocatorInitialPoolRange{0 , 0 };
92
+
93
+ LibPrespecializedState () {
94
+ loggingEnabled =
95
+ runtime::environment::SWIFT_DEBUG_ENABLE_LIB_PRESPECIALIZED_LOGGING ();
96
+ data = findLibPrespecialized ();
97
+
98
+ #if DYLD_GET_SWIFT_PRESPECIALIZED_DATA_DEFINED
99
+ size_t sharedCacheLength;
100
+ sharedCacheRange.start =
101
+ (uintptr_t )_dyld_get_shared_cache_range (&sharedCacheLength);
102
+ sharedCacheRange.end = sharedCacheRange.start + sharedCacheLength;
103
+
104
+ auto [initialPoolStart, initialPoolLength] =
105
+ MetadataAllocator::InitialPoolLocation ();
106
+ metadataAllocatorInitialPoolRange.start = (uintptr_t )initialPoolStart;
107
+ metadataAllocatorInitialPoolRange.end =
108
+ metadataAllocatorInitialPoolRange.start + initialPoolLength;
109
+ #endif
110
+ }
111
+ };
112
+
113
+ static Lazy<LibPrespecializedState> LibPrespecialized;
114
+
115
+ #define LOG (fmt, ...) \
116
+ do { \
117
+ if (SWIFT_UNLIKELY (prespecialized.loggingEnabled )) \
118
+ fprintf (stderr, " Prespecializations library: " fmt " \n " , __VA_ARGS__); \
119
+ } while (0 )
120
+
78
121
const LibPrespecializedData<InProcess> *swift::getLibPrespecializedData () {
79
122
return SWIFT_LAZY_CONSTANT (findLibPrespecialized ());
80
123
}
81
124
82
125
// Returns true if the type has any arguments that aren't plain types (packs or
83
126
// unknown kinds).
84
- static bool hasNonTypeGenericArguments (const TypeContextDescriptor *description) {
85
- auto generics = description->getGenericContext ();
86
- if (!generics)
87
- return false ;
88
-
127
+ static bool
128
+ hasNonTypeGenericArguments (const TargetGenericContext<InProcess> *generics) {
89
129
for (auto param : generics->getGenericParams ())
90
130
if (param.getKind () != GenericParamKind::Type)
91
131
return true ;
92
132
93
133
return false ;
94
134
}
95
135
136
+ static bool
137
+ isPotentialPrespecializedPointer (LibPrespecializedState &prespecialized,
138
+ const void *pointer) {
139
+ // Prespecialized metadata descriptors and arguments are always in the shared
140
+ // cache. They're either statically emitted metadata, or they're
141
+ // prespecialized metadata. Anything that's dynamically allocated, or
142
+ // statically allocated outside the shared cache, is not a possible candidate.
143
+
144
+ // If we're loading a debug libprespecialized, we can't do these checks, so
145
+ // just say everything is a potential argument. Performance is not so
146
+ // important in that case.
147
+ if (!prespecialized.sharedCacheRange .contains (prespecialized.data ))
148
+ return true ;
149
+
150
+ // Anything outside the shared cache isn't a potential argument.
151
+ if (!prespecialized.sharedCacheRange .contains (pointer))
152
+ return false ;
153
+
154
+ // Dynamically allocated metadata could be within the shared cache, in the
155
+ // initial metadata allocation pool. Reject anything in that region.
156
+ if (prespecialized.metadataAllocatorInitialPoolRange .contains (pointer))
157
+ return false ;
158
+
159
+ return true ;
160
+ }
161
+
96
162
static bool disableForValidation = false ;
97
163
98
164
void
@@ -114,24 +180,40 @@ swift::getLibPrespecializedMetadata(const TypeContextDescriptor *description,
114
180
|| disablePrespecializedMetadata.load (std::memory_order_acquire)))
115
181
return nullptr ;
116
182
117
- auto *data = getLibPrespecializedData ();
183
+ auto &prespecialized = LibPrespecialized.get ();
184
+
185
+ auto *data = prespecialized.data ;
118
186
if (!data)
119
187
return nullptr ;
120
188
189
+ auto *generics = description->getGenericContext ();
190
+ if (!generics)
191
+ return nullptr ;
192
+
121
193
// We don't support types with pack parameters yet (and especially not types
122
194
// with unknown parameter kinds) so don't even try to look those up.
123
- if (hasNonTypeGenericArguments (description ))
195
+ if (hasNonTypeGenericArguments (generics ))
124
196
return nullptr ;
125
197
198
+ if (!isPotentialPrespecializedPointer (prespecialized, description)) {
199
+ LOG (" Rejecting descriptor %p, not in the shared cache" ,
200
+ (const void *)description);
201
+ return nullptr ;
202
+ }
203
+
204
+ auto numKeyArguments = generics->getGenericContextHeader ().NumKeyArguments ;
205
+ for (unsigned i = 0 ; i < numKeyArguments; i++) {
206
+ if (!isPotentialPrespecializedPointer (prespecialized, arguments[i])) {
207
+ LOG (" Rejecting argument %u %p to descriptor %p, not in the shared cache" ,
208
+ i, arguments[i], (const void *)description);
209
+ return nullptr ;
210
+ }
211
+ }
212
+
126
213
Demangler dem;
127
214
auto mangleNode = _buildDemanglingForGenericType (description, arguments, dem);
128
215
if (!mangleNode) {
129
- if (SWIFT_UNLIKELY (runtime::environment::
130
- SWIFT_DEBUG_ENABLE_LIB_PRESPECIALIZED_LOGGING ()))
131
- fprintf (stderr,
132
- " Prespecializations library: failed to build demangling with "
133
- " descriptor %p.\n " ,
134
- description);
216
+ LOG (" failed to build demangling with descriptor %p." , description);
135
217
return nullptr ;
136
218
}
137
219
@@ -159,10 +241,7 @@ swift::getLibPrespecializedMetadata(const TypeContextDescriptor *description,
159
241
auto *metadataMap = data->getMetadataMap ();
160
242
auto *element = metadataMap->find (key.data (), key.size ());
161
243
auto *result = element ? element->value : nullptr ;
162
- if (SWIFT_UNLIKELY (runtime::environment::
163
- SWIFT_DEBUG_ENABLE_LIB_PRESPECIALIZED_LOGGING ()))
164
- fprintf (stderr, " Prespecializations library: found %p for key '%.*s'.\n " ,
165
- result, (int )key.size (), key.data ());
244
+ LOG (" found %p for key '%.*s'." , result, (int )key.size (), key.data ());
166
245
return result;
167
246
}
168
247
0 commit comments