Index: src/OFObject.m ================================================================== --- src/OFObject.m +++ src/OFObject.m @@ -63,12 +63,12 @@ #if defined(OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR) extern id of_forward(id, SEL, ...); extern struct stret of_forward_stret(id, SEL, ...); #else -# define of_forward NULL -# define of_forward_stret NULL +# define of_forward of_method_not_found +# define of_forward_stret of_method_not_found_stret #endif struct pre_ivar { int32_t retainCount; struct pre_mem *firstMem, *lastMem; @@ -135,73 +135,15 @@ * never return. */ abort(); } -#ifdef OF_OBJFW_RUNTIME -static IMP -commonForwardHandler(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]) { - if (![obj respondsToSelector: sel]) { - fprintf(stderr, "Runtime error: [%s " - "resolveClassMethod: %s] returned true " - "without adding the method!\n", - class_getName(obj), sel_getName(sel)); - abort(); - } - - return lookup(obj, sel); - } - } else { - Class c = object_getClass(obj); - - if ([c respondsToSelector: @selector(resolveInstanceMethod:)] && - [c resolveInstanceMethod: sel]) { - if (![obj respondsToSelector: sel]) { - fprintf(stderr, "Runtime error: [%s " - "resolveInstanceMethod: %s] returned true " - "without adding the method!\n", - class_getName(object_getClass(obj)), - sel_getName(sel)); - abort(); - } - - 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 forward; - } -#endif - +void +of_method_not_found_stret(void *st, id obj, SEL sel) +{ of_method_not_found(obj, sel); - return NULL; -} - -static IMP -forwardHandler(id obj, SEL sel) -{ - return commonForwardHandler(obj, sel, objc_msg_lookup, (IMP)of_forward); -} - -static IMP -forwardHandlerStret(id obj, SEL sel) -{ - return commonForwardHandler(obj, sel, - objc_msg_lookup_stret, (IMP)of_forward_stret); -} -#endif +} #ifndef HAVE_OBJC_ENUMERATIONMUTATION void objc_enumerationMutation(id object) { @@ -277,17 +219,11 @@ { #if !defined(OF_APPLE_RUNTIME) || defined(__OBJC2__) objc_setUncaughtExceptionHandler(uncaughtExceptionHandler); #endif -#if defined(OF_OBJFW_RUNTIME) - objc_forward_handler = forwardHandler; - objc_forward_handler_stret = forwardHandlerStret; -#elif defined(OF_APPLE_RUNTIME) && \ - defined(OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR) objc_setForwardHandler(of_forward, of_forward_stret); -#endif #ifdef HAVE_OBJC_ENUMERATIONMUTATION objc_setEnumerationMutationHandler(enumerationMutationHandler); #endif Index: src/forwarding/apple-forwarding-arm.S ================================================================== --- src/forwarding/apple-forwarding-arm.S +++ src/forwarding/apple-forwarding-arm.S @@ -30,91 +30,91 @@ .section __TEXT, __text, regular, pure_instructions .arm .align 2 _of_forward: - stmfd sp!, {r0-r3, lr} + stmfd sp!, {r0-r4, lr} fstmfdd sp!, {d0-d7} + + ldr r4, L_sel_forwardingTargetForSelector_$indirect_L0 +L0: + ldr r4, [pc, r4] blx _object_getClass - ldr r1, L_sel_forwardingTargetForSelector_$indirect_L0 -L0: - ldr r1, [pc, r1] - stmfd sp!, {r1} + mov r1, r4 blx _class_respondsToSelector - ldmfd sp!, {r1} + cmp r0, #0 beq fail ldr r0, [sp, #64] + mov r1, r4 ldr r2, [sp, #68] blx _objc_msgSend cmp r0, #0 beq fail - ldr r1, [sp, #64] cmp r0, r1 beq fail fldmfdd sp!, {d0-d7} add sp, sp, #4 @ throw away r0 - ldmfd sp!, {r1-r3, lr} + ldmfd sp!, {r1-r4, lr} b _objc_msgSend fail: fldmfdd sp!, {d0-d7} - ldmfd sp!, {r0-r3, lr} + ldmfd sp!, {r0-r4, lr} b _of_method_not_found .align 2 _of_forward_stret: - stmfd sp!, {r0-r3, lr} + stmfd sp!, {r0-r4, lr} fstmfdd sp!, {d0-d7} + + ldr r4, L_sel_forwardingTargetForSelector_$indirect_L1 +L1: + ldr r4, [pc, r4] mov r0, r1 blx _object_getClass - ldr r1, L_sel_forwardingTargetForSelector_$indirect_L1 -L1: - ldr r1, [pc, r1] - stmfd sp!, {r1} + mov r1, r4 blx _class_respondsToSelector - ldmfd sp!, {r1} + cmp r0, #0 beq fail_stret ldr r0, [sp, #68] + mov r1, r4 ldr r2, [sp, #72] blx _objc_msgSend cmp r0, #0 beq fail_stret - ldr r1, [sp, #68] cmp r0, r1 beq fail_stret mov r1, r0 fldmfdd sp!, {d0-d7} ldmfd sp!, {r0} add sp, sp, #4 @ throw away r1 - ldmfd sp!, {r2-r3, lr} + ldmfd sp!, {r2-r4, lr} b _objc_msgSend_stret fail_stret: fldmfdd sp!, {d0-d7} - ldmfd sp!, {r0-r3, lr} - mov r0, r1 - mov r1, r2 - b _of_method_not_found + ldmfd sp!, {r0-r4, lr} + b _of_method_not_found_stret .data_region L_sel_forwardingTargetForSelector_$indirect_L0: .long L_sel_forwardingTargetForSelector_-(L0+8) L_sel_forwardingTargetForSelector_$indirect_L1: .long L_sel_forwardingTargetForSelector_-(L1+8) .end_data_region Index: src/forwarding/apple-forwarding-arm64.S ================================================================== --- src/forwarding/apple-forwarding-arm64.S +++ src/forwarding/apple-forwarding-arm64.S @@ -54,10 +54,11 @@ add x19, x19, L_sel_forwardingTargetForSelector_@PAGEOFF ldr x19, [x19] mov x1, x19 bl _class_respondsToSelector + cbz x0, fail ldp x0, x2, [sp] mov x1, x19 bl _objc_msgSend Index: src/forwarding/apple-forwarding-i386.S ================================================================== --- src/forwarding/apple-forwarding-i386.S +++ src/forwarding/apple-forwarding-i386.S @@ -36,18 +36,20 @@ pushl %ebx subl $20, %esp call get_eip .L0: + movl 8(%ebp), %eax movl %eax, (%esp) call _object_getClass movl %eax, (%esp) movl L_sel_forwardingTargetForSelector_-.L0(%ebx), %eax movl %eax, 4(%esp) call _class_respondsToSelector + testl %eax, %eax jz fail movl 8(%ebp), %eax movl %eax, (%esp) @@ -57,11 +59,10 @@ movl %eax, 8(%esp) call _objc_msgSend testl %eax, %eax jz fail - cmpl 8(%ebp), %eax je fail movl %eax, 8(%ebp) @@ -85,18 +86,20 @@ pushl %ebx subl $20, %esp call get_eip .L1: + movl 12(%ebp), %eax movl %eax, (%esp) call _object_getClass movl %eax, (%esp) movl L_sel_forwardingTargetForSelector_-.L1(%ebx), %eax movl %eax, 4(%esp) call _class_respondsToSelector + testl %eax, %eax jz fail_stret movl 12(%ebp), %eax movl %eax, (%esp) @@ -106,11 +109,10 @@ movl %eax, 8(%esp) call _objc_msgSend testl %eax, %eax jz fail_stret - cmpl 12(%ebp), %eax je fail_stret movl %eax, 12(%ebp) @@ -119,19 +121,14 @@ popl %ebp jmp _objc_msgSend_stret fail_stret: - movl 12(%ebp), %eax - movl %eax, 8(%ebp) - movl 16(%ebp), %eax - movl %eax, 12(%ebp) - addl $20, %esp popl %ebx popl %ebp - jmp _of_method_not_found + jmp _of_method_not_found_stret get_eip: movl (%esp), %ebx ret Index: src/forwarding/apple-forwarding-ppc.S ================================================================== --- src/forwarding/apple-forwarding-ppc.S +++ src/forwarding/apple-forwarding-ppc.S @@ -70,12 +70,14 @@ bl L0 L0: mflr r13 addis r13, r13, ha16(L_sel_forwardingTargetForSelector_-L0) lwz r13, lo16(L_sel_forwardingTargetForSelector_-L0)(r13) + mr r4, r13 bl _class_respondsToSelector + cmpwi r3, 0 beq- fail lwz r3, 216(r1) mr r4, r13 @@ -82,11 +84,10 @@ lwz r5, 220(r1) bl _objc_msgSend cmpwi r3, 0 beq- fail - lwz r4, 216(r1) cmpw r3, r4 beq- fail /* Restore all arguments and r13, except r3 */ @@ -172,12 +173,14 @@ bl L1 L1: mflr r13 addis r13, r13, ha16(L_sel_forwardingTargetForSelector_-L1) lwz r13, lo16(L_sel_forwardingTargetForSelector_-L1)(r13) + mr r4, r13 bl _class_respondsToSelector + cmpwi r3, 0 beq- fail_stret lwz r3, 212(r1) mr r4, r13 @@ -184,11 +187,10 @@ lwz r5, 216(r1) bl _objc_msgSend cmpwi r3, 0 beq- fail_stret - lwz r4, 212(r1) cmpw r3, r4 beq- fail_stret mr r4, r3 @@ -223,13 +225,14 @@ mtlr r0 b _objc_msgSend_stret fail_stret: - lwz r3, 212(r1) - lwz r4, 216(r1) + lwz r3, 208(r1) + lwz r4, 212(r1) + lwz r5, 216(r1) addi r1, r1, 184 lwz r0, 8(r1) mtlr r0 - b _of_method_not_found + b _of_method_not_found_stret Index: src/forwarding/apple-forwarding-x86_64.S ================================================================== --- src/forwarding/apple-forwarding-x86_64.S +++ src/forwarding/apple-forwarding-x86_64.S @@ -54,24 +54,25 @@ call _object_getClass movq %rax, %rdi movq L_sel_forwardingTargetForSelector_(%rip), %rsi call _class_respondsToSelector + testq %rax, %rax jz fail movq -0x10(%rbp), %rdi movq L_sel_forwardingTargetForSelector_(%rip), %rsi movq -0x18(%rbp), %rdx call _objc_msgSend - movq %rax, %rdi - testq %rdi, %rdi + testq %rax, %rax jz fail - - cmpq -0x10(%rbp), %rdi + cmpq -0x10(%rbp), %rax je fail + + movq %rax, %rdi /* Restore all arguments, except %rdi */ movdqa -0xC0(%rbp), %xmm7 movdqa -0xB0(%rbp), %xmm6 movdqa -0xA0(%rbp), %xmm5 @@ -134,17 +135,17 @@ movq -0x18(%rbp), %rdi movq L_sel_forwardingTargetForSelector_(%rip), %rsi movq -0x20(%rbp), %rdx call _objc_msgSend - movq %rax, %rsi - testq %rsi, %rsi + testq %rax, %rax jz fail_stret - - cmpq -0x18(%rbp), %rsi + cmpq -0x18(%rbp), %rax je fail_stret + + movq %rax, %rsi /* Restore all arguments, except %rsi */ movdqa -0xC0(%rbp), %xmm7 movdqa -0xB0(%rbp), %xmm6 movdqa -0xA0(%rbp), %xmm5 @@ -164,12 +165,13 @@ popq %rbp jmp _objc_msgSend_stret fail_stret: - movq -0x18(%rbp), %rdi - movq -0x20(%rbp), %rsi + movq -0x10(%rbp), %rdi + movq -0x18(%rbp), %rsi + movq -0x20(%rbp), %rdx movq %rbp, %rsp popq %rbp - jmp _of_method_not_found + jmp _of_method_not_found_stret Index: src/forwarding/forwarding-amd64-elf.S ================================================================== --- src/forwarding/forwarding-amd64-elf.S +++ src/forwarding/forwarding-amd64-elf.S @@ -38,16 +38,33 @@ movdqa %xmm4, -0x90(%rbp) movdqa %xmm5, -0xA0(%rbp) movdqa %xmm6, -0xB0(%rbp) movdqa %xmm7, -0xC0(%rbp) + call object_getClass@PLT + + movq %rax, %rdi + leaq sel_forwardingTargetForSelector_(%rip), %rsi + call class_respondsToSelector@PLT + + testq %rax, %rax + jz fail + + movq -0x10(%rbp), %rdi leaq sel_forwardingTargetForSelector_(%rip), %rsi call objc_msg_lookup@PLT + movq -0x10(%rbp), %rdi leaq sel_forwardingTargetForSelector_(%rip), %rsi movq -0x18(%rbp), %rdx call *%rax + + testq %rax, %rax + jz fail + cmpq -0x10(%rbp), %rax + je fail + movq %rax, -0x10(%rbp) movq %rax, %rdi movq -0x18(%rbp), %rsi call objc_msg_lookup@PLT @@ -72,10 +89,19 @@ movq %rbp, %rsp popq %rbp jmpq *%r11 + +fail: + movq -0x10(%rbp), %rdi + movq -0x18(%rbp), %rsi + + movq %rbp, %rsp + popq %rbp + + jmp of_method_not_found@PLT .type of_forward, %function .size of_forward, .-of_forward of_forward_stret: pushq %rbp @@ -98,16 +124,33 @@ movdqa %xmm5, -0xA0(%rbp) movdqa %xmm6, -0xB0(%rbp) movdqa %xmm7, -0xC0(%rbp) movq %rsi, %rdi + call object_getClass@PLT + + movq %rax, %rdi + leaq sel_forwardingTargetForSelector_(%rip), %rsi + call class_respondsToSelector@PLT + + testq %rax, %rax + jz fail_stret + + movq -0x18(%rbp), %rdi leaq sel_forwardingTargetForSelector_(%rip), %rsi call objc_msg_lookup@PLT + movq -0x18(%rbp), %rdi leaq sel_forwardingTargetForSelector_(%rip), %rsi movq -0x20(%rbp), %rdx call *%rax + + testq %rax, %rax + jz fail_stret + cmpq -0x18(%rbp), %rax + je fail_stret + movq %rax, -0x18(%rbp) movq %rax, %rdi movq -0x20(%rbp), %rsi call objc_msg_lookup_stret@PLT @@ -132,10 +175,20 @@ movq %rbp, %rsp popq %rbp jmpq *%r11 + +fail_stret: + movq -0x10(%rbp), %rdi + movq -0x18(%rbp), %rsi + movq -0x20(%rbp), %rdx + + movq %rbp, %rsp + popq %rbp + + jmp of_method_not_found_stret@PLT .type of_forward_stret, %function .size of_forward_stret, .-of_forward_stret init: leaq module(%rip), %rdi Index: src/forwarding/forwarding-arm-elf.S ================================================================== --- src/forwarding/forwarding-arm-elf.S +++ src/forwarding/forwarding-arm-elf.S @@ -17,63 +17,105 @@ .globl of_forward .globl of_forward_stret .section .text of_forward: - stmfd sp!, {r0-r3, lr} + stmfd sp!, {r0-r4, lr} fstmfdd sp!, {d0-d7} - ldr r1, sel_forwardingTargetForSelector_$indirect_L0 + ldr r4, sel_forwardingTargetForSelector_$indirect_L0 .L0: - add r1, pc - stmfd sp!, {r1} + add r4, pc + + bl object_getClass(PLT) + + mov r1, r4 + bl class_respondsToSelector(PLT) + + cmp r0, #0 + beq fail + + ldr r0, [sp, #64] + mov r1, r4 bl objc_msg_lookup(PLT) - ldmfd sp!, {r1} mov r12, r0 ldr r0, [sp, #64] + mov r1, r4 ldr r2, [sp, #68] blx r12 + + cmp r0, #0 + beq fail + ldr r1, [sp, #64] + cmp r0, r1 + beq fail str r0, [sp, #64] ldr r1, [sp, #68] bl objc_msg_lookup(PLT) mov r12, r0 fldmfdd sp!, {d0-d7} - ldmfd sp!, {r0-r3, lr} + ldmfd sp!, {r0-r4, lr} bx r12 + +fail: + fldmfdd sp!, {d0-d7} + ldmfd sp!, {r0-r4, lr} + b of_method_not_found(PLT) .type of_forward, %function .size of_forward, .-of_forward of_forward_stret: - stmfd sp!, {r0-r3, lr} + stmfd sp!, {r0-r4, lr} fstmfdd sp!, {d0-d7} - mov r0, r1 - ldr r1, sel_forwardingTargetForSelector_$indirect_L1 + ldr r4, sel_forwardingTargetForSelector_$indirect_L1 .L1: - add r1, pc - stmfd sp!, {r1} + add r4, pc + + mov r0, r1 + bl object_getClass(PLT) + + mov r1, r4 + bl class_respondsToSelector(PLT) + + cmp r0, #0 + beq fail_stret + + ldr r0, [sp, #68] + mov r1, r4 bl objc_msg_lookup(PLT) - ldmfd sp!, {r1} mov r12, r0 ldr r0, [sp, #68] + mov r1, r4 ldr r2, [sp, #72] blx r12 + cmp r0, #0 + beq fail_stret + ldr r1, [sp, #68] + cmp r0, r1 + beq fail_stret + str r0, [sp, #68] ldr r1, [sp, #72] bl objc_msg_lookup_stret(PLT) mov r12, r0 fldmfdd sp!, {d0-d7} - ldmfd sp!, {r0-r3, lr} + ldmfd sp!, {r0-r4, lr} bx r12 + +fail_stret: + fldmfdd sp!, {d0-d7} + ldmfd sp!, {r0-r4, lr} + b of_method_not_found_stret(PLT) .type of_forward_stret, %function .size of_forward_stret, .-of_forward_stret init: ldr r0, module_indirect_L2 Index: src/forwarding/forwarding-mips-elf.S ================================================================== --- src/forwarding/forwarding-mips-elf.S +++ src/forwarding/forwarding-mips-elf.S @@ -14,120 +14,151 @@ * file. */ .globl of_forward .globl of_forward_stret + +#ifdef __PIC__ +.macro j_pic symbol + lw $t9, %call16(\symbol)($gp) + jr $t9 +.endm +.macro jal_pic symbol + lw $t9, %call16(\symbol)($gp) + jalr $t9 +.endm +#else +.macro j_pic symbol + j \symbol +.endm +.macro jal_pic symbol + jal \symbol +.endm +#endif .section .text of_forward: #ifdef __PIC__ lui $gp, %hi(_gp_disp) addiu $gp, $gp, %lo(_gp_disp) addu $gp, $gp, $t9 #endif - addiu $sp, $sp, -72 + addiu $sp, $sp, -96 /* * O32: The registers for floating point arguments don't need to be * saved, as the ABI specifies that all remaining arguments are passed * in integer registers if the first argument is passed in an integer * register. This is always the case, as the first argument is always * self. */ - sw $gp, 0($sp) - sw $ra, 4($sp) - sw $a0, 8($sp) - sw $a1, 12($sp) - sw $a2, 16($sp) - sw $a3, 20($sp) -#ifdef __mips_eabi - /* For some reason, $a4-$a8 are not always defined */ - sw $8, 24($sp) - sw $9, 28($sp) - sw $10, 32($sp) - sw $11, 36($sp) - - swc1 $f12, 40($sp) - swc1 $f13, 44($sp) - swc1 $f14, 48($sp) - swc1 $f15, 52($sp) - swc1 $f16, 56($sp) - swc1 $f17, 60($sp) - swc1 $f18, 64($sp) - swc1 $f19, 68($sp) -#endif - -#ifdef __PIC__ - lw $a1, %got(sel_forwardingTargetForSelector_)($gp) -#else - lui $a1, %hi(sel_forwardingTargetForSelector_) -#endif - addiu $a1, $a1, %lo(sel_forwardingTargetForSelector_) -#ifdef __PIC__ - lw $t9, %call16(objc_msg_lookup)($gp) - jalr $t9 -#else - jal objc_msg_lookup -#endif - - lw $gp, 0($sp) - lw $a0, 8($sp) -#ifdef __PIC__ - lw $a1, %got(sel_forwardingTargetForSelector_)($gp) -#else - lui $a1, %hi(sel_forwardingTargetForSelector_) -#endif - addiu $a1, $a1, %lo(sel_forwardingTargetForSelector_) - lw $a2, 12($sp) -#ifdef __PIC__ - move $t9, $v0 - jalr $t9 -#else - jalr $v0 -#endif - sw $v0, 8($sp) - - lw $gp, 0($sp) - move $a0, $v0 - lw $a1, 12($sp) -#ifdef __PIC__ - lw $t9, %call16(objc_msg_lookup)($gp) - jalr $t9 -#else - jal objc_msg_lookup -#endif - -#ifdef __mips_eabi - lwc1 $f19, 68($sp) - lwc1 $f18, 64($sp) - lwc1 $f17, 60($sp) - lwc1 $f16, 56($sp) - lwc1 $f15, 52($sp) - lwc1 $f14, 48($sp) - lwc1 $f13, 44($sp) - lwc1 $f12, 40($sp) - - lw $11, 36($sp) - lw $10, 32($sp) - lw $9, 28($sp) - lw $8, 24($sp) -#endif - lw $a3, 20($sp) - lw $a2, 16($sp) - lw $a1, 12($sp) - lw $a0, 8($sp) - lw $ra, 4($sp) - - addiu $sp, $sp, 72 - -#ifdef __PIC__ - move $t9, $v0 - jr $t9 -#else - jr $v0 -#endif + sw $ra, 16($sp) + sw $s0, 20($sp) + sw $s1, 24($sp) + + sw $a0, 28($sp) + sw $a1, 32($sp) + sw $a2, 36($sp) + sw $a3, 40($sp) +#ifdef __mips_eabi + /* For some reason, $a4-$a8 are not always defined */ + sw $8, 44($sp) + sw $9, 48($sp) + sw $10, 52($sp) + sw $11, 56($sp) + + swc1 $f12, 60($sp) + swc1 $f13, 64($sp) + swc1 $f14, 68($sp) + swc1 $f15, 72($sp) + swc1 $f16, 76($sp) + swc1 $f17, 80($sp) + swc1 $f18, 84($sp) + swc1 $f19, 88($sp) +#endif + + move $s0, $gp +#ifdef __PIC__ + lw $s1, %got(sel_forwardingTargetForSelector_)($gp) +#else + lui $s1, %hi(sel_forwardingTargetForSelector_) +#endif + addiu $s1, $s1, %lo(sel_forwardingTargetForSelector_) + + jal_pic object_getClass + + move $gp, $s0 + move $a0, $v0 + move $a1, $s1 + jal_pic class_respondsToSelector + beqz $v0, fail + + move $gp, $s0 + lw $a0, 28($sp) + move $a1, $s1 + jal_pic objc_msg_lookup + + move $gp, $s0 + lw $a0, 28($sp) + move $a1, $s1 + lw $a2, 32($sp) + move $t9, $v0 + jalr $t9 + + beqz $v0, fail + lw $t0, 28($sp) + beq $v0, $t0, fail + + sw $v0, 28($sp) + + move $gp, $s0 + move $a0, $v0 + lw $a1, 32($sp) + jal_pic objc_msg_lookup + +#ifdef __mips_eabi + lwc1 $f19, 88($sp) + lwc1 $f18, 84($sp) + lwc1 $f17, 80($sp) + lwc1 $f16, 76($sp) + lwc1 $f15, 72($sp) + lwc1 $f14, 68($sp) + lwc1 $f13, 64($sp) + lwc1 $f12, 60($sp) + + lw $11, 56($sp) + lw $10, 52($sp) + lw $9, 48($sp) + lw $8, 44($sp) +#endif + lw $a3, 40($sp) + lw $a2, 36($sp) + lw $a1, 32($sp) + lw $a0, 28($sp) + + lw $s1, 24($sp) + lw $s0, 20($sp) + lw $ra, 16($sp) + + addiu $sp, $sp, 96 + + move $t9, $v0 + jr $t9 + +fail: + move $gp, $s0 + + lw $a1, 32($sp) + lw $a0, 28($sp) + lw $s1, 24($sp) + lw $s0, 20($sp) + lw $ra, 16($sp) + + addiu $sp, $sp, 96 + + j_pic of_method_not_found .type of_forward, %function .size of_forward, .-of_forward of_forward_stret: #ifdef __PIC__ @@ -134,112 +165,126 @@ lui $gp, %hi(_gp_disp) addiu $gp, $gp, %lo(_gp_disp) addu $gp, $gp, $t9 #endif - addiu $sp, $sp, -72 + addiu $sp, $sp, -96 /* * O32: The registers for floating point arguments don't need to be * saved, as the ABI specifies that all remaining arguments are passed * in integer registers if the first argument is passed in an integer * register. This is always the case, as the first argument is always * self. */ - sw $gp, 0($sp) - sw $ra, 4($sp) - sw $a0, 8($sp) - sw $a1, 12($sp) - sw $a2, 16($sp) - sw $a3, 20($sp) -#ifdef __mips_eabi - /* For some reason, $a4-$a8 are not always defined */ - sw $8, 24($sp) - sw $9, 28($sp) - sw $10, 32($sp) - sw $11, 36($sp) - - swc1 $f12, 40($sp) - swc1 $f13, 44($sp) - swc1 $f14, 48($sp) - swc1 $f15, 52($sp) - swc1 $f16, 56($sp) - swc1 $f17, 60($sp) - swc1 $f18, 64($sp) - swc1 $f19, 68($sp) -#endif - - move $a0, $a1 -#ifdef __PIC__ - lw $a1, %got(sel_forwardingTargetForSelector_)($gp) -#else - lui $a1, %hi(sel_forwardingTargetForSelector_) -#endif - addiu $a1, $a1, %lo(sel_forwardingTargetForSelector_) -#ifdef __PIC__ - lw $t9, %call16(objc_msg_lookup)($gp) - jalr $t9 -#else - jal objc_msg_lookup -#endif - - lw $gp, 0($sp) - lw $a0, 12($sp) -#ifdef __PIC__ - lw $a1, %got(sel_forwardingTargetForSelector_)($gp) -#else - lui $a1, %hi(sel_forwardingTargetForSelector_) -#endif - addiu $a1, $a1, %lo(sel_forwardingTargetForSelector_) - lw $a2, 16($sp) -#ifdef __PIC__ - move $t9, $v0 - jalr $t9 -#else - jalr $v0 -#endif - sw $v0, 12($sp) - - lw $gp, 0($sp) - move $a0, $v0 - lw $a1, 16($sp) -#ifdef __PIC__ - lw $t9, %call16(objc_msg_lookup_stret)($gp) - jalr $t9 -#else - jal objc_msg_lookup_stret -#endif - -#ifdef __mips_eabi - lwc1 $f19, 68($sp) - lwc1 $f18, 64($sp) - lwc1 $f17, 60($sp) - lwc1 $f16, 56($sp) - lwc1 $f15, 52($sp) - lwc1 $f14, 48($sp) - lwc1 $f13, 44($sp) - lwc1 $f12, 40($sp) - - lw $11, 36($sp) - lw $10, 32($sp) - lw $9, 28($sp) - lw $8, 24($sp) -#endif - lw $a3, 20($sp) - lw $a2, 16($sp) - lw $a1, 12($sp) - lw $a0, 8($sp) - lw $ra, 4($sp) - - addiu $sp, $sp, 72 - -#ifdef __PIC__ - move $t9, $v0 - jr $t9 -#else - jr $v0 -#endif + sw $ra, 16($sp) + sw $s0, 20($sp) + sw $s1, 24($sp) + + sw $a0, 28($sp) + sw $a1, 32($sp) + sw $a2, 36($sp) + sw $a3, 40($sp) +#ifdef __mips_eabi + /* For some reason, $a4-$a8 are not always defined */ + sw $8, 44($sp) + sw $9, 48($sp) + sw $10, 52($sp) + sw $11, 56($sp) + + swc1 $f12, 60($sp) + swc1 $f13, 64($sp) + swc1 $f14, 68($sp) + swc1 $f15, 72($sp) + swc1 $f16, 76($sp) + swc1 $f17, 80($sp) + swc1 $f18, 84($sp) + swc1 $f19, 88($sp) +#endif + + move $s0, $gp +#ifdef __PIC__ + lw $s1, %got(sel_forwardingTargetForSelector_)($gp) +#else + lui $s1, %hi(sel_forwardingTargetForSelector_) +#endif + addiu $s1, $s1, %lo(sel_forwardingTargetForSelector_) + + move $a0, $a1 + jal_pic object_getClass + + move $gp, $s0 + move $a0, $v0 + move $a1, $s1 + jal_pic class_respondsToSelector + beqz $v0, fail_stret + + move $gp, $s0 + lw $a0, 32($sp) + move $a1, $s1 + jal_pic objc_msg_lookup + + move $gp, $s0 + lw $a0, 32($sp) + move $a1, $s1 + lw $a2, 36($sp) + move $t9, $v0 + jalr $t9 + + beqz $v0, fail_stret + lw $t0, 32($sp) + beq $v0, $t0, fail_stret + + sw $v0, 32($sp) + + move $gp, $s0 + move $a0, $v0 + lw $a1, 36($sp) + jal_pic objc_msg_lookup_stret + +#ifdef __mips_eabi + lwc1 $f19, 88($sp) + lwc1 $f18, 84($sp) + lwc1 $f17, 80($sp) + lwc1 $f16, 76($sp) + lwc1 $f15, 72($sp) + lwc1 $f14, 68($sp) + lwc1 $f13, 64($sp) + lwc1 $f12, 60($sp) + + lw $11, 56($sp) + lw $10, 52($sp) + lw $9, 48($sp) + lw $8, 44($sp) +#endif + lw $a3, 40($sp) + lw $a2, 36($sp) + lw $a1, 32($sp) + lw $a0, 28($sp) + + lw $s1, 24($sp) + lw $s0, 20($sp) + lw $ra, 16($sp) + + addiu $sp, $sp, 96 + + move $t9, $v0 + jr $t9 + +fail_stret: + move $gp, $s0 + + lw $a2, 36($sp) + lw $a1, 32($sp) + lw $a0, 28($sp) + lw $s1, 24($sp) + lw $s0, 20($sp) + lw $ra, 16($sp) + + addiu $sp, $sp, 96 + + j_pic of_method_not_found_stret .type of_forward_stret, %function .size of_forward_stret, .-of_forward_stret init: #ifdef __PIC__ Index: src/forwarding/forwarding-ppc-elf.S ================================================================== --- src/forwarding/forwarding-ppc-elf.S +++ src/forwarding/forwarding-ppc-elf.S @@ -41,10 +41,20 @@ stfd %f5, 72(%r1) stfd %f6, 80(%r1) stfd %f7, 88(%r1) stfd %f8, 96(%r1) + bl object_getClass@plt + + lis %r4, sel_forwardingTargetForSelector_@ha + la %r4, sel_forwardingTargetForSelector_@l(%r4) + bl class_respondsToSelector@plt + + cmpwi %r3, 0 + beq- fail + + lwz %r3, 8(%r1) lis %r4, sel_forwardingTargetForSelector_@ha la %r4, sel_forwardingTargetForSelector_@l(%r4) bl objc_msg_lookup@plt mtctr %r3 @@ -51,10 +61,17 @@ lwz %r3, 8(%r1) lis %r4, sel_forwardingTargetForSelector_@ha la %r4, sel_forwardingTargetForSelector_@l(%r4) lwz %r5, 12(%r1) bctrl + + cmpwi %r3, 0 + beq- fail + lwz %r4, 8(%r1) + cmpw %r3, %r4 + beq- fail + stw %r3, 8(%r1) lwz %r4, 12(%r1) bl objc_msg_lookup@plt mtctr %r3 @@ -81,10 +98,20 @@ lwz %r0, 116(%r1) mtlr %r0 addi %r1, %r1, 112 bctr + +fail: + lwz %r3, 8(%r1) + lwz %r4, 12(%r1) + + lwz %r0, 116(%r1) + mtlr %r0 + addi %r1, %r1, 112 + + b of_method_not_found@plt .type of_forward, %function .size of_forward, .-of_forward of_forward_stret: stwu %r1, -112(%r1) @@ -110,10 +137,20 @@ stfd %f6, 80(%r1) stfd %f7, 88(%r1) stfd %f8, 96(%r1) mr %r3, %r4 + bl object_getClass@plt + + lis %r4, sel_forwardingTargetForSelector_@ha + la %r4, sel_forwardingTargetForSelector_@l(%r4) + bl class_respondsToSelector@plt + + cmpwi %r3, 0 + beq- fail_stret + + lwz %r3, 12(%r1) lis %r4, sel_forwardingTargetForSelector_@ha la %r4, sel_forwardingTargetForSelector_@l(%r4) bl objc_msg_lookup@plt mtctr %r3 @@ -120,10 +157,17 @@ lwz %r3, 12(%r1) lis %r4, sel_forwardingTargetForSelector_@ha la %r4, sel_forwardingTargetForSelector_@l(%r4) lwz %r5, 16(%r1) bctrl + + cmpwi %r3, 0 + beq- fail_stret + lwz %r4, 12(%r1) + cmpw %r3, %r4 + beq- fail_stret + stw %r3, 12(%r1) lwz %r4, 16(%r1) bl objc_msg_lookup_stret@plt mtctr %r3 @@ -150,10 +194,21 @@ lwz %r0, 116(%r1) mtlr %r0 addi %r1, %r1, 112 bctr + +fail_stret: + lwz %r3, 8(%r1) + lwz %r4, 12(%r1) + lwz %r5, 16(%r1) + + lwz %r0, 116(%r1) + mtlr %r0 + addi %r1, %r1, 112 + + b of_method_not_found_stret@plt .type of_forward_stret, %function .size of_forward_stret, .-of_forward_stret init: lis %r3, module@ha Index: src/forwarding/forwarding-x86-elf.S ================================================================== --- src/forwarding/forwarding-x86-elf.S +++ src/forwarding/forwarding-x86-elf.S @@ -25,10 +25,25 @@ pushl %ebx subl $20, %esp call get_eip .L0: + + movl 8(%ebp), %eax + movl %eax, (%esp) + leal object_getClass-.L0(%ebx), %eax + call *%eax + + movl %eax, (%esp) + leal sel_forwardingTargetForSelector_-.L0(%ebx), %eax + movl %eax, 4(%esp) + leal class_respondsToSelector-.L0(%ebx), %eax + call *%eax + + testl %eax, %eax + jz fail + movl 8(%ebp), %eax movl %eax, (%esp) leal sel_forwardingTargetForSelector_-.L0(%ebx), %eax movl %eax, 4(%esp) leal objc_msg_lookup-.L0(%ebx), %eax @@ -39,18 +54,32 @@ leal sel_forwardingTargetForSelector_-.L0(%ebx), %edx movl %edx, 4(%esp) movl 12(%ebp), %edx movl %edx, 8(%esp) call *%eax + + testl %eax, %eax + jz fail + cmpl 8(%ebp), %eax + je fail movl %eax, 8(%ebp) movl %eax, (%esp) movl 12(%ebp), %eax movl %eax, 4(%esp) leal objc_msg_lookup-.L0(%ebx), %eax call *%eax + addl $20, %esp + popl %ebx + popl %ebp + + jmp *%eax + +fail: + leal of_method_not_found-.L0(%ebx), %eax + addl $20, %esp popl %ebx popl %ebp jmp *%eax @@ -64,10 +93,25 @@ pushl %ebx subl $20, %esp call get_eip .L1: + + movl 12(%ebp), %eax + movl %eax, (%esp) + leal object_getClass-.L1(%ebx), %eax + call *%eax + + movl %eax, (%esp) + leal sel_forwardingTargetForSelector_-.L1(%ebx), %eax + movl %eax, 4(%esp) + leal class_respondsToSelector-.L1(%ebx), %eax + call *%eax + + testl %eax, %eax + jz fail_stret + movl 12(%ebp), %eax movl %eax, (%esp) leal sel_forwardingTargetForSelector_-.L1(%ebx), %eax movl %eax, 4(%esp) leal objc_msg_lookup-.L1(%ebx), %eax @@ -78,18 +122,32 @@ leal sel_forwardingTargetForSelector_-.L1(%ebx), %edx movl %edx, 4(%esp) movl 16(%ebp), %edx movl %edx, 8(%esp) call *%eax + + testl %eax, %eax + jz fail_stret + cmpl 12(%ebp), %eax + je fail_stret movl %eax, 12(%ebp) movl %eax, (%esp) movl 16(%ebp), %eax movl %eax, 4(%esp) leal objc_msg_lookup_stret-.L1(%ebx), %eax call *%eax + addl $20, %esp + popl %ebx + popl %ebp + + jmp *%eax + +fail_stret: + leal of_method_not_found_stret-.L1(%ebx), %eax + addl $20, %esp popl %ebx popl %ebp jmp *%eax Index: src/forwarding/forwarding-x86-win32.S ================================================================== --- src/forwarding/forwarding-x86-win32.S +++ src/forwarding/forwarding-x86-win32.S @@ -25,10 +25,25 @@ pushl %ebx subl $20, %esp call get_eip .L0: + + movl 8(%ebp), %eax + movl %eax, (%esp) + leal _object_getClass-.L0(%ebx), %eax + call *%eax + + movl %eax, (%esp) + leal sel_forwardingTargetForSelector_-.L0(%ebx), %eax + movl %eax, 4(%esp) + leal _class_respondsToSelector-.L0(%ebx), %eax + call *%eax + + testl %eax, %eax + jz fail + movl 8(%ebp), %eax movl %eax, (%esp) leal sel_forwardingTargetForSelector_-.L0(%ebx), %eax movl %eax, 4(%esp) leal _objc_msg_lookup-.L0(%ebx), %eax @@ -39,18 +54,32 @@ leal sel_forwardingTargetForSelector_-.L0(%ebx), %edx movl %edx, 4(%esp) movl 12(%ebp), %edx movl %edx, 8(%esp) call *%eax + + testl %eax, %eax + jz fail + cmpl 8(%ebp), %eax + je fail movl %eax, 8(%ebp) movl %eax, (%esp) movl 12(%ebp), %eax movl %eax, 4(%esp) leal _objc_msg_lookup-.L0(%ebx), %eax call *%eax + addl $20, %esp + popl %ebx + popl %ebp + + jmp *%eax + +fail: + leal _of_method_not_found-.L0(%ebx), %eax + addl $20, %esp popl %ebx popl %ebp jmp *%eax @@ -62,10 +91,25 @@ pushl %ebx subl $20, %esp call get_eip .L1: + + movl 12(%ebp), %eax + movl %eax, (%esp) + leal _object_getClass-.L1(%ebx), %eax + call *%eax + + movl %eax, (%esp) + leal sel_forwardingTargetForSelector_-.L1(%ebx), %eax + movl %eax, 4(%esp) + leal _class_respondsToSelector-.L1(%ebx), %eax + call *%eax + + testl %eax, %eax + jz fail_stret + movl 12(%ebp), %eax movl %eax, (%esp) leal sel_forwardingTargetForSelector_-.L1(%ebx), %eax movl %eax, 4(%esp) leal _objc_msg_lookup-.L1(%ebx), %eax @@ -76,18 +120,32 @@ leal sel_forwardingTargetForSelector_-.L1(%ebx), %edx movl %edx, 4(%esp) movl 16(%ebp), %edx movl %edx, 8(%esp) call *%eax + + testl %eax, %eax + jz fail_stret + cmpl 12(%ebp), %eax + je fail_stret movl %eax, 12(%ebp) movl %eax, (%esp) movl 16(%ebp), %eax movl %eax, 4(%esp) leal _objc_msg_lookup_stret-.L1(%ebx), %eax call *%eax + addl $20, %esp + popl %ebx + popl %ebp + + jmp *%eax + +fail_stret: + leal _of_method_not_found_stret-.L1(%ebx), %eax + addl $20, %esp popl %ebx popl %ebp jmp *%eax Index: src/runtime/lookup-asm/lookup-asm-amd64-elf.S ================================================================== --- src/runtime/lookup-asm/lookup-asm-amd64-elf.S +++ src/runtime/lookup-asm/lookup-asm-amd64-elf.S @@ -20,11 +20,11 @@ .globl objc_msg_lookup_stret .globl objc_msg_lookup_super .globl objc_msg_lookup_super_stret .section .text -.macro generate_lookup name not_found_handler +.macro generate_lookup name not_found \name: testq %rdi, %rdi jz ret_nil movq (%rdi), %r8 @@ -41,11 +41,11 @@ #endif movq (%r8,%rcx,8), %r8 movq (%r8,%rdx,8), %rax testq %rax, %rax - jz \not_found_handler@PLT + jz \not_found@PLT ret .type \name, %function .size \name, .-\name .endm @@ -62,12 +62,12 @@ jmp .main_\lookup .type \name, %function .size \name, .-\name .endm -generate_lookup objc_msg_lookup objc_not_found_handler -generate_lookup objc_msg_lookup_stret objc_not_found_handler_stret +generate_lookup objc_msg_lookup objc_method_not_found +generate_lookup objc_msg_lookup_stret objc_method_not_found_stret generate_lookup_super objc_msg_lookup_super objc_msg_lookup generate_lookup_super objc_msg_lookup_super_stret objc_msg_lookup_stret ret_nil: leaq nil_method(%rip), %rax Index: src/runtime/lookup-asm/lookup-asm-amd64-macho.S ================================================================== --- src/runtime/lookup-asm/lookup-asm-amd64-macho.S +++ src/runtime/lookup-asm/lookup-asm-amd64-macho.S @@ -58,12 +58,12 @@ movq 64(%r8), %r8 movq %rdi, %rax jmp Lmain$1 .endmacro -generate_lookup _objc_msg_lookup, _objc_not_found_handler -generate_lookup _objc_msg_lookup_stret, _objc_not_found_handler_stret +generate_lookup _objc_msg_lookup, _objc_method_not_found +generate_lookup _objc_msg_lookup_stret, _objc_method_not_found_stret generate_lookup_super _objc_msg_lookup_super, _objc_msg_lookup generate_lookup_super _objc_msg_lookup_super_stret, _objc_msg_lookup_stret ret_nil: leaq nil_method(%rip), %rax Index: src/runtime/lookup-asm/lookup-asm-arm-elf.S ================================================================== --- src/runtime/lookup-asm/lookup-asm-arm-elf.S +++ src/runtime/lookup-asm/lookup-asm-arm-elf.S @@ -20,11 +20,11 @@ .globl objc_msg_lookup_stret .globl objc_msg_lookup_super .globl objc_msg_lookup_super_stret .section .text -.macro generate_lookup name not_found_handler +.macro generate_lookup name not_found \name: cmp r0, #0 beq ret_nil ldr r2, [r0, #0] @@ -39,11 +39,11 @@ ldr r2, [r2, r3, lsl #2] ldrb r3, [r1, #0] ldr r2, [r2, r3, lsl #2] cmp r2, #0 - beq \not_found_handler(PLT) + beq \not_found(PLT) mov r0, r2 bx lr .type \name, %function .size \name, .-\name @@ -61,12 +61,12 @@ b .main_\lookup .type \name, %function .size \name, .-\name .endm -generate_lookup objc_msg_lookup objc_not_found_handler -generate_lookup objc_msg_lookup_stret objc_not_found_handler_stret +generate_lookup objc_msg_lookup objc_method_not_found +generate_lookup objc_msg_lookup_stret objc_method_not_found_stret generate_lookup_super objc_msg_lookup_super objc_msg_lookup generate_lookup_super objc_msg_lookup_super_stret objc_msg_lookup_stret ret_nil: adr r0, nil_method Index: src/runtime/lookup-asm/lookup-asm-mips-elf.S ================================================================== --- src/runtime/lookup-asm/lookup-asm-mips-elf.S +++ src/runtime/lookup-asm/lookup-asm-mips-elf.S @@ -20,11 +20,11 @@ .globl objc_msg_lookup_stret .globl objc_msg_lookup_super .globl objc_msg_lookup_super_stret .section .text -.macro generate_lookup name not_found_handler +.macro generate_lookup name not_found \name: beqz $a0, .ret_nil_\name lw $t0, 0($a0) lw $t0, 32($t0) @@ -62,11 +62,11 @@ lw $t0, 0($t0) #ifdef __PIC__ beqz $t0, .forward_\name #else - beqz $t0, \not_found_handler + beqz $t0, \not_found #endif move $v0, $t0 j $ra @@ -83,11 +83,11 @@ lui $gp, %hi(_gp_disp) addiu $gp, $gp, %lo(_gp_disp) addu $gp, $gp, $t9 addiu $gp, $gp, .forward_\name-\name - lw $t9, %call16(\not_found_handler)($gp) + lw $t9, %call16(\not_found)($gp) jr $t9 #endif .type \name, %function .size \name, .-\name .endm @@ -111,12 +111,12 @@ j $ra .type \name, %function .size \name, .-\name .endm -generate_lookup objc_msg_lookup objc_not_found_handler -generate_lookup objc_msg_lookup_stret objc_not_found_handler_stret +generate_lookup objc_msg_lookup objc_method_not_found +generate_lookup objc_msg_lookup_stret objc_method_not_found_stret generate_lookup_super objc_msg_lookup_super objc_msg_lookup generate_lookup_super objc_msg_lookup_super_stret objc_msg_lookup_stret nil_method: move $v0, $zero Index: src/runtime/lookup-asm/lookup-asm-ppc-elf.S ================================================================== --- src/runtime/lookup-asm/lookup-asm-ppc-elf.S +++ src/runtime/lookup-asm/lookup-asm-ppc-elf.S @@ -20,11 +20,11 @@ .globl objc_msg_lookup_stret .globl objc_msg_lookup_super .globl objc_msg_lookup_super_stret .section .text -.macro generate_lookup name not_found_handler +.macro generate_lookup name not_found \name: cmpwi %r3, 0 beq- ret_nil lwz %r5, 0(%r3) @@ -54,11 +54,11 @@ mr %r3, %r5 blr .forward_\name: - b \not_found_handler@plt + b \not_found@plt .type \name, %function .size \name, .-\name .endm .macro generate_lookup_super name lookup @@ -73,12 +73,12 @@ b .main_\lookup .type \name, %function .size \name, .-\name .endm -generate_lookup objc_msg_lookup objc_not_found_handler -generate_lookup objc_msg_lookup_stret objc_not_found_handler_stret +generate_lookup objc_msg_lookup objc_method_not_found +generate_lookup objc_msg_lookup_stret objc_method_not_found_stret generate_lookup_super objc_msg_lookup_super objc_msg_lookup generate_lookup_super objc_msg_lookup_super_stret objc_msg_lookup_stret ret_nil: mflr %r0 Index: src/runtime/lookup-asm/lookup-asm-x86-elf.S ================================================================== --- src/runtime/lookup-asm/lookup-asm-x86-elf.S +++ src/runtime/lookup-asm/lookup-asm-x86-elf.S @@ -20,11 +20,11 @@ .globl objc_msg_lookup_stret .globl objc_msg_lookup_super .globl objc_msg_lookup_super_stret .section .text -.macro generate_lookup name not_found_handler +.macro generate_lookup name not_found \name: movl 4(%esp), %edx testl %edx, %edx jz ret_nil @@ -49,11 +49,11 @@ ret .forward_\name: call get_eip .forward_L0_\name: - addl $\not_found_handler-.forward_L0_\name, %eax + addl $\not_found-.forward_L0_\name, %eax jmp *%eax .type \name, %function .size \name, .-\name .endm @@ -68,12 +68,12 @@ jmp .main_\lookup .type \name, %function .size \name, .-\name .endm -generate_lookup objc_msg_lookup objc_not_found_handler -generate_lookup objc_msg_lookup_stret objc_not_found_handler_stret +generate_lookup objc_msg_lookup objc_method_not_found +generate_lookup objc_msg_lookup_stret objc_method_not_found_stret generate_lookup_super objc_msg_lookup_super objc_msg_lookup generate_lookup_super objc_msg_lookup_super_stret objc_msg_lookup_stret ret_nil: call get_eip Index: src/runtime/lookup-asm/lookup-asm-x86-win32.S ================================================================== --- src/runtime/lookup-asm/lookup-asm-x86-win32.S +++ src/runtime/lookup-asm/lookup-asm-x86-win32.S @@ -20,11 +20,11 @@ .globl _objc_msg_lookup_stret .globl _objc_msg_lookup_super .globl _objc_msg_lookup_super_stret .section .text -.macro generate_lookup name not_found_handler +.macro generate_lookup name not_found \name: movl 4(%esp), %edx testl %edx, %edx jz ret_nil @@ -49,11 +49,11 @@ ret .forward_\name: call get_eip .forward_L0_\name: - addl $\not_found_handler-.forward_L0_\name, %eax + addl $\not_found-.forward_L0_\name, %eax jmp *%eax .endm .macro generate_lookup_super name lookup \name: @@ -64,12 +64,12 @@ movl 4(%edx), %edx movl 32(%edx), %edx jmp .main_\lookup .endm -generate_lookup _objc_msg_lookup _objc_not_found_handler -generate_lookup _objc_msg_lookup_stret _objc_not_found_handler_stret +generate_lookup _objc_msg_lookup _objc_method_not_found +generate_lookup _objc_msg_lookup_stret _objc_method_not_found_stret generate_lookup_super _objc_msg_lookup_super _objc_msg_lookup generate_lookup_super _objc_msg_lookup_super_stret _objc_msg_lookup_stret ret_nil: call get_eip Index: src/runtime/lookup.m ================================================================== --- src/runtime/lookup.m +++ src/runtime/lookup.m @@ -21,16 +21,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; +static void *forward_handler = NULL; +static void *forward_handler_stret = NULL; static IMP -common_not_found_handler(id obj, SEL sel, IMP (*lookup)(id, SEL), - IMP (*forward_handler)(id, SEL)) +common_method_not_found(id obj, SEL sel, IMP (*lookup)(id, SEL), void *forward) { 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)); @@ -52,29 +51,67 @@ * been initialized together with its superclasses. */ return lookup(obj, sel); } - if (forward_handler != NULL) - return forward_handler(obj, sel); + /* Try resolveClassMethod:/resolveInstanceMethod: */ + if (class_isMetaClass(object_getClass(obj))) { + Class cls = object_getClass(obj); + + if (class_respondsToSelector(cls, + @selector(resolveClassMethod:)) && + [obj resolveClassMethod: sel]) { + if (!class_respondsToSelector(cls, sel)) + OBJC_ERROR("[%s resolveClassMethod: %s] " + "returned true without adding the method!", + class_getName(obj), sel_getName(sel)); + + return lookup(obj, sel); + } + } else { + Class cls = object_getClass(obj); + Class metacls = object_getClass(cls); + + if (class_respondsToSelector(metacls, + @selector(resolveInstanceMethod:)) && + [cls resolveInstanceMethod: sel]) { + if (!class_respondsToSelector(cls, sel)) + OBJC_ERROR("[%s resolveInstanceMethod: %s] " + "returned true without adding the method!", + class_getName(object_getClass(obj)), + sel_getName(sel)); + + return lookup(obj, sel); + } + } + + if (forward != NULL) + return forward; 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) +objc_method_not_found(id obj, SEL sel) { - return common_not_found_handler(obj, sel, objc_msg_lookup, - objc_forward_handler); + return common_method_not_found(obj, sel, objc_msg_lookup, + forward_handler); } IMP -objc_not_found_handler_stret(id obj, SEL sel) +objc_method_not_found_stret(id obj, SEL sel) +{ + return common_method_not_found(obj, sel, objc_msg_lookup_stret, + forward_handler_stret); +} + +void +objc_setForwardHandler(void *forward, void *forward_stret) { - return common_not_found_handler(obj, sel, objc_msg_lookup_stret, - objc_forward_handler_stret); + forward_handler = forward; + forward_handler_stret = forward_stret; } bool class_respondsToSelector(Class cls, SEL sel) { @@ -90,11 +127,11 @@ { return nil; } static OF_INLINE IMP -common_lookup(id obj, SEL sel, IMP (*not_found_handler)(id, SEL)) +common_lookup(id obj, SEL sel, IMP (*not_found)(id, SEL)) { IMP imp; if (obj == nil) return (IMP)nil_method; @@ -101,51 +138,51 @@ imp = objc_sparsearray_get(object_getClass(obj)->dtable, (uint32_t)sel->uid); if (imp == NULL) - return not_found_handler(obj, sel); + return not_found(obj, sel); return imp; } IMP objc_msg_lookup(id obj, SEL sel) { - return common_lookup(obj, sel, objc_not_found_handler); + return common_lookup(obj, sel, objc_method_not_found); } IMP objc_msg_lookup_stret(id obj, SEL sel) { - return common_lookup(obj, sel, objc_not_found_handler_stret); + return common_lookup(obj, sel, objc_method_not_found_stret); } static OF_INLINE IMP common_lookup_super(struct objc_super *super, SEL sel, - IMP (*not_found_handler)(id, SEL)) + IMP (*not_found)(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 not_found_handler(super->self, sel); + return not_found(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); + return common_lookup_super(super, sel, objc_method_not_found); } IMP objc_msg_lookup_super_stret(struct objc_super *super, SEL sel) { - return common_lookup_super(super, sel, objc_not_found_handler_stret); + return common_lookup_super(super, sel, objc_method_not_found_stret); } #endif Index: src/runtime/runtime.h ================================================================== --- src/runtime/runtime.h +++ src/runtime/runtime.h @@ -206,12 +206,11 @@ 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 void objc_setForwardHandler(void*, void*); extern id objc_autorelease(id); extern void* objc_autoreleasePoolPush(void); extern void objc_autoreleasePoolPop(void*); extern id _objc_rootAutorelease(id); /* Used by the compiler, but can be called manually. */ Index: tests/ForwardingTests.m ================================================================== --- tests/ForwardingTests.m +++ tests/ForwardingTests.m @@ -45,19 +45,21 @@ @end @interface ForwardingTest (Test) + (void)test; - (void)test; -- (bool)forwardingTargetTest: (intptr_t)a0 - : (intptr_t)a1 - : (double)a2 - : (double)a3; +- (uint32_t)forwardingTargetTest: (intptr_t)a0 + : (intptr_t)a1 + : (double)a2 + : (double)a3; - (OFString*)forwardingTargetVarArgTest: (OFConstantString*)fmt, ...; - (long double)forwardingTargetFPRetTest; - (struct stret_test)forwardingTargetStRetTest; -- (void)notExistant; -- (struct stret_test)notExistantStRet; +- (void)forwardingTargetNilTest; +- (void)forwardingTargetSelfTest; +- (struct stret_test)forwardingTargetNilStRetTest; +- (struct stret_test)forwardingTargetSelfStRetTest; @end @interface ForwardingTarget: OFObject @end @@ -114,32 +116,40 @@ sel_isEqual(selector, @selector(forwardingTargetVarArgTest:)) || sel_isEqual(selector, @selector(forwardingTargetFPRetTest)) || sel_isEqual(selector, @selector(forwardingTargetStRetTest))) return (id)((char*)target + (ptrdiff_t)add); - return nil; + if (sel_isEqual(selector, @selector(forwardingTargetNilTest)) || + sel_isEqual(selector, @selector(forwardingTargetNilStRetTest))) + return nil; + + if (sel_isEqual(selector, @selector(forwardingTargetSelfTest)) || + sel_isEqual(selector, @selector(forwardingTargetSelfStRetTest))) + return self; + + abort(); } @end @implementation ForwardingTarget -- (bool)forwardingTargetTest: (intptr_t)a0 - : (intptr_t)a1 - : (double)a2 - : (double)a3 +- (uint32_t)forwardingTargetTest: (intptr_t)a0 + : (intptr_t)a1 + : (double)a2 + : (double)a3 { OF_ENSURE(self == target); if (a0 != 0xDEADBEEF) - return false; + return 0; if (a1 != -1) - return false; + return 0; if (a2 != 1.25) - return false; + return 0; if (a3 != 2.75) - return false; + return 0; - return true; + return 0x12345678; } - (OFString*)forwardingTargetVarArgTest: (OFConstantString*)fmt, ... { va_list args; @@ -195,26 +205,32 @@ target = [[[ForwardingTarget alloc] init] autorelease]; TEST(@"-[forwardingTargetForSelector:]", [t forwardingTargetTest: 0xDEADBEEF : -1 : 1.25 - : 2.75]) - TEST(@"-[forwardingTargetForSelector:] with variable arguments", + : 2.75] == 0x12345678) + TEST(@"-[forwardingTargetForSelector:] variable arguments", [([t forwardingTargetVarArgTest: FMT, ARGS]) isEqual: RESULT]) - TEST(@"-[forwardingTargetForSelector:] with fp return", + TEST(@"-[forwardingTargetForSelector:] fp return", [t forwardingTargetFPRetTest] == 12345678.00006103515625) # ifdef OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET - TEST(@"-[forwardingTargetForSelector:] with struct return", + TEST(@"-[forwardingTargetForSelector:] struct return", !memcmp([t forwardingTargetStRetTest].s, "abcdefghijklmnopqrstuvwxyz", 27)) # endif - EXPECT_EXCEPTION(@"-[forwardingTargetForSelector:] with nil target", - OFNotImplementedException, [t notExistant]) + EXPECT_EXCEPTION(@"-[forwardingTargetForSelector:] nil target", + OFNotImplementedException, [t forwardingTargetNilTest]) + EXPECT_EXCEPTION(@"-[forwardingTargetForSelector:] self target", + OFNotImplementedException, [t forwardingTargetSelfTest]) # ifdef OF_HAVE_FORWARDING_TARGET_FOR_SELECTOR_STRET - EXPECT_EXCEPTION(@"-[forwardingTargetForSelector:] with nil target + " - @"stret", OFNotImplementedException, [t notExistantStRet]) + EXPECT_EXCEPTION(@"-[forwardingTargetForSelector:] nil target + " + @"stret", OFNotImplementedException, + [t forwardingTargetNilStRetTest]) + EXPECT_EXCEPTION(@"-[forwardingTargetForSelector:] self target + " + @"stret", OFNotImplementedException, + [t forwardingTargetSelfStRetTest]) # endif #endif [pool drain]; } @end