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
185 call _class_lookupMethodAndLoadCache
191 // message send to nil: return zero
193 // eax is already zero
201 OBJC_EXPORT __declspec(naked) double objc_msgSend_fpret(id a, SEL b, ...)
207 // load receiver and selector
212 // check whether selector is ignored
216 // check whether receiver is nil
220 // receiver (in eax) is non-nil: search the cache
223 // CacheLookup WORD_RETURN, MSG_SEND
232 mov eax, buckets[edi][edx*4]
235 cmp ecx, method_name[eax]
241 mov eax, method_imp[eax]
248 // cache miss: search method lists
255 // MethodTableLookup WORD_RETURN, MSG_SEND
258 call _class_lookupMethodAndLoadCache
264 // message send to nil: return zero
273 OBJC_EXPORT __declspec(naked) id objc_msgSendSuper(struct objc_super *a, SEL b, ...)
279 // load class and selector
282 mov edx, super_class[eax]
285 // check whether selector is ignored
289 // search the cache (class in edx)
290 // CacheLookup WORD_RETURN, MSG_SENDSUPER
299 mov eax, buckets[edi][edx*4]
302 cmp ecx, method_name[eax]
308 mov eax, method_imp[eax]
312 mov edx, super_receiver[edx]
318 // cache miss: search method lists
324 mov eax, super_receiver[edx]
326 mov eax, super_class[edx]
328 // MethodTableLookup WORD_RETURN, MSG_SENDSUPER
331 call _class_lookupMethodAndLoadCache
340 OBJC_EXPORT __declspec(naked) void objc_msgSend_stret(void)
346 // load receiver and selector
347 mov ecx, SELECTOR_STRET
351 // check whether selector is ignored
355 // check whether receiver is nil
359 // receiver (in eax) is non-nil: search the cache
362 // CacheLookup WORD_RETURN, MSG_SEND
371 mov eax, buckets[edi][edx*4]
374 cmp ecx, method_name[eax]
380 mov eax, method_imp[eax]
383 mov edx, kFwdMsgSendStret
387 // cache miss: search method lists
394 // MethodTableLookup WORD_RETURN, MSG_SEND
397 call _class_lookupMethodAndLoadCache
399 mov edx, kFwdMsgSendStret
403 // message send to nil: return zero
405 // eax is already zero
413 OBJC_EXPORT __declspec(naked) id objc_msgSendSuper_stret(struct objc_super *a, SEL b, ...)
419 // load class and selector
421 mov ecx, SELECTOR_STRET
422 mov edx, super_class[eax]
425 // check whether selector is ignored
429 // search the cache (class in edx)
430 // CacheLookup WORD_RETURN, MSG_SENDSUPER
439 mov eax, buckets[edi][edx*4]
442 cmp ecx, method_name[eax]
448 mov eax, method_imp[eax]
452 mov edx, super_receiver[edx]
454 mov edx, kFwdMsgSendStret
458 // cache miss: search method lists
464 mov eax, super_receiver[edx]
466 mov eax, super_class[edx]
468 // MethodTableLookup WORD_RETURN, MSG_SENDSUPER
471 call _class_lookupMethodAndLoadCache
473 mov edx, kFwdMsgSendStret
480 OBJC_EXPORT __declspec(naked) id _objc_msgForward(id a, SEL b, ...)
483 mov ecx, _objc_forward_handler
484 // forward:: support omitted here
489 OBJC_EXPORT __declspec(naked) id _objc_msgForward_stret(id a, SEL b, ...)
492 mov ecx, _objc_forward_stret_handler
493 // forward:: support omitted here
499 __declspec(naked) id _objc_msgForward_internal(id a, SEL b, ...)
502 cmp edx, kFwdMsgSendStret
506 jmp _objc_msgForward_stret
511 OBJC_EXPORT __declspec(naked) void method_invoke(void)
518 mov edx, method_name[ecx]
519 mov eax, method_imp[ecx]
528 OBJC_EXPORT __declspec(naked) void method_invoke_stret(void)
534 mov ecx, SELECTOR_STRET
535 mov edx, method_name[ecx]
536 mov eax, method_imp[ecx]
537 mov SELECTOR_STRET, edx
545 __declspec(naked) id _objc_ignored_method(id obj, SEL sel)