Skip to content

Commit edb292d

Browse files
committed
[Runtime] Do a proper hash table lookup in the prespecializations library.
We were doing a linear scan of the table contents as a stopgap. Stop doing that, and compute the proper key for the lookup, matching the one used in the builder.
1 parent 4bc7726 commit edb292d

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"
@@ -74,36 +75,35 @@ swift::getLibPrespecializedMetadata(const TypeContextDescriptor *description,
7475
if (!data)
7576
return nullptr;
7677

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

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

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)