]> git.saurik.com Git - apple/objc4.git/blob - runtime/Messengers.subproj/objc-msg-simulator-i386.s
objc4-706.tar.gz
[apple/objc4.git] / runtime / Messengers.subproj / objc-msg-simulator-i386.s
1 /*
2 * Copyright (c) 1999-2009 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 #include <TargetConditionals.h>
25 #if defined(__i386__) && TARGET_OS_SIMULATOR
26
27 #include "objc-config.h"
28
29 .data
30
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.
34
35 .align 2
36 .private_extern _objc_entryPoints
37 _objc_entryPoints:
38 .long _cache_getImp
39 .long _objc_msgSend
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
46 .long _objc_msgLookup
47 .long _objc_msgLookup_fpret
48 .long _objc_msgLookup_stret
49 .long _objc_msgLookupSuper2
50 .long _objc_msgLookupSuper2_stret
51 .long 0
52
53 .private_extern _objc_exitPoints
54 _objc_exitPoints:
55 .long LExit_cache_getImp
56 .long LExit_objc_msgSend
57 .long LExit_objc_msgSend_fpret
58 .long LExit_objc_msgSend_stret
59 .long LExit_objc_msgSendSuper
60 .long LExit_objc_msgSendSuper2
61 .long LExit_objc_msgSendSuper_stret
62 .long LExit_objc_msgSendSuper2_stret
63 .long LExit_objc_msgLookup
64 .long LExit_objc_msgLookup_fpret
65 .long LExit_objc_msgLookup_stret
66 .long LExit_objc_msgLookupSuper2
67 .long LExit_objc_msgLookupSuper2_stret
68 .long 0
69
70
71 /********************************************************************
72 * List every exit insn from every messenger for debugger use.
73 * Format:
74 * (
75 * 1 word instruction's address
76 * 1 word type (ENTER or FAST_EXIT or SLOW_EXIT or NIL_EXIT)
77 * )
78 * 1 word zero
79 *
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 ********************************************************************/
86
87 #define ENTER 1
88 #define FAST_EXIT 2
89 #define SLOW_EXIT 3
90 #define NIL_EXIT 4
91
92 .section __DATA,__objc_msg_break
93 .globl _gdb_objc_messenger_breakpoints
94 _gdb_objc_messenger_breakpoints:
95 // contents populated by the macros below
96
97 .macro MESSENGER_START
98 4:
99 .section __DATA,__objc_msg_break
100 .long 4b
101 .long ENTER
102 .text
103 .endmacro
104 .macro MESSENGER_END_FAST
105 4:
106 .section __DATA,__objc_msg_break
107 .long 4b
108 .long FAST_EXIT
109 .text
110 .endmacro
111 .macro MESSENGER_END_SLOW
112 4:
113 .section __DATA,__objc_msg_break
114 .long 4b
115 .long SLOW_EXIT
116 .text
117 .endmacro
118 .macro MESSENGER_END_NIL
119 4:
120 .section __DATA,__objc_msg_break
121 .long 4b
122 .long NIL_EXIT
123 .text
124 .endmacro
125
126
127 /********************************************************************
128 * Names for relative labels
129 * DO NOT USE THESE LABELS ELSEWHERE
130 * Reserved labels: 5: 6: 7: 8: 9:
131 ********************************************************************/
132 #define LCacheMiss 5
133 #define LCacheMiss_f 5f
134 #define LCacheMiss_b 5b
135 #define LNilTestDone 6
136 #define LNilTestDone_f 6f
137 #define LNilTestDone_b 6b
138 #define LNilTestSlow 7
139 #define LNilTestSlow_f 7f
140 #define LNilTestSlow_b 7b
141 #define LGetIsaDone 8
142 #define LGetIsaDone_f 8f
143 #define LGetIsaDone_b 8b
144 #define LGetIsaSlow 9
145 #define LGetIsaSlow_f 9f
146 #define LGetIsaSlow_b 9b
147
148 /********************************************************************
149 * Macro parameters
150 ********************************************************************/
151
152
153 #define NORMAL 0
154 #define FPRET 1
155 #define STRET 2
156
157 #define CALL 100
158 #define GETIMP 101
159 #define LOOKUP 102
160
161
162 /********************************************************************
163 *
164 * Structure definitions.
165 *
166 ********************************************************************/
167
168 // Offsets from %esp
169 #define self 4
170 #define super 4
171 #define selector 8
172 #define marg_size 12
173 #define marg_list 16
174 #define first_arg 12
175
176 #define struct_addr 4
177
178 #define self_stret 8
179 #define super_stret 8
180 #define selector_stret 12
181 #define marg_size_stret 16
182 #define marg_list_stret 20
183
184 // objc_super parameter to sendSuper
185 #define receiver 0
186 #define class 4
187
188 // Selected field offsets in class structure
189 #define isa 0
190 #define superclass 4
191
192 // Method descriptor
193 #define method_name 0
194 #define method_imp 8
195
196
197 //////////////////////////////////////////////////////////////////////
198 //
199 // ENTRY functionName
200 //
201 // Assembly directives to begin an exported function.
202 //
203 // Takes: functionName - name of the exported function
204 //////////////////////////////////////////////////////////////////////
205
206 .macro ENTRY
207 .text
208 .globl $0
209 .align 2, 0x90
210 $0:
211 .endmacro
212
213 .macro STATIC_ENTRY
214 .text
215 .private_extern $0
216 .align 4, 0x90
217 $0:
218 .endmacro
219
220 //////////////////////////////////////////////////////////////////////
221 //
222 // END_ENTRY functionName
223 //
224 // Assembly directives to end an exported function. Just a placeholder,
225 // a close-parenthesis for ENTRY, until it is needed for something.
226 //
227 // Takes: functionName - name of the exported function
228 //////////////////////////////////////////////////////////////////////
229
230 .macro END_ENTRY
231 LExit$0:
232 .endmacro
233
234
235 /********************************************************************
236 * UNWIND name, flags
237 * Unwind info generation
238 ********************************************************************/
239 .macro UNWIND
240 .section __LD,__compact_unwind,regular,debug
241 .long $0
242 .set LUnwind$0, LExit$0 - $0
243 .long LUnwind$0
244 .long $1
245 .long 0 /* no personality */
246 .long 0 /* no LSDA */
247 .text
248 .endmacro
249
250 #define NoFrame 0x02010000 // no frame, no SP adjustment except return address
251 #define FrameWithNoSaves 0x01000000 // frame, no non-volatile saves
252
253
254 /////////////////////////////////////////////////////////////////////
255 //
256 // CacheLookup return-type, caller
257 //
258 // Locate the implementation for a selector in a class method cache.
259 //
260 // Takes:
261 // $0 = NORMAL, FPRET, STRET
262 // $1 = CALL, LOOKUP, GETIMP
263 // ecx = selector to search for
264 // edx = class to search
265 //
266 // On exit: ecx clobbered
267 // (found) calls or returns IMP in eax, eq/ne set for forwarding
268 // (not found) jumps to LCacheMiss, class still in edx
269 //
270 /////////////////////////////////////////////////////////////////////
271
272 .macro CacheHit
273
274 // CacheHit must always be preceded by a not-taken `jne` instruction
275 // in case the imp is _objc_msgForward_impcache.
276
277 // eax = found bucket
278
279 .if $1 == GETIMP
280 movl 4(%eax), %eax // return imp
281 ret
282
283 .else
284
285 .if $0 != STRET
286 // eq already set for forwarding by `jne`
287 .else
288 test %eax, %eax // set ne for stret forwarding
289 .endif
290
291 .if $1 == CALL
292 MESSENGER_END_FAST
293 jmp *4(%eax) // call imp
294
295 .elseif $1 == LOOKUP
296 movl 4(%eax), %eax // return imp
297 ret
298
299 .else
300 .abort oops
301 .endif
302
303 .endif
304
305 .endmacro
306
307
308 .macro CacheLookup
309
310 movzwl 12(%edx), %eax // eax = mask
311 andl %ecx, %eax // eax = SEL & mask
312 shll $$3, %eax // eax = offset = (SEL & mask) * 8
313 addl 8(%edx), %eax // eax = bucket = cache->buckets+offset
314 cmpl (%eax), %ecx // if (bucket->sel != SEL)
315 jne 1f // scan more
316 // The `jne` above sets flags for CacheHit
317 CacheHit $0, $1 // call or return imp
318
319 1:
320 // loop
321 cmpl $$1, (%eax)
322 jbe 3f // if (bucket->sel <= 1) wrap or miss
323
324 addl $$8, %eax // bucket++
325 2:
326 cmpl (%eax), %ecx // if (bucket->sel != sel)
327 jne 1b // scan more
328 // The `jne` above sets flags for CacheHit
329 CacheHit $0, $1 // call or return imp
330
331 3:
332 // wrap or miss
333 jb LCacheMiss_f // if (bucket->sel < 1) cache miss
334 // wrap
335 movl 4(%eax), %eax // bucket->imp is really first bucket
336 jmp 2f
337
338 // Clone scanning loop to miss instead of hang when cache is corrupt.
339 // The slow path may detect any corruption and halt later.
340
341 1:
342 // loop
343 cmpq $$1, (%eax)
344 jbe 3f // if (bucket->sel <= 1) wrap or miss
345
346 addl $$8, %eax // bucket++
347 2:
348 cmpl (%eax), %ecx // if (bucket->sel != sel)
349 jne 1b // scan more
350 // The `jne` above sets flags for CacheHit
351 CacheHit $0, $1 // call or return imp
352
353 3:
354 // double wrap or miss
355 jmp LCacheMiss_f
356
357 .endmacro
358
359
360 /////////////////////////////////////////////////////////////////////
361 //
362 // MethodTableLookup NORMAL|STRET
363 //
364 // Takes:
365 // receiver (not struct objc_super) and selector on stack
366 // edx = class to search
367 //
368 // On exit: IMP in eax, eq/ne set for forwarding
369 //
370 /////////////////////////////////////////////////////////////////////
371
372 .macro MethodTableLookup
373 pushl %ebp
374 movl %esp, %ebp
375
376 subl $$(8+5*16), %esp
377
378 .if $0 == NORMAL
379 movl self+4(%ebp), %eax
380 movl selector+4(%ebp), %ecx
381 .else
382 movl self_stret+4(%ebp), %eax
383 movl selector_stret+4(%ebp), %ecx
384 .endif
385
386 movdqa %xmm3, 4*16(%esp)
387 movdqa %xmm2, 3*16(%esp)
388 movdqa %xmm1, 2*16(%esp)
389 movdqa %xmm0, 1*16(%esp)
390
391 movl %edx, 8(%esp) // class
392 movl %ecx, 4(%esp) // selector
393 movl %eax, 0(%esp) // receiver
394 call __class_lookupMethodAndLoadCache3
395
396 // imp in eax
397
398 movdqa 4*16(%esp), %xmm3
399 movdqa 3*16(%esp), %xmm2
400 movdqa 2*16(%esp), %xmm1
401 movdqa 1*16(%esp), %xmm0
402
403 .if $0 == NORMAL
404 cmp %eax, %eax // set eq for nonstret forwarding
405 .else
406 test %eax, %eax // set ne for stret forwarding
407 .endif
408
409 leave
410
411 .endmacro
412
413
414 /////////////////////////////////////////////////////////////////////
415 //
416 // NilTest return-type
417 //
418 // Takes: $0 = NORMAL or FPRET or STRET
419 // eax = receiver
420 //
421 // On exit: Loads non-nil receiver in eax and self(esp) or self_stret(esp),
422 // or returns zero.
423 //
424 // NilTestReturnZero return-type
425 //
426 // Takes: $0 = NORMAL or FPRET or STRET
427 // eax = receiver
428 //
429 // On exit: Loads non-nil receiver in eax and self(esp) or self_stret(esp),
430 // or returns zero.
431 //
432 // NilTestReturnIMP return-type
433 //
434 // Takes: $0 = NORMAL or FPRET or STRET
435 // eax = receiver
436 //
437 // On exit: Loads non-nil receiver in eax and self(esp) or self_stret(esp),
438 // or returns an IMP in eax that returns zero.
439 //
440 /////////////////////////////////////////////////////////////////////
441
442 .macro ZeroReturn
443 xorl %eax, %eax
444 xorl %edx, %edx
445 xorps %xmm0, %xmm0
446 xorps %xmm1, %xmm1
447 .endmacro
448
449 .macro ZeroReturnFPRET
450 fldz
451 .endmacro
452
453 .macro ZeroReturnSTRET
454 // empty
455 .endmacro
456
457 STATIC_ENTRY __objc_msgNil
458 ZeroReturn
459 ret
460 END_ENTRY __objc_msgNil
461
462 STATIC_ENTRY __objc_msgNil_fpret
463 ZeroReturnFPRET
464 ret
465 END_ENTRY __objc_msgNil_fpret
466
467 STATIC_ENTRY __objc_msgNil_stret
468 ZeroReturnSTRET
469 ret $4
470 END_ENTRY __objc_msgNil_stret
471
472
473 .macro NilTest
474 testl %eax, %eax
475 jz LNilTestSlow_f
476 LNilTestDone:
477 .endmacro
478
479 .macro NilTestReturnZero
480 .align 3
481 LNilTestSlow:
482
483 .if $0 == NORMAL
484 ZeroReturn
485 MESSENGER_END_NIL
486 ret
487 .elseif $0 == FPRET
488 ZeroReturnFPRET
489 MESSENGER_END_NIL
490 ret
491 .elseif $0 == STRET
492 ZeroReturnSTRET
493 MESSENGER_END_NIL
494 ret $$4
495 .else
496 .abort oops
497 .endif
498 .endmacro
499
500 .macro NilTestReturnIMP
501 .align 3
502 LNilTestSlow:
503
504 call 1f
505 1: pop %eax
506 .if $0 == NORMAL
507 leal __objc_msgNil-1b(%eax), %eax
508 .elseif $0 == FPRET
509 leal __objc_msgNil_fpret-1b(%eax), %eax
510 .elseif $0 == STRET
511 leal __objc_msgNil_stret-1b(%eax), %eax
512 .else
513 .abort oops
514 .endif
515 ret
516 .endmacro
517
518
519 /********************************************************************
520 * IMP _cache_getImp(Class cls, SEL sel)
521 *
522 * If found, returns method implementation.
523 * If not found, returns NULL.
524 ********************************************************************/
525
526 STATIC_ENTRY _cache_getImp
527
528 // load the class and selector
529 movl selector(%esp), %ecx
530 movl self(%esp), %edx
531
532 CacheLookup NORMAL, GETIMP // returns IMP on success
533
534 LCacheMiss:
535 // cache miss, return nil
536 xorl %eax, %eax
537 ret
538
539 END_ENTRY _cache_getImp
540
541
542 /********************************************************************
543 *
544 * id objc_msgSend(id self, SEL _cmd, ...);
545 * IMP objc_msgLookup(id self, SEL _cmd, ...);
546 *
547 * objc_msgLookup ABI:
548 * IMP returned in eax
549 * Forwarding returned in Z flag
550 * edx reserved for our use but not used
551 *
552 ********************************************************************/
553
554 ENTRY _objc_msgSend
555 UNWIND _objc_msgSend, NoFrame
556 MESSENGER_START
557
558 movl selector(%esp), %ecx
559 movl self(%esp), %eax
560
561 NilTest NORMAL
562
563 movl isa(%eax), %edx // class = self->isa
564 CacheLookup NORMAL, CALL // calls IMP on success
565
566 NilTestReturnZero NORMAL
567
568 LCacheMiss:
569 // isa still in edx
570 MESSENGER_END_SLOW
571 jmp __objc_msgSend_uncached
572
573 END_ENTRY _objc_msgSend
574
575
576 ENTRY _objc_msgLookup
577 UNWIND _objc_msgLookup, NoFrame
578
579 movl selector(%esp), %ecx
580 movl self(%esp), %eax
581
582 NilTest NORMAL
583
584 movl isa(%eax), %edx // class = self->isa
585 CacheLookup NORMAL, LOOKUP // returns IMP on success
586
587 NilTestReturnIMP NORMAL
588
589 LCacheMiss:
590 // isa still in edx
591 jmp __objc_msgLookup_uncached
592
593 END_ENTRY _objc_msgLookup
594
595
596 /********************************************************************
597 *
598 * id objc_msgSendSuper(struct objc_super *super, SEL _cmd, ...);
599 * IMP objc_msgLookupSuper(struct objc_super *super, SEL _cmd, ...);
600 *
601 ********************************************************************/
602
603 ENTRY _objc_msgSendSuper
604 UNWIND _objc_msgSendSuper, NoFrame
605 MESSENGER_START
606
607 movl selector(%esp), %ecx
608 movl super(%esp), %eax // struct objc_super
609 movl class(%eax), %edx // struct objc_super->class
610 movl receiver(%eax), %eax // struct objc_super->receiver
611 movl %eax, super(%esp) // replace super arg with receiver
612 CacheLookup NORMAL, CALL // calls IMP on success
613
614 LCacheMiss:
615 // class still in edx
616 MESSENGER_END_SLOW
617 jmp __objc_msgSend_uncached
618
619 END_ENTRY _objc_msgSendSuper
620
621
622
623 ENTRY _objc_msgLookupSuper
624 UNWIND _objc_msgLookupSuper, NoFrame
625
626 movl selector(%esp), %ecx
627 movl super(%esp), %eax // struct objc_super
628 movl class(%eax), %edx // struct objc_super->class
629 movl receiver(%eax), %eax // struct objc_super->receiver
630 movl %eax, super(%esp) // replace super arg with receiver
631 CacheLookup NORMAL, LOOKUP // returns IMP on success
632
633 LCacheMiss:
634 // class still in edx
635 jmp __objc_msgLookup_uncached
636
637 END_ENTRY _objc_msgLookupSuper
638
639
640 /********************************************************************
641 *
642 * id objc_msgSendSuper2(struct objc_super *super, SEL _cmd, ...);
643 * IMP objc_msgLookupSuper2(struct objc_super *super, SEL _cmd, ...);
644 *
645 ********************************************************************/
646
647 ENTRY _objc_msgSendSuper2
648 UNWIND _objc_msgSendSuper2, NoFrame
649 MESSENGER_START
650
651 movl selector(%esp), %ecx
652 movl super(%esp), %eax // struct objc_super
653 movl class(%eax), %edx // struct objc_super->class
654 movl receiver(%eax), %eax // struct objc_super->receiver
655 movl %eax, super(%esp) // replace super arg with receiver
656 movl superclass(%edx), %edx // edx = objc_super->class->super_class
657 CacheLookup NORMAL, CALL // calls IMP on success
658
659 LCacheMiss:
660 // class still in edx
661 MESSENGER_END_SLOW
662 jmp __objc_msgSend_uncached
663
664 END_ENTRY _objc_msgSendSuper2
665
666
667 ENTRY _objc_msgLookupSuper2
668 UNWIND _objc_msgLookupSuper2, NoFrame
669
670 movl selector(%esp), %ecx
671 movl super(%esp), %eax // struct objc_super
672 movl class(%eax), %edx // struct objc_super->class
673 movl receiver(%eax), %eax // struct objc_super->receiver
674 movl %eax, super(%esp) // replace super arg with receiver
675 movl superclass(%edx), %edx // edx = objc_super->class->super_class
676 CacheLookup NORMAL, LOOKUP // returns IMP on success
677
678 LCacheMiss:
679 // class still in edx
680 jmp __objc_msgLookup_uncached
681
682 END_ENTRY _objc_msgLookupSuper2
683
684
685 /********************************************************************
686 *
687 * double objc_msgSend_fpret(id self, SEL _cmd, ...);
688 * IMP objc_msgLookup_fpret(id self, SEL _cmd, ...);
689 *
690 ********************************************************************/
691
692 ENTRY _objc_msgSend_fpret
693 UNWIND _objc_msgSend_fpret, NoFrame
694 MESSENGER_START
695
696 movl selector(%esp), %ecx
697 movl self(%esp), %eax
698
699 NilTest FPRET
700
701 movl isa(%eax), %edx // class = self->isa
702 CacheLookup FPRET, CALL // calls IMP on success
703
704 NilTestReturnZero FPRET
705
706 LCacheMiss:
707 // class still in edx
708 MESSENGER_END_SLOW
709 jmp __objc_msgSend_uncached
710
711 END_ENTRY _objc_msgSend_fpret
712
713
714 ENTRY _objc_msgLookup_fpret
715 UNWIND _objc_msgLookup_fpret, NoFrame
716
717 movl selector(%esp), %ecx
718 movl self(%esp), %eax
719
720 NilTest FPRET
721
722 movl isa(%eax), %edx // class = self->isa
723 CacheLookup FPRET, LOOKUP // returns IMP on success
724
725 NilTestReturnIMP FPRET
726
727 LCacheMiss:
728 // class still in edx
729 jmp __objc_msgLookup_uncached
730
731 END_ENTRY _objc_msgLookup_fpret
732
733
734 /********************************************************************
735 *
736 * void objc_msgSend_stret(void *st_addr, id self, SEL _cmd, ...);
737 * IMP objc_msgLookup_stret(void *st_addr, id self, SEL _cmd, ...);
738 *
739 ********************************************************************/
740
741 ENTRY _objc_msgSend_stret
742 UNWIND _objc_msgSend_stret, NoFrame
743 MESSENGER_START
744
745 movl selector_stret(%esp), %ecx
746 movl self_stret(%esp), %eax
747
748 NilTest STRET
749
750 movl isa(%eax), %edx // class = self->isa
751 CacheLookup STRET, CALL // calls IMP on success
752
753 NilTestReturnZero STRET
754
755 LCacheMiss:
756 // class still in edx
757 MESSENGER_END_SLOW
758 jmp __objc_msgSend_stret_uncached
759
760 END_ENTRY _objc_msgSend_stret
761
762
763 ENTRY _objc_msgLookup_stret
764 UNWIND _objc_msgLookup_stret, NoFrame
765
766 movl selector_stret(%esp), %ecx
767 movl self_stret(%esp), %eax
768
769 NilTest STRET
770
771 movl isa(%eax), %edx // class = self->isa
772 CacheLookup STRET, LOOKUP // returns IMP on success
773
774 NilTestReturnIMP STRET
775
776 LCacheMiss:
777 // class still in edx
778 jmp __objc_msgLookup_stret_uncached
779
780 END_ENTRY _objc_msgLookup_stret
781
782
783 /********************************************************************
784 *
785 * void objc_msgSendSuper_stret(void *st_addr, struct objc_super *super, SEL _cmd, ...);
786 * IMP objc_msgLookupSuper_stret(void *st_addr, struct objc_super *super, SEL _cmd, ...);
787 *
788 ********************************************************************/
789
790 ENTRY _objc_msgSendSuper_stret
791 UNWIND _objc_msgSendSuper_stret, NoFrame
792 MESSENGER_START
793
794 movl selector_stret(%esp), %ecx
795 movl super_stret(%esp), %eax // struct objc_super
796 movl class(%eax), %edx // struct objc_super->class
797 movl receiver(%eax), %eax // struct objc_super->receiver
798 movl %eax, super_stret(%esp) // replace super arg with receiver
799 CacheLookup STRET, CALL // calls IMP on success
800
801 LCacheMiss:
802 // class still in edx
803 MESSENGER_END_SLOW
804 jmp __objc_msgSend_stret_uncached
805
806 END_ENTRY _objc_msgSendSuper_stret
807
808
809 ENTRY _objc_msgLookupSuper_stret
810 UNWIND _objc_msgLookupSuper_stret, NoFrame
811
812 movl selector_stret(%esp), %ecx
813 movl super_stret(%esp), %eax // struct objc_super
814 movl class(%eax), %edx // struct objc_super->class
815 movl receiver(%eax), %eax // struct objc_super->receiver
816 movl %eax, super_stret(%esp) // replace super arg with receiver
817 CacheLookup STRET, LOOKUP // returns IMP on success
818
819 LCacheMiss:
820 // class still in edx
821 jmp __objc_msgLookup_stret_uncached
822
823 END_ENTRY _objc_msgLookupSuper_stret
824
825
826 /********************************************************************
827 *
828 * void objc_msgSendSuper2_stret(void *st_addr, struct objc_super *super, SEL _cmd, ...);
829 * IMP objc_msgLookupSuper2_stret(void *st_addr, struct objc_super *super, SEL _cmd, ...);
830 *
831 ********************************************************************/
832
833 ENTRY _objc_msgSendSuper2_stret
834 UNWIND _objc_msgSendSuper2_stret, NoFrame
835 MESSENGER_START
836
837 movl selector_stret(%esp), %ecx
838 movl super_stret(%esp), %eax // struct objc_super
839 movl class(%eax), %edx // struct objc_super->class
840 movl receiver(%eax), %eax // struct objc_super->receiver
841 movl %eax, super_stret(%esp) // replace super arg with receiver
842 mov superclass(%edx), %edx // edx = objc_super->class->super_class
843 CacheLookup STRET, CALL // calls IMP on success
844
845 // cache miss: go search the method lists
846 LCacheMiss:
847 // class still in edx
848 MESSENGER_END_SLOW
849 jmp __objc_msgSend_stret_uncached
850
851 END_ENTRY _objc_msgSendSuper2_stret
852
853
854 ENTRY _objc_msgLookupSuper2_stret
855 UNWIND _objc_msgLookupSuper2_stret, NoFrame
856
857 movl selector_stret(%esp), %ecx
858 movl super_stret(%esp), %eax // struct objc_super
859 movl class(%eax), %edx // struct objc_super->class
860 movl receiver(%eax), %eax // struct objc_super->receiver
861 movl %eax, super_stret(%esp) // replace super arg with receiver
862 mov superclass(%edx), %edx // edx = objc_super->class->super_class
863 CacheLookup STRET, LOOKUP // returns IMP on success
864
865 // cache miss: go search the method lists
866 LCacheMiss:
867 // class still in edx
868 jmp __objc_msgLookup_stret_uncached
869
870 END_ENTRY _objc_msgLookupSuper2_stret
871
872
873 /********************************************************************
874 *
875 * _objc_msgSend_uncached
876 * _objc_msgSend_stret_uncached
877 * _objc_msgLookup_uncached
878 * _objc_msgLookup_stret_uncached
879 *
880 * The uncached method lookup.
881 *
882 ********************************************************************/
883
884 STATIC_ENTRY __objc_msgSend_uncached
885 UNWIND __objc_msgSend_uncached, FrameWithNoSaves
886
887 // THIS IS NOT A CALLABLE C FUNCTION
888 // Out-of-band edx is the searched class
889
890 // edx is already the class to search
891 MethodTableLookup NORMAL
892 jmp *%eax // call imp
893
894 END_ENTRY __objc_msgSend_uncached
895
896
897 STATIC_ENTRY __objc_msgSend_stret_uncached
898 UNWIND __objc_msgSend_stret_uncached, FrameWithNoSaves
899
900 // THIS IS NOT A CALLABLE C FUNCTION
901 // Out-of-band edx is the searched class
902
903 // edx is already the class to search
904 MethodTableLookup STRET
905 jmp *%eax // call imp
906
907 END_ENTRY __objc_msgSend_stret_uncached
908
909
910 STATIC_ENTRY __objc_msgLookup_uncached
911 UNWIND __objc_msgLookup_uncached, FrameWithNoSaves
912
913 // THIS IS NOT A CALLABLE C FUNCTION
914 // Out-of-band edx is the searched class
915
916 // edx is already the class to search
917 MethodTableLookup NORMAL // eax = IMP
918 ret
919
920 END_ENTRY __objc_msgLookup_uncached
921
922
923 STATIC_ENTRY __objc_msgLookup_stret_uncached
924 UNWIND __objc_msgLookup_stret_uncached, FrameWithNoSaves
925
926 // THIS IS NOT A CALLABLE C FUNCTION
927 // Out-of-band edx is the searched class
928
929 // edx is already the class to search
930 MethodTableLookup STRET // eax = IMP
931 ret
932
933 END_ENTRY __objc_msgLookup_stret_uncached
934
935
936 /********************************************************************
937 *
938 * id _objc_msgForward(id self, SEL _cmd,...);
939 *
940 * _objc_msgForward and _objc_msgForward_stret are the externally-callable
941 * functions returned by things like method_getImplementation().
942 * _objc_msgForward_impcache is the function pointer actually stored in
943 * method caches.
944 *
945 ********************************************************************/
946
947 .non_lazy_symbol_pointer
948 L_forward_handler:
949 .indirect_symbol __objc_forward_handler
950 .long 0
951 L_forward_stret_handler:
952 .indirect_symbol __objc_forward_stret_handler
953 .long 0
954
955 STATIC_ENTRY __objc_msgForward_impcache
956 // Method cache version
957
958 // THIS IS NOT A CALLABLE C FUNCTION
959 // Out-of-band condition register is NE for stret, EQ otherwise.
960
961 MESSENGER_START
962 nop
963 MESSENGER_END_SLOW
964
965 jne __objc_msgForward_stret
966 jmp __objc_msgForward
967
968 END_ENTRY _objc_msgForward_impcache
969
970
971 ENTRY __objc_msgForward
972 // Non-struct return version
973
974 call 1f
975 1: popl %edx
976 movl L_forward_handler-1b(%edx), %edx
977 jmp *(%edx)
978
979 END_ENTRY __objc_msgForward
980
981
982 ENTRY __objc_msgForward_stret
983 // Struct return version
984
985 call 1f
986 1: popl %edx
987 movl L_forward_stret_handler-1b(%edx), %edx
988 jmp *(%edx)
989
990 END_ENTRY __objc_msgForward_stret
991
992
993 ENTRY _objc_msgSend_debug
994 jmp _objc_msgSend
995 END_ENTRY _objc_msgSend_debug
996
997 ENTRY _objc_msgSendSuper2_debug
998 jmp _objc_msgSendSuper2
999 END_ENTRY _objc_msgSendSuper2_debug
1000
1001 ENTRY _objc_msgSend_stret_debug
1002 jmp _objc_msgSend_stret
1003 END_ENTRY _objc_msgSend_stret_debug
1004
1005 ENTRY _objc_msgSendSuper2_stret_debug
1006 jmp _objc_msgSendSuper2_stret
1007 END_ENTRY _objc_msgSendSuper2_stret_debug
1008
1009 ENTRY _objc_msgSend_fpret_debug
1010 jmp _objc_msgSend_fpret
1011 END_ENTRY _objc_msgSend_fpret_debug
1012
1013
1014 ENTRY _objc_msgSend_noarg
1015 jmp _objc_msgSend
1016 END_ENTRY _objc_msgSend_noarg
1017
1018
1019 ENTRY _method_invoke
1020
1021 movl selector(%esp), %ecx
1022 movl method_name(%ecx), %edx
1023 movl method_imp(%ecx), %eax
1024 movl %edx, selector(%esp)
1025 jmp *%eax
1026
1027 END_ENTRY _method_invoke
1028
1029
1030 ENTRY _method_invoke_stret
1031
1032 movl selector_stret(%esp), %ecx
1033 movl method_name(%ecx), %edx
1034 movl method_imp(%ecx), %eax
1035 movl %edx, selector_stret(%esp)
1036 jmp *%eax
1037
1038 END_ENTRY _method_invoke_stret
1039
1040
1041 .section __DATA,__objc_msg_break
1042 .long 0
1043 .long 0
1044
1045 #endif