Skip to content

Commit 4d24a27

Browse files
authored
Merge pull request #41987 from rjmccall/runtime-generic-signature
[NFC] Introduce abstractions for working with generic signatures in the runtime
2 parents cff885c + 91c1d79 commit 4d24a27

File tree

3 files changed

+109
-68
lines changed

3 files changed

+109
-68
lines changed

include/swift/ABI/GenericContext.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,33 @@ class TargetGenericRequirementDescriptor {
184184
using GenericRequirementDescriptor =
185185
TargetGenericRequirementDescriptor<InProcess>;
186186

187+
/// A runtime description of a generic signature.
188+
class RuntimeGenericSignature {
189+
GenericContextDescriptorHeader Header;
190+
const GenericParamDescriptor *Params;
191+
const GenericRequirementDescriptor *Requirements;
192+
public:
193+
RuntimeGenericSignature()
194+
: Header{0, 0, 0, 0}, Params(nullptr), Requirements(nullptr) {}
195+
196+
RuntimeGenericSignature(const GenericContextDescriptorHeader &header,
197+
const GenericParamDescriptor *params,
198+
const GenericRequirementDescriptor *requirements)
199+
: Header(header), Params(params), Requirements(requirements) {}
200+
201+
llvm::ArrayRef<GenericParamDescriptor> getParams() const {
202+
return llvm::makeArrayRef(Params, Header.NumParams);
203+
}
204+
205+
llvm::ArrayRef<GenericRequirementDescriptor> getRequirements() const {
206+
return llvm::makeArrayRef(Requirements, Header.NumRequirements);
207+
}
208+
209+
size_t getArgumentLayoutSizeInWords() const {
210+
return Header.getArgumentLayoutSizeInWords();
211+
}
212+
};
213+
187214
template<typename Runtime>
188215
class TargetGenericEnvironment
189216
: public swift::ABI::TrailingObjects<TargetGenericEnvironment<Runtime>,
@@ -341,6 +368,13 @@ class TrailingGenericContextObjects<TargetSelf<Runtime>,
341368
* sizeof(StoredPointer);
342369
}
343370

371+
RuntimeGenericSignature getGenericSignature() const {
372+
if (!asSelf()->isGeneric()) return RuntimeGenericSignature();
373+
return {getGenericContextHeader(),
374+
getGenericParams().data(),
375+
getGenericRequirements().data()};
376+
}
377+
344378
protected:
345379
size_t numTrailingObjects(OverloadToken<GenericContextHeaderType>) const {
346380
return asSelf()->isGeneric() ? 1 : 0;

stdlib/public/runtime/Metadata.cpp

Lines changed: 10 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -366,25 +366,10 @@ namespace {
366366
class GenericMetadataCache :
367367
public MetadataCache<GenericCacheEntry, GenericMetadataCacheTag> {
368368
public:
369-
uint16_t NumKeyParameters;
370-
uint16_t NumWitnessTables;
369+
GenericSignatureLayout SigLayout;
371370

372371
GenericMetadataCache(const TargetGenericContext<InProcess> &genericContext)
373-
: NumKeyParameters(0), NumWitnessTables(0) {
374-
// Count up the # of key parameters and # of witness tables.
375-
376-
// Find key generic parameters.
377-
for (const auto &gp : genericContext.getGenericParams()) {
378-
if (gp.hasKeyArgument())
379-
++NumKeyParameters;
380-
}
381-
382-
// Find witness tables.
383-
for (const auto &req : genericContext.getGenericRequirements()) {
384-
if (req.Flags.hasKeyArgument() &&
385-
req.getKind() == GenericRequirementKind::Protocol)
386-
++NumWitnessTables;
387-
}
372+
: SigLayout(genericContext.getGenericSignature()) {
388373
}
389374
};
390375

@@ -759,7 +744,7 @@ _cacheCanonicalSpecializedMetadata(const TypeContextDescriptor *description) {
759744
auto request =
760745
MetadataRequest(MetadataState::Complete, /*isNonBlocking*/ true);
761746
assert(description->getFullGenericContextHeader().Base.NumKeyArguments ==
762-
cache.NumKeyParameters + cache.NumWitnessTables);
747+
cache.SigLayout.sizeInWords());
763748
if (auto *classDescription = dyn_cast<ClassDescriptor>(description)) {
764749
auto canonicalMetadataAccessors = classDescription->getCanonicalMetadataPrespecializationAccessors();
765750
for (auto &canonicalMetadataAccessorPtr : canonicalMetadataAccessors) {
@@ -768,8 +753,7 @@ _cacheCanonicalSpecializedMetadata(const TypeContextDescriptor *description) {
768753
auto *canonicalMetadata = response.Value;
769754
const void *const *arguments =
770755
reinterpret_cast<const void *const *>(canonicalMetadata->getGenericArgs());
771-
auto key = MetadataCacheKey(cache.NumKeyParameters, cache.NumWitnessTables,
772-
arguments);
756+
auto key = MetadataCacheKey(cache.SigLayout, arguments);
773757
auto result = cache.getOrInsert(key, MetadataRequest(MetadataState::Complete, /*isNonBlocking*/true), canonicalMetadata);
774758
(void)result;
775759
assert(result.second.Value == canonicalMetadata);
@@ -780,8 +764,7 @@ _cacheCanonicalSpecializedMetadata(const TypeContextDescriptor *description) {
780764
Metadata *canonicalMetadata = canonicalMetadataPtr.get();
781765
const void *const *arguments =
782766
reinterpret_cast<const void *const *>(canonicalMetadata->getGenericArgs());
783-
auto key = MetadataCacheKey(cache.NumKeyParameters, cache.NumWitnessTables,
784-
arguments);
767+
auto key = MetadataCacheKey(cache.SigLayout, arguments);
785768
auto result = cache.getOrInsert(key, MetadataRequest(MetadataState::Complete, /*isNonBlocking*/true), canonicalMetadata);
786769
(void)result;
787770
assert(result.second.Value == canonicalMetadata);
@@ -828,8 +811,7 @@ MetadataResponse swift::swift_getCanonicalSpecializedMetadata(
828811
const void *const *arguments =
829812
reinterpret_cast<const void *const *>(candidate->getGenericArgs());
830813
auto &cache = getCache(*description);
831-
auto key = MetadataCacheKey(cache.NumKeyParameters, cache.NumWitnessTables,
832-
arguments);
814+
auto key = MetadataCacheKey(cache.SigLayout, arguments);
833815
auto result = cache.getOrInsert(key, request, candidate);
834816

835817
cachedMetadataAddr->store(result.second.Value, std::memory_order_release);
@@ -843,9 +825,8 @@ _swift_getGenericMetadata(MetadataRequest request, const void *const *arguments,
843825
const TypeContextDescriptor *description) {
844826
auto &cache = getCache(*description);
845827
assert(description->getFullGenericContextHeader().Base.NumKeyArguments ==
846-
cache.NumKeyParameters + cache.NumWitnessTables);
847-
auto key = MetadataCacheKey(cache.NumKeyParameters, cache.NumWitnessTables,
848-
arguments);
828+
cache.SigLayout.sizeInWords());
829+
auto key = MetadataCacheKey(cache.SigLayout, arguments);
849830
auto result = cache.getOrInsert(key, request, description, arguments);
850831

851832
return result.second;
@@ -5488,11 +5469,8 @@ static Result performOnMetadataCache(const Metadata *metadata,
54885469
reinterpret_cast<const void * const *>(
54895470
description->getGenericArguments(metadata));
54905471
auto &cache = getCache(*description);
5491-
size_t numGenericArgs = generics.Base.NumKeyArguments;
5492-
assert(numGenericArgs == cache.NumKeyParameters + cache.NumWitnessTables);
5493-
(void)numGenericArgs;
5494-
auto key = MetadataCacheKey(cache.NumKeyParameters, cache.NumWitnessTables,
5495-
genericArgs);
5472+
assert(generics.Base.NumKeyArguments == cache.SigLayout.sizeInWords());
5473+
auto key = MetadataCacheKey(cache.SigLayout, genericArgs);
54965474

54975475
return std::move(callbacks).forGenericMetadata(metadata, description,
54985476
cache, key);

stdlib/public/runtime/MetadataCache.h

Lines changed: 65 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -398,11 +398,43 @@ class SimpleLockingCacheEntryBase {
398398
}
399399
};
400400

401+
/// A summary of the information from a generic signature that's
402+
/// sufficient to compare arguments.
403+
struct GenericSignatureLayout {
404+
uint16_t NumKeyParameters = 0;
405+
uint16_t NumWitnessTables = 0;
406+
407+
GenericSignatureLayout(const RuntimeGenericSignature &sig) {
408+
for (const auto &gp : sig.getParams()) {
409+
if (gp.hasKeyArgument())
410+
++NumKeyParameters;
411+
}
412+
for (const auto &reqt : sig.getRequirements()) {
413+
if (reqt.Flags.hasKeyArgument() &&
414+
reqt.getKind() == GenericRequirementKind::Protocol)
415+
++NumWitnessTables;
416+
}
417+
}
418+
419+
size_t sizeInWords() const {
420+
return NumKeyParameters + NumWitnessTables;
421+
}
422+
423+
friend bool operator==(const GenericSignatureLayout &lhs,
424+
const GenericSignatureLayout &rhs) {
425+
return lhs.NumKeyParameters == rhs.NumKeyParameters &&
426+
lhs.NumWitnessTables == rhs.NumWitnessTables;
427+
}
428+
friend bool operator!=(const GenericSignatureLayout &lhs,
429+
const GenericSignatureLayout &rhs) {
430+
return !(lhs == rhs);
431+
}
432+
};
433+
401434
/// A key value as provided to the concurrent map.
402435
class MetadataCacheKey {
403436
const void * const *Data;
404-
uint16_t NumKeyParameters;
405-
uint16_t NumWitnessTables;
437+
GenericSignatureLayout Layout;
406438
uint32_t Hash;
407439

408440
/// Compare two witness tables, which may involving checking the
@@ -445,16 +477,15 @@ class MetadataCacheKey {
445477
/// Compare the content from two keys.
446478
static int compareContent(const void * const *adata,
447479
const void * const *bdata,
448-
unsigned numKeyParameters,
449-
unsigned numWitnessTables) {
480+
const GenericSignatureLayout &layout) {
450481
// Compare generic arguments for key parameters.
451-
for (unsigned i = 0; i != numKeyParameters; ++i) {
482+
for (unsigned i = 0; i != layout.NumKeyParameters; ++i) {
452483
if (auto result = comparePointers(*adata++, *bdata++))
453484
return result;
454485
}
455486

456487
// Compare witness tables.
457-
for (unsigned i = 0; i != numWitnessTables; ++i) {
488+
for (unsigned i = 0; i != layout.NumWitnessTables; ++i) {
458489
if (auto result =
459490
compareWitnessTables((const WitnessTable *)*adata++,
460491
(const WitnessTable *)*bdata++))
@@ -465,30 +496,24 @@ class MetadataCacheKey {
465496
}
466497

467498
public:
468-
MetadataCacheKey(uint16_t numKeyParams,
469-
uint16_t numWitnessTables,
499+
MetadataCacheKey(const GenericSignatureLayout &layout,
470500
const void * const *data)
471-
: Data(data), NumKeyParameters(numKeyParams),
472-
NumWitnessTables(numWitnessTables), Hash(computeHash()) { }
501+
: Data(data), Layout(layout), Hash(computeHash()) { }
473502

474-
MetadataCacheKey(uint16_t numKeyParams,
475-
uint16_t numWitnessTables,
503+
MetadataCacheKey(const GenericSignatureLayout &layout,
476504
const void * const *data,
477505
uint32_t hash)
478-
: Data(data), NumKeyParameters(numKeyParams),
479-
NumWitnessTables(numWitnessTables), Hash(hash) {}
506+
: Data(data), Layout(layout), Hash(hash) {}
480507

481508
bool operator==(MetadataCacheKey rhs) const {
482509
// Compare the hashes.
483510
if (hash() != rhs.hash()) return false;
484511

485512
// Compare the sizes.
486-
if (NumKeyParameters != rhs.NumKeyParameters) return false;
487-
if (NumWitnessTables != rhs.NumWitnessTables) return false;
513+
if (Layout != rhs.Layout) return false;
488514

489515
// Compare the content.
490-
return compareContent(begin(), rhs.begin(), NumKeyParameters,
491-
NumWitnessTables) == 0;
516+
return compareContent(begin(), rhs.begin(), Layout) == 0;
492517
}
493518

494519
int compare(const MetadataCacheKey &rhs) const {
@@ -499,40 +524,47 @@ class MetadataCacheKey {
499524

500525
// Compare the # of key parameters.
501526
if (auto keyParamsComparison =
502-
compareIntegers(NumKeyParameters, rhs.NumKeyParameters)) {
527+
compareIntegers(Layout.NumKeyParameters,
528+
rhs.Layout.NumKeyParameters)) {
503529
return keyParamsComparison;
504530
}
505531

506532
// Compare the # of witness tables.
507533
if (auto witnessTablesComparison =
508-
compareIntegers(NumWitnessTables, rhs.NumWitnessTables)) {
534+
compareIntegers(Layout.NumWitnessTables,
535+
rhs.Layout.NumWitnessTables)) {
509536
return witnessTablesComparison;
510537
}
511538

512539
// Compare the content.
513-
return compareContent(begin(), rhs.begin(), NumKeyParameters,
514-
NumWitnessTables);
540+
return compareContent(begin(), rhs.begin(), Layout);
515541
}
516542

517-
uint16_t numKeyParameters() const { return NumKeyParameters; }
518-
uint16_t numWitnessTables() const { return NumWitnessTables; }
519-
520543
uint32_t hash() const {
521544
return Hash;
522545
}
523546

547+
const GenericSignatureLayout &layout() const {
548+
return Layout;
549+
}
550+
524551
friend llvm::hash_code hash_value(const MetadataCacheKey &key) {
525552
return key.Hash;
526553
}
527554

528555
const void * const *begin() const { return Data; }
529556
const void * const *end() const { return Data + size(); }
530-
unsigned size() const { return NumKeyParameters + NumWitnessTables; }
557+
unsigned size() const { return Layout.sizeInWords(); }
558+
559+
void installInto(const void **buffer) const {
560+
// FIXME: variadic-parameter-packs
561+
memcpy(buffer, Data, size() * sizeof(const void *));
562+
}
531563

532564
private:
533565
uint32_t computeHash() const {
534-
size_t H = 0x56ba80d1u * NumKeyParameters;
535-
for (unsigned index = 0; index != NumKeyParameters; ++index) {
566+
size_t H = 0x56ba80d1u * Layout.NumKeyParameters;
567+
for (unsigned index = 0; index != Layout.NumKeyParameters; ++index) {
536568
H = (H >> 10) | (H << ((sizeof(size_t) * 8) - 10));
537569
H ^= (reinterpret_cast<size_t>(Data[index])
538570
^ (reinterpret_cast<size_t>(Data[index]) >> 19));
@@ -1331,7 +1363,7 @@ class VariadicMetadataCacheEntryBase :
13311363
using OverloadToken = typename TrailingObjects::template OverloadToken<T>;
13321364

13331365
size_t numTrailingObjects(OverloadToken<const void *>) const {
1334-
return NumKeyParameters + NumWitnessTables;
1366+
return Layout.sizeInWords();
13351367
}
13361368

13371369
template <class... Args>
@@ -1343,8 +1375,7 @@ class VariadicMetadataCacheEntryBase :
13431375

13441376
private:
13451377
/// These are set during construction and never changed.
1346-
const uint16_t NumKeyParameters;
1347-
const uint16_t NumWitnessTables;
1378+
const GenericSignatureLayout Layout;
13481379
const uint32_t Hash;
13491380

13501381
/// Valid if TrackingInfo.getState() >= PrivateMetadataState::Abstract.
@@ -1364,18 +1395,16 @@ class VariadicMetadataCacheEntryBase :
13641395
PrivateMetadataState initialState,
13651396
ValueType value)
13661397
: super(worker, initialState),
1367-
NumKeyParameters(key.numKeyParameters()),
1368-
NumWitnessTables(key.numWitnessTables()),
1398+
Layout(key.layout()),
13691399
Hash(key.hash()),
13701400
Value(value) {
13711401
assert((value != nullptr) ==
13721402
(initialState != PrivateMetadataState::Allocating));
1373-
memcpy(this->template getTrailingObjects<const void *>(),
1374-
key.begin(), key.size() * sizeof(const void *));
1403+
key.installInto(this->template getTrailingObjects<const void *>());
13751404
}
13761405

13771406
MetadataCacheKey getKey() const {
1378-
return MetadataCacheKey(NumKeyParameters, NumWitnessTables,
1407+
return MetadataCacheKey(Layout,
13791408
this->template getTrailingObjects<const void*>(),
13801409
Hash);
13811410
}

0 commit comments

Comments
 (0)