2 * Copyright (c) 1999-2009 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_IPHONE_SIMULATOR
27 #include "objc-config.h"
31 // _objc_entryPoints and _objc_exitPoints are used by objc
32 // to get the critical regions for which method caches
33 // cannot be garbage collected.
36 .private_extern _objc_entryPoints
40 .long _objc_msgSend_fpret
41 .long _objc_msgSend_stret
42 .long _objc_msgSendSuper
43 .long _objc_msgSendSuper2
44 .long _objc_msgSendSuper_stret
45 .long _objc_msgSendSuper2_stret
48 .private_extern _objc_exitPoints
52 .long LMsgSendFpretExit
53 .long LMsgSendStretExit
54 .long LMsgSendSuperExit
55 .long LMsgSendSuper2Exit
56 .long LMsgSendSuperStretExit
57 .long LMsgSendSuper2StretExit
61 /********************************************************************
62 * List every exit insn from every messenger for debugger use.
65 * 1 word instruction's address
66 * 1 word type (ENTER or FAST_EXIT or SLOW_EXIT or NIL_EXIT)
70 * ENTER is the start of a dispatcher
71 * FAST_EXIT is method dispatch
72 * SLOW_EXIT is uncached method lookup
73 * NIL_EXIT is returning zero from a message sent to nil
74 * These must match objc-gdb.h.
75 ********************************************************************/
82 .section __DATA,__objc_msg_break
83 .globl _gdb_objc_messenger_breakpoints
84 _gdb_objc_messenger_breakpoints:
85 // contents populated by the macros below
87 .macro MESSENGER_START
89 .section __DATA,__objc_msg_break
94 .macro MESSENGER_END_FAST
96 .section __DATA,__objc_msg_break
101 .macro MESSENGER_END_SLOW
103 .section __DATA,__objc_msg_break
108 .macro MESSENGER_END_NIL
110 .section __DATA,__objc_msg_break
117 /********************************************************************
118 * Names for relative labels
119 * DO NOT USE THESE LABELS ELSEWHERE
120 * Reserved labels: 5: 6: 7: 8: 9:
121 ********************************************************************/
123 #define LCacheMiss_f 5f
124 #define LCacheMiss_b 5b
125 #define LNilTestDone 6
126 #define LNilTestDone_f 6f
127 #define LNilTestDone_b 6b
128 #define LNilTestSlow 7
129 #define LNilTestSlow_f 7f
130 #define LNilTestSlow_b 7b
131 #define LGetIsaDone 8
132 #define LGetIsaDone_f 8f
133 #define LGetIsaDone_b 8b
134 #define LGetIsaSlow 9
135 #define LGetIsaSlow_f 9f
136 #define LGetIsaSlow_b 9b
138 /********************************************************************
140 ********************************************************************/
147 #define SUPER_STRET 6
150 /********************************************************************
152 * Structure definitions.
154 ********************************************************************/
164 #define struct_addr 4
167 #define super_stret 8
168 #define selector_stret 12
169 #define marg_size_stret 16
170 #define marg_list_stret 20
172 // objc_super parameter to sendSuper
176 // Selected field offsets in class structure
181 #define method_name 0
185 //////////////////////////////////////////////////////////////////////
187 // ENTRY functionName
189 // Assembly directives to begin an exported function.
191 // Takes: functionName - name of the exported function
192 //////////////////////////////////////////////////////////////////////
210 //////////////////////////////////////////////////////////////////////
212 // END_ENTRY functionName
214 // Assembly directives to end an exported function. Just a placeholder,
215 // a close-parenthesis for ENTRY, until it is needed for something.
217 // Takes: functionName - name of the exported function
218 //////////////////////////////////////////////////////////////////////
225 /////////////////////////////////////////////////////////////////////
227 // CacheLookup return-type
229 // Locate the implementation for a selector in a class method cache.
232 // $0 = NORMAL, FPRET, STRET, SUPER, SUPER_STRET, GETIMP
233 // ecx = selector to search for
234 // edx = class to search
236 // On exit: ecx clobbered
237 // (found) calls or returns IMP in eax, eq/ne set for forwarding
238 // (not found) jumps to LCacheMiss, class still in edx
240 /////////////////////////////////////////////////////////////////////
244 // CacheHit must always be preceded by a not-taken `jne` instruction
245 // in case the imp is _objc_msgForward_impcache.
248 movl 4(%eax), %eax // return imp
251 leal __objc_msgSend_uncached_impcache-4b(%edx), %edx
254 xor %eax, %eax // don't return msgSend_uncached
256 .elseif $0 == NORMAL || $0 == FPRET
257 // eq already set for forwarding by `jne`
259 jmp *4(%eax) // call imp
261 test %eax, %eax // set ne for stret forwarding
263 jmp *4(%eax) // call imp
265 // replace "super" arg with "receiver"
266 movl super(%esp), %ecx // get super structure
267 movl receiver(%ecx), %ecx // get messaged object
268 movl %ecx, super(%esp) // make it the first argument
269 cmp %eax, %eax // set eq for non-stret forwarding
271 jmp *4(%eax) // call imp
272 .elseif $0 == SUPER_STRET
273 // replace "super" arg with "receiver"
274 movl super_stret(%esp), %ecx // get super structure
275 movl receiver(%ecx), %ecx // get messaged object
276 movl %ecx, super_stret(%esp) // make it the first argument
277 test %eax, %eax // set ne for stret forwarding
279 jmp *4(%eax) // call imp
289 movzwl 12(%edx), %eax // eax = mask
290 andl %ecx, %eax // eax = SEL & mask
291 shll $$3, %eax // eax = offset = (SEL & mask) * 8
292 addl 8(%edx), %eax // eax = bucket = cache->buckets+offset
293 cmpl (%eax), %ecx // if (bucket->sel != SEL)
295 // The `jne` above sets flags for CacheHit
296 CacheHit $0 // call or return imp
301 jbe 3f // if (bucket->sel <= 1) wrap or miss
303 addl $$8, %eax // bucket++
305 cmpl (%eax), %ecx // if (bucket->sel != sel)
307 // The `jne` above sets flags for CacheHit
308 CacheHit $0 // call or return imp
312 jb LCacheMiss_f // if (bucket->sel < 1) cache miss
314 movl 4(%eax), %eax // bucket->imp is really first bucket
317 // Clone scanning loop to miss instead of hang when cache is corrupt.
318 // The slow path may detect any corruption and halt later.
323 jbe 3f // if (bucket->sel <= 1) wrap or miss
325 addl $$8, %eax // bucket++
327 cmpl (%eax), %ecx // if (bucket->sel != sel)
329 // The `jne` above sets flags for CacheHit
330 CacheHit $0 // call or return imp
333 // double wrap or miss
339 /////////////////////////////////////////////////////////////////////
344 // $0 = NORMAL, FPRET, STRET, SUPER, SUPER_STRET
347 // edx = class to search
349 // On exit: calls IMP, eq/ne set for forwarding
351 /////////////////////////////////////////////////////////////////////
353 .macro MethodTableLookup
356 .cfi_def_cfa_offset 8
360 .cfi_def_cfa_register ebp
362 subl $$(8+5*16), %esp
364 movdqa %xmm3, 4*16(%esp)
365 movdqa %xmm2, 3*16(%esp)
366 movdqa %xmm1, 2*16(%esp)
367 movdqa %xmm0, 1*16(%esp)
369 movl %edx, 8(%esp) // class
370 movl %ecx, 4(%esp) // selector
371 movl %eax, 0(%esp) // receiver
372 call __class_lookupMethodAndLoadCache3
376 movdqa 4*16(%esp), %xmm3
377 movdqa 3*16(%esp), %xmm2
378 movdqa 2*16(%esp), %xmm1
379 movdqa 1*16(%esp), %xmm0
386 // replace "super" arg with "receiver"
387 movl super(%esp), %ecx // get super structure
388 movl receiver(%ecx), %ecx // get messaged object
389 movl %ecx, super(%esp) // make it the first argument
390 .elseif $0 == SUPER_STRET
391 // replace "super" arg with "receiver"
392 movl super_stret(%esp), %ecx // get super structure
393 movl receiver(%ecx), %ecx // get messaged object
394 movl %ecx, super_stret(%esp) // make it the first argument
397 .if $0 == STRET || $0 == SUPER_STRET
398 // set ne (stret) for forwarding; eax != 0
400 jmp *%eax // call imp
402 // set eq (non-stret) for forwarding
404 jmp *%eax // call imp
410 /////////////////////////////////////////////////////////////////////
412 // NilTest return-type
414 // Takes: $0 = NORMAL or FPRET or STRET
417 // On exit: Loads non-nil receiver in eax and self(esp) or self_stret(esp),
420 // NilTestSupport return-type
422 // Takes: $0 = NORMAL or FPRET or STRET
425 // On exit: Loads non-nil receiver in eax and self(esp) or self_stret(esp),
428 /////////////////////////////////////////////////////////////////////
436 .macro NilTestSupport
448 // eax is already zero
458 /********************************************************************
459 * IMP _cache_getImp(Class cls, SEL sel)
461 * If found, returns method implementation.
462 * If not found, returns NULL.
463 ********************************************************************/
465 STATIC_ENTRY _cache_getImp
467 // load the class and selector
468 movl selector(%esp), %ecx
469 movl self(%esp), %edx
471 CacheLookup GETIMP // returns IMP on success
474 // cache miss, return nil
479 END_ENTRY _cache_getImp
482 /********************************************************************
484 * id objc_msgSend(id self, SEL _cmd,...);
486 ********************************************************************/
491 movl selector(%esp), %ecx
492 movl self(%esp), %eax
496 movl isa(%eax), %edx // class = self->isa
497 CacheLookup NORMAL // calls IMP on success
499 NilTestSupport NORMAL
503 movl selector(%esp), %ecx
504 movl self(%esp), %eax
505 MethodTableLookup NORMAL // calls IMP
508 END_ENTRY _objc_msgSend
511 /********************************************************************
513 * id objc_msgSendSuper(struct objc_super *super, SEL _cmd,...);
515 * struct objc_super {
519 ********************************************************************/
521 ENTRY _objc_msgSendSuper
524 movl selector(%esp), %ecx
525 movl super(%esp), %eax // struct objc_super
526 movl class(%eax), %edx // struct objc_super->class
527 CacheLookup SUPER // calls IMP on success
530 // class still in edx
531 movl selector(%esp), %ecx
532 movl super(%esp), %eax
533 movl receiver(%eax), %eax
534 MethodTableLookup SUPER // calls IMP
537 END_ENTRY _objc_msgSendSuper
540 ENTRY _objc_msgSendSuper2
543 movl selector(%esp), %ecx
544 movl super(%esp), %eax // struct objc_super
545 movl class(%eax), %eax // struct objc_super->class
546 mov superclass(%eax), %edx // edx = objc_super->class->super_class
547 CacheLookup SUPER // calls IMP on success
550 // class still in edx
551 movl selector(%esp), %ecx
552 movl super(%esp), %eax
553 movl receiver(%eax), %eax
554 MethodTableLookup SUPER // calls IMP
557 END_ENTRY _objc_msgSendSuper2
560 /********************************************************************
562 * double objc_msgSend_fpret(id self, SEL _cmd,...);
564 ********************************************************************/
566 ENTRY _objc_msgSend_fpret
569 movl selector(%esp), %ecx
570 movl self(%esp), %eax
574 movl isa(%eax), %edx // class = self->isa
575 CacheLookup FPRET // calls IMP on success
580 // class still in edx
581 movl selector(%esp), %ecx
582 movl self(%esp), %eax
583 MethodTableLookup FPRET // calls IMP
586 END_ENTRY _objc_msgSend_fpret
589 /********************************************************************
591 * void objc_msgSend_stret(void *st_addr , id self, SEL _cmd, ...);
594 * objc_msgSend_stret is the struct-return form of msgSend.
595 * The ABI calls for (sp+4) to be used as the address of the structure
596 * being returned, with the parameters in the succeeding locations.
598 * On entry: (sp+4)is the address where the structure is returned,
599 * (sp+8) is the message receiver,
600 * (sp+12) is the selector
601 ********************************************************************/
603 ENTRY _objc_msgSend_stret
606 movl selector_stret(%esp), %ecx
607 movl self_stret(%esp), %eax
611 movl isa(%eax), %edx // class = self->isa
612 CacheLookup STRET // calls IMP on success
617 // class still in edx
618 movl selector_stret(%esp), %ecx
619 movl self_stret(%esp), %eax
620 MethodTableLookup STRET // calls IMP
623 END_ENTRY _objc_msgSend_stret
626 /********************************************************************
628 * void objc_msgSendSuper_stret(void *st_addr, struct objc_super *super, SEL _cmd, ...);
630 * struct objc_super {
635 * objc_msgSendSuper_stret is the struct-return form of msgSendSuper.
636 * The ABI calls for (sp+4) to be used as the address of the structure
637 * being returned, with the parameters in the succeeding registers.
639 * On entry: (sp+4)is the address where the structure is returned,
640 * (sp+8) is the address of the objc_super structure,
641 * (sp+12) is the selector
643 ********************************************************************/
645 ENTRY _objc_msgSendSuper_stret
648 movl selector_stret(%esp), %ecx
649 movl super_stret(%esp), %eax // struct objc_super
650 movl class(%eax), %edx // struct objc_super->class
651 CacheLookup SUPER_STRET // calls IMP on success
654 // class still in edx
655 movl selector_stret(%esp), %ecx
656 movl super_stret(%esp), %eax
657 movl receiver(%eax), %eax
658 MethodTableLookup SUPER_STRET // calls IMP
660 LMsgSendSuperStretExit:
661 END_ENTRY _objc_msgSendSuper_stret
664 ENTRY _objc_msgSendSuper2_stret
667 movl selector_stret(%esp), %ecx
668 movl super_stret(%esp), %eax // struct objc_super
669 movl class(%eax), %eax // struct objc_super->class
670 mov superclass(%eax), %edx // edx = objc_super->class->super_class
671 CacheLookup SUPER_STRET // calls IMP on success
673 // cache miss: go search the method lists
675 // class still in edx
676 movl selector_stret(%esp), %ecx
677 movl super_stret(%esp), %eax
678 movl receiver(%eax), %eax
679 MethodTableLookup SUPER_STRET // calls IMP
681 LMsgSendSuper2StretExit:
682 END_ENTRY _objc_msgSendSuper2_stret
685 /********************************************************************
687 * _objc_msgSend_uncached_impcache
688 * _objc_msgSend_uncached
689 * _objc_msgSend_stret_uncached
691 * Used to erase method cache entries in-place by
692 * bouncing them to the uncached lookup.
694 ********************************************************************/
696 STATIC_ENTRY __objc_msgSend_uncached_impcache
697 // Method cache version
699 // THIS IS NOT A CALLABLE C FUNCTION
700 // Out-of-band condition register is NE for stret, EQ otherwise.
701 // Out-of-band edx is the searched class
707 jne __objc_msgSend_stret_uncached
708 jmp __objc_msgSend_uncached
710 END_ENTRY __objc_msgSend_uncached_impcache
713 STATIC_ENTRY __objc_msgSend_uncached
715 // THIS IS NOT A CALLABLE C FUNCTION
716 // Out-of-band edx is the searched class
718 // edx is already the class to search
719 movl selector(%esp), %ecx
720 MethodTableLookup NORMAL // calls IMP
722 END_ENTRY __objc_msgSend_uncached
725 STATIC_ENTRY __objc_msgSend_stret_uncached
727 // THIS IS NOT A CALLABLE C FUNCTION
728 // Out-of-band edx is the searched class
730 // edx is already the class to search
731 movl selector_stret(%esp), %ecx
732 MethodTableLookup STRET // calls IMP
734 END_ENTRY __objc_msgSend_stret_uncached
738 /********************************************************************
740 * id _objc_msgForward(id self, SEL _cmd,...);
742 * _objc_msgForward and _objc_msgForward_stret are the externally-callable
743 * functions returned by things like method_getImplementation().
744 * _objc_msgForward_impcache is the function pointer actually stored in
747 ********************************************************************/
749 .non_lazy_symbol_pointer
751 .indirect_symbol __objc_forward_handler
753 L_forward_stret_handler:
754 .indirect_symbol __objc_forward_stret_handler
757 STATIC_ENTRY __objc_msgForward_impcache
758 // Method cache version
760 // THIS IS NOT A CALLABLE C FUNCTION
761 // Out-of-band condition register is NE for stret, EQ otherwise.
767 jne __objc_msgForward_stret
768 jmp __objc_msgForward
770 END_ENTRY _objc_msgForward_impcache
773 ENTRY __objc_msgForward
774 // Non-struct return version
778 movl L_forward_handler-1b(%edx), %edx
781 END_ENTRY __objc_msgForward
784 ENTRY __objc_msgForward_stret
785 // Struct return version
789 movl L_forward_stret_handler-1b(%edx), %edx
792 END_ENTRY __objc_msgForward_stret
795 ENTRY _objc_msgSend_debug
797 END_ENTRY _objc_msgSend_debug
799 ENTRY _objc_msgSendSuper2_debug
800 jmp _objc_msgSendSuper2
801 END_ENTRY _objc_msgSendSuper2_debug
803 ENTRY _objc_msgSend_stret_debug
804 jmp _objc_msgSend_stret
805 END_ENTRY _objc_msgSend_stret_debug
807 ENTRY _objc_msgSendSuper2_stret_debug
808 jmp _objc_msgSendSuper2_stret
809 END_ENTRY _objc_msgSendSuper2_stret_debug
811 ENTRY _objc_msgSend_fpret_debug
812 jmp _objc_msgSend_fpret
813 END_ENTRY _objc_msgSend_fpret_debug
816 ENTRY _objc_msgSend_noarg
818 END_ENTRY _objc_msgSend_noarg
823 movl selector(%esp), %ecx
824 movl method_name(%ecx), %edx
825 movl method_imp(%ecx), %eax
826 movl %edx, selector(%esp)
829 END_ENTRY _method_invoke
832 ENTRY _method_invoke_stret
834 movl selector_stret(%esp), %ecx
835 movl method_name(%ecx), %edx
836 movl method_imp(%ecx), %eax
837 movl %edx, selector_stret(%esp)
840 END_ENTRY _method_invoke_stret
843 STATIC_ENTRY __objc_ignored_method
845 movl self(%esp), %eax
848 END_ENTRY __objc_ignored_method
852 .section __DATA,__objc_msg_break