1 #include "objc-private.h"
3 // out-of-band parameter to objc_msgForward
5 #define kFwdMsgSendStret 0
7 // objc_msgSend parameters
10 #define SELECTOR 12[ebp]
11 #define FIRST_ARG 16[ebp]
13 // objc_msgSend_stret parameters
14 #define STRUCT_ADDR 8[ebp]
15 #define SELF_STRET 12[ebp]
16 #define SUPER_STRET 12[ebp]
17 #define SELECTOR_STRET 16[ebp]
19 // objc_super parameter to sendSuper
20 #define super_receiver 0
23 // struct objc_class fields
27 // struct objc_method fields
31 // struct objc_cache fields
36 void *_objc_forward_handler = NULL;
37 void *_objc_forward_stret_handler = NULL;
39 __declspec(naked) Method _cache_getMethod(Class cls, SEL sel, IMP objc_msgForward_imp)
48 // CacheLookup WORD_RETURN, CACHE_GET
58 mov eax, buckets[edi][edx*4]
61 cmp ecx, method_name[eax]
75 cmp ecx, method_imp[eax]
84 __declspec(naked) IMP _cache_getImp(Class cls, SEL sel)
93 // CacheLookup WORD_RETURN, CACHE_GET
103 mov eax, buckets[edi][edx*4]
106 cmp ecx, method_name[eax]
121 mov eax, method_imp[eax]
128 OBJC_EXPORT __declspec(naked) id objc_msgSend(id a, SEL b, ...)
134 // load receiver and selector
138 // check whether receiver is nil
142 // receiver (in eax) is non-nil: search the cache
145 // CacheLookup WORD_RETURN, MSG_SEND
154 mov eax, buckets[edi][edx*4]
157 cmp ecx, method_name[eax]
163 mov eax, method_imp[eax]
170 // cache miss: search method lists
177 // MethodTableLookup WORD_RETURN, MSG_SEND
182 call lookUpImpOrFoward
188 // message send to nil: return zero
190 // eax is already zero
198 OBJC_EXPORT __declspec(naked) double objc_msgSend_fpret(id a, SEL b, ...)
204 // load receiver and selector
208 // check whether receiver is nil
212 // receiver (in eax) is non-nil: search the cache
215 // CacheLookup WORD_RETURN, MSG_SEND
224 mov eax, buckets[edi][edx*4]
227 cmp ecx, method_name[eax]
233 mov eax, method_imp[eax]
240 // cache miss: search method lists
247 // MethodTableLookup WORD_RETURN, MSG_SEND
252 call lookUpImpOrFoward
258 // message send to nil: return zero
267 OBJC_EXPORT __declspec(naked) id objc_msgSendSuper(struct objc_super *a, SEL b, ...)
273 // load class and selector
276 mov edx, super_class[eax]
278 // search the cache (class in edx)
279 // CacheLookup WORD_RETURN, MSG_SENDSUPER
288 mov eax, buckets[edi][edx*4]
291 cmp ecx, method_name[eax]
297 mov eax, method_imp[eax]
301 mov edx, super_receiver[edx]
307 // cache miss: search method lists
313 mov edx, super_receiver[eax]
315 mov eax, super_class[eax]
317 // MethodTableLookup WORD_RETURN, MSG_SENDSUPER
322 call lookUpImpOrFoward
331 OBJC_EXPORT __declspec(naked) void objc_msgSend_stret(void)
337 // load receiver and selector
338 mov ecx, SELECTOR_STRET
341 // check whether receiver is nil
345 // receiver (in eax) is non-nil: search the cache
348 // CacheLookup WORD_RETURN, MSG_SEND
357 mov eax, buckets[edi][edx*4]
360 cmp ecx, method_name[eax]
366 mov eax, method_imp[eax]
369 mov edx, kFwdMsgSendStret
373 // cache miss: search method lists
380 // MethodTableLookup WORD_RETURN, MSG_SEND
385 call lookUpImpOrFoward
387 mov edx, kFwdMsgSendStret
391 // message send to nil: return zero
393 // eax is already zero
401 OBJC_EXPORT __declspec(naked) id objc_msgSendSuper_stret(struct objc_super *a, SEL b, ...)
407 // load class and selector
409 mov ecx, SELECTOR_STRET
410 mov edx, super_class[eax]
412 // search the cache (class in edx)
413 // CacheLookup WORD_RETURN, MSG_SENDSUPER
422 mov eax, buckets[edi][edx*4]
425 cmp ecx, method_name[eax]
431 mov eax, method_imp[eax]
435 mov edx, super_receiver[edx]
437 mov edx, kFwdMsgSendStret
441 // cache miss: search method lists
447 mov edx, super_receiver[eax]
449 mov eax, super_class[eax]
451 // MethodTableLookup WORD_RETURN, MSG_SENDSUPER
456 call lookUpImpOrFoward
458 mov edx, kFwdMsgSendStret
465 OBJC_EXPORT __declspec(naked) id _objc_msgForward(id a, SEL b, ...)
468 mov ecx, _objc_forward_handler
473 OBJC_EXPORT __declspec(naked) id _objc_msgForward_stret(id a, SEL b, ...)
476 mov ecx, _objc_forward_stret_handler
482 __declspec(naked) id _objc_msgForward_cached(id a, SEL b, ...)
485 cmp edx, kFwdMsgSendStret
489 jmp _objc_msgForward_stret
494 OBJC_EXPORT __declspec(naked) void method_invoke(void)
501 mov edx, method_name[ecx]
502 mov eax, method_imp[ecx]
511 OBJC_EXPORT __declspec(naked) void method_invoke_stret(void)
517 mov ecx, SELECTOR_STRET
518 mov edx, method_name[ecx]
519 mov eax, method_imp[ecx]
520 mov SELECTOR_STRET, edx