2 * Copyright (c) 1999-2007 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 #include <TargetConditionals.h>
25 #if defined(__i386__) && !TARGET_OS_SIMULATOR
27 /********************************************************************
28 ********************************************************************
30 ** objc-msg-i386.s - i386 code to support objc messaging.
32 ********************************************************************
33 ********************************************************************/
36 /********************************************************************
37 * Data used by the ObjC runtime.
39 ********************************************************************/
43 // _objc_entryPoints and _objc_exitPoints are used by objc
44 // to get the critical regions for which method caches
45 // cannot be garbage collected.
48 .private_extern _objc_entryPoints
51 .long __cache_getMethod
53 .long _objc_msgSend_fpret
54 .long _objc_msgSend_stret
55 .long _objc_msgSendSuper
56 .long _objc_msgSendSuper_stret
59 .private_extern _objc_exitPoints
64 .long LMsgSendFpretExit
65 .long LMsgSendStretExit
66 .long LMsgSendSuperExit
67 .long LMsgSendSuperStretExit
71 /********************************************************************
72 * List every exit insn from every messenger for debugger use.
75 * 1 word instruction's address
76 * 1 word type (ENTER or FAST_EXIT or SLOW_EXIT or NIL_EXIT)
80 * ENTER is the start of a dispatcher
81 * FAST_EXIT is method dispatch
82 * SLOW_EXIT is uncached method lookup
83 * NIL_EXIT is returning zero from a message sent to nil
84 * These must match objc-gdb.h.
85 ********************************************************************/
92 .section __DATA,__objc_msg_break
93 .globl _gdb_objc_messenger_breakpoints
94 _gdb_objc_messenger_breakpoints:
95 // contents populated by the macros below
97 .macro MESSENGER_START
99 .section __DATA,__objc_msg_break
104 .macro MESSENGER_END_FAST
106 .section __DATA,__objc_msg_break
111 .macro MESSENGER_END_SLOW
113 .section __DATA,__objc_msg_break
118 .macro MESSENGER_END_NIL
120 .section __DATA,__objc_msg_break
127 /********************************************************************
131 ********************************************************************/
149 /********************************************************************
151 * Structure definitions.
153 ********************************************************************/
155 // objc_super parameter to sendSuper
159 // Selected field offsets in class structure
170 buckets = 8 // variable length array
172 #if defined(OBJC_INSTRUMENTED)
173 // Cache instrumentation data, follows buckets
175 hitProbes = hitCount + 4
176 maxHitProbes = hitProbes + 4
177 missCount = maxHitProbes + 4
178 missProbes = missCount + 4
179 maxMissProbes = missProbes + 4
180 flushCount = maxMissProbes + 4
181 flushedEntries = flushCount + 4
183 // Buckets in CacheHitHistogram and CacheMissHistogram
184 CACHE_HISTOGRAM_SIZE = 512
188 //////////////////////////////////////////////////////////////////////
190 // ENTRY functionName
192 // Assembly directives to begin an exported function.
194 // Takes: functionName - name of the exported function
195 //////////////////////////////////////////////////////////////////////
211 //////////////////////////////////////////////////////////////////////
213 // END_ENTRY functionName
215 // Assembly directives to end an exported function. Just a placeholder,
216 // a close-parenthesis for ENTRY, until it is needed for something.
218 // Takes: functionName - name of the exported function
219 //////////////////////////////////////////////////////////////////////
224 //////////////////////////////////////////////////////////////////////
228 // Calls mcount() profiling routine. Must be called immediately on
229 // function entry, before any prologue executes.
231 //////////////////////////////////////////////////////////////////////
235 // Current stack contents: ret
239 // Current stack contents: ret, ebp, pad, pad
247 /////////////////////////////////////////////////////////////////////
250 // CacheLookup WORD_RETURN | STRUCT_RETURN, MSG_SEND | MSG_SENDSUPER | CACHE_GET, cacheMissLabel
252 // Locate the implementation for a selector in a class method cache.
254 // Takes: WORD_RETURN (first parameter is at sp+4)
255 // STRUCT_RETURN (struct address is at sp+4, first parameter at sp+8)
256 // MSG_SEND (first parameter is receiver)
257 // MSG_SENDSUPER (first parameter is address of objc_super structure)
258 // CACHE_GET (first parameter is class; return method triplet)
260 // class to search in %edx
262 // cacheMissLabel = label to branch to iff method is not cached
264 // On exit: (found) MSG_SEND and MSG_SENDSUPER: return imp in eax
265 // (found) CACHE_GET: return method triplet in eax
266 // (not found) jumps to cacheMissLabel
268 /////////////////////////////////////////////////////////////////////
271 // Values to specify to method lookup macros whether the return type of
272 // the method is word or structure.
276 // Values to specify to method lookup macros whether the first argument
277 // is an object/class reference or a 'objc_super' structure.
278 MSG_SEND = 0 // first argument is receiver, search the isa
279 MSG_SENDSUPER = 1 // first argument is objc_super, search the class
280 CACHE_GET = 2 // first argument is class, search that class
284 // load variables and save caller registers.
286 pushl %edi // save scratch register
287 movl cache(%edx), %edi // cache = class->cache
288 pushl %esi // save scratch register
290 #if defined(OBJC_INSTRUMENTED)
291 pushl %ebx // save non-volatile register
292 pushl %eax // save cache pointer
293 xorl %ebx, %ebx // probeCount = 0
295 movl mask(%edi), %esi // mask = cache->mask
296 movl %ecx, %edx // index = selector
297 shrl $$2, %edx // index = selector >> 2
299 // search the receiver's cache
304 // eax = method (soon)
305 LMsgSendProbeCache_$0_$1_$2:
306 #if defined(OBJC_INSTRUMENTED)
307 addl $$1, %ebx // probeCount += 1
309 andl %esi, %edx // index &= mask
310 movl buckets(%edi, %edx, 4), %eax // meth = cache->buckets[index]
312 testl %eax, %eax // check for end of bucket
313 je LMsgSendCacheMiss_$0_$1_$2 // go to cache miss code
314 cmpl method_name(%eax), %ecx // check for method name match
315 je LMsgSendCacheHit_$0_$1_$2 // go handle cache hit
316 addl $$1, %edx // bump index ...
317 jmp LMsgSendProbeCache_$0_$1_$2 // ... and loop
319 // not found in cache: restore state and go to callers handler
320 LMsgSendCacheMiss_$0_$1_$2:
321 #if defined(OBJC_INSTRUMENTED)
322 popl %edx // retrieve cache pointer
323 movl mask(%edx), %esi // mask = cache->mask
324 testl %esi, %esi // a mask of zero is only for the...
325 je LMsgSendMissInstrumentDone_$0_$1_$2 // ... emptyCache, do not record anything
327 // locate and update the CacheInstrumentation structure
328 addl $$1, %esi // entryCount = mask + 1
329 shll $$2, %esi // tableSize = entryCount * sizeof(entry)
330 addl $buckets, %esi // offset = buckets + tableSize
331 addl %edx, %esi // cacheData = &cache->buckets[mask+1]
333 movl missCount(%esi), %edi //
335 movl %edi, missCount(%esi) // cacheData->missCount += 1
336 movl missProbes(%esi), %edi //
338 movl %edi, missProbes(%esi) // cacheData->missProbes += probeCount
339 movl maxMissProbes(%esi), %edi// if (cacheData->maxMissProbes < probeCount)
341 jge LMsgSendMaxMissProbeOK_$0_$1_$2 //
342 movl %ebx, maxMissProbes(%esi)// cacheData->maxMissProbes = probeCount
343 LMsgSendMaxMissProbeOK_$0_$1_$2:
345 // update cache miss probe histogram
346 cmpl $CACHE_HISTOGRAM_SIZE, %ebx // pin probeCount to max index
347 jl LMsgSendMissHistoIndexSet_$0_$1_$2
348 movl $(CACHE_HISTOGRAM_SIZE-1), %ebx
349 LMsgSendMissHistoIndexSet_$0_$1_$2:
350 LEA_STATIC_DATA %esi, _CacheMissHistogram, EXTERNAL_SYMBOL
351 shll $$2, %ebx // convert probeCount to histogram index
352 addl %ebx, %esi // calculate &CacheMissHistogram[probeCount<<2]
353 movl 0(%esi), %edi // get current tally
355 movl %edi, 0(%esi) // tally += 1
356 LMsgSendMissInstrumentDone_$0_$1_$2:
357 popl %ebx // restore non-volatile register
360 .if $0 == WORD_RETURN // Regular word return
361 .if $1 == MSG_SEND // MSG_SEND
362 popl %esi // restore callers register
363 popl %edi // restore callers register
364 movl self(%esp), %edx // get messaged object
365 movl isa(%edx), %eax // get objects class
366 .elseif $1 == MSG_SENDSUPER // MSG_SENDSUPER
367 // replace "super" arg with "receiver"
368 movl super+8(%esp), %edi // get super structure
369 movl receiver(%edi), %edx // get messaged object
370 movl %edx, super+8(%esp) // make it the first argument
371 movl class(%edi), %eax // get messaged class
372 popl %esi // restore callers register
373 popl %edi // restore callers register
375 popl %esi // restore callers register
376 popl %edi // restore callers register
378 .else // Struct return
379 .if $1 == MSG_SEND // MSG_SEND (stret)
380 popl %esi // restore callers register
381 popl %edi // restore callers register
382 movl self_stret(%esp), %edx // get messaged object
383 movl isa(%edx), %eax // get objects class
384 .elseif $1 == MSG_SENDSUPER // MSG_SENDSUPER (stret)
385 // replace "super" arg with "receiver"
386 movl super_stret+8(%esp), %edi// get super structure
387 movl receiver(%edi), %edx // get messaged object
388 movl %edx, super_stret+8(%esp)// make it the first argument
389 movl class(%edi), %eax // get messaged class
390 popl %esi // restore callers register
391 popl %edi // restore callers register
393 !! This should not happen.
400 jmp $2 // go to callers handler
402 // eax points to matching cache entry
404 LMsgSendCacheHit_$0_$1_$2:
405 #if defined(OBJC_INSTRUMENTED)
406 popl %edx // retrieve cache pointer
407 movl mask(%edx), %esi // mask = cache->mask
408 testl %esi, %esi // a mask of zero is only for the...
409 je LMsgSendHitInstrumentDone_$0_$1_$2 // ... emptyCache, do not record anything
411 // locate and update the CacheInstrumentation structure
412 addl $$1, %esi // entryCount = mask + 1
413 shll $$2, %esi // tableSize = entryCount * sizeof(entry)
414 addl $buckets, %esi // offset = buckets + tableSize
415 addl %edx, %esi // cacheData = &cache->buckets[mask+1]
417 movl hitCount(%esi), %edi
419 movl %edi, hitCount(%esi) // cacheData->hitCount += 1
420 movl hitProbes(%esi), %edi
422 movl %edi, hitProbes(%esi) // cacheData->hitProbes += probeCount
423 movl maxHitProbes(%esi), %edi// if (cacheData->maxHitProbes < probeCount)
425 jge LMsgSendMaxHitProbeOK_$0_$1_$2
426 movl %ebx, maxHitProbes(%esi)// cacheData->maxHitProbes = probeCount
427 LMsgSendMaxHitProbeOK_$0_$1_$2:
429 // update cache hit probe histogram
430 cmpl $CACHE_HISTOGRAM_SIZE, %ebx // pin probeCount to max index
431 jl LMsgSendHitHistoIndexSet_$0_$1_$2
432 movl $(CACHE_HISTOGRAM_SIZE-1), %ebx
433 LMsgSendHitHistoIndexSet_$0_$1_$2:
434 LEA_STATIC_DATA %esi, _CacheHitHistogram, EXTERNAL_SYMBOL
435 shll $$2, %ebx // convert probeCount to histogram index
436 addl %ebx, %esi // calculate &CacheHitHistogram[probeCount<<2]
437 movl 0(%esi), %edi // get current tally
439 movl %edi, 0(%esi) // tally += 1
440 LMsgSendHitInstrumentDone_$0_$1_$2:
441 popl %ebx // restore non-volatile register
444 // load implementation address, restore state, and we're done
446 // method triplet is already in eax
448 movl method_imp(%eax), %eax // imp = method->method_imp
451 .if $0 == WORD_RETURN // Regular word return
452 .if $1 == MSG_SENDSUPER // MSG_SENDSUPER
453 // replace "super" arg with "self"
454 movl super+8(%esp), %edi
455 movl receiver(%edi), %esi
456 movl %esi, super+8(%esp)
458 .else // Struct return
459 .if $1 == MSG_SENDSUPER // MSG_SENDSUPER (stret)
460 // replace "super" arg with "self"
461 movl super_stret+8(%esp), %edi
462 movl receiver(%edi), %esi
463 movl %esi, super_stret+8(%esp)
467 // restore caller registers
473 /////////////////////////////////////////////////////////////////////
475 // MethodTableLookup WORD_RETURN | STRUCT_RETURN, MSG_SEND | MSG_SENDSUPER
477 // Takes: WORD_RETURN (first parameter is at sp+4)
478 // STRUCT_RETURN (struct address is at sp+4, first parameter at sp+8)
479 // MSG_SEND (first parameter is receiver)
480 // MSG_SENDSUPER (first parameter is address of objc_super structure)
485 // (all set by CacheLookup's miss case)
487 // Stack must be at 0xXXXXXXXc on entrance.
489 // On exit: esp unchanged
492 /////////////////////////////////////////////////////////////////////
494 .macro MethodTableLookup
497 // stack has return address and nothing else
498 subl $$(12+5*16), %esp
500 movdqa %xmm3, 4*16(%esp)
501 movdqa %xmm2, 3*16(%esp)
502 movdqa %xmm1, 2*16(%esp)
503 movdqa %xmm0, 1*16(%esp)
505 movl %eax, 8(%esp) // class
506 movl %ecx, 4(%esp) // selector
507 movl %edx, 0(%esp) // receiver
508 call __class_lookupMethodAndLoadCache3
510 movdqa 4*16(%esp), %xmm3
511 movdqa 3*16(%esp), %xmm2
512 movdqa 2*16(%esp), %xmm1
513 movdqa 1*16(%esp), %xmm0
515 addl $$(12+5*16), %esp // pop parameters
519 /********************************************************************
520 * Method _cache_getMethod(Class cls, SEL sel, IMP msgForward_internal_imp)
522 * If found, returns method triplet pointer.
523 * If not found, returns NULL.
525 * NOTE: _cache_getMethod never returns any cache entry whose implementation
526 * is _objc_msgForward_impcache. It returns 1 instead. This prevents thread-
527 * safety and memory management bugs in _class_lookupMethodAndLoadCache.
528 * See _class_lookupMethodAndLoadCache for details.
530 * _objc_msgForward_impcache is passed as a parameter because it's more
531 * efficient to do the (PIC) lookup once in the caller than repeatedly here.
532 ********************************************************************/
534 STATIC_ENTRY __cache_getMethod
536 // load the class and selector
537 movl selector(%esp), %ecx
538 movl self(%esp), %edx
541 CacheLookup WORD_RETURN, CACHE_GET, LGetMethodMiss
543 // cache hit, method triplet in %eax
544 movl first_arg(%esp), %ecx // check for _objc_msgForward_impcache
545 cmpl method_imp(%eax), %ecx // if (imp==_objc_msgForward_impcache)
546 je 1f // return (Method)1
547 ret // else return method triplet address
552 // cache miss, return nil
553 xorl %eax, %eax // zero %eax
557 END_ENTRY __cache_getMethod
560 /********************************************************************
561 * IMP _cache_getImp(Class cls, SEL sel)
563 * If found, returns method implementation.
564 * If not found, returns NULL.
565 ********************************************************************/
567 STATIC_ENTRY __cache_getImp
569 // load the class and selector
570 movl selector(%esp), %ecx
571 movl self(%esp), %edx
574 CacheLookup WORD_RETURN, CACHE_GET, LGetImpMiss
576 // cache hit, method triplet in %eax
577 movl method_imp(%eax), %eax // return method imp
581 // cache miss, return nil
582 xorl %eax, %eax // zero %eax
586 END_ENTRY __cache_getImp
589 /********************************************************************
591 * id objc_msgSend(id self, SEL _cmd,...);
593 ********************************************************************/
599 // load receiver and selector
600 movl selector(%esp), %ecx
601 movl self(%esp), %eax
603 // check whether receiver is nil
607 // receiver (in %eax) is non-nil: search the cache
609 movl isa(%eax), %edx // class = self->isa
610 CacheLookup WORD_RETURN, MSG_SEND, LMsgSendCacheMiss
611 xor %edx, %edx // set nonstret for msgForward_internal
615 // cache miss: go search the method lists
617 MethodTableLookup WORD_RETURN, MSG_SEND
618 xor %edx, %edx // set nonstret for msgForward_internal
619 jmp *%eax // goto *imp
621 // message sent to nil: redirect to nil receiver, if any
623 // %eax is already zero
630 // guaranteed non-nil entry point (disabled for now)
631 // .globl _objc_msgSendNonNil
632 // _objc_msgSendNonNil:
633 // movl self(%esp), %eax
634 // jmp LMsgSendReceiverOk
637 END_ENTRY _objc_msgSend
639 /********************************************************************
641 * id objc_msgSendSuper(struct objc_super *super, SEL _cmd,...);
643 * struct objc_super {
647 ********************************************************************/
649 ENTRY _objc_msgSendSuper
653 // load selector and class to search
654 movl super(%esp), %eax // struct objc_super
655 movl selector(%esp), %ecx
656 movl class(%eax), %edx // struct objc_super->class
658 // search the cache (class in %edx)
659 CacheLookup WORD_RETURN, MSG_SENDSUPER, LMsgSendSuperCacheMiss
660 xor %edx, %edx // set nonstret for msgForward_internal
662 jmp *%eax // goto *imp
664 // cache miss: go search the method lists
665 LMsgSendSuperCacheMiss:
666 MethodTableLookup WORD_RETURN, MSG_SENDSUPER
667 xor %edx, %edx // set nonstret for msgForward_internal
668 jmp *%eax // goto *imp
670 // ignored selector: return self
671 LMsgSendSuperIgnored:
672 movl super(%esp), %eax
673 movl receiver(%eax), %eax
678 END_ENTRY _objc_msgSendSuper
680 /********************************************************************
681 * id objc_msgSendv(id self, SEL _cmd, unsigned size, marg_list frame);
684 * (sp+4) is the message receiver,
685 * (sp+8) is the selector,
686 * (sp+12) is the size of the marg_list, in bytes,
687 * (sp+16) is the address of the marg_list
689 ********************************************************************/
694 trap // _objc_msgSendv is not for the kernel
698 // stack is currently aligned assuming no extra arguments
699 movl (marg_list+4)(%ebp), %edx
700 addl $8, %edx // skip self & selector
701 movl (marg_size+4)(%ebp), %ecx
702 subl $8, %ecx // skip self & selector
706 // %esp = %esp - (16 - ((numVariableArguments & 3) << 2))
707 movl %ecx, %eax // 16-byte align stack
715 movl 0(%edx, %ecx, 4), %eax
720 movl (selector+4)(%ebp), %ecx
722 movl (self+4)(%ebp),%ecx
730 END_ENTRY _objc_msgSendv
732 /********************************************************************
734 * double objc_msgSend_fpret(id self, SEL _cmd,...);
736 ********************************************************************/
738 ENTRY _objc_msgSend_fpret
742 // load receiver and selector
743 movl selector(%esp), %ecx
744 movl self(%esp), %eax
746 // check whether receiver is nil
748 je LMsgSendFpretNilSelf
750 // receiver (in %eax) is non-nil: search the cache
751 LMsgSendFpretReceiverOk:
752 movl isa(%eax), %edx // class = self->isa
753 CacheLookup WORD_RETURN, MSG_SEND, LMsgSendFpretCacheMiss
754 xor %edx, %edx // set nonstret for msgForward_internal
756 jmp *%eax // goto *imp
758 // cache miss: go search the method lists
759 LMsgSendFpretCacheMiss:
760 MethodTableLookup WORD_RETURN, MSG_SEND
761 xor %edx, %edx // set nonstret for msgForward_internal
762 jmp *%eax // goto *imp
764 // message sent to nil: redirect to nil receiver, if any
765 LMsgSendFpretNilSelf:
766 // %eax is already zero
773 END_ENTRY _objc_msgSend_fpret
775 /********************************************************************
776 * double objc_msgSendv_fpret(id self, SEL _cmd, unsigned size, marg_list frame);
779 * (sp+4) is the message receiver,
780 * (sp+8) is the selector,
781 * (sp+12) is the size of the marg_list, in bytes,
782 * (sp+16) is the address of the marg_list
784 ********************************************************************/
786 ENTRY _objc_msgSendv_fpret
789 trap // _objc_msgSendv is not for the kernel
793 // stack is currently aligned assuming no extra arguments
794 movl (marg_list+4)(%ebp), %edx
795 addl $8, %edx // skip self & selector
796 movl (marg_size+4)(%ebp), %ecx
797 subl $8, %ecx // skip self & selector
799 je LMsgSendvFpretArgsOK
801 // %esp = %esp - (16 - ((numVariableArguments & 3) << 2))
802 movl %ecx, %eax // 16-byte align stack
808 LMsgSendvFpretArgLoop:
810 movl 0(%edx, %ecx, 4), %eax
812 jg LMsgSendvFpretArgLoop
814 LMsgSendvFpretArgsOK:
815 movl (selector+4)(%ebp), %ecx
817 movl (self+4)(%ebp),%ecx
819 call _objc_msgSend_fpret
825 END_ENTRY _objc_msgSendv_fpret
827 /********************************************************************
829 * void objc_msgSend_stret(void *st_addr , id self, SEL _cmd, ...);
832 * objc_msgSend_stret is the struct-return form of msgSend.
833 * The ABI calls for (sp+4) to be used as the address of the structure
834 * being returned, with the parameters in the succeeding locations.
836 * On entry: (sp+4)is the address where the structure is returned,
837 * (sp+8) is the message receiver,
838 * (sp+12) is the selector
839 ********************************************************************/
841 ENTRY _objc_msgSend_stret
845 // load receiver and selector
846 movl self_stret(%esp), %eax
847 movl (selector_stret)(%esp), %ecx
849 // check whether receiver is nil
851 je LMsgSendStretNilSelf
853 // receiver (in %eax) is non-nil: search the cache
854 LMsgSendStretReceiverOk:
855 movl isa(%eax), %edx // class = self->isa
856 CacheLookup STRUCT_RETURN, MSG_SEND, LMsgSendStretCacheMiss
857 movl $1, %edx // set stret for objc_msgForward
859 jmp *%eax // goto *imp
861 // cache miss: go search the method lists
862 LMsgSendStretCacheMiss:
863 MethodTableLookup STRUCT_RETURN, MSG_SEND
864 movl $1, %edx // set stret for objc_msgForward
865 jmp *%eax // goto *imp
867 // message sent to nil: redirect to nil receiver, if any
868 LMsgSendStretNilSelf:
870 ret $4 // pop struct return address (#2995932)
872 // guaranteed non-nil entry point (disabled for now)
873 // .globl _objc_msgSendNonNil_stret
874 // _objc_msgSendNonNil_stret:
876 // movl self_stret(%esp), %eax
877 // jmp LMsgSendStretReceiverOk
880 END_ENTRY _objc_msgSend_stret
882 /********************************************************************
884 * void objc_msgSendSuper_stret(void *st_addr, struct objc_super *super, SEL _cmd, ...);
886 * struct objc_super {
891 * objc_msgSendSuper_stret is the struct-return form of msgSendSuper.
892 * The ABI calls for (sp+4) to be used as the address of the structure
893 * being returned, with the parameters in the succeeding registers.
895 * On entry: (sp+4)is the address where the structure is returned,
896 * (sp+8) is the address of the objc_super structure,
897 * (sp+12) is the selector
899 ********************************************************************/
901 ENTRY _objc_msgSendSuper_stret
905 // load selector and class to search
906 movl super_stret(%esp), %eax // struct objc_super
907 movl (selector_stret)(%esp), %ecx // get selector
908 movl class(%eax), %edx // struct objc_super->class
910 // search the cache (class in %edx)
911 CacheLookup STRUCT_RETURN, MSG_SENDSUPER, LMsgSendSuperStretCacheMiss
912 movl $1, %edx // set stret for objc_msgForward
914 jmp *%eax // goto *imp
916 // cache miss: go search the method lists
917 LMsgSendSuperStretCacheMiss:
918 MethodTableLookup STRUCT_RETURN, MSG_SENDSUPER
919 movl $1, %edx // set stret for objc_msgForward
920 jmp *%eax // goto *imp
922 LMsgSendSuperStretExit:
923 END_ENTRY _objc_msgSendSuper_stret
926 /********************************************************************
927 * void objc_msgSendv_stret(void *st_addr, id self, SEL _cmd, unsigned size, marg_list frame);
929 * objc_msgSendv_stret is the struct-return form of msgSendv.
930 * This function does not use the struct-return ABI; instead, the
931 * structure return address is passed as a normal parameter.
933 * On entry: (sp+4) is the address in which the returned struct is put,
934 * (sp+8) is the message receiver,
935 * (sp+12) is the selector,
936 * (sp+16) is the size of the marg_list, in bytes,
937 * (sp+20) is the address of the marg_list
939 ********************************************************************/
941 ENTRY _objc_msgSendv_stret
944 trap // _objc_msgSendv_stret is not for the kernel
948 subl $12, %esp // align stack assuming no extra arguments
949 movl (marg_list_stret+4)(%ebp), %edx
950 addl $8, %edx // skip self & selector
951 movl (marg_size_stret+4)(%ebp), %ecx
952 subl $5, %ecx // skip self & selector
954 jle LMsgSendvStretArgsOK
956 // %esp = %esp - (16 - ((numVariableArguments & 3) << 2))
957 movl %ecx, %eax // 16-byte align stack
963 LMsgSendvStretArgLoop:
965 movl 0(%edx, %ecx, 4), %eax
967 jg LMsgSendvStretArgLoop
969 LMsgSendvStretArgsOK:
970 movl (selector_stret+4)(%ebp), %ecx
972 movl (self_stret+4)(%ebp),%ecx
974 movl (struct_addr+4)(%ebp),%ecx
976 call _objc_msgSend_stret
982 END_ENTRY _objc_msgSendv_stret
985 /********************************************************************
987 * id _objc_msgForward(id self, SEL _cmd,...);
989 ********************************************************************/
991 // _FwdSel is @selector(forward::), set up in map_images().
992 // ALWAYS dereference _FwdSel to get to "forward::" !!
995 .private_extern _FwdSel
1000 LUnkSelStr: .ascii "Does not recognize selector %s (while forwarding %s)\0"
1002 .non_lazy_symbol_pointer
1004 .indirect_symbol __objc_forward_handler
1006 L_forward_stret_handler:
1007 .indirect_symbol __objc_forward_stret_handler
1010 STATIC_ENTRY __objc_msgForward_impcache
1011 // Method cache version
1013 // THIS IS NOT A CALLABLE C FUNCTION
1014 // Out-of-band register %edx is nonzero for stret, zero otherwise
1020 // Check return type (stret or not)
1022 jnz __objc_msgForward_stret
1023 jmp __objc_msgForward
1025 END_ENTRY _objc_msgForward_impcache
1028 ENTRY __objc_msgForward
1029 // Non-struct return version
1031 // Get PIC base into %edx
1032 call L__objc_msgForward$pic_base
1033 L__objc_msgForward$pic_base:
1036 // Call user handler, if any
1037 movl L_forward_handler-L__objc_msgForward$pic_base(%edx),%ecx
1039 testl %ecx, %ecx // if not NULL
1040 je 1f // skip to default handler
1041 jmp *%ecx // call __objc_forward_handler
1048 // Die if forwarding "forward::"
1049 movl (selector+4)(%ebp), %eax
1050 movl _FwdSel-L__objc_msgForward$pic_base(%edx),%ecx
1054 // Call [receiver forward:sel :margs]
1055 subl $8, %esp // 16-byte align the stack
1056 leal (self+4)(%ebp), %ecx
1057 pushl %ecx // &margs
1059 movl _FwdSel-L__objc_msgForward$pic_base(%edx),%ecx
1060 pushl %ecx // forward::
1061 pushl (self+4)(%ebp) // receiver
1070 // Call __objc_error(receiver, "unknown selector %s %s", "forward::", forwardedSel)
1071 subl $8, %esp // 16-byte align the stack
1072 pushl (selector+4+4)(%ebp) // the forwarded selector
1073 movl _FwdSel-L__objc_msgForward$pic_base(%edx),%eax
1075 leal LUnkSelStr-L__objc_msgForward$pic_base(%edx),%eax
1077 pushl (self+4)(%ebp)
1078 call ___objc_error // never returns
1080 END_ENTRY __objc_msgForward
1083 ENTRY __objc_msgForward_stret
1084 // Struct return version
1086 // Get PIC base into %edx
1087 call L__objc_msgForwardStret$pic_base
1088 L__objc_msgForwardStret$pic_base:
1091 // Call user handler, if any
1092 movl L_forward_stret_handler-L__objc_msgForwardStret$pic_base(%edx), %ecx
1094 testl %ecx, %ecx // if not NULL
1095 je 1f // skip to default handler
1096 jmp *%ecx // call __objc_forward_stret_handler
1103 // Die if forwarding "forward::"
1104 movl (selector_stret+4)(%ebp), %eax
1105 movl _FwdSel-L__objc_msgForwardStret$pic_base(%edx), %ecx
1107 je LMsgForwardStretError
1109 // Call [receiver forward:sel :margs]
1110 subl $8, %esp // 16-byte align the stack
1111 leal (self_stret+4)(%ebp), %ecx
1112 pushl %ecx // &margs
1114 movl _FwdSel-L__objc_msgForwardStret$pic_base(%edx),%ecx
1115 pushl %ecx // forward::
1116 pushl (self_stret+4)(%ebp) // receiver
1122 ret $4 // pop struct return address (#2995932)
1124 LMsgForwardStretError:
1125 // Call __objc_error(receiver, "unknown selector %s %s", "forward::", forwardedSelector)
1126 subl $8, %esp // 16-byte align the stack
1127 pushl (selector_stret+4+4)(%ebp) // the forwarded selector
1128 leal _FwdSel-L__objc_msgForwardStret$pic_base(%edx),%eax
1130 leal LUnkSelStr-L__objc_msgForwardStret$pic_base(%edx),%eax
1132 pushl (self_stret+4)(%ebp)
1133 call ___objc_error // never returns
1135 END_ENTRY __objc_msgForward_stret
1138 ENTRY _method_invoke
1140 movl selector(%esp), %ecx
1141 movl method_name(%ecx), %edx
1142 movl method_imp(%ecx), %eax
1143 movl %edx, selector(%esp)
1146 END_ENTRY _method_invoke
1149 ENTRY _method_invoke_stret
1151 movl selector_stret(%esp), %ecx
1152 movl method_name(%ecx), %edx
1153 movl method_imp(%ecx), %eax
1154 movl %edx, selector_stret(%esp)
1157 END_ENTRY _method_invoke_stret
1160 .section __DATA,__objc_msg_break