Fix Building For i386/Non-OBJC2

This commit is contained in:
Thomas A 2022-04-29 10:13:27 -07:00
parent 09e9e2f56c
commit 5a22f74c04
6 changed files with 106 additions and 17 deletions

View File

@ -46,6 +46,14 @@ extern "C" {
#include <os/variant_private.h>
}
#ifdef DARLING
#if __OBJC2__
#define DARLING_GET_SUPER_CLASS getSuperclass()
#else
#define DARLING_GET_SUPER_CLASS superclass
#endif
#endif
@interface NSInvocation
- (SEL)selector;
@end
@ -572,7 +580,11 @@ objc_loadWeakRetained(id *location)
// callout with the lock held.
if (cls->isInitialized() || _thisThreadIsInitializingClass(cls)) {
BOOL (*tryRetain)(id, SEL) = (BOOL(*)(id, SEL))
#if defined(DARLING) && defined(__i386__)
class_getMethodImplementation(cls, @selector(retainWeakReference));
#else
lookUpImpOrForwardTryCache(obj, @selector(retainWeakReference), cls);
#endif
if ((IMP)tryRetain == _objc_msgForward) {
result = nil;
}
@ -2013,7 +2025,7 @@ objc_opt_isKindOfClass(id obj, Class otherClass)
if (slowpath(!obj)) return NO;
Class cls = obj->getIsa();
if (fastpath(!cls->hasCustomCore())) {
for (Class tcls = cls; tcls; tcls = tcls->getSuperclass()) {
for (Class tcls = cls; tcls; tcls = tcls->DARLING_GET_SUPER_CLASS) {
if (tcls == otherClass) return YES;
}
return NO;
@ -2266,11 +2278,11 @@ NONLAZY_CLASS_LOAD
}
+ (Class)superclass {
return self->getSuperclass();
return self->DARLING_GET_SUPER_CLASS;
}
- (Class)superclass {
return [self class]->getSuperclass();
return [self class]->DARLING_GET_SUPER_CLASS;
}
+ (BOOL)isMemberOfClass:(Class)cls {
@ -2282,28 +2294,28 @@ NONLAZY_CLASS_LOAD
}
+ (BOOL)isKindOfClass:(Class)cls {
for (Class tcls = self->ISA(); tcls; tcls = tcls->getSuperclass()) {
for (Class tcls = self->ISA(); tcls; tcls = tcls->DARLING_GET_SUPER_CLASS) {
if (tcls == cls) return YES;
}
return NO;
}
- (BOOL)isKindOfClass:(Class)cls {
for (Class tcls = [self class]; tcls; tcls = tcls->getSuperclass()) {
for (Class tcls = [self class]; tcls; tcls = tcls->DARLING_GET_SUPER_CLASS) {
if (tcls == cls) return YES;
}
return NO;
}
+ (BOOL)isSubclassOfClass:(Class)cls {
for (Class tcls = self; tcls; tcls = tcls->getSuperclass()) {
for (Class tcls = self; tcls; tcls = tcls->DARLING_GET_SUPER_CLASS) {
if (tcls == cls) return YES;
}
return NO;
}
+ (BOOL)isAncestorOfObject:(NSObject *)obj {
for (Class tcls = [obj class]; tcls; tcls = tcls->getSuperclass()) {
for (Class tcls = [obj class]; tcls; tcls = tcls->DARLING_GET_SUPER_CLASS) {
if (tcls == self) return YES;
}
return NO;
@ -2323,7 +2335,7 @@ NONLAZY_CLASS_LOAD
+ (BOOL)conformsToProtocol:(Protocol *)protocol {
if (!protocol) return NO;
for (Class tcls = self; tcls; tcls = tcls->getSuperclass()) {
for (Class tcls = self; tcls; tcls = tcls->DARLING_GET_SUPER_CLASS) {
if (class_conformsToProtocol(tcls, protocol)) return YES;
}
return NO;
@ -2331,7 +2343,7 @@ NONLAZY_CLASS_LOAD
- (BOOL)conformsToProtocol:(Protocol *)protocol {
if (!protocol) return NO;
for (Class tcls = [self class]; tcls; tcls = tcls->getSuperclass()) {
for (Class tcls = [self class]; tcls; tcls = tcls->DARLING_GET_SUPER_CLASS) {
if (class_conformsToProtocol(tcls, protocol)) return YES;
}
return NO;

View File

@ -336,7 +336,11 @@ static void _class_resolveClassMethod(id inst, SEL sel, Class cls)
ASSERT(cls->isMetaClass());
SEL resolve_sel = @selector(resolveClassMethod:);
#if defined(DARLING) && defined(__i386__)
if (!lookUpImpOrNil(inst, resolve_sel, cls)) {
#else
if (!lookUpImpOrNilTryCache(inst, resolve_sel, cls)) {
#endif
// Resolver not implemented.
return;
}
@ -346,7 +350,11 @@ static void _class_resolveClassMethod(id inst, SEL sel, Class cls)
// Cache the result (good or bad) so the resolver doesn't fire next time.
// +resolveClassMethod adds to self->ISA() a.k.a. cls
#if defined(DARLING) && defined(__i386__)
IMP imp = lookUpImpOrNil(inst, sel, cls);
#else
IMP imp = lookUpImpOrNilTryCache(inst, sel, cls);
#endif
if (resolved && PrintResolving) {
if (imp) {
_objc_inform("RESOLVE: method %c[%s %s] "
@ -376,7 +384,11 @@ static void _class_resolveInstanceMethod(id inst, SEL sel, Class cls)
{
SEL resolve_sel = @selector(resolveInstanceMethod:);
#if defined(DARLING) && defined(__i386__)
if (! lookUpImpOrNil(cls, resolve_sel, cls->ISA())) {
#else
if (! lookUpImpOrNilTryCache(cls, resolve_sel, cls->ISA())) {
#endif
// Resolver not implemented.
return;
}
@ -386,7 +398,11 @@ static void _class_resolveInstanceMethod(id inst, SEL sel, Class cls)
// Cache the result (good or bad) so the resolver doesn't fire next time.
// +resolveInstanceMethod adds to self a.k.a. cls
#if defined(DARLING) && defined(__i386__)
IMP imp = lookUpImpOrNil(inst, sel, cls);
#else
IMP imp = lookUpImpOrNilTryCache(inst, sel, cls);
#endif
if (resolved && PrintResolving) {
if (imp) {
@ -424,7 +440,11 @@ _class_resolveMethod(id inst, SEL sel, Class cls)
// try [nonMetaClass resolveClassMethod:sel]
// and [cls resolveInstanceMethod:sel]
_class_resolveClassMethod(inst, sel, cls);
#if defined(DARLING) && defined(__i386__)
if (!lookUpImpOrNil(inst, sel, cls)) {
#else
if (!lookUpImpOrNilTryCache(inst, sel, cls)) {
#endif
_class_resolveInstanceMethod(inst, sel, cls);
}
}
@ -475,7 +495,11 @@ IMP lookUpImpOrForward(id inst, SEL sel, Class cls, int behavior)
methodListLock.assertUnlocked();
// Optimistic cache lookup
#ifdef DARLING
if ((behavior & LOOKUP_NOCACHE) == 0) {
#else
if (behavior & LOOKUP_CACHE) {
#endif
methodPC = _cache_getImp(cls, sel);
if (methodPC) goto out_nolock;
}
@ -2442,7 +2466,11 @@ void *objc_destructInstance(id obj)
}
if (isa->instancesHaveAssociatedObjects()) {
#ifdef DARLING
_object_remove_assocations(obj,false);
#else
_object_remove_assocations(obj);
#endif
}
objc_clear_deallocating(obj);

View File

@ -163,6 +163,14 @@
#include <os/linker_set.h>
#endif
#ifdef DARLING
#if __OBJC2__
#define DARLING_GET_SUPER_CLASS getSuperclass()
#else
#define DARLING_GET_SUPER_CLASS superclass
#endif
#endif
/***********************************************************************
* Information about multi-thread support:
*
@ -200,7 +208,11 @@ Class object_setClass(id obj, Class cls)
if (!cls->isFuture() && !cls->isInitialized()) {
// use lookUpImpOrNilTryCache to indirectly provoke +initialize
// to avoid duplicating the code to actually send +initialize
#if defined(DARLING) && defined(__i386__)
lookUpImpOrNil(nil, @selector(initialize), cls, LOOKUP_INITIALIZE);
#else
lookUpImpOrNilTryCache(nil, @selector(initialize), cls, LOOKUP_INITIALIZE);
#endif
}
return obj->changeIsa(cls);
@ -284,7 +296,7 @@ _class_lookUpIvar(Class cls, Ivar ivar, ptrdiff_t& ivarOffset,
// Preflight the hasAutomaticIvars check
// because _class_getClassForIvar() may need to take locks.
bool hasAutomaticIvars = NO;
for (Class c = cls; c; c = c->getSuperclass()) {
for (Class c = cls; c; c = c->DARLING_GET_SUPER_CLASS) {
if (c->hasAutomaticIvars()) {
hasAutomaticIvars = YES;
break;
@ -443,7 +455,7 @@ static void object_cxxDestructFromClass(id obj, Class cls)
// Call cls's dtor first, then superclasses's dtors.
for ( ; cls; cls = cls->getSuperclass()) {
for ( ; cls; cls = cls->DARLING_GET_SUPER_CLASS) {
if (!cls->hasCxxDtor()) return;
dtor = (void(*)(id))
lookupMethodInClassAndLoadCache(cls, SEL_cxx_destruct);
@ -493,7 +505,7 @@ object_cxxConstructFromClass(id obj, Class cls, int flags)
id (*ctor)(id);
Class supercls;
supercls = cls->getSuperclass();
supercls = cls->DARLING_GET_SUPER_CLASS;
// Call superclasses' ctors first, if any.
if (supercls && supercls->hasCxxCtor()) {
@ -512,7 +524,7 @@ object_cxxConstructFromClass(id obj, Class cls, int flags)
}
if (fastpath((*ctor)(obj))) return obj; // ctor called and succeeded - ok
supercls = cls->getSuperclass(); // this reload avoids a spill on the stack
supercls = cls->DARLING_GET_SUPER_CLASS; // this reload avoids a spill on the stack
// This class's ctor was called and failed.
// Call superclasses's dtors to clean up.
@ -532,7 +544,7 @@ object_cxxConstructFromClass(id obj, Class cls, int flags)
**********************************************************************/
void fixupCopiedIvars(id newObject, id oldObject)
{
for (Class cls = oldObject->ISA(); cls; cls = cls->getSuperclass()) {
for (Class cls = oldObject->ISA(); cls; cls = cls->DARLING_GET_SUPER_CLASS) {
if (cls->hasAutomaticIvars()) {
// Use alignedInstanceStart() because unaligned bytes at the start
// of this class's ivars are not represented in the layout bitmap.
@ -643,7 +655,11 @@ class_respondsToSelector_inst(id inst, SEL sel, Class cls)
{
// Avoids +initialize because it historically did so.
// We're not returning a callable IMP anyway.
#if defined(DARLING) && defined(__i386__)
return sel && cls && lookUpImpOrNil(inst, sel, cls, LOOKUP_RESOLVER);
#else
return sel && cls && lookUpImpOrNilTryCache(inst, sel, cls, LOOKUP_RESOLVER);
#endif
}
@ -673,7 +689,11 @@ IMP class_getMethodImplementation(Class cls, SEL sel)
lockdebug_assert_no_locks_locked_except({ &loadMethodLock });
#if defined(DARLING) && defined(__i386__)
imp = lookUpImpOrNil(nil, sel, cls, LOOKUP_INITIALIZE | LOOKUP_RESOLVER);
#else
imp = lookUpImpOrNilTryCache(nil, sel, cls, LOOKUP_INITIALIZE | LOOKUP_RESOLVER);
#endif
// Translate forwarding function to C-callable external version
if (!imp) {
@ -780,7 +800,7 @@ Class _calloc_class(size_t size)
Class class_getSuperclass(Class cls)
{
if (!cls) return nil;
return cls->getSuperclass();
return cls->DARLING_GET_SUPER_CLASS;
}
BOOL class_isMetaClass(Class cls)

View File

@ -97,6 +97,15 @@
#include "objc-initialize.h"
#include "DenseMapExtras.h"
#ifdef DARLING
#if __OBJC2__
#define DARLING_GET_SUPER_CLASS getSuperclass()
#else
#define DARLING_GET_SUPER_CLASS superclass
#endif
#endif
/* classInitLock protects CLS_INITIALIZED and CLS_INITIALIZING, and
* is signalled when any class is done initializing.
* Threads that are waiting for a class to finish initializing wait on this. */
@ -396,10 +405,15 @@ static bool classHasTrivialInitialize(Class cls)
{
if (cls->isRootClass() || cls->isRootMetaclass()) return true;
Class rootCls = cls->ISA()->ISA()->getSuperclass();
Class rootCls = cls->ISA()->ISA()->DARLING_GET_SUPER_CLASS;
#if defined(DARLING) && defined(__i386__)
IMP rootImp = lookUpImpOrNil(rootCls, @selector(initialize), rootCls->ISA());
IMP imp = lookUpImpOrNil(cls, @selector(initialize), cls->ISA());
#else
IMP rootImp = lookUpImpOrNilTryCache(rootCls, @selector(initialize), rootCls->ISA());
IMP imp = lookUpImpOrNilTryCache(cls, @selector(initialize), cls->ISA());
#endif
return (imp == nil || imp == (IMP)&objc_noop_imp || imp == rootImp);
}
@ -500,7 +514,7 @@ void initializeNonMetaClass(Class cls)
// Make sure super is done initializing BEFORE beginning to initialize cls.
// See note about deadlock above.
supercls = cls->getSuperclass();
supercls = cls->DARLING_GET_SUPER_CLASS;
if (supercls && !supercls->isInitialized()) {
initializeNonMetaClass(supercls);
}

View File

@ -609,6 +609,14 @@ extern IMP lookUpImpOrForward(id obj, SEL, Class cls, int behavior);
extern IMP lookUpImpOrForwardTryCache(id obj, SEL, Class cls, int behavior = 0);
extern IMP lookUpImpOrNilTryCache(id obj, SEL, Class cls, int behavior = 0);
#ifdef DARLING
static inline IMP
lookUpImpOrNil(id obj, SEL sel, Class cls, int behavior = 0)
{
return lookUpImpOrForward(obj, sel, cls, behavior | LOOKUP_NIL);
}
#endif
extern IMP lookupMethodInClassAndLoadCache(Class cls, SEL sel);
struct IMPAndSEL {

View File

@ -407,9 +407,16 @@ weak_register_no_lock(weak_table_t *weak_table, id referent_id,
// Use lookUpImpOrForward so we can avoid the assert in
// class_getInstanceMethod, since we intentionally make this
// callout with the lock held.
#if defined(DARLING) && defined(__i386__)
BOOL (*allowsWeakReference)(objc_object *, SEL) =
(BOOL(*)(objc_object *, SEL))
object_getMethodImplementation((id)referent,
@selector(allowsWeakReference));
#else
auto allowsWeakReference = (BOOL(*)(objc_object *, SEL))
lookUpImpOrForwardTryCache((id)referent, @selector(allowsWeakReference),
referent->getIsa());
#endif
if ((IMP)allowsWeakReference == _objc_msgForward) {
return nil;
}