.macro MSGSEND receiver, sel, fpret .cfi_startproc movl \receiver(%esp), %eax test %eax, %eax # If the receiver is nil jz 4f # return nil test $SMALLOBJ_MASK, %eax # Check if the receiver is a small object jnz 6f # Get the small object class mov (%eax), %eax # Load the class 1: # classLoaded movl \sel(%esp), %ecx mov DTABLE_OFFSET(%eax), %eax # Load the dtable from the class mov (%ecx), %ecx # Load the selector index # Register use at this point: # %eax: dtable # %ecx: Selector index # %edx: selector index fragment mov SHIFT_OFFSET(%eax), %edx # Load the shift (dtable size) cmpl $8, %edx # If this is a small dtable, jump to the small dtable handlers je 2f cmpl $0, %edx je 3f mov %ecx, %edx shrl $16, %edx movl DATA_OFFSET(%eax, %edx, 4), %eax 2: # dtable16: movzbl %ch, %edx movl DATA_OFFSET(%eax, %edx, 4), %eax 3: # dtable8: movzbl %cl, %edx movl DATA_OFFSET(%eax, %edx, 4), %eax test %eax, %eax jz 5f # Nil slot - invoke some kind of forwarding mechanism mov SLOT_OFFSET(%eax), %ecx #ifdef _MSC_VER call *CDECL(__guard_check_icall_fptr) #endif jmp *%ecx 4: # returnNil: .if \fpret fldz .else xor %eax, %eax # return 0 (int) xor %edx, %edx # Return 64-bit zero (%edx is # caller-save, so it's safe to do this in the general case. .endif ret 5: # slowSend: mov \sel(%esp), %ecx lea \receiver(%esp), %eax push %ecx # Unused, stack alignment push %ecx # _cmd push %eax # &self .cfi_def_cfa_offset 16 call CDECL(slowMsgLookup)@PLT add $12, %esp # restore the stack #ifdef _MSC_VER mov %eax, %ecx call *CDECL(__guard_check_icall_fptr) jmp *%ecx #else jmp *%eax #endif 6: # smallObject: push %ebx # Save old %ebx calll 7f 7: popl %ebx; 8: #if __ELF__ # ELF can support GOT-relative addressing; # PE/COFF and Mach-O need a text relocation. addl $_GLOBAL_OFFSET_TABLE_+(8b-7b), %ebx leal SmallObjectClasses@GOTOFF(%ebx), %eax #else leal CDECL(SmallObjectClasses), %eax #endif mov (%eax), %eax popl %ebx jmp 1b .cfi_endproc .endm #ifdef _WIN32 .text .def @feat.00; .scl 3; .type 0; .endef .globl @feat.00 @feat.00 = 1 .def _objc_msgSend; .scl 2; .type 32; .endef .def _objc_msgSend_fpret; .scl 2; .type 32; .endef .def _objc_msgSend_stret; .scl 2; .type 32; .endef #endif .globl CDECL(objc_msgSend_fpret) TYPE_DIRECTIVE(CDECL(objc_msgSend_fpret), @function) CDECL(objc_msgSend_fpret): MSGSEND 4, 8, 1 .globl CDECL(objc_msgSend) TYPE_DIRECTIVE(CDECL(objc_msgSend), @function) CDECL(objc_msgSend): MSGSEND 4, 8, 0 .globl CDECL(objc_msgSend_stret) TYPE_DIRECTIVE(CDECL(objc_msgSend_stret), @function) CDECL(objc_msgSend_stret): MSGSEND 8, 12, 0 #ifdef _WIN32 .section .drectve,"yn" EXPORT_SYMBOL(objc_msgSend) EXPORT_SYMBOL(objc_msgSend_stret) EXPORT_SYMBOL(objc_msgSend_fpret) #endif