Index: configure.ac ================================================================== --- configure.ac +++ configure.ac @@ -262,10 +262,12 @@ AC_CHECK_LIB(objc, objc_msgSend, [ LIBS="-lobjc $LIBS" ], [ AC_MSG_ERROR([libobjc not found!]) ]) + + AC_SUBST(APPLE_FORWARDING_S, "apple-forwarding.S") ;; esac AC_CHECK_FUNC(objc_constructInstance, [], [ AC_SUBST(INSTANCE_M, "instance.m") Index: extra.mk.in ================================================================== --- extra.mk.in +++ extra.mk.in @@ -6,13 +6,14 @@ OBJFW_LIB_MAJOR_MINOR = ${OBJFW_LIB_MAJOR}.${OBJFW_LIB_MINOR} OBJFW_BRIDGE_SHARED_LIB = @OBJFW_BRIDGE_SHARED_LIB@ OBJFW_BRIDGE_STATIC_LIB = @OBJFW_BRIDGE_STATIC_LIB@ +APPLE_FORWARDING_S = @APPLE_FORWARDING_S@ ASPRINTF_M = @ASPRINTF_M@ -AUTORELEASE_M = @AUTORELEASE_M@ ATOMIC_H = @ATOMIC_H@ +AUTORELEASE_M = @AUTORELEASE_M@ BIN_PREFIX = @BIN_PREFIX@ BRIDGE = @BRIDGE@ EXCEPTIONS_A = @EXCEPTIONS_A@ EXCEPTIONS_EXCEPTIONS_A = @EXCEPTIONS_EXCEPTIONS_A@ EXCEPTIONS_EXCEPTIONS_LIB_A = @EXCEPTIONS_EXCEPTIONS_LIB_A@ Index: src/Makefile ================================================================== --- src/Makefile +++ src/Makefile @@ -98,10 +98,11 @@ ${OFSTREAMOBSERVER_KQUEUE_M} \ ${OFSTREAMOBSERVER_POLL_M} \ ${OFSTREAMOBSERVER_SELECT_M} \ OFString_UTF8.m \ OFTCPSocket+SOCKS5.m \ + ${APPLE_FORWARDING_S} \ ${ASPRINTF_M} \ ${FOUNDATION_COMPAT_M} \ iso_8859_15.m \ windows_1252.m @@ -109,9 +110,12 @@ LIB_OBJS_EXTRA = ${EXCEPTIONS_EXCEPTIONS_LIB_A} ${RUNTIME_RUNTIME_LIB_A} include ../buildsys.mk CPPFLAGS += -I. -I.. -Iexceptions -Iruntime +AS = ${OBJC} +ASFLAGS = ${CPPFLAGS} +AS_DEPENDS = ${OBJC_DEPENDS} LD = ${OBJC} LDFLAGS += ${REEXPORT_LIBOBJC} ${MACH_ALIAS_LIST} ${BRIDGE}: ${SHARED_LIB} Index: src/OFObject.m ================================================================== --- src/OFObject.m +++ src/OFObject.m @@ -64,10 +64,15 @@ #if defined(OF_ATOMIC_OPS) # import "atomic.h" #elif defined(OF_THREADS) # import "threading.h" #endif + +#if defined(OF_APPLE_RUNTIME) && defined(__x86_64__) +extern id of_forward(id, SEL, ...); +extern struct stret of_forward_stret(id, SEL, ...); +#endif struct pre_ivar { int32_t retainCount; struct pre_mem *firstMem, *lastMem; #if !defined(OF_ATOMIC_OPS) && defined(OF_THREADS) @@ -111,25 +116,23 @@ @throw [OFEnumerationMutationException exceptionWithClass: [object class] object: object]; } -#ifdef OF_OBJFW_RUNTIME -static id -method_not_found_handler(id obj, SEL sel, ...) +void +of_method_not_found(id obj, SEL sel) { fprintf(stderr, "Runtime error: Selector %s is not implemented in " "class %s!\n", sel_getName(sel), class_getName(object_getClass(obj))); abort(); } +#ifdef OF_OBJFW_RUNTIME static IMP forward_handler(id obj, SEL sel) { - id target; - /* Try resolveClassMethod:/resolveInstanceMethod: */ if (class_isMetaClass(object_getClass(obj))) { if ([obj respondsToSelector: @selector(resolveClassMethod:)] && [obj resolveClassMethod: sel]) { if (![obj respondsToSelector: sel]) { @@ -159,16 +162,20 @@ return objc_msg_lookup(obj, sel); } } /* Try forwardingTargetForSelector: */ - target = [obj forwardingTargetForSelector: sel]; + if (class_respondsToSelector(object_getClass(obj), + @selector(forwardingTargetForSelector:))) { + id target = [obj forwardingTargetForSelector: sel]; - if (target != obj && target != nil) - return objc_msg_lookup(target, sel); + if (target != obj && target != nil) + return objc_msg_lookup(target, sel); + } - return method_not_found_handler; + of_method_not_found(obj, sel); + return NULL; } #endif #ifndef HAVE_OBJC_ENUMERATIONMUTATION void @@ -246,12 +253,16 @@ { #if !defined(OF_APPLE_RUNTIME) || defined(__OBJC2__) objc_setUncaughtExceptionHandler(uncaught_exception_handler); #endif -#ifdef OF_OBJFW_RUNTIME +#if defined(OF_OBJFW_RUNTIME) objc_forward_handler = forward_handler; +#elif defined(OF_APPLE_RUNTIME) +# ifdef __x86_64__ + objc_setForwardHandler(of_forward, of_forward_stret); +# endif #endif #ifdef HAVE_OBJC_ENUMERATIONMUTATION objc_setEnumerationMutationHandler(enumeration_mutation_handler); #endif ADDED src/apple-forwarding-x86_64.S Index: src/apple-forwarding-x86_64.S ================================================================== --- src/apple-forwarding-x86_64.S +++ src/apple-forwarding-x86_64.S @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +.globl _of_forward +.globl _of_forward_stret + +.section __TEXT, __objc_methname, cstring_literals +L_str_forwardingTargetForSelector: + .asciz "forwardingTargetForSelector:" + +.section __DATA, __objc_selrefs, literal_pointers, no_dead_strip +L_sel_forwardingTargetForSelector: + .quad L_str_forwardingTargetForSelector + +.section __DATA, __objc_imageinfo, regular, no_dead_strip + .long 0, 0 + +.section __TEXT, __text, regular, pure_instructions +.macro forward dispatch_func + push %rbp + movq %rsp, %rbp + + /* Save all arguments */ + subq $0xC0, %rsp /* 16-byte alignment */ + movq %rax, 0xA8(%rsp) + movq %rdi, 0xA0(%rsp) + movq %rsi, 0x98(%rsp) + movq %rdx, 0x90(%rsp) + movq %rcx, 0x88(%rsp) + movq %r8, 0x80(%rsp) + movq %r9, 0x78(%rsp) + movd %xmm0, 0x70(%rsp) + movd %xmm1, 0x60(%rsp) + movd %xmm2, 0x50(%rsp) + movd %xmm3, 0x40(%rsp) + movd %xmm4, 0x30(%rsp) + movd %xmm5, 0x20(%rsp) + movd %xmm6, 0x10(%rsp) + movd %xmm7, (%rsp) + + call _object_getClass + movq %rax, %rdi + movq L_sel_forwardingTargetForSelector(%rip), %rsi + call _class_respondsToSelector + test %rax, %rax + jz fail + + movq 0xA0(%rsp), %rdi + movq L_sel_forwardingTargetForSelector(%rip), %rsi + movq 0x98(%rsp), %rdx + call \dispatch_func + movq %rax, %rdi + + test %rdi, %rdi + jz fail + + cmp 0xA0(%rsp), %rdi + je fail + + /* Restore all arguments, except %rdi */ + movd (%rsp), %xmm7 + movd 0x10(%rsp), %xmm6 + movd 0x20(%rsp), %xmm5 + movd 0x30(%rsp), %xmm4 + movd 0x40(%rsp), %xmm3 + movd 0x50(%rsp), %xmm2 + movd 0x60(%rsp), %xmm1 + movd 0x70(%rsp), %xmm0 + movq 0x78(%rsp), %r9 + movq 0x80(%rsp), %r8 + movq 0x88(%rsp), %rcx + movq 0x90(%rsp), %rdx + movq 0x98(%rsp), %rsi + movq 0xA8(%rsp), %rax + + movq %rbp, %rsp + pop %rbp + + jmp \dispatch_func +.endmacro + +_of_forward: + forward _objc_msgSend +_of_forward_stret: + forward _objc_msgSend_stret + +fail: + movq 0xA0(%rsp), %rdi + movq 0x98(%rsp), %rsi + + movq %rbp, %rsp + pop %rbp + + jmp _of_method_not_found ADDED src/apple-forwarding.S Index: src/apple-forwarding.S ================================================================== --- src/apple-forwarding.S +++ src/apple-forwarding.S @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#ifdef __x86_64__ +# include "apple-forwarding-x86_64.S" +#endif Index: src/runtime/Makefile ================================================================== --- src/runtime/Makefile +++ src/runtime/Makefile @@ -23,6 +23,7 @@ include ../../buildsys.mk CPPFLAGS += -I. -I.. -I../.. AS = ${OBJC} ASFLAGS = ${CPPFLAGS} +AS_DEPENDS = ${OBJC_DEPENDS} LD = ${OBJC}