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
139 // check whether selector is ignored
143 // check whether receiver is nil
147 // receiver (in eax) is non-nil: search the cache
150 // CacheLookup WORD_RETURN, MSG_SEND
159 mov eax, buckets[edi][edx*4]
162 cmp ecx, method_name[eax]
168 mov eax, method_imp[eax]
175 // cache miss: search method lists
182 // MethodTableLookup WORD_RETURN, MSG_SEND
186 call _class_lookupMethodAndLoadCache3
192 // message send to nil: return zero
194 // eax is already zero
202 OBJC_EXPORT __declspec(naked) double objc_msgSend_fpret(id a, SEL b, ...)
208 // load receiver and selector
213 // check whether selector is ignored
217 // check whether receiver is nil
221 // receiver (in eax) is non-nil: search the cache
224 // CacheLookup WORD_RETURN, MSG_SEND
233 mov eax, buckets[edi][edx*4]
236 cmp ecx, method_name[eax]
242 mov eax, method_imp[eax]
249 // cache miss: search method lists
256 // MethodTableLookup WORD_RETURN, MSG_SEND
260 call _class_lookupMethodAndLoadCache3
266 // message send to nil: return zero
275 OBJC_EXPORT __declspec(naked) id objc_msgSendSuper(struct objc_super *a, SEL b, ...)
281 // load class and selector
284 mov edx, super_class[eax]
287 // check whether selector is ignored
291 // search the cache (class in edx)
292 // CacheLookup WORD_RETURN, MSG_SENDSUPER
301 mov eax, buckets[edi][edx*4]
304 cmp ecx, method_name[eax]
310 mov eax, method_imp[eax]
314 mov edx, super_receiver[edx]
320 // cache miss: search method lists
326 mov edx, super_receiver[eax]
328 mov eax, super_class[eax]
330 // MethodTableLookup WORD_RETURN, MSG_SENDSUPER
334 call _class_lookupMethodAndLoadCache3
343 OBJC_EXPORT __declspec(naked) void objc_msgSend_stret(void)
349 // load receiver and selector
350 mov ecx, SELECTOR_STRET
354 // check whether selector is ignored
358 // check whether receiver is nil
362 // receiver (in eax) is non-nil: search the cache
365 // CacheLookup WORD_RETURN, MSG_SEND
374 mov eax, buckets[edi][edx*4]
377 cmp ecx, method_name[eax]
383 mov eax, method_imp[eax]
386 mov edx, kFwdMsgSendStret
390 // cache miss: search method lists
397 // MethodTableLookup WORD_RETURN, MSG_SEND
401 call _class_lookupMethodAndLoadCache3
403 mov edx, kFwdMsgSendStret
407 // message send to nil: return zero
409 // eax is already zero
417 OBJC_EXPORT __declspec(naked) id objc_msgSendSuper_stret(struct objc_super *a, SEL b, ...)
423 // load class and selector
425 mov ecx, SELECTOR_STRET
426 mov edx, super_class[eax]
429 // check whether selector is ignored
433 // search the cache (class in edx)
434 // CacheLookup WORD_RETURN, MSG_SENDSUPER
443 mov eax, buckets[edi][edx*4]
446 cmp ecx, method_name[eax]
452 mov eax, method_imp[eax]
456 mov edx, super_receiver[edx]
458 mov edx, kFwdMsgSendStret
462 // cache miss: search method lists
468 mov edx, super_receiver[eax]
470 mov eax, super_class[eax]
472 // MethodTableLookup WORD_RETURN, MSG_SENDSUPER
476 call _class_lookupMethodAndLoadCache3
478 mov edx, kFwdMsgSendStret
485 OBJC_EXPORT __declspec(naked) id _objc_msgForward(id a, SEL b, ...)
488 mov ecx, _objc_forward_handler
493 OBJC_EXPORT __declspec(naked) id _objc_msgForward_stret(id a, SEL b, ...)
496 mov ecx, _objc_forward_stret_handler
502 __declspec(naked) id _objc_msgForward_cached(id a, SEL b, ...)
505 cmp edx, kFwdMsgSendStret
509 jmp _objc_msgForward_stret
514 OBJC_EXPORT __declspec(naked) void method_invoke(void)
521 mov edx, method_name[ecx]
522 mov eax, method_imp[ecx]
531 OBJC_EXPORT __declspec(naked) void method_invoke_stret(void)
537 mov ecx, SELECTOR_STRET
538 mov edx, method_name[ecx]
539 mov eax, method_imp[ecx]
540 mov SELECTOR_STRET, edx
548 __declspec(naked) id _objc_ignored_method(id obj, SEL sel)