mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Only use metadata patterns for generic types; perform other
initialization in-place on demand. Initialize parent metadata references correctly on struct and enum metadata. Also includes several minor improvements related to relative pointers that I was using before deciding to simply switch the parent reference to an absolute reference to get better access patterns.
This commit is contained in:
@@ -243,28 +243,11 @@ swift::swift_allocateGenericValueMetadata(GenericMetadata *pattern,
|
||||
pattern->AddressPoint;
|
||||
auto patternMetadata = reinterpret_cast<const ValueMetadata*>(patternBytes);
|
||||
metadata->Description = patternMetadata->Description.get();
|
||||
metadata->Parent = patternMetadata->Parent.get();
|
||||
metadata->Parent = patternMetadata->Parent;
|
||||
|
||||
return metadata;
|
||||
}
|
||||
|
||||
/// Entrypoint for non-generic types with resilient layout.
|
||||
const Metadata *
|
||||
swift::swift_getResilientMetadata(GenericMetadata *pattern) {
|
||||
assert(pattern->NumKeyArguments == 0);
|
||||
|
||||
auto entry = getCache(pattern).findOrAdd(nullptr, 0,
|
||||
[&]() -> GenericCacheEntry* {
|
||||
// Create new metadata to cache.
|
||||
auto metadata = pattern->CreateFunction(pattern, nullptr);
|
||||
auto entry = GenericCacheEntry::getFromMetadata(pattern, metadata);
|
||||
entry->Value = metadata;
|
||||
return entry;
|
||||
});
|
||||
|
||||
return entry->Value;
|
||||
}
|
||||
|
||||
/// The primary entrypoint.
|
||||
SWIFT_RT_ENTRY_VISIBILITY
|
||||
const Metadata *
|
||||
@@ -1473,8 +1456,13 @@ static void _swift_initGenericClassObjCName(ClassMetadata *theClass) {
|
||||
}
|
||||
#endif
|
||||
|
||||
static void _swift_initializeSuperclass(ClassMetadata *theClass,
|
||||
bool copyFieldOffsetVectors) {
|
||||
/// Initialize the invariant superclass components of a class metadata,
|
||||
/// such as the generic type arguments, field offsets, and so on.
|
||||
///
|
||||
/// This may also relocate the metadata object if it wasn't allocated
|
||||
/// with enough space.
|
||||
static ClassMetadata *_swift_initializeSuperclass(ClassMetadata *theClass,
|
||||
bool copyFieldOffsetVectors) {
|
||||
#if SWIFT_OBJC_INTEROP
|
||||
// If the class is generic, we need to give it a name for Objective-C.
|
||||
if (theClass->getDescription()->GenericParams.isGeneric())
|
||||
@@ -1483,7 +1471,43 @@ static void _swift_initializeSuperclass(ClassMetadata *theClass,
|
||||
|
||||
const ClassMetadata *theSuperclass = theClass->SuperClass;
|
||||
if (theSuperclass == nullptr)
|
||||
return;
|
||||
return theClass;
|
||||
|
||||
// Relocate the metadata if necessary.
|
||||
//
|
||||
// For now, we assume that relocation is only required when the parent
|
||||
// class has prefix matter we didn't know about. This isn't consistent
|
||||
// with general class resilience, however.
|
||||
if (theSuperclass->isTypeMetadata()) {
|
||||
auto superAP = theSuperclass->getClassAddressPoint();
|
||||
auto oldClassAP = theClass->getClassAddressPoint();
|
||||
if (superAP > oldClassAP) {
|
||||
size_t extraPrefixSize = superAP - oldClassAP;
|
||||
size_t oldClassSize = theClass->getClassSize();
|
||||
|
||||
// Allocate a new metadata object.
|
||||
auto rawNewClass = (char*) malloc(extraPrefixSize + oldClassSize);
|
||||
auto rawOldClass = (const char*) theClass;
|
||||
auto rawSuperclass = (const char*) theSuperclass;
|
||||
|
||||
// Copy the extra prefix from the superclass.
|
||||
memcpy((void**) (rawNewClass),
|
||||
(void* const *) (rawSuperclass - superAP),
|
||||
extraPrefixSize);
|
||||
// Copy the rest of the data from the derived class.
|
||||
memcpy((void**) (rawNewClass + extraPrefixSize),
|
||||
(void* const *) (rawOldClass - oldClassAP),
|
||||
oldClassSize);
|
||||
|
||||
// Update the class extents on the new metadata object.
|
||||
theClass = reinterpret_cast<ClassMetadata*>(rawNewClass + oldClassAP);
|
||||
theClass->setClassAddressPoint(superAP);
|
||||
theClass->setClassSize(extraPrefixSize + oldClassSize);
|
||||
|
||||
// The previous metadata should be global data, so we have no real
|
||||
// choice but to drop it on the floor.
|
||||
}
|
||||
}
|
||||
|
||||
// If any ancestor classes have generic parameters or field offset
|
||||
// vectors, inherit them.
|
||||
@@ -1528,15 +1552,24 @@ static void _swift_initializeSuperclass(ClassMetadata *theClass,
|
||||
= (const ClassMetadata *)object_getClass((id)theSuperclass);
|
||||
theMetaclass->SuperClass = theSuperMetaclass;
|
||||
#endif
|
||||
|
||||
return theClass;
|
||||
}
|
||||
|
||||
static MetadataAllocator &getResilientMetadataAllocator() {
|
||||
// This should be constant-initialized, but this is safe.
|
||||
static MetadataAllocator allocator;
|
||||
return allocator;
|
||||
}
|
||||
|
||||
/// Initialize the field offset vector for a dependent-layout class, using the
|
||||
/// "Universal" layout strategy.
|
||||
void swift::swift_initClassMetadata_UniversalStrategy(ClassMetadata *self,
|
||||
size_t numFields,
|
||||
const ClassFieldLayout *fieldLayouts,
|
||||
size_t *fieldOffsets) {
|
||||
_swift_initializeSuperclass(self, /*copyFieldOffsetVectors=*/true);
|
||||
ClassMetadata *
|
||||
swift::swift_initClassMetadata_UniversalStrategy(ClassMetadata *self,
|
||||
size_t numFields,
|
||||
const ClassFieldLayout *fieldLayouts,
|
||||
size_t *fieldOffsets) {
|
||||
self = _swift_initializeSuperclass(self, /*copyFieldOffsetVectors=*/true);
|
||||
|
||||
// Start layout by appending to a standard heap object header.
|
||||
size_t size, alignMask;
|
||||
@@ -1625,9 +1658,10 @@ void swift::swift_initClassMetadata_UniversalStrategy(ClassMetadata *self,
|
||||
// even if Swift doesn't, because of SwiftObject.)
|
||||
rodata->InstanceStart = size;
|
||||
|
||||
auto &allocator = unsafeGetInitializedCache(
|
||||
self->getDescription()->getGenericMetadataPattern())
|
||||
.getAllocator();
|
||||
auto genericPattern = self->getDescription()->getGenericMetadataPattern();
|
||||
auto &allocator =
|
||||
genericPattern ? unsafeGetInitializedCache(genericPattern).getAllocator()
|
||||
: getResilientMetadataAllocator();
|
||||
|
||||
// Always clone the ivar descriptors.
|
||||
if (numFields) {
|
||||
@@ -1703,6 +1737,8 @@ void swift::swift_initClassMetadata_UniversalStrategy(ClassMetadata *self,
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/// \brief Fetch the type metadata associated with the formal dynamic
|
||||
@@ -2460,19 +2496,6 @@ void _swift_debug_verifyTypeLayoutAttribute(Metadata *type,
|
||||
}
|
||||
#endif
|
||||
|
||||
SWIFT_RUNTIME_EXPORT
|
||||
extern "C"
|
||||
void swift_initializeSuperclass(ClassMetadata *theClass,
|
||||
bool copyFieldOffsetVectors) {
|
||||
// Copy generic parameters and field offset vectors from the superclass.
|
||||
_swift_initializeSuperclass(theClass, copyFieldOffsetVectors);
|
||||
|
||||
#if SWIFT_OBJC_INTEROP
|
||||
// Register the class pair with the ObjC runtime.
|
||||
swift_instantiateObjCClass(theClass);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*** Protocol witness tables *************************************************/
|
||||
|
||||
namespace {
|
||||
|
||||
Reference in New Issue
Block a user