4 ms·
Would be interesting to see an updated writeup with focus on iOS on ARM.
by 0x0 15y ago
Would be interesting to see an updated writeup with focus on iOS on ARM.
- pmjordan 15y agoHere's the disassembly for objc_msgSend on ARMv6, iOS4.2.1 (sorry no ARMv7 devices on my desk at the moment). I'll try to annotate it: 0x32d98f0c <objc_msgSend+0>: teq r0, #0 ; 0x0 0x32d98f10 <objc_msgSend+4>: moveq r1, #0 ; 0x0 0x32d98f14 <objc_msgSend+8>: bxeq lr Tests if r0 (the receiver) is nil, and if so, sets r1 selector to 0x0 and returns. I guess there's no nil handler on ARM. Simple function return values are in registers r0-r3, so I guess r1 is set to 0 in case the caller is expecting a long long. If receiver is non-nil: 0x32d98f18 <objc_msgSend+12>: push {r3, r4, r5, r6} 0x32d98f1c <objc_msgSend+16>: ldr r4, [r0] ^ this loads the class pointer (isa) into r4 This looks similar to the bit twiddling x86 cache lookup in the class; it's somewhat harder to read than the x86 due to ARM's bit packing shortcuts[1]: 0x32d98f20 <objc_msgSend+20>: ldr r5, [r4, #8] 0x32d98f24 <objc_msgSend+24>: ldr r6, [r5] 0x32d98f28 <objc_msgSend+28>: add r3, r5, #8 ; 0x8 0x32d98f2c <objc_msgSend+32>: and r5, r6, r1, lsr #2 0x32d98f30 <objc_msgSend+36>: ldr r4, [r3, r5, lsl #2] Check if the method is NULL, and if so, jump to the cache miss at the end: 0x32d98f34 <objc_msgSend+40>: teq r4, #0 ; 0x0 0x32d98f38 <objc_msgSend+44>: add r5, r5, #1 ; 0x1 0x32d98f3c <objc_msgSend+48>: beq 0x32d98f60 <objc_msgSend+84> This would appear to be the part checking if this is the cache entry we're looking for: 0x32d98f40 <objc_msgSend+52>: ldr r12, [r4] 0x32d98f44 <objc_msgSend+56>: teq r1, r12 0x32d98f48 <objc_msgSend+60>: and r5, r5, r6 If it isn't, loop: 0x32d98f4c <objc_msgSend+64>: bne 0x32d98f30 <objc_msgSend+36> If it is, restore the registers and do an indirect jump into the method we found (I'm not sure what the teq r4,r4 is for): 0x32d98f50 <objc_msgSend+68>: ldr r12, [r4, #8] 0x32d98f54 <objc_msgSend+72>: teq r4, r4 0x32d98f58 <objc_msgSend+76>: pop {r3, r4, r5, r6} 0x32d98f5c <objc_msgSend+80>: bx r12 Tail call into the slow version with full lookup (after restoring the clobbered registers and the stack pointer): 0x32d98f60 <objc_msgSend+84>: pop {r3, r4, r5, r6} 0x32d98f64 <objc_msgSend+88>: b 0x32d98f68 <objc_msgSend_uncached> [1] A lazy excuse of course. I just haven't read or written anywhere near as much ARM assembly as x86.
- 0xced 15y agoThe source code of the Objective-C runtime is actually open source. See http://opensource.apple.com/source/objc4/objc4-493.11/runtime/Messengers.subproj/objc-msg-arm.s http://opensource.apple.com/source/objc4/objc4-493.11/runtim... for another commented version of objc_msgSend on ARM.
- pmjordan 15y agoAh, indeed. I checked the iOS section of opensource.apple.com and didn't find it there and falsely assumed that meant the ARM version was proprietary.