Skip to content

Commit d645922

Browse files
committed
[Runtime] Use nominal type descriptor references for non-foreign types.
Rather than emitting unique, direct type metadata for non-foreign types, emit a reference to the nominal type descriptor. This collapses the set of type metadata reference kinds to 3: nominal type descriptor, (indirect) Objective-C class object, and nonuniqued foreign type metadata.
1 parent b25dc44 commit d645922

File tree

7 files changed

+37
-106
lines changed

7 files changed

+37
-106
lines changed

include/swift/ABI/MetadataValues.h

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -173,18 +173,10 @@ enum : unsigned {
173173

174174
/// Kinds of type metadata/protocol conformance records.
175175
enum class TypeMetadataRecordKind : unsigned {
176-
/// The conformance is universal and might apply to any type.
177-
/// getDirectType() is nil.
178-
Universal,
179-
180-
/// The conformance is for a nongeneric native struct or enum type.
181-
/// getDirectType() points to the canonical metadata for the type.
182-
UniqueDirectType,
183-
184176
/// The conformance is for a nongeneric foreign struct or enum type.
185177
/// getDirectType() points to a nonunique metadata record for the type, which
186178
/// needs to be uniqued by the runtime.
187-
NonuniqueDirectType,
179+
NonuniqueDirectType = 0x02,
188180

189181
/// The conformance is for a nongeneric class type.
190182
/// getIndirectClass() points to a variable that contains the pointer to the
@@ -193,12 +185,12 @@ enum class TypeMetadataRecordKind : unsigned {
193185
///
194186
/// On platforms without ObjC interop, this indirection isn't necessary,
195187
/// and classes are emitted as UniqueDirectType.
196-
UniqueIndirectClass,
188+
UniqueIndirectClass = 0x03,
197189

198190
/// The conformance is for a generic or resilient type.
199191
/// getNominalTypeDescriptor() points to the nominal type descriptor shared
200192
/// by all metadata instantiations of this type.
201-
UniqueNominalTypeDescriptor,
193+
UniqueNominalTypeDescriptor = 0x04,
202194
};
203195

204196
/// Kinds of reference to protocol conformance.

include/swift/Runtime/Metadata.h

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2464,7 +2464,7 @@ struct TargetTypeMetadataRecord {
24642464

24652465
/// The nominal type descriptor for a resilient or generic type.
24662466
RelativeDirectPointer<TargetNominalTypeDescriptor<Runtime>>
2467-
TypeDescriptor;
2467+
TypeDescriptor;
24682468
};
24692469

24702470
/// Flags describing the type metadata record.
@@ -2477,10 +2477,6 @@ struct TargetTypeMetadataRecord {
24772477

24782478
const TargetMetadata<Runtime> *getDirectType() const {
24792479
switch (Flags.getTypeKind()) {
2480-
case TypeMetadataRecordKind::Universal:
2481-
return nullptr;
2482-
2483-
case TypeMetadataRecordKind::UniqueDirectType:
24842480
case TypeMetadataRecordKind::NonuniqueDirectType:
24852481
break;
24862482

@@ -2495,14 +2491,10 @@ struct TargetTypeMetadataRecord {
24952491
const TargetNominalTypeDescriptor<Runtime> *
24962492
getNominalTypeDescriptor() const {
24972493
switch (Flags.getTypeKind()) {
2498-
case TypeMetadataRecordKind::Universal:
2499-
return nullptr;
2500-
25012494
case TypeMetadataRecordKind::UniqueNominalTypeDescriptor:
25022495
break;
25032496

25042497
case TypeMetadataRecordKind::UniqueIndirectClass:
2505-
case TypeMetadataRecordKind::UniqueDirectType:
25062498
case TypeMetadataRecordKind::NonuniqueDirectType:
25072499
assert(false && "not generic metadata pattern");
25082500
}
@@ -2587,10 +2579,6 @@ struct TargetProtocolConformanceRecord {
25872579

25882580
const TargetMetadata<Runtime> *getDirectType() const {
25892581
switch (Flags.getTypeKind()) {
2590-
case TypeMetadataRecordKind::Universal:
2591-
return nullptr;
2592-
2593-
case TypeMetadataRecordKind::UniqueDirectType:
25942582
case TypeMetadataRecordKind::NonuniqueDirectType:
25952583
break;
25962584

@@ -2604,13 +2592,9 @@ struct TargetProtocolConformanceRecord {
26042592

26052593
const TargetClassMetadata<Runtime> * const *getIndirectClass() const {
26062594
switch (Flags.getTypeKind()) {
2607-
case TypeMetadataRecordKind::Universal:
2608-
return nullptr;
2609-
26102595
case TypeMetadataRecordKind::UniqueIndirectClass:
26112596
break;
26122597

2613-
case TypeMetadataRecordKind::UniqueDirectType:
26142598
case TypeMetadataRecordKind::NonuniqueDirectType:
26152599
case TypeMetadataRecordKind::UniqueNominalTypeDescriptor:
26162600
assert(false && "not indirect class object");
@@ -2622,14 +2606,10 @@ struct TargetProtocolConformanceRecord {
26222606
const TargetNominalTypeDescriptor<Runtime> *
26232607
getNominalTypeDescriptor() const {
26242608
switch (Flags.getTypeKind()) {
2625-
case TypeMetadataRecordKind::Universal:
2626-
return nullptr;
2627-
26282609
case TypeMetadataRecordKind::UniqueNominalTypeDescriptor:
26292610
break;
26302611

26312612
case TypeMetadataRecordKind::UniqueIndirectClass:
2632-
case TypeMetadataRecordKind::UniqueDirectType:
26332613
case TypeMetadataRecordKind::NonuniqueDirectType:
26342614
assert(false && "not generic metadata pattern");
26352615
}

lib/IRGen/GenClass.cpp

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "swift/AST/PrettyStackTrace.h"
2828
#include "swift/AST/TypeMemberVisitor.h"
2929
#include "swift/AST/Types.h"
30+
#include "swift/ClangImporter/ClangModule.h"
3031
#include "swift/IRGen/Linking.h"
3132
#include "swift/SIL/SILModule.h"
3233
#include "swift/SIL/SILType.h"
@@ -2339,13 +2340,6 @@ bool irgen::doesClassMetadataRequireDynamicInitialization(IRGenModule &IGM,
23392340
bool irgen::doesConformanceReferenceNominalTypeDescriptor(IRGenModule &IGM,
23402341
CanType conformingType) {
23412342
NominalTypeDecl *nom = conformingType->getAnyNominal();
2342-
auto *clas = dyn_cast<ClassDecl>(nom);
2343-
if (nom->isGenericContext() && (!clas || !clas->usesObjCGenericsModel()))
2344-
return true;
2345-
2346-
if (clas && doesClassMetadataRequireDynamicInitialization(IGM, clas))
2347-
return true;
2348-
2349-
return false;
2343+
return !isa<ClangModuleUnit>(nom->getModuleScopeContext());
23502344
}
23512345

lib/IRGen/GenDecl.cpp

Lines changed: 18 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2210,48 +2210,26 @@ getTypeEntityInfo(IRGenModule &IGM, CanType conformingType) {
22102210
entity = LinkEntity::forNominalTypeDescriptor(nom);
22112211
defaultTy = IGM.NominalTypeDescriptorTy;
22122212
defaultPtrTy = IGM.NominalTypeDescriptorPtrTy;
2213-
} else if (clas) {
2214-
if (clas->isForeign()) {
2215-
typeKind = TypeMetadataRecordKind::NonuniqueDirectType;
2216-
entity = LinkEntity::forForeignTypeMetadataCandidate(conformingType);
2217-
defaultTy = IGM.TypeMetadataStructTy;
2218-
defaultPtrTy = IGM.TypeMetadataPtrTy;
2219-
} else {
2220-
if (hasKnownSwiftMetadata(IGM, clas)) {
2221-
typeKind = TypeMetadataRecordKind::UniqueDirectType;
2222-
entity = LinkEntity::forTypeMetadata(
2223-
conformingType,
2224-
TypeMetadataAddress::AddressPoint,
2225-
/*isPattern*/ false);
2226-
defaultTy = IGM.TypeMetadataStructTy;
2227-
} else {
2228-
// Form the class reference.
2229-
(void)IGM.getAddrOfObjCClassRef(clas);
2230-
2231-
typeKind = TypeMetadataRecordKind::UniqueIndirectClass;
2232-
entity = LinkEntity::forObjCClassRef(clas);
2233-
defaultTy = IGM.TypeMetadataPtrTy;
2234-
}
2235-
defaultPtrTy = IGM.TypeMetadataPtrTy;
2236-
}
2213+
} else if (clas && !clas->isForeign()) {
2214+
// A reference to an Objective-C class object.
2215+
assert(clas->isObjC() && "Must have an Objective-C class here");
2216+
assert(!hasKnownSwiftMetadata(IGM, clas) &&
2217+
"Should use nominal type descriptor");
2218+
2219+
// Form the class reference.
2220+
(void)IGM.getAddrOfObjCClassRef(clas);
2221+
2222+
typeKind = TypeMetadataRecordKind::UniqueIndirectClass;
2223+
entity = LinkEntity::forObjCClassRef(clas);
2224+
defaultTy = IGM.TypeMetadataPtrTy;
2225+
defaultPtrTy = IGM.TypeMetadataPtrTy;
22372226
} else {
22382227
// Metadata for Clang types should be uniqued like foreign classes.
2239-
if (isa<ClangModuleUnit>(nom->getModuleScopeContext())) {
2240-
typeKind = TypeMetadataRecordKind::NonuniqueDirectType;
2241-
entity = LinkEntity::forForeignTypeMetadataCandidate(conformingType);
2242-
defaultTy = IGM.TypeMetadataStructTy;
2243-
defaultPtrTy = IGM.TypeMetadataPtrTy;
2244-
} else {
2245-
// We can reference the canonical metadata for native value types
2246-
// directly.
2247-
typeKind = TypeMetadataRecordKind::UniqueDirectType;
2248-
entity = LinkEntity::forTypeMetadata(
2249-
conformingType,
2250-
TypeMetadataAddress::AddressPoint,
2251-
/*isPattern*/ false);
2252-
defaultTy = IGM.TypeMetadataStructTy;
2253-
defaultPtrTy = IGM.TypeMetadataPtrTy;
2254-
}
2228+
assert(isa<ClangModuleUnit>(nom->getModuleScopeContext()));
2229+
typeKind = TypeMetadataRecordKind::NonuniqueDirectType;
2230+
entity = LinkEntity::forForeignTypeMetadataCandidate(conformingType);
2231+
defaultTy = IGM.TypeMetadataStructTy;
2232+
defaultPtrTy = IGM.TypeMetadataPtrTy;
22552233
}
22562234

22572235
auto flags = ProtocolConformanceFlags().withTypeKind(typeKind);

stdlib/public/runtime/MetadataLookup.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,6 @@ swift::swift_registerTypeMetadataRecords(const TypeMetadataRecord *begin,
128128
template<>
129129
const Metadata *TypeMetadataRecord::getCanonicalTypeMetadata() const {
130130
switch (getTypeKind()) {
131-
case TypeMetadataRecordKind::UniqueDirectType:
132-
return getDirectType();
133131
case TypeMetadataRecordKind::NonuniqueDirectType: {
134132
const ForeignTypeMetadata *FMD =
135133
static_cast<const ForeignTypeMetadata *>(getDirectType());

stdlib/public/runtime/ProtocolConformance.cpp

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,8 @@ template<> void ProtocolConformanceRecord::dump() const {
4848
};
4949

5050
switch (auto kind = getTypeKind()) {
51-
case TypeMetadataRecordKind::Universal:
52-
printf("universal");
53-
break;
54-
case TypeMetadataRecordKind::UniqueDirectType:
5551
case TypeMetadataRecordKind::NonuniqueDirectType:
56-
printf("%s direct type ",
57-
kind == TypeMetadataRecordKind::UniqueDirectType
58-
? "unique" : "nonunique");
52+
printf("direct type nonunique ");
5953
if (const auto *ntd = getDirectType()->getNominalTypeDescriptor()) {
6054
printf("%s", ntd->Name.get());
6155
} else {
@@ -99,9 +93,6 @@ template<> void ProtocolConformanceRecord::dump() const {
9993
template <>
10094
const Metadata *ProtocolConformanceRecord::getCanonicalTypeMetadata() const {
10195
switch (getTypeKind()) {
102-
case TypeMetadataRecordKind::UniqueDirectType:
103-
// Already unique.
104-
return getDirectType();
10596
case TypeMetadataRecordKind::NonuniqueDirectType: {
10697
// Ask the runtime for the unique metadata record we've canonized.
10798
const ForeignTypeMetadata *FMD =
@@ -117,8 +108,6 @@ const Metadata *ProtocolConformanceRecord::getCanonicalTypeMetadata() const {
117108
return nullptr;
118109

119110
case TypeMetadataRecordKind::UniqueNominalTypeDescriptor:
120-
case TypeMetadataRecordKind::Universal:
121-
// The record does not apply to a single type.
122111
return nullptr;
123112
}
124113

test/IRGen/protocol_conformance_records.swift

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ public protocol Runcible {
1313
// -- protocol descriptor
1414
// CHECK-SAME: [[RUNCIBLE:@_T028protocol_conformance_records8RuncibleMp]]
1515
// -- type metadata
16-
// CHECK-SAME: @_T028protocol_conformance_records15NativeValueTypeVMf
16+
// CHECK-SAME: @_T028protocol_conformance_records15NativeValueTypeVMn
1717
// -- witness table
1818
// CHECK-SAME: @_T028protocol_conformance_records15NativeValueTypeVAA8RuncibleAAWP
19-
// -- flags 0x01: unique direct metadata
20-
// CHECK-SAME: i32 1
19+
// -- flags 0x04: unique nominal type descriptor
20+
// CHECK-SAME: i32 4
2121
// CHECK-SAME: },
2222
public struct NativeValueType: Runcible {
2323
public func runce() {}
@@ -27,11 +27,11 @@ public struct NativeValueType: Runcible {
2727
// -- protocol descriptor
2828
// CHECK-SAME: [[RUNCIBLE]]
2929
// -- class metadata
30-
// CHECK-SAME: @_T028protocol_conformance_records15NativeClassTypeCMf
30+
// CHECK-SAME: @_T028protocol_conformance_records15NativeClassTypeCMn
3131
// -- witness table
3232
// CHECK-SAME: @_T028protocol_conformance_records15NativeClassTypeCAA8RuncibleAAWP
33-
// -- flags 0x01: unique direct metadata
34-
// CHECK-SAME: i32 1
33+
// -- flags 0x04: unique nominal type descriptor
34+
// CHECK-SAME: i32 4
3535
// CHECK-SAME: },
3636
public class NativeClassType: Runcible {
3737
public func runce() {}
@@ -55,11 +55,11 @@ public struct NativeGenericType<T>: Runcible {
5555
// -- protocol descriptor
5656
// CHECK-SAME: [[RUNCIBLE]]
5757
// -- type metadata
58-
// CHECK-SAME: @got._T0SiN
58+
// CHECK-SAME: @got._T0SiMn
5959
// -- witness table
6060
// CHECK-SAME: @_T0Si28protocol_conformance_records8RuncibleAAWP
61-
// -- flags 0x01: unique direct metadata
62-
// CHECK-SAME: i32 1
61+
// -- flags 0x04: unique nominal type descriptor
62+
// CHECK-SAME: i32 4
6363
// CHECK-SAME: }
6464
extension Int: Runcible {
6565
public func runce() {}
@@ -71,11 +71,11 @@ extension Int: Runcible {
7171
// -- protocol descriptor
7272
// CHECK-SAME: [[RUNCIBLE]]
7373
// -- nominal type descriptor
74-
// CHECK-SAME: @got._T016resilient_struct4SizeVN
74+
// CHECK-SAME: @got._T016resilient_struct4SizeVMn
7575
// -- witness table
7676
// CHECK-SAME: @_T016resilient_struct4SizeV28protocol_conformance_records8RuncibleADWP
77-
// -- flags 0x01: unique direct metadata
78-
// CHECK-SAME: i32 1
77+
// -- flags 0x04: unique nominal type descriptor
78+
// CHECK-SAME: i32 4
7979
// CHECK-SAME: }
8080

8181
extension Size: Runcible {

0 commit comments

Comments
 (0)