Skip to content

Commit a7c5c80

Browse files
committed
Compute class metadata bounds solely from class-descriptor chain information.
Change the "metadata base offset" variable into a "class metadata bounds" variable that contains the base offset and the +/- bounds on the class. Link this variable from the class descriptor when the class has a resilient superclass; otherwise, store the +/- bounds there. Use this variable to compute the immediate-members offset for various runtime queries. Teach the runtime to fill it in lazily and remove the code to compute it from the generated code for instantiation. Identify generic arguments with the start of the immediate class metadata members / end of the {struct,enum} metadata header and remove the generic-arguments offset from generic type descriptors.
1 parent e9e71f8 commit a7c5c80

18 files changed

+578
-410
lines changed

include/swift/Remote/MetadataReader.h

+78-16
Original file line numberDiff line numberDiff line change
@@ -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>

0 commit comments

Comments
 (0)