Skip to content

Commit 46ddceb

Browse files
authored
Merge pull request #71184 from mikeash/libprespecialize-metadata-name-lookup
[Runtime] Do a proper hash table lookup in the prespecializations library.
2 parents 840b1df + edb292d commit 46ddceb

File tree

5 files changed

+77
-41
lines changed

5 files changed

+77
-41
lines changed

include/swift/Runtime/PrebuiltStringMap.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ struct PrebuiltStringMap {
5757
PrebuiltStringMap(uint64_t arraySize) : arraySize(arraySize) {}
5858

5959
// Based on MurmurHash2
60-
uint64_t hash(const void *data, size_t len) {
60+
uint64_t hash(const void *data, size_t len) const {
6161
uint64_t magic = 0xc6a4a7935bd1e995ULL;
6262
uint64_t salt = 47;
6363

@@ -148,8 +148,12 @@ struct PrebuiltStringMap {
148148

149149
/// Look up the given string in the table. Requires that StringTy be
150150
/// `const char *`.
151-
ArrayElement *find(const char *toFind) {
151+
const ArrayElement *find(const char *toFind) const {
152152
size_t len = strlen(toFind);
153+
return find(toFind, len);
154+
}
155+
156+
const ArrayElement *find(const char *toFind, size_t len) const {
153157
uint64_t hashValue = hash(toFind, len);
154158

155159
size_t index = hashValue % arraySize;

stdlib/public/runtime/Demangle.cpp

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -266,8 +266,8 @@ _buildDemanglingForMetadataPack(MetadataPackPointer pack, size_t count,
266266
return node;
267267
}
268268

269-
/// Build an array of demangling trees for each generic argument of the given
270-
/// type metadata.
269+
/// Build an array of demangling trees for each generic argument to the given
270+
/// generic type context descriptor.
271271
///
272272
/// Note:
273273
/// - The input array has an entry for those generic parameter descriptors which
@@ -286,15 +286,14 @@ _buildDemanglingForMetadataPack(MetadataPackPointer pack, size_t count,
286286
/// The output array is flat; the generic parameters of each depth are
287287
/// concatenated together.
288288
static bool _buildDemanglingForGenericArgs(
289-
const Metadata *type,
290289
const TypeContextDescriptor *description,
290+
const Metadata *const *genericArgs,
291291
llvm::SmallVectorImpl<NodePointer> &demangledGenerics,
292292
Demangle::Demangler &Dem) {
293293
auto generics = description->getGenericContext();
294294
if (!generics)
295295
return true;
296296

297-
auto genericArgs = description->getGenericArguments(type);
298297
auto packHeader = generics->getGenericPackShapeHeader();
299298
auto packDescriptors = generics->getGenericPackShapeDescriptors();
300299

@@ -420,12 +419,16 @@ _buildDemanglingForNominalType(const Metadata *type, Demangle::Demangler &Dem) {
420419
return nullptr;
421420
}
422421

423-
// Gather the complete set of generic arguments that must be written to
424-
// form this type.
425422
llvm::SmallVector<NodePointer, 8> demangledGenerics;
426-
if (!_buildDemanglingForGenericArgs(type, description, demangledGenerics, Dem))
427-
return nullptr;
428-
423+
if (description->isGeneric()) {
424+
auto genericArgs = description->getGenericArguments(type);
425+
// Gather the complete set of generic arguments that must be written to
426+
// form this type.
427+
if (!_buildDemanglingForGenericArgs(description, genericArgs,
428+
demangledGenerics, Dem))
429+
return nullptr;
430+
}
431+
429432
return _buildDemanglingForContext(description, demangledGenerics, Dem);
430433
}
431434

@@ -819,6 +822,25 @@ swift::_swift_buildDemanglingForMetadata(const Metadata *type,
819822
return nullptr;
820823
}
821824

825+
Demangle::NodePointer
826+
swift::_buildDemanglingForGenericType(const TypeContextDescriptor *description,
827+
const void *const *arguments,
828+
Demangle::Demangler &Dem) {
829+
auto kind = description->getKind();
830+
if (kind != ContextDescriptorKind::Class &&
831+
kind != ContextDescriptorKind::Enum &&
832+
kind != ContextDescriptorKind::Struct)
833+
return nullptr;
834+
835+
llvm::SmallVector<NodePointer, 8> demangledGenerics;
836+
if (!_buildDemanglingForGenericArgs(description,
837+
(const Metadata *const *)arguments,
838+
demangledGenerics, Dem))
839+
return nullptr;
840+
841+
return _buildDemanglingForContext(description, demangledGenerics, Dem);
842+
}
843+
822844
// NB: This function is not used directly in the Swift codebase, but is
823845
// exported for Xcode support and is used by the sanitizers. Please coordinate
824846
// before changing.

stdlib/public/runtime/EnvironmentVariables.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@ VARIABLE(SWIFT_DEBUG_ENABLE_LIB_PRESPECIALIZED, bool, true,
9494
VARIABLE(SWIFT_DEBUG_LIB_PRESPECIALIZED_PATH, string, "",
9595
"A path to a prespecializations library to use at runtime.")
9696

97+
VARIABLE(SWIFT_DEBUG_ENABLE_LIB_PRESPECIALIZED_LOGGING, bool, false,
98+
"Enable debug logging of prespecializations library use.")
99+
97100
VARIABLE(SWIFT_ROOT, string, "",
98101
"Overrides the root directory of the Swift installation. "
99102
"This is used to locate auxiliary files relative to the runtime "

stdlib/public/runtime/LibPrespecialized.cpp

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#include "swift/Runtime/LibPrespecialized.h"
14+
#include "Private.h"
1415
#include "swift/Basic/Lazy.h"
1516
#include "swift/Runtime/EnvironmentVariables.h"
1617
#include "swift/Runtime/Metadata.h"
@@ -75,36 +76,35 @@ swift::getLibPrespecializedMetadata(const TypeContextDescriptor *description,
7576
if (!data)
7677
return nullptr;
7778

78-
auto *metadataMap = data->getMetadataMap();
79-
80-
// TODO: This linear search is a stopgap until we work out the right
81-
// representation for the string keys.
82-
size_t count = metadataMap->arraySize;
83-
auto *entries = metadataMap->array();
84-
for (size_t i = 0; i < count; i++) {
85-
if (entries[i].key == nullptr)
86-
continue;
87-
88-
Metadata *candidate = entries[i].value;
89-
auto *candidateDescription = candidate->getDescription();
90-
if (description != candidateDescription)
91-
continue;
92-
93-
auto *candidateArguments = candidate->getGenericArgs();
94-
95-
bool match = true;
96-
97-
const auto &genericContext = *description->getGenericContext();
98-
const auto &header = genericContext.getGenericContextHeader();
99-
for (unsigned param = 0; param < header.NumParams; param++)
100-
if (arguments[param] != candidateArguments[param]) {
101-
match = false;
102-
break;
103-
}
104-
105-
if (match)
106-
return candidate;
79+
Demangler dem;
80+
auto mangleNode = _buildDemanglingForGenericType(description, arguments, dem);
81+
if (mangleNode->getKind() != Node::Kind::Global) {
82+
auto wrapper = dem.createNode(Node::Kind::Global);
83+
wrapper->addChild(mangleNode, dem);
84+
mangleNode = wrapper;
85+
}
86+
auto resolver = [](SymbolicReferenceKind kind,
87+
const void *ref) -> NodePointer {
88+
swift::fatalError(0,
89+
"Unexpected symbolic reference %p in generated mangle "
90+
"tree for generic type lookup.",
91+
ref);
92+
};
93+
auto mangling = Demangle::mangleNode(mangleNode, resolver, dem);
94+
if (!mangling.isSuccess()) {
95+
swift::warning(0,
96+
"Mangling for prespecialized metadata failed with code %d",
97+
mangling.error().code);
98+
return nullptr;
10799
}
108100

109-
return nullptr;
101+
auto key = mangling.result();
102+
auto *metadataMap = data->getMetadataMap();
103+
auto *element = metadataMap->find(key.data(), key.size());
104+
auto *result = element ? element->value : nullptr;
105+
if (SWIFT_UNLIKELY(runtime::environment::
106+
SWIFT_DEBUG_ENABLE_LIB_PRESPECIALIZED_LOGGING()))
107+
fprintf(stderr, "Prespecializations library: found %p for key '%.*s'.\n",
108+
result, (int)key.size(), key.data());
109+
return result;
110110
}

stdlib/public/runtime/Private.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,13 @@ class TypeInfo {
280280
Demangle::NodePointer _swift_buildDemanglingForMetadata(const Metadata *type,
281281
Demangle::Demangler &Dem);
282282

283+
/// Build the demangling for the generic type that's created by specializing
284+
/// the given type context descriptor with the given arguments.
285+
Demangle::NodePointer
286+
_buildDemanglingForGenericType(const TypeContextDescriptor *description,
287+
const void *const *arguments,
288+
Demangle::Demangler &Dem);
289+
283290
/// Callback used to provide the substitution of a generic parameter
284291
/// (described by depth/index) to its metadata.
285292
///

0 commit comments

Comments
 (0)