Index: src/OFObject.m ================================================================== --- src/OFObject.m +++ src/OFObject.m @@ -61,21 +61,14 @@ # import "threading.h" #endif #if defined(OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR) extern id of_forward(id, SEL, ...); -# ifdef OF_APPLE_RUNTIME -/* - * Forwarding for methods returning structs only works with the Apple ABI, as - * with the GNU ABI, there is no way of knowing if a struct is returned and if - * so how. - * As forwardingTargetForSelector: only works for architectures for which - * assembly has been written anyway, it makes sense to switch to - * objc_msgSend(_{st,fp}ret) for those architectures to solve this problem. - */ extern struct stret of_forward_stret(id, SEL, ...); -# endif +#else +# define of_forward NULL +# define of_forward_stret NULL #endif struct pre_ivar { int32_t retainCount; struct pre_mem *firstMem, *lastMem; @@ -144,11 +137,11 @@ abort(); } #ifdef OF_OBJFW_RUNTIME static IMP -forward_handler(id obj, SEL sel) +common_forward_handler(id obj, SEL sel, IMP (*lookup)(id, SEL), IMP forward) { /* Try resolveClassMethod:/resolveInstanceMethod: */ if (class_isMetaClass(object_getClass(obj))) { if ([obj respondsToSelector: @selector(resolveClassMethod:)] && [obj resolveClassMethod: sel]) { @@ -158,11 +151,11 @@ "without adding the method!\n", class_getName(obj), sel_getName(sel)); abort(); } - return objc_msg_lookup(obj, sel); + return lookup(obj, sel); } } else { Class c = object_getClass(obj); if ([c respondsToSelector: @selector(resolveInstanceMethod:)] && @@ -174,27 +167,41 @@ class_getName(object_getClass(obj)), sel_getName(sel)); abort(); } - return objc_msg_lookup(obj, sel); + return lookup(obj, sel); } } #ifdef OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR if (class_respondsToSelector(object_getClass(obj), @selector(forwardingTargetForSelector:))) { id target = [obj forwardingTargetForSelector: sel]; if (target != nil && target != obj) - return (IMP)of_forward; + return forward; } #endif of_method_not_found(obj, sel); return NULL; } + +static IMP +forward_handler(id obj, SEL sel) +{ + return common_forward_handler(obj, sel, + objc_msg_lookup, (IMP)of_forward); +} + +static IMP +forward_handler_stret(id obj, SEL sel) +{ + return common_forward_handler(obj, sel, + objc_msg_lookup_stret, (IMP)of_forward_stret); +} #endif #ifndef HAVE_OBJC_ENUMERATIONMUTATION void objc_enumerationMutation(id object) @@ -273,11 +280,12 @@ objc_setUncaughtExceptionHandler(uncaught_exception_handler); #endif #if defined(OF_OBJFW_RUNTIME) objc_forward_handler = forward_handler; -#elif defined(OF_APPLE_RUNTIME) && !defined(__ppc64__) + objc_forward_handler_stret = forward_handler_stret; +#elif defined(OF_APPLE_RUNTIME) && defined(HAVE_FORWARDING_TARGET_FOR_SELECTOR) objc_setForwardHandler(of_forward, of_forward_stret); #endif #ifdef HAVE_OBJC_ENUMERATIONMUTATION objc_setEnumerationMutationHandler(enumeration_mutation_handler); Index: src/forwarding-amd64-elf.S ================================================================== --- src/forwarding-amd64-elf.S +++ src/forwarding-amd64-elf.S @@ -13,13 +13,15 @@ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ .globl of_forward +.globl of_forward_stret .section .text of_forward: +of_forward_stret: /* FIXME */ pushq %rbp movq %rsp, %rbp /* Save all arguments */ subq $0xC0, %rsp /* 16-byte alignment */ Index: src/forwarding-arm-elf.S ================================================================== --- src/forwarding-arm-elf.S +++ src/forwarding-arm-elf.S @@ -13,13 +13,15 @@ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ .globl of_forward +.globl of_forward_stret .section .text of_forward: +of_forward_stret: /* FIXME */ stmfd sp!, {r0-r3, lr} fstmfdd sp!, {d0-d7} ldr r1, sel_forwardingTargetForSelector__indirect_L0 .L0: Index: src/forwarding-mips-elf.S ================================================================== --- src/forwarding-mips-elf.S +++ src/forwarding-mips-elf.S @@ -13,13 +13,15 @@ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ .globl of_forward +.globl of_forward_stret .section .text of_forward: +of_forward_stret: /* FIXME */ #ifdef __PIC__ lui $gp, %hi(_gp_disp) addiu $gp, $gp, %lo(_gp_disp) addu $gp, $gp, $t9 #endif Index: src/forwarding-x86-elf.S ================================================================== --- src/forwarding-x86-elf.S +++ src/forwarding-x86-elf.S @@ -13,13 +13,15 @@ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ .globl of_forward +.globl of_forward_stret .section .text of_forward: +of_forward_stret: /* FIXME */ pushl %ebp movl %esp, %ebp pushl %ebx subl $20, %esp Index: src/runtime/lookup-asm-amd64-elf.S ================================================================== --- src/runtime/lookup-asm-amd64-elf.S +++ src/runtime/lookup-asm-amd64-elf.S @@ -15,14 +15,17 @@ */ #include "config.h" .globl objc_msg_lookup +.globl objc_msg_lookup_stret .globl objc_msg_lookup_super +.globl objc_msg_lookup_super_stret .section .text objc_msg_lookup: +objc_msg_lookup_stret: /* FIXME */ testq %rdi, %rdi jz ret_nil movq (%rdi), %r8 movq 64(%r8), %r8 @@ -49,10 +52,11 @@ ret .type objc_msg_lookup, %function .size objc_msg_lookup, .-objc_msg_lookup objc_msg_lookup_super: +objc_msg_lookup_super_stret: /* FIXME */ movq (%rdi), %rax testq %rax, %rax jz ret_nil movq 8(%rdi), %r8 Index: src/runtime/lookup-asm-amd64-macho.S ================================================================== --- src/runtime/lookup-asm-amd64-macho.S +++ src/runtime/lookup-asm-amd64-macho.S @@ -15,14 +15,17 @@ */ #include "config.h" .globl _objc_msg_lookup +.globl _objc_msg_lookup_stret .globl _objc_msg_lookup_super +.globl _objc_msg_lookup_super_stret .section __TEXT, __text, regular, pure_instructions _objc_msg_lookup: +_objc_msg_lookup_stret: /* FIXME */ testq %rdi, %rdi jz ret_nil movq (%rdi), %r8 movq 64(%r8), %r8 @@ -47,10 +50,11 @@ ret_nil: leaq nil_method(%rip), %rax ret _objc_msg_lookup_super: +_objc_msg_lookup_super_stret: /* FIXME */ movq (%rdi), %rax testq %rax, %rax jz ret_nil movq 8(%rdi), %r8 Index: src/runtime/lookup-asm-arm-elf.S ================================================================== --- src/runtime/lookup-asm-arm-elf.S +++ src/runtime/lookup-asm-arm-elf.S @@ -15,14 +15,17 @@ */ #include "config.h" .globl objc_msg_lookup +.globl objc_msg_lookup_stret .globl objc_msg_lookup_super +.globl objc_msg_lookup_super_stret .section .text objc_msg_lookup: +objc_msg_lookup_stret: /* FIXME */ cmp r0, #0 beq ret_nil ldr r2, [r0, #0] ldr r2, [r2, #32] @@ -48,10 +51,11 @@ bx lr .type objc_msg_lookup, %function .size objc_msg_lookup, .-objc_msg_lookup objc_msg_lookup_super: +objc_msg_lookup_super_stret: /* FIXME */ ldr r2, [r0, #0] cmp r0, #0 beq ret_nil ldr r2, [r0, #4] Index: src/runtime/lookup-asm-mips-elf.S ================================================================== --- src/runtime/lookup-asm-mips-elf.S +++ src/runtime/lookup-asm-mips-elf.S @@ -15,14 +15,17 @@ */ #include "config.h" .globl objc_msg_lookup +.globl objc_msg_lookup_stret .globl objc_msg_lookup_super +.globl objc_msg_lookup_super_stret .section .text objc_msg_lookup: +objc_msg_lookup_stret: /* FIXME */ beqz $a0, ret_nil lw $t0, 0($a0) lw $t0, 32($t0) @@ -87,10 +90,11 @@ #endif .type objc_msg_lookup, %function .size objc_msg_lookup, .-objc_msg_lookup objc_msg_lookup_super: +objc_msg_lookup_super_stret: /* FIXME */ lw $t0, 0($a0) beqz $t0, ret_nil lw $t0, 4($a0) lw $t0, 32($t0) Index: src/runtime/lookup-asm-ppc-elf.S ================================================================== --- src/runtime/lookup-asm-ppc-elf.S +++ src/runtime/lookup-asm-ppc-elf.S @@ -15,14 +15,17 @@ */ #include "config.h" .globl objc_msg_lookup +.globl objc_msg_lookup_stret .globl objc_msg_lookup_super +.globl objc_msg_lookup_super_stret .section .text objc_msg_lookup: +objc_msg_lookup_stret: /* FIXME */ cmpwi %r3, 0 beq- ret_nil lwz %r5, 0(%r3) lwz %r5, 32(%r5) @@ -56,10 +59,11 @@ forward: b objc_not_found_handler@plt objc_msg_lookup_super: +objc_msg_lookup_super_stret: /* FIXME */ lwz %r5, 0(%r3) cmpwi %r5, 0 beq- ret_nil lwz %r5, 4(%r3) Index: src/runtime/lookup-asm-x86-elf.S ================================================================== --- src/runtime/lookup-asm-x86-elf.S +++ src/runtime/lookup-asm-x86-elf.S @@ -15,14 +15,17 @@ */ #include "config.h" .globl objc_msg_lookup +.globl objc_msg_lookup_stret .globl objc_msg_lookup_super +.globl objc_msg_lookup_super_stret .section .text objc_msg_lookup: +objc_msg_lookup: /* FIXME */ movl 4(%esp), %edx testl %edx, %edx jz ret_nil movl (%edx), %edx @@ -62,10 +65,11 @@ ret .type objc_msg_lookup, %function .size objc_msg_lookup, .-objc_msg_lookup objc_msg_lookup_super: +objc_msg_lookup_super_stret: /* FIXME */ movl 4(%esp), %edx cmpl $0, (%edx) je ret_nil movl 4(%edx), %edx Index: src/runtime/lookup.m ================================================================== --- src/runtime/lookup.m +++ src/runtime/lookup.m @@ -22,13 +22,15 @@ #import "runtime.h" #import "runtime-private.h" #import "macros.h" IMP (*objc_forward_handler)(id, SEL) = NULL; +IMP (*objc_forward_handler_stret)(id, SEL) = NULL; -IMP -objc_not_found_handler(id obj, SEL sel) +static IMP +common_not_found_handler(id obj, SEL sel, IMP (*lookup)(id, SEL), + IMP (*forward_handler)(id, SEL)) { bool is_class = object_getClass(obj)->info & OBJC_CLASS_INFO_METACLASS; if (!(object_getClass(obj)->info & OBJC_CLASS_INFO_INITIALIZED)) { Class cls = (is_class ? (Class)obj : object_getClass(obj)); @@ -35,11 +37,11 @@ objc_initialize_class(cls); if (!(cls->info & OBJC_CLASS_INFO_SETUP)) { if (is_class) - return objc_msg_lookup(nil, sel); + return lookup(nil, sel); else OBJC_ERROR("Could not dispatch message for " "incomplete class %s!", cls->name); } @@ -47,19 +49,33 @@ * We don't need to handle the case that super was called. * The reason for this is that a call to super is not possible * before a message to the class has been sent and it thus has * been initialized together with its superclasses. */ - return objc_msg_lookup(obj, sel); + return lookup(obj, sel); } - if (objc_forward_handler != NULL) - return objc_forward_handler(obj, sel); + if (forward_handler != NULL) + return forward_handler(obj, sel); OBJC_ERROR("Selector %c[%s] is not implemented for class %s!", (is_class ? '+' : '-'), sel_getName(sel), object_getClassName(obj)); } + +IMP +objc_not_found_handler(id obj, SEL sel) +{ + return common_not_found_handler(obj, sel, objc_msg_lookup, + objc_forward_handler); +} + +IMP +objc_not_found_handler_stret(id obj, SEL sel) +{ + return common_not_found_handler(obj, sel, objc_msg_lookup_stret, + objc_forward_handler_stret); +} bool class_respondsToSelector(Class cls, SEL sel) { if (cls == Nil) @@ -73,12 +89,12 @@ nil_method(id self, SEL _cmd) { return nil; } -IMP -objc_msg_lookup(id obj, SEL sel) +static OF_INLINE IMP +common_lookup(id obj, SEL sel, IMP (*not_found_handler)(id, SEL)) { IMP imp; if (obj == nil) return (IMP)nil_method; @@ -85,26 +101,51 @@ imp = objc_sparsearray_get(object_getClass(obj)->dtable, (uint32_t)sel->uid); if (imp == NULL) - return objc_not_found_handler(obj, sel); + return not_found_handler(obj, sel); return imp; } IMP -objc_msg_lookup_super(struct objc_super *super, SEL sel) +objc_msg_lookup(id obj, SEL sel) +{ + return common_lookup(obj, sel, objc_not_found_handler); +} + +IMP +objc_msg_lookup_stret(id obj, SEL sel) +{ + return common_lookup(obj, sel, objc_not_found_handler_stret); +} + +static OF_INLINE IMP +common_lookup_super(struct objc_super *super, SEL sel, + IMP (*not_found_handler)(id, SEL)) { IMP imp; if (super->self == nil) return (IMP)nil_method; imp = objc_sparsearray_get(super->cls->dtable, (uint32_t)sel->uid); if (imp == NULL) - return objc_not_found_handler(super->self, sel); + return not_found_handler(super->self, sel); return imp; } + +IMP +objc_msg_lookup_super(struct objc_super *super, SEL sel) +{ + return common_lookup_super(super, sel, objc_not_found_handler); +} + +IMP +objc_msg_lookup_super_stret(struct objc_super *super, SEL sel) +{ + return common_lookup_super(super, sel, objc_not_found_handler_stret); +} #endif Index: src/runtime/runtime.h ================================================================== --- src/runtime/runtime.h +++ src/runtime/runtime.h @@ -186,18 +186,21 @@ extern const char* objc_get_type_encoding(Class, SEL); extern Class object_getClass(id); extern Class object_setClass(id, Class); extern const char* object_getClassName(id); extern IMP objc_msg_lookup(id, SEL); +extern IMP objc_msg_lookup_stret(id, SEL); extern IMP objc_msg_lookup_super(struct objc_super*, SEL); +extern IMP objc_msg_lookup_super_stret(struct objc_super*, SEL); extern const char* protocol_getName(Protocol*); extern bool protocol_isEqual(Protocol*, Protocol*); extern bool protocol_conformsToProtocol(Protocol*, Protocol*); extern void objc_exit(void); extern objc_uncaught_exception_handler objc_setUncaughtExceptionHandler( objc_uncaught_exception_handler); extern IMP (*objc_forward_handler)(id, SEL); +extern IMP (*objc_forward_handler_stret)(id, SEL); extern id objc_autorelease(id); extern void* objc_autoreleasePoolPush(void); extern void objc_autoreleasePoolPop(void*); extern id _objc_rootAutorelease(id); #ifdef __cplusplus