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