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