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:
John McCall
2016-03-23 16:56:29 -07:00
parent 898e0971d9
commit 41efb3d4d3
34 changed files with 1529 additions and 619 deletions

View File

@@ -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 {