Skip to content

Commit 583bec3

Browse files
committed
Add a runtime function to query the current runtime state of a metadata.
This functions returns the metadata purely for liveness purposes.
1 parent eb2f2fe commit 583bec3

File tree

5 files changed

+59
-4
lines changed

5 files changed

+59
-4
lines changed

include/swift/Runtime/Metadata.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3981,6 +3981,11 @@ swift_allocateGenericValueMetadata(const ValueTypeDescriptor *description,
39813981
const GenericValueMetadataPattern *pattern,
39823982
size_t extraDataSize);
39833983

3984+
/// \brief Check that the given metadata has the right state.
3985+
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
3986+
MetadataResponse swift_checkMetadataState(MetadataRequest request,
3987+
const Metadata *type);
3988+
39843989
/// Instantiate a resilient or generic protocol witness table.
39853990
///
39863991
/// \param genericTable - The witness table template for the

include/swift/Runtime/RuntimeFunctions.def

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -826,6 +826,13 @@ FUNCTION(AllocateGenericValueMetadata, swift_allocateGenericValueMetadata,
826826
ARGS(TypeContextDescriptorPtrTy, Int8PtrPtrTy, Int8PtrPtrTy, SizeTy),
827827
ATTRS(NoUnwind))
828828

829+
// MetadataResponse swift_checkMetadataState(MetadataRequest request,
830+
// cosnt Metadata *type);
831+
FUNCTION(CheckMetadataState, swift_checkMetadataState, SwiftCC,
832+
RETURNS(TypeMetadataResponseTy),
833+
ARGS(SizeTy, TypeMetadataPtrTy),
834+
ATTRS(NoUnwind, ReadOnly))
835+
829836
// const ProtocolWitnessTable *
830837
// swift_getGenericWitnessTable(GenericProtocolWitnessTable *genericTable,
831838
// const Metadata *type,

stdlib/public/runtime/Metadata.cpp

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3233,13 +3233,16 @@ static Result performOnMetadataCache(const Metadata *metadata,
32333233
const TypeContextDescriptor *description;
32343234
if (auto classMetadata = dyn_cast<ClassMetadata>(metadata)) {
32353235
description = classMetadata->getDescription();
3236-
} else {
3237-
auto valueMetadata = cast<ValueMetadata>(metadata);
3236+
} else if (auto valueMetadata = dyn_cast<ValueMetadata>(metadata)) {
32383237
description = valueMetadata->getDescription();
3238+
} else {
3239+
return std::move(callbacks).forOtherMetadata(metadata);
3240+
}
3241+
3242+
if (!description->isGeneric()) {
3243+
return std::move(callbacks).forOtherMetadata(metadata);
32393244
}
32403245

3241-
assert(description->isGeneric() &&
3242-
"only generic metadata can delay evaluation for now");
32433246
auto &generics = description->getFullGenericContextHeader();
32443247

32453248
auto genericArgs =
@@ -3265,6 +3268,10 @@ bool swift::addToMetadataQueue(
32653268
MetadataCacheKey key) && {
32663269
return cache.enqueue(key, std::move(QueueEntry));
32673270
}
3271+
3272+
bool forOtherMetadata(const Metadata *metadata) && {
3273+
swift_runtime_unreachable("metadata should always be complete");
3274+
}
32683275
} callbacks = { std::move(queueEntry) };
32693276

32703277
// Set the requirement.
@@ -3295,12 +3302,38 @@ void swift::resumeMetadataCompletion(
32953302
// non-key arguments.
32963303
key.KeyData.begin());
32973304
}
3305+
3306+
void forOtherMetadata(const Metadata *metadata) && {
3307+
swift_runtime_unreachable("metadata should always be complete");
3308+
}
32983309
} callbacks = { std::move(queueEntry) };
32993310

33003311
auto metadata = queueEntry->Value;
33013312
performOnMetadataCache<void>(metadata, std::move(callbacks));
33023313
}
33033314

3315+
MetadataResponse swift::swift_checkMetadataState(MetadataRequest request,
3316+
const Metadata *type) {
3317+
struct CheckStateCallbacks {
3318+
MetadataRequest Request;
3319+
3320+
/// Generic types just need to be awaited.
3321+
MetadataResponse forGenericMetadata(const Metadata *type,
3322+
const TypeContextDescriptor *description,
3323+
GenericMetadataCache &cache,
3324+
MetadataCacheKey key) && {
3325+
return cache.await(key, Request);
3326+
}
3327+
3328+
/// All other type metadata are always complete.
3329+
MetadataResponse forOtherMetadata(const Metadata *type) && {
3330+
return MetadataResponse{type, MetadataState::Complete};
3331+
}
3332+
} callbacks = { request };
3333+
3334+
return performOnMetadataCache<MetadataResponse>(type, std::move(callbacks));
3335+
}
3336+
33043337
/***************************************************************************/
33053338
/*** Allocator implementation **********************************************/
33063339
/***************************************************************************/

stdlib/public/runtime/MetadataCache.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,15 @@ class LockingConcurrentMap {
176176

177177
return entry->enqueue(*Concurrency, std::forward<ArgTys>(args)...);
178178
}
179+
180+
/// Given that an entry already exists, await it.
181+
template <class KeyType, class... ArgTys>
182+
Status await(KeyType key, ArgTys &&...args) {
183+
auto entry = Map.find(key);
184+
assert(entry && "entry doesn't already exist!");
185+
186+
return entry->await(*Concurrency, std::forward<ArgTys>(args)...);
187+
}
179188
};
180189

181190
/// A base class for metadata cache entries which supports an unfailing

validation-test/stdlib/MicroStdlib/Inputs/RuntimeStubs.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ int $SBi64_WV;
66
int $SBi8_WV;
77
void swift_getEnumCaseSinglePayload(void) {}
88
void swift_getGenericMetadata(void) {}
9+
void swift_checkMetadataState(void) {}
910
void swift_slowAlloc(void) {}
1011
void swift_slowDealloc(void) {}
1112
void swift_storeEnumTagSinglePayload(void) {}

0 commit comments

Comments
 (0)