Runtime: Flesh out swift_updateClassMetadata() to use _objc_realizeClassFromSwift()

This commit is contained in:
Slava Pestov
2018-10-18 16:21:42 -07:00
parent 4cecc268dc
commit 9024768b0e

View File

@@ -43,6 +43,7 @@
#else #else
#include <sys/mman.h> #include <sys/mman.h>
#include <unistd.h> #include <unistd.h>
#include <dlfcn.h>
#endif #endif
#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Hashing.h" #include "llvm/ADT/Hashing.h"
@@ -2610,16 +2611,41 @@ swift::swift_initClassMetadata(ClassMetadata *self,
} }
#if SWIFT_OBJC_INTEROP #if SWIFT_OBJC_INTEROP
// Suppress diagnostic about the availability of _objc_realizeClassFromSwift.
// We test availability with a nullptr check, but the compiler doesn't see that.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
void void
swift::swift_updateClassMetadata(ClassMetadata *self, swift::swift_updateClassMetadata(ClassMetadata *self,
ClassLayoutFlags layoutFlags, ClassLayoutFlags layoutFlags,
size_t numFields, size_t numFields,
const TypeLayout * const *fieldTypes, const TypeLayout * const *fieldTypes,
size_t *fieldOffsets) { size_t *fieldOffsets) {
#ifndef NDEBUG #ifndef OBJC_REALIZECLASSFROMSWIFT_DEFINED
// If there is a mangled superclass name, demangle it to the superclass // Temporary workaround until _objc_realizeClassFromSwift is in the SDK.
// type. static auto _objc_realizeClassFromSwift =
(Class (*)(Class _Nullable, void* _Nullable))
dlsym(RTLD_NEXT, "_objc_realizeClassFromSwift");
#endif
bool requiresUpdate = (_objc_realizeClassFromSwift != nullptr);
// If we're on a newer runtime, we're going to be initializing the
// field offset vector. Realize the superclass metadata first, even
// though our superclass field references it statically.
const ClassMetadata *super = nullptr; const ClassMetadata *super = nullptr;
// In assert builds, realize the superclass metadata even if we're
// on an older runtime.
#ifndef NDEBUG
bool realizeSuperclass = true;
#else
bool realizeSuperclass = requiresUpdate;
#endif
if (realizeSuperclass) {
if (auto superclassNameBase = self->getDescription()->SuperclassType.get()) { if (auto superclassNameBase = self->getDescription()->SuperclassType.get()) {
StringRef superclassName = StringRef superclassName =
Demangle::makeSymbolicMangledNameStringRef(superclassNameBase); Demangle::makeSymbolicMangledNameStringRef(superclassNameBase);
@@ -2633,35 +2659,48 @@ swift::swift_updateClassMetadata(ClassMetadata *self,
superclassName.str().c_str()); superclassName.str().c_str());
} }
#if SWIFT_OBJC_INTEROP
if (auto objcWrapper = dyn_cast<ObjCClassWrapperMetadata>(superclass)) if (auto objcWrapper = dyn_cast<ObjCClassWrapperMetadata>(superclass))
superclass = objcWrapper->Class; superclass = objcWrapper->Class;
#endif
super = cast<ClassMetadata>(superclass); super = cast<ClassMetadata>(superclass);
} }
// Check that it matches what's already in there.
if (!super) if (!super)
assert(self->Superclass == getRootSuperclass()); assert(self->Superclass == getRootSuperclass());
else else
assert(self->Superclass == super); assert(self->Superclass == super);
#endif }
// FIXME: Plumb this through (void) super;
#if 1
// If we're running on a older Objective-C runtime, just realize
// the class.
if (!requiresUpdate) {
// Realize the class. This causes the runtime to slide the field offsets
// stored in the field offset globals.
//
// Note that the field offset vector is *not* updated; however in
// Objective-C interop mode, we don't actually use the field offset vector
// of non-generic classes.
//
// In particular, class mirrors always use the Objective-C ivar descriptors,
// which point at field offset globals and not the field offset vector.
swift_getInitializedObjCClass((Class)self); swift_getInitializedObjCClass((Class)self);
#else } else {
// Update the field offset vector using runtime type information; the layout
// of resilient types might be different than the statically-emitted layout.
initClassFieldOffsetVector(self, numFields, fieldTypes, fieldOffsets); initClassFieldOffsetVector(self, numFields, fieldTypes, fieldOffsets);
// Copy field offset vector entries to the field offset globals.
initObjCClass(self, numFields, fieldTypes, fieldOffsets); initObjCClass(self, numFields, fieldTypes, fieldOffsets);
// Register this class with the runtime. This will also cause the // See remark above about how this slides field offset globals.
// runtime to slide the field offsets stored in the field offset _objc_realizeClassFromSwift((Class)self, (Class)self);
// globals. Note that the field offset vector is *not* updated; }
// however we should not be using it for anything in a non-generic
// class.
swift_getInitializedObjCClassWithoutCallback(self);
#endif
} }
#pragma clang diagnostic pop
#endif #endif
#ifndef NDEBUG #ifndef NDEBUG