Skip to content

Commit 50ec3d3

Browse files
authored
Merge pull request swiftlang#15672 from rjmccall/cyclic-metadata-4.2
[4.2] Finish the first stage of incomplete type metadata support
2 parents c8238e6 + 8b5210b commit 50ec3d3

30 files changed

+1492
-610
lines changed

include/swift/ABI/MetadataValues.h

Lines changed: 65 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1385,28 +1385,74 @@ class GenericMetadataPatternFlags : public FlagSet<uint32_t> {
13851385

13861386
/// The public state of a metadata.
13871387
enum class MetadataState : size_t {
1388-
/// A request for fully-completed metadata. The metadata must be
1389-
/// prepared for all supported type operations. This is a superset
1390-
/// of the requirements of LayoutComplete.
1388+
// The values of this enum are set up to give us some future flexibility
1389+
// in adding states. The compiler emits unsigned comparisons against
1390+
// these values, so adding states that aren't totally ordered with at
1391+
// least the existing values will pose a problem; but we also use a
1392+
// gradually-shrinking bitset in case it's useful to track states as
1393+
// separate capabilities. Specific values have been chosen so that a
1394+
// MetadataRequest of 0 represents a blocking complete request, which
1395+
// is the most likely request from ordinary code. The total size of a
1396+
// state is kept to 8 bits so that a full request, even with additional
1397+
// flags, can be materialized as a single immediate on common ISAs, and
1398+
// so that the state can be extracted with a byte truncation.
1399+
// The spacing between states reflects guesswork about where new
1400+
// states/capabilities are most likely to be added.
1401+
1402+
/// The metadata is fully complete. By definition, this is the
1403+
/// end-state of all metadata. Generally, metadata is expected to be
1404+
/// complete before it can be passed to arbitrary code, e.g. as
1405+
/// a generic argument to a function or as a metatype value.
13911406
///
1392-
/// For example, a class must be ready for subclassing and instantiation:
1393-
/// it must have a completed instance layout and (under ObjCInterop)
1394-
/// must have been realized by the Objective-C runtime.
1395-
Complete,
1396-
1397-
/// A request for metadata that can be used for type layout; that is,
1398-
/// the type's value witness table must be completely initialized.
1399-
LayoutComplete,
1400-
1401-
/// A request for a metadata pointer that fully identifies the type.
1402-
/// Basic type structure, such as the type context descriptor and the
1403-
/// list of generic arguments, should have been installed, but there is
1404-
/// no requirement for a valid value witness table.
1405-
Abstract,
1407+
/// In addition to the requirements of NonTransitiveComplete, certain
1408+
/// transitive completeness guarantees must hold. Most importantly,
1409+
/// complete nominal type metadata transitively guarantee the completion
1410+
/// of their stored generic type arguments and superclass metadata.
1411+
Complete = 0x00,
1412+
1413+
/// The metadata is fully complete except for any transitive completeness
1414+
/// guarantees.
1415+
///
1416+
/// In addition to the requirements of LayoutComplete, metadata in this
1417+
/// state must be prepared for all basic type operations. This includes:
1418+
///
1419+
/// - any sort of internal layout necessary to allocate and work
1420+
/// with concrete values of the type, such as the instance layout
1421+
/// of a class;
1422+
///
1423+
/// - any sort of external dynamic registration that might be required
1424+
/// for the type, such as the realization of a class by the Objective-C
1425+
/// runtime; and
1426+
///
1427+
/// - the initialization of any other information kept in the metadata
1428+
/// object, such as a class's v-table.
1429+
NonTransitiveComplete = 0x01,
1430+
1431+
/// The metadata is ready for the layout of other types that store values
1432+
/// of this type.
1433+
///
1434+
/// In addition to the requirements of Abstract, metadata in this state
1435+
/// must have a valid value witness table, meaning that its size,
1436+
/// alignment, and basic type properties (such as POD-ness) have been
1437+
/// computed.
1438+
LayoutComplete = 0x3F,
1439+
1440+
/// The metadata has its basic identity established. It is possible to
1441+
/// determine what formal type it corresponds to. Among other things, it
1442+
/// is possible to use the runtime mangling facilities with the type.
1443+
///
1444+
/// For example, a metadata for a generic struct has a metadata kind,
1445+
/// a type descriptor, and all of its type arguments. However, it does not
1446+
/// necessarily have a meaningful value-witness table.
1447+
///
1448+
/// References to other types that are not part of the type's basic identity
1449+
/// may not yet have been established. Most crucially, this includes the
1450+
/// superclass pointer.
1451+
Abstract = 0xFF,
14061452
};
14071453

1408-
/// Something that can be static_asserted in all the places where we depend
1409-
/// on metadata state ordering.
1454+
/// Something that can be static_asserted in all the places where we do
1455+
/// comparisons on metadata states.
14101456
constexpr const bool MetadataStateIsReverseOrdered = true;
14111457

14121458
/// Return true if the first metadata state is at least as advanced as the

include/swift/Runtime/Debug.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ struct RuntimeErrorDetails {
167167
uintptr_t framesToSkip;
168168

169169
// Address of some associated object (if there's any).
170-
void *memoryAddress;
170+
const void *memoryAddress;
171171

172172
// A structure describing an extra thread (and its stack) that is related.
173173
struct Thread {

include/swift/Runtime/Metadata.h

Lines changed: 71 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -195,25 +195,45 @@ using Metadata = TargetMetadata<InProcess>;
195195
/// For performance, functions returning this type should use SWIFT_CC so
196196
/// that the components are returned as separate values.
197197
struct MetadataResponse {
198-
/// For metadata access functions, this is the requested metadata.
199-
///
200-
/// For metadata initialization functions, this is either null,
201-
/// indicating that initialization was successful, or a metadata on
202-
/// which initialization depends for further progress.
198+
/// The requested metadata.
203199
const Metadata *Value;
204200

205-
/// For metadata access functions, this is the current state of the
206-
/// metadata returned. Always use this instead of trying to inspect
207-
/// the metadata directly; an incomplete metadata may be getting
208-
/// initialized concurrently. This can generally be ignored if the
209-
/// metadata request was for abstract metadata or if the request is
210-
/// blocking.
211-
///
212-
/// For metadata initialization functions, this is the state that the
213-
/// given metadata needs to be in before initialization can continue.
201+
/// The current state of the metadata returned. Always use this
202+
/// instead of trying to inspect the metadata directly to see if it
203+
/// satisfies the request. An incomplete metadata may be getting
204+
/// initialized concurrently. But this can generally be ignored if
205+
/// the metadata request was for abstract metadata or if the request
206+
/// is blocking.
214207
MetadataState State;
215208
};
216-
using MetadataDependency = MetadataResponse;
209+
210+
/// A dependency on the metadata progress of other type, indicating that
211+
/// initialization of a metadata cannot progress until another metadata
212+
/// reaches a particular state.
213+
///
214+
/// For performance, functions returning this type should use SWIFT_CC so
215+
/// that the components are returned as separate values.
216+
struct MetadataDependency {
217+
/// Either null, indicating that initialization was successful, or
218+
/// a metadata on which initialization depends for further progress.
219+
const Metadata *Value;
220+
221+
/// The state that Metadata needs to be in before initialization
222+
/// can continue.
223+
MetadataState Requirement;
224+
225+
MetadataDependency() : Value(nullptr) {}
226+
MetadataDependency(const Metadata *metadata, MetadataState requirement)
227+
: Value(metadata), Requirement(requirement) {}
228+
229+
explicit operator bool() const { return Value != nullptr; }
230+
231+
bool operator==(MetadataDependency other) const {
232+
assert(Value && other.Value);
233+
return Value == other.Value &&
234+
Requirement == other.Requirement;
235+
}
236+
};
217237

218238
template <typename Runtime> struct TargetProtocolConformanceDescriptor;
219239

@@ -1848,6 +1868,10 @@ struct TargetTupleTypeMetadata : public TargetMetadata<Runtime> {
18481868
OpaqueValue *findIn(OpaqueValue *tuple) const {
18491869
return (OpaqueValue*) (((char*) tuple) + Offset);
18501870
}
1871+
1872+
const TypeLayout *getTypeLayout() const {
1873+
return Type->getTypeLayout();
1874+
}
18511875
};
18521876

18531877
Element *getElements() {
@@ -3438,6 +3462,8 @@ class TargetTypeContextDescriptor
34383462
return getFullGenericContextHeader();
34393463
}
34403464

3465+
llvm::ArrayRef<GenericParamDescriptor> getGenericParams() const;
3466+
34413467
/// Return the offset of the start of generic arguments in the nominal
34423468
/// type's metadata. The returned value is measured in sizeof(void*).
34433469
int32_t getGenericArgumentOffset() const;
@@ -3575,6 +3601,7 @@ class TargetClassDescriptor final
35753601
using TrailingGenericContextObjects::getGenericContext;
35763602
using TrailingGenericContextObjects::getGenericContextHeader;
35773603
using TrailingGenericContextObjects::getFullGenericContextHeader;
3604+
using TrailingGenericContextObjects::getGenericParams;
35783605
using TargetTypeContextDescriptor<Runtime>::getTypeContextDescriptorFlags;
35793606

35803607
/// The superclass of this class. This pointer can be interpreted
@@ -3791,6 +3818,7 @@ class TargetStructDescriptor final
37913818
using TrailingGenericContextObjects::getGenericContext;
37923819
using TrailingGenericContextObjects::getGenericContextHeader;
37933820
using TrailingGenericContextObjects::getFullGenericContextHeader;
3821+
using TrailingGenericContextObjects::getGenericParams;
37943822

37953823
/// The number of stored properties in the struct.
37963824
/// If there is a field offset vector, this is its length.
@@ -3833,6 +3861,7 @@ class TargetEnumDescriptor final
38333861
using TrailingGenericContextObjects::getGenericContext;
38343862
using TrailingGenericContextObjects::getGenericContextHeader;
38353863
using TrailingGenericContextObjects::getFullGenericContextHeader;
3864+
using TrailingGenericContextObjects::getGenericParams;
38363865

38373866
/// The number of non-empty cases in the enum are in the low 24 bits;
38383867
/// the offset of the payload size in the metadata record in words,
@@ -3937,6 +3966,21 @@ TargetTypeContextDescriptor<Runtime>::getFullGenericContextHeader() const {
39373966
}
39383967
}
39393968

3969+
template <typename Runtime>
3970+
llvm::ArrayRef<GenericParamDescriptor>
3971+
TargetTypeContextDescriptor<Runtime>::getGenericParams() const {
3972+
switch (this->getKind()) {
3973+
case ContextDescriptorKind::Class:
3974+
return llvm::cast<TargetClassDescriptor<Runtime>>(this)->getGenericParams();
3975+
case ContextDescriptorKind::Enum:
3976+
return llvm::cast<TargetEnumDescriptor<Runtime>>(this)->getGenericParams();
3977+
case ContextDescriptorKind::Struct:
3978+
return llvm::cast<TargetStructDescriptor<Runtime>>(this)->getGenericParams();
3979+
default:
3980+
swift_runtime_unreachable("Not a type context descriptor.");
3981+
}
3982+
}
3983+
39403984
/// \brief Fetch a uniqued metadata object for a generic nominal type.
39413985
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
39423986
MetadataResponse
@@ -4093,21 +4137,24 @@ swift_getForeignTypeMetadata(ForeignTypeMetadata *nonUnique);
40934137
/// \param proposedWitnesses - an optional proposed set of value witnesses.
40944138
/// This is useful when working with a non-dependent tuple type
40954139
/// where the entrypoint is just being used to unique the metadata.
4096-
SWIFT_RUNTIME_EXPORT
4097-
const TupleTypeMetadata *
4098-
swift_getTupleTypeMetadata(TupleTypeFlags flags,
4140+
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
4141+
MetadataResponse
4142+
swift_getTupleTypeMetadata(MetadataRequest request,
4143+
TupleTypeFlags flags,
40994144
const Metadata * const *elements,
41004145
const char *labels,
41014146
const ValueWitnessTable *proposedWitnesses);
41024147

4103-
SWIFT_RUNTIME_EXPORT
4104-
const TupleTypeMetadata *
4105-
swift_getTupleTypeMetadata2(const Metadata *elt0, const Metadata *elt1,
4148+
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
4149+
MetadataResponse
4150+
swift_getTupleTypeMetadata2(MetadataRequest request,
4151+
const Metadata *elt0, const Metadata *elt1,
41064152
const char *labels,
41074153
const ValueWitnessTable *proposedWitnesses);
4108-
SWIFT_RUNTIME_EXPORT
4109-
const TupleTypeMetadata *
4110-
swift_getTupleTypeMetadata3(const Metadata *elt0, const Metadata *elt1,
4154+
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
4155+
MetadataResponse
4156+
swift_getTupleTypeMetadata3(MetadataRequest request,
4157+
const Metadata *elt0, const Metadata *elt1,
41114158
const Metadata *elt2, const char *labels,
41124159
const ValueWitnessTable *proposedWitnesses);
41134160

include/swift/Runtime/RuntimeFunctions.def

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -869,31 +869,35 @@ FUNCTION(GetObjCClassFromMetadata, swift_getObjCClassFromMetadata, C_CC,
869869
ARGS(TypeMetadataPtrTy),
870870
ATTRS(NoUnwind, ReadNone))
871871

872-
// Metadata *swift_getTupleTypeMetadata(TupleTypeFlags flags,
873-
// Metadata * const *elts,
874-
// const char *labels,
875-
// value_witness_table_t *proposed);
876-
FUNCTION(GetTupleMetadata, swift_getTupleTypeMetadata, C_CC,
877-
RETURNS(TypeMetadataPtrTy),
878-
ARGS(SizeTy, TypeMetadataPtrTy->getPointerTo(0),
872+
// MetadataResponse swift_getTupleTypeMetadata(MetadataRequest request,
873+
// TupleTypeFlags flags,
874+
// Metadata * const *elts,
875+
// const char *labels,
876+
// value_witness_table_t *proposed);
877+
FUNCTION(GetTupleMetadata, swift_getTupleTypeMetadata, SwiftCC,
878+
RETURNS(TypeMetadataResponseTy),
879+
ARGS(SizeTy, SizeTy, TypeMetadataPtrTy->getPointerTo(0),
879880
Int8PtrTy, WitnessTablePtrTy),
880881
ATTRS(NoUnwind, ReadOnly))
881882

882-
// Metadata *swift_getTupleTypeMetadata2(Metadata *elt0, Metadata *elt1,
883-
// const char *labels,
884-
// value_witness_table_t *proposed);
885-
FUNCTION(GetTupleMetadata2, swift_getTupleTypeMetadata2, C_CC,
886-
RETURNS(TypeMetadataPtrTy),
887-
ARGS(TypeMetadataPtrTy, TypeMetadataPtrTy,
883+
// MetadataResponse swift_getTupleTypeMetadata2(MetadataRequest request,
884+
// Metadata *elt0, Metadata *elt1,
885+
// const char *labels,
886+
// value_witness_table_t *proposed);
887+
FUNCTION(GetTupleMetadata2, swift_getTupleTypeMetadata2, SwiftCC,
888+
RETURNS(TypeMetadataResponseTy),
889+
ARGS(SizeTy, TypeMetadataPtrTy, TypeMetadataPtrTy,
888890
Int8PtrTy, WitnessTablePtrTy),
889891
ATTRS(NoUnwind, ReadOnly))
890892

891-
// Metadata *swift_getTupleTypeMetadata3(Metadata *elt0, Metadata *elt1,
892-
// Metadata *elt2, const char *labels,
893-
// value_witness_table_t *proposed);
894-
FUNCTION(GetTupleMetadata3, swift_getTupleTypeMetadata3, C_CC,
895-
RETURNS(TypeMetadataPtrTy),
896-
ARGS(TypeMetadataPtrTy, TypeMetadataPtrTy, TypeMetadataPtrTy,
893+
// MetadataResponse swift_getTupleTypeMetadata3(MetadataRequest request,
894+
// Metadata *elt0, Metadata *elt1,
895+
// Metadata *elt2,
896+
// const char *labels,
897+
// value_witness_table_t *proposed);
898+
FUNCTION(GetTupleMetadata3, swift_getTupleTypeMetadata3, SwiftCC,
899+
RETURNS(TypeMetadataResponseTy),
900+
ARGS(SizeTy, TypeMetadataPtrTy, TypeMetadataPtrTy, TypeMetadataPtrTy,
897901
Int8PtrTy, WitnessTablePtrTy),
898902
ATTRS(NoUnwind, ReadOnly))
899903

lib/IRGen/Fulfillment.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,7 @@ bool FulfillmentMap::addFulfillment(FulfillmentKey key,
325325
static StringRef getStateName(MetadataState state) {
326326
switch (state) {
327327
case MetadataState::Complete: return "complete";
328+
case MetadataState::NonTransitiveComplete: return "non-transitive-complete";
328329
case MetadataState::LayoutComplete: return "layout-complete";
329330
case MetadataState::Abstract: return "abstract";
330331
}

lib/IRGen/GenMeta.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1910,9 +1910,8 @@ namespace {
19101910
void emitStoreOfSuperclass(IRGenFunction &IGF, CanType superclassType,
19111911
llvm::Value *metadata,
19121912
MetadataDependencyCollector *collector) {
1913-
auto request =
1914-
DynamicMetadataRequest::getNonBlocking(MetadataState::Complete,
1915-
collector);
1913+
auto request = DynamicMetadataRequest::getNonBlocking(
1914+
MetadataState::NonTransitiveComplete, collector);
19161915

19171916
llvm::Value *superMetadata =
19181917
emitClassHeapMetadataRef(IGF, superclassType,

lib/IRGen/LocalTypeData.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,8 @@ class LocalTypeDataCache {
169169
/// An abstract entry in the cache, which requires some amount of
170170
/// non-trivial evaluation to derive the desired value.
171171
struct AbstractCacheEntry : CacheEntry {
172-
unsigned SourceIndex : 32 - LocalTypeDataValue::StateSize;
173-
unsigned State : LocalTypeDataValue::StateSize;
172+
unsigned SourceIndex;
173+
unsigned State;
174174
MetadataPath Path;
175175

176176
AbstractCacheEntry(DominancePoint point, bool isConditional,

lib/IRGen/MetadataPath.h

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -37,27 +37,8 @@ namespace irgen {
3737
class DynamicMetadataRequest;
3838
class IRGenFunction;
3939
class LocalTypeDataKey;
40-
class LocalTypeDataValue;
4140
class MetadataResponse;
4241

43-
class LocalTypeDataValue {
44-
public:
45-
enum { StateSize = 2 };
46-
47-
private:
48-
llvm::PointerIntPair<llvm::Value*, StateSize, MetadataState> Value;
49-
50-
public:
51-
LocalTypeDataValue() {}
52-
LocalTypeDataValue(llvm::Value *value, MetadataState state)
53-
: Value(value, state) {}
54-
55-
explicit operator bool() const { return Value.getOpaqueValue() != nullptr; }
56-
57-
llvm::Value *getValue() const { return Value.getPointer(); }
58-
MetadataState getState() const { return Value.getInt(); }
59-
};
60-
6142
/// A path from one source metadata --- either Swift type metadata or a Swift
6243
/// protocol conformance --- to another.
6344
class MetadataPath {

0 commit comments

Comments
 (0)