1 #include "objc-private.h"
3 // out-of-band parameter to objc_msgForward
5 #define kFwdMsgSendStret 0
7 // objc_msgSend parameters
13 // objc_msgSend_stret parameters
17 #define selector_stret 12
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)
42 mov ecx, selector[esp]
45 // CacheLookup WORD_RETURN, CACHE_GET
55 mov eax, buckets[edi][edx*4]
58 cmp ecx, method_name[eax]
70 mov ecx, 8+first_arg[esp]
71 cmp ecx, method_imp[eax]
79 __declspec(naked) IMP _cache_getImp(Class cls, SEL sel)
82 mov ecx, selector[esp]
85 // CacheLookup WORD_RETURN, CACHE_GET
95 mov eax, buckets[edi][edx*4]
98 cmp ecx, method_name[eax]
112 mov eax, method_imp[eax]
119 OBJC_EXPORT __declspec(naked) id objc_msgSend(id a, SEL b, ...)
122 // load receiver and selector
123 mov ecx, selector[esp]
127 // check whether selector is ignored
131 // check whether receiver is nil
135 // receiver (in eax) is non-nil: search the cache
138 // CacheLookup WORD_RETURN, MSG_SEND
147 mov eax, buckets[edi][edx*4]
150 cmp ecx, method_name[eax]
156 mov eax, method_imp[eax]
162 // cache miss: search method lists
169 // MethodTableLookup WORD_RETURN, MSG_SEND
173 call _class_lookupMethodAndLoadCache
179 // message send to nil: return zero
181 // eax is already zero
188 OBJC_EXPORT __declspec(naked) double objc_msgSend_fpret(id a, SEL b, ...)
191 // load receiver and selector
192 mov ecx, selector[esp]
196 // check whether selector is ignored
200 // check whether receiver is nil
204 // receiver (in eax) is non-nil: search the cache
207 // CacheLookup WORD_RETURN, MSG_SEND
216 mov eax, buckets[edi][edx*4]
219 cmp ecx, method_name[eax]
225 mov eax, method_imp[eax]
231 // cache miss: search method lists
238 // MethodTableLookup WORD_RETURN, MSG_SEND
242 call _class_lookupMethodAndLoadCache
248 // message send to nil: return zero
256 OBJC_EXPORT __declspec(naked) id objc_msgSendSuper(struct objc_super *a, SEL b, ...)
259 // load class and selector
261 mov ecx, selector[esp]
262 mov edx, super_class[eax]
265 // check whether selector is ignored
269 // search the cache (class in edx)
270 // CacheLookup WORD_RETURN, MSG_SENDSUPER
279 mov eax, buckets[edi][edx*4]
282 cmp ecx, method_name[eax]
288 mov eax, method_imp[eax]
292 mov edx, super_receiver[edx]
297 // cache miss: search method lists
303 mov eax, super_receiver[edx]
305 mov eax, super_class[edx]
307 // MethodTableLookup WORD_RETURN, MSG_SENDSUPER
311 call _class_lookupMethodAndLoadCache
320 OBJC_EXPORT __declspec(naked) void objc_msgSend_stret(void)
323 // load receiver and selector
324 mov ecx, selector_stret[esp]
325 mov eax, self_stret[esp]
328 // check whether selector is ignored
332 // check whether receiver is nil
336 // receiver (in eax) is non-nil: search the cache
339 // CacheLookup WORD_RETURN, MSG_SEND
348 mov eax, buckets[edi][edx*4]
351 cmp ecx, method_name[eax]
357 mov eax, method_imp[eax]
360 mov edx, kFwdMsgSendStret
363 // cache miss: search method lists
367 mov eax, self_stret[esp]
370 // MethodTableLookup WORD_RETURN, MSG_SEND
374 call _class_lookupMethodAndLoadCache
377 mov edx, kFwdMsgSendStret
380 // message send to nil: return zero
382 // eax is already zero
389 OBJC_EXPORT __declspec(naked) id objc_msgSendSuper_stret(struct objc_super *a, SEL b, ...)
392 // load class and selector
393 mov eax, super_stret[esp]
394 mov ecx, selector_stret[esp]
395 mov edx, super_class[eax]
398 // check whether selector is ignored
402 // search the cache (class in edx)
403 // CacheLookup WORD_RETURN, MSG_SENDSUPER
412 mov eax, buckets[edi][edx*4]
415 cmp ecx, method_name[eax]
421 mov eax, method_imp[eax]
425 mov edx, super_receiver[edx]
427 mov edx, kFwdMsgSendStret
430 // cache miss: search method lists
435 mov edx, super_stret[esp]
436 mov eax, super_receiver[edx]
437 mov super_stret[esp], eax
438 mov eax, super_class[edx]
440 // MethodTableLookup WORD_RETURN, MSG_SENDSUPER
444 call _class_lookupMethodAndLoadCache
447 mov edx, kFwdMsgSendStret
453 OBJC_EXPORT __declspec(naked) id _objc_msgForward(id a, SEL b, ...)
456 mov ecx, _objc_forward_handler
457 // forward:: support omitted here
462 OBJC_EXPORT __declspec(naked) id _objc_msgForward_stret(id a, SEL b, ...)
465 mov ecx, _objc_forward_stret_handler
466 // forward:: support omitted here
472 __declspec(naked) id _objc_msgForward_internal(id a, SEL b, ...)
475 cmp edx, kFwdMsgSendStret
479 jmp _objc_msgForward_stret
484 OBJC_EXPORT __declspec(naked) void method_invoke(void)
487 mov ecx, selector[esp]
488 mov edx, method_name[ecx]
489 mov eax, method_imp[ecx]
490 mov selector[esp], edx
496 OBJC_EXPORT __declspec(naked) void method_invoke_stret(void)
499 mov ecx, selector_stret[esp]
500 mov edx, method_name[ecx]
501 mov eax, method_imp[ecx]
502 mov selector_stret[esp], edx