mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Runtime: Flesh out swift_updateClassMetadata() to use _objc_realizeClassFromSwift()
This commit is contained in:
@@ -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,58 +2611,96 @@ 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;
|
||||||
if (auto superclassNameBase = self->getDescription()->SuperclassType.get()) {
|
|
||||||
StringRef superclassName =
|
// In assert builds, realize the superclass metadata even if we're
|
||||||
Demangle::makeSymbolicMangledNameStringRef(superclassNameBase);
|
// on an older runtime.
|
||||||
SubstGenericParametersFromMetadata substitutions(self);
|
#ifndef NDEBUG
|
||||||
const Metadata *superclass =
|
bool realizeSuperclass = true;
|
||||||
_getTypeByMangledName(superclassName, substitutions);
|
#else
|
||||||
if (!superclass) {
|
bool realizeSuperclass = requiresUpdate;
|
||||||
fatalError(0,
|
#endif
|
||||||
"failed to demangle superclass of %s from mangled name '%s'\n",
|
|
||||||
self->getDescription()->Name.get(),
|
if (realizeSuperclass) {
|
||||||
superclassName.str().c_str());
|
if (auto superclassNameBase = self->getDescription()->SuperclassType.get()) {
|
||||||
|
StringRef superclassName =
|
||||||
|
Demangle::makeSymbolicMangledNameStringRef(superclassNameBase);
|
||||||
|
SubstGenericParametersFromMetadata substitutions(self);
|
||||||
|
const Metadata *superclass =
|
||||||
|
_getTypeByMangledName(superclassName, substitutions);
|
||||||
|
if (!superclass) {
|
||||||
|
fatalError(0,
|
||||||
|
"failed to demangle superclass of %s from mangled name '%s'\n",
|
||||||
|
self->getDescription()->Name.get(),
|
||||||
|
superclassName.str().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto objcWrapper = dyn_cast<ObjCClassWrapperMetadata>(superclass))
|
||||||
|
superclass = objcWrapper->Class;
|
||||||
|
|
||||||
|
super = cast<ClassMetadata>(superclass);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SWIFT_OBJC_INTEROP
|
// Check that it matches what's already in there.
|
||||||
if (auto objcWrapper = dyn_cast<ObjCClassWrapperMetadata>(superclass))
|
if (!super)
|
||||||
superclass = objcWrapper->Class;
|
assert(self->Superclass == getRootSuperclass());
|
||||||
#endif
|
else
|
||||||
|
assert(self->Superclass == super);
|
||||||
super = cast<ClassMetadata>(superclass);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!super)
|
(void) super;
|
||||||
assert(self->Superclass == getRootSuperclass());
|
|
||||||
else
|
|
||||||
assert(self->Superclass == super);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// FIXME: Plumb this through
|
// If we're running on a older Objective-C runtime, just realize
|
||||||
#if 1
|
// the class.
|
||||||
swift_getInitializedObjCClass((Class)self);
|
if (!requiresUpdate) {
|
||||||
#else
|
// Realize the class. This causes the runtime to slide the field offsets
|
||||||
initClassFieldOffsetVector(self, numFields, fieldTypes, fieldOffsets);
|
// stored in the field offset globals.
|
||||||
initObjCClass(self, numFields, fieldTypes, fieldOffsets);
|
//
|
||||||
|
// 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);
|
||||||
|
} 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);
|
||||||
|
|
||||||
// Register this class with the runtime. This will also cause the
|
// Copy field offset vector entries to the field offset globals.
|
||||||
// runtime to slide the field offsets stored in the field offset
|
initObjCClass(self, numFields, fieldTypes, fieldOffsets);
|
||||||
// globals. Note that the field offset vector is *not* updated;
|
|
||||||
// however we should not be using it for anything in a non-generic
|
// See remark above about how this slides field offset globals.
|
||||||
// class.
|
_objc_realizeClassFromSwift((Class)self, (Class)self);
|
||||||
swift_getInitializedObjCClassWithoutCallback(self);
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma clang diagnostic pop
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
|
|||||||
Reference in New Issue
Block a user