Skip to content

Commit 50aa064

Browse files
authored
Merge pull request #14958 from rjmccall/class-instantiation-patterns
2 parents 26c08fb + a7c5c80 commit 50aa064

35 files changed

+1341
-770
lines changed

include/swift/ABI/MetadataValues.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,6 +1021,10 @@ class TypeContextDescriptorFlags : public FlagSet<uint16_t> {
10211021
/// Only meaningful for class descriptors.
10221022
Class_SuperclassReferenceKind = 12,
10231023
Class_SuperclassReferenceKind_width = 2,
1024+
1025+
/// Whether the immediate class members in this metadata are allocated
1026+
/// at negative offsets. For now, we don't use this.
1027+
Class_AreImmediateMembersNegative = 11,
10241028
};
10251029

10261030
public:
@@ -1037,6 +1041,9 @@ class TypeContextDescriptorFlags : public FlagSet<uint16_t> {
10371041
FLAGSET_DEFINE_FLAG_ACCESSORS(Class_HasResilientSuperclass,
10381042
class_hasResilientSuperclass,
10391043
class_setHasResilientSuperclass)
1044+
FLAGSET_DEFINE_FLAG_ACCESSORS(Class_AreImmediateMembersNegative,
1045+
class_areImmediateMembersNegative,
1046+
class_setAreImmediateMembersNegative)
10401047

10411048
FLAGSET_DEFINE_FIELD_ACCESSORS(Class_SuperclassReferenceKind,
10421049
Class_SuperclassReferenceKind_width,

include/swift/Basic/FlagSet.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ class FlagSet {
6060
if (value) {
6161
Bits |= maskFor<Bit>();
6262
} else {
63-
Bits |= ~maskFor<Bit>();
63+
Bits &= ~maskFor<Bit>();
6464
}
6565
}
6666

include/swift/Remote/MetadataReader.h

Lines changed: 80 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ class MetadataReader {
233233
return StoredPointer();
234234

235235
auto classMeta = cast<TargetClassMetadata<Runtime>>(meta);
236-
return classMeta->SuperClass;
236+
return classMeta->Superclass;
237237
}
238238

239239
/// Given a remote pointer to class metadata, attempt to discover its class
@@ -537,32 +537,24 @@ class MetadataReader {
537537
///
538538
/// The offset is in units of words, from the start of the class's
539539
/// metadata.
540-
llvm::Optional<uint32_t>
540+
llvm::Optional<int32_t>
541541
readGenericArgsOffset(MetadataRef metadata,
542542
ContextDescriptorRef descriptor) {
543543
switch (descriptor->getKind()) {
544544
case ContextDescriptorKind::Class: {
545545
auto type = cast<TargetClassDescriptor<Runtime>>(descriptor);
546546

547-
auto *classMetadata = dyn_cast<TargetClassMetadata<Runtime>>(metadata);
548-
if (!classMetadata)
549-
return llvm::None;
550-
551-
if (!classMetadata->SuperClass)
552-
return type->getGenericArgumentOffset(nullptr, nullptr);
547+
if (!type->hasResilientSuperclass())
548+
return type->getNonResilientGenericArgumentOffset();
553549

554-
auto superMetadata = readMetadata(classMetadata->SuperClass);
555-
if (!superMetadata)
550+
auto bounds = readMetadataBoundsOfSuperclass(descriptor);
551+
if (!bounds)
556552
return llvm::None;
557553

558-
auto superClassMetadata =
559-
dyn_cast<TargetClassMetadata<Runtime>>(superMetadata);
560-
if (!superClassMetadata)
561-
return llvm::None;
554+
bounds->adjustForSubclass(type->areImmediateMembersNegative(),
555+
type->NumImmediateMembers);
562556

563-
auto result =
564-
type->getGenericArgumentOffset(classMetadata, superClassMetadata);
565-
return result;
557+
return bounds->ImmediateMembersOffset / sizeof(StoredPointer);
566558
}
567559

568560
case ContextDescriptorKind::Enum: {
@@ -580,6 +572,76 @@ class MetadataReader {
580572
}
581573
}
582574

575+
using ClassMetadataBounds = TargetClassMetadataBounds<Runtime>;
576+
577+
// This follows computeMetadataBoundsForSuperclass.
578+
llvm::Optional<ClassMetadataBounds>
579+
readMetadataBoundsOfSuperclass(ContextDescriptorRef subclassRef) {
580+
auto subclass = cast<TargetClassDescriptor<Runtime>>(subclassRef);
581+
582+
auto rawSuperclass =
583+
resolveNullableRelativeField(subclassRef, subclass->Superclass);
584+
if (!rawSuperclass) {
585+
return ClassMetadataBounds::forSwiftRootClass();
586+
}
587+
588+
return forTypeReference<ClassMetadataBounds>(
589+
subclass->getSuperclassReferenceKind(), *rawSuperclass,
590+
[&](ContextDescriptorRef superclass)
591+
-> llvm::Optional<ClassMetadataBounds> {
592+
if (!isa<TargetClassDescriptor<Runtime>>(superclass))
593+
return llvm::None;
594+
return readMetadataBoundsOfSuperclass(superclass);
595+
},
596+
[&](MetadataRef metadata) -> llvm::Optional<ClassMetadataBounds> {
597+
auto cls = dyn_cast<TargetClassMetadata<Runtime>>(metadata);
598+
if (!cls)
599+
return llvm::None;
600+
601+
return cls->getClassBoundsAsSwiftSuperclass();
602+
});
603+
}
604+
605+
template <class Result, class DescriptorFn, class MetadataFn>
606+
llvm::Optional<Result>
607+
forTypeReference(TypeMetadataRecordKind refKind, StoredPointer ref,
608+
const DescriptorFn &descriptorFn,
609+
const MetadataFn &metadataFn) {
610+
switch (refKind) {
611+
case TypeMetadataRecordKind::IndirectNominalTypeDescriptor: {
612+
StoredPointer descriptorAddress = 0;
613+
if (!Reader->readInteger(RemoteAddress(ref), &descriptorAddress))
614+
return llvm::None;
615+
616+
ref = descriptorAddress;
617+
LLVM_FALLTHROUGH;
618+
}
619+
620+
case TypeMetadataRecordKind::DirectNominalTypeDescriptor: {
621+
auto descriptor = readContextDescriptor(ref);
622+
if (!descriptor)
623+
return llvm::None;
624+
625+
return descriptorFn(descriptor);
626+
}
627+
628+
case TypeMetadataRecordKind::IndirectObjCClass: {
629+
StoredPointer classRef = 0;
630+
if (!Reader->readInteger(RemoteAddress(ref), &classRef))
631+
return llvm::None;
632+
633+
auto metadata = readMetadata(classRef);
634+
if (!metadata)
635+
return llvm::None;
636+
637+
return metadataFn(metadata);
638+
}
639+
640+
default:
641+
return llvm::None;
642+
}
643+
}
644+
583645
/// Read a single generic type argument from a bound generic type
584646
/// metadata.
585647
llvm::Optional<StoredPointer>
@@ -921,7 +983,7 @@ class MetadataReader {
921983
if (descriptorAddress || !skipArtificialSubclasses)
922984
return static_cast<StoredPointer>(descriptorAddress);
923985

924-
auto superclassMetadataAddress = classMeta->SuperClass;
986+
auto superclassMetadataAddress = classMeta->Superclass;
925987
if (!superclassMetadataAddress)
926988
return 0;
927989

0 commit comments

Comments
 (0)