]> git.saurik.com Git - apple/objc4.git/blob - runtime/Messengers.subproj/objc-msg-simulator-i386.s
objc4-493.9.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_IPHONE_SIMULATOR
26
27 #define __OBJC2__ 1
28
29 #include "objc-config.h"
30
31 .data
32
33 // Substitute receiver for messages sent to nil (usually also nil)
34 // id _objc_nilReceiver
35 .align 4
36 .private_extern __objc_nilReceiver
37 __objc_nilReceiver:
38 .long 0
39
40 // _objc_entryPoints and _objc_exitPoints are used by objc
41 // to get the critical regions for which method caches
42 // cannot be garbage collected.
43
44 .private_extern _objc_entryPoints
45 _objc_entryPoints:
46 .long __cache_getImp
47 .long __cache_getMethod
48 .long _objc_msgSend
49 .long _objc_msgSend_fpret
50 .long _objc_msgSend_stret
51 .long _objc_msgSendSuper
52 .long _objc_msgSendSuper2
53 .long _objc_msgSendSuper_stret
54 .long _objc_msgSendSuper2_stret
55 .long 0
56
57 .private_extern _objc_exitPoints
58 _objc_exitPoints:
59 .long LGetImpExit
60 .long LGetMethodExit
61 .long LMsgSendExit
62 .long LMsgSendFpretExit
63 .long LMsgSendStretExit
64 .long LMsgSendSuperExit
65 .long LMsgSendSuper2Exit
66 .long LMsgSendSuperStretExit
67 .long LMsgSendSuper2StretExit
68 .long 0
69
70
71 /********************************************************************
72 *
73 * Structure definitions.
74 *
75 ********************************************************************/
76
77 // Offsets from %esp
78 self = 4
79 super = 4
80 selector = 8
81 marg_size = 12
82 marg_list = 16
83 first_arg = 12
84
85 struct_addr = 4
86
87 self_stret = 8
88 super_stret = 8
89 selector_stret = 12
90 marg_size_stret = 16
91 marg_list_stret = 20
92
93 // objc_super parameter to sendSuper
94 receiver = 0
95 class = 4
96
97 // Selected field offsets in class structure
98 isa = 0
99 superclass = 4
100 #if __OBJC2__
101 cache = 8
102 #else
103 cache = 32
104 #endif
105
106 // Method descriptor
107 method_name = 0
108 method_imp = 8
109
110 // Cache header
111 mask = 0
112 occupied = 4
113 buckets = 8 // variable length array
114
115
116 //////////////////////////////////////////////////////////////////////
117 //
118 // ENTRY functionName
119 //
120 // Assembly directives to begin an exported function.
121 //
122 // Takes: functionName - name of the exported function
123 //////////////////////////////////////////////////////////////////////
124
125 .macro ENTRY
126 .text
127 .globl $0
128 .align 2, 0x90
129 $0:
130 .endmacro
131
132 .macro STATIC_ENTRY
133 .text
134 .private_extern $0
135 .align 4, 0x90
136 $0:
137 .endmacro
138
139 //////////////////////////////////////////////////////////////////////
140 //
141 // END_ENTRY functionName
142 //
143 // Assembly directives to end an exported function. Just a placeholder,
144 // a close-parenthesis for ENTRY, until it is needed for something.
145 //
146 // Takes: functionName - name of the exported function
147 //////////////////////////////////////////////////////////////////////
148
149 .macro END_ENTRY
150 .endmacro
151
152
153 /////////////////////////////////////////////////////////////////////
154 //
155 //
156 // CacheLookup WORD_RETURN | STRUCT_RETURN, MSG_SEND | MSG_SENDSUPER | MSG_SENDSUPER2 | CACHE_GET, cacheMissLabel
157 //
158 // Locate the implementation for a selector in a class method cache.
159 //
160 // Takes: WORD_RETURN (first parameter is at sp+4)
161 // STRUCT_RETURN (struct address is at sp+4, first parameter at sp+8)
162 // MSG_SEND (first parameter is receiver)
163 // MSG_SENDSUPER[2] (first parameter is address of objc_super structure)
164 // CACHE_GET (first parameter is class; return method triplet)
165 // selector in %ecx
166 // class to search in %edx
167 //
168 // cacheMissLabel = label to branch to iff method is not cached
169 //
170 // On exit: (found) MSG_SEND and MSG_SENDSUPER[2]: return imp in eax
171 // (found) CACHE_GET: return method triplet in eax
172 // (not found) jumps to cacheMissLabel
173 //
174 /////////////////////////////////////////////////////////////////////
175
176
177 // Values to specify to method lookup macros whether the return type of
178 // the method is word or structure.
179 WORD_RETURN = 0
180 STRUCT_RETURN = 1
181
182 // Values to specify to method lookup macros whether the first argument
183 // is an object/class reference or a 'objc_super' structure.
184 MSG_SEND = 0 // first argument is receiver, search the isa
185 MSG_SENDSUPER = 1 // first argument is objc_super, search the class
186 MSG_SENDSUPER2 = 2 // first argument is objc_super, search the class
187 CACHE_GET = 3 // first argument is class, search that class
188
189 .macro CacheLookup
190
191 // load variables and save caller registers.
192
193 pushl %edi // save scratch register
194 movl cache(%edx), %edi // cache = class->cache
195 pushl %esi // save scratch register
196
197 movl mask(%edi), %esi // mask = cache->mask
198 movl %ecx, %edx // index = selector
199 shrl $$2, %edx // index = selector >> 2
200
201 // search the receiver's cache
202 // ecx = selector
203 // edi = cache
204 // esi = mask
205 // edx = index
206 // eax = method (soon)
207 LMsgSendProbeCache_$0_$1_$2:
208 andl %esi, %edx // index &= mask
209 movl buckets(%edi, %edx, 4), %eax // meth = cache->buckets[index]
210
211 testl %eax, %eax // check for end of bucket
212 je LMsgSendCacheMiss_$0_$1_$2 // go to cache miss code
213 cmpl method_name(%eax), %ecx // check for method name match
214 je LMsgSendCacheHit_$0_$1_$2 // go handle cache hit
215 addl $$1, %edx // bump index ...
216 jmp LMsgSendProbeCache_$0_$1_$2 // ... and loop
217
218 // not found in cache: restore state and go to callers handler
219 LMsgSendCacheMiss_$0_$1_$2:
220
221 .if $0 == WORD_RETURN // Regular word return
222 .if $1 == MSG_SEND // MSG_SEND
223 popl %esi // restore callers register
224 popl %edi // restore callers register
225 movl self(%esp), %eax // get messaged object
226 movl isa(%eax), %eax // get objects class
227 .elseif $1 == MSG_SENDSUPER || $1 == MSG_SENDSUPER2 // MSG_SENDSUPER[2]
228 // replace "super" arg with "receiver"
229 movl super+8(%esp), %edi // get super structure
230 movl receiver(%edi), %esi // get messaged object
231 movl %esi, super+8(%esp) // make it the first argument
232 movl class(%edi), %eax // get messaged class
233 .if $1 == MSG_SENDSUPER2
234 movl superclass(%eax), %eax // get messaged class
235 .endif
236 popl %esi // restore callers register
237 popl %edi // restore callers register
238 .else // CACHE_GET
239 popl %esi // restore callers register
240 popl %edi // restore callers register
241 .endif
242 .else // Struct return
243 .if $1 == MSG_SEND // MSG_SEND (stret)
244 popl %esi // restore callers register
245 popl %edi // restore callers register
246 movl self_stret(%esp), %eax // get messaged object
247 movl isa(%eax), %eax // get objects class
248 .elseif $1 == MSG_SENDSUPER || $1 == MSG_SENDSUPER2 // MSG_SENDSUPER[2] (stret)
249 // replace "super" arg with "receiver"
250 movl super_stret+8(%esp), %edi// get super structure
251 movl receiver(%edi), %esi // get messaged object
252 movl %esi, super_stret+8(%esp)// make it the first argument
253 movl class(%edi), %eax // get messaged class
254 .if $1 == MSG_SENDSUPER2
255 movl superclass(%eax), %eax // get messaged class
256 .endif
257 popl %esi // restore callers register
258 popl %edi // restore callers register
259 .else // CACHE_GET
260 !! This should not happen.
261 .endif
262 .endif
263
264 jmp $2 // go to callers handler
265
266 // eax points to matching cache entry
267 .align 4, 0x90
268 LMsgSendCacheHit_$0_$1_$2:
269
270 // load implementation address, restore state, and we're done
271 .if $1 == CACHE_GET
272 // method triplet is already in eax
273 .else
274 movl method_imp(%eax), %eax // imp = method->method_imp
275 .endif
276
277 .if $0 == WORD_RETURN // Regular word return
278 .if $1 == MSG_SENDSUPER || $1 == MSG_SENDSUPER2
279 // replace "super" arg with "self"
280 movl super+8(%esp), %edi
281 movl receiver(%edi), %esi
282 movl %esi, super+8(%esp)
283 .endif
284 .else // Struct return
285 .if $1 == MSG_SENDSUPER || $1 == MSG_SENDSUPER2
286 // replace "super" arg with "self"
287 movl super_stret+8(%esp), %edi
288 movl receiver(%edi), %esi
289 movl %esi, super_stret+8(%esp)
290 .endif
291 .endif
292
293 // restore caller registers
294 popl %esi
295 popl %edi
296 .endmacro
297
298
299 /////////////////////////////////////////////////////////////////////
300 //
301 // MethodTableLookup WORD_RETURN | STRUCT_RETURN, MSG_SEND | MSG_SENDSUPER
302 //
303 // Takes: WORD_RETURN (first parameter is at sp+4)
304 // STRUCT_RETURN (struct address is at sp+4, first parameter at sp+8)
305 // MSG_SEND (first parameter is receiver)
306 // MSG_SENDSUPER (first parameter is address of objc_super structure)
307 //
308 // Stack must be at 0xXXXXXXXc on entrance.
309 //
310 // On exit: Register parameters restored from CacheLookup
311 // imp in eax
312 //
313 /////////////////////////////////////////////////////////////////////
314
315 .macro MethodTableLookup
316
317 subl $$4, %esp // 16-byte align the stack
318 // push args (class, selector)
319 pushl %ecx
320 pushl %eax
321 call __class_lookupMethodAndLoadCache
322 addl $$12, %esp // pop parameters and alignment
323 .endmacro
324
325
326 /********************************************************************
327 * Method _cache_getMethod(Class cls, SEL sel, IMP msgForward_internal_imp)
328 *
329 * If found, returns method triplet pointer.
330 * If not found, returns NULL.
331 *
332 * NOTE: _cache_getMethod never returns any cache entry whose implementation
333 * is _objc_msgForward_internal. It returns 1 instead. This prevents thread-
334 * safety and memory management bugs in _class_lookupMethodAndLoadCache.
335 * See _class_lookupMethodAndLoadCache for details.
336 *
337 * _objc_msgForward_internal is passed as a parameter because it's more
338 * efficient to do the (PIC) lookup once in the caller than repeatedly here.
339 ********************************************************************/
340
341 .private_extern __cache_getMethod
342 ENTRY __cache_getMethod
343
344 // load the class and selector
345 movl selector(%esp), %ecx
346 movl self(%esp), %edx
347
348 // do lookup
349 CacheLookup WORD_RETURN, CACHE_GET, LGetMethodMiss
350
351 // cache hit, method triplet in %eax
352 movl first_arg(%esp), %ecx // check for _objc_msgForward_internal
353 cmpl method_imp(%eax), %ecx // if (imp==_objc_msgForward_internal)
354 je 1f // return (Method)1
355 ret // else return method triplet address
356 1: movl $1, %eax
357 ret
358
359 LGetMethodMiss:
360 // cache miss, return nil
361 xorl %eax, %eax // zero %eax
362 ret
363
364 LGetMethodExit:
365 END_ENTRY __cache_getMethod
366
367
368 /********************************************************************
369 * IMP _cache_getImp(Class cls, SEL sel)
370 *
371 * If found, returns method implementation.
372 * If not found, returns NULL.
373 ********************************************************************/
374
375 .private_extern __cache_getImp
376 ENTRY __cache_getImp
377
378 // load the class and selector
379 movl selector(%esp), %ecx
380 movl self(%esp), %edx
381
382 // do lookup
383 CacheLookup WORD_RETURN, CACHE_GET, LGetImpMiss
384
385 // cache hit, method triplet in %eax
386 movl method_imp(%eax), %eax // return method imp
387 ret
388
389 LGetImpMiss:
390 // cache miss, return nil
391 xorl %eax, %eax // zero %eax
392 ret
393
394 LGetImpExit:
395 END_ENTRY __cache_getImp
396
397
398 /********************************************************************
399 *
400 * id objc_msgSend(id self, SEL _cmd,...);
401 *
402 ********************************************************************/
403
404 ENTRY _objc_msgSend
405
406 // load receiver and selector
407 movl selector(%esp), %ecx
408 movl self(%esp), %eax
409
410 #if SUPPORT_IGNORED_SELECTOR_CONSTANT
411 // check whether selector is ignored
412 cmpl $ kIgnore, %ecx
413 je LMsgSendDone // return self from %eax
414 #endif
415
416 // check whether receiver is nil
417 testl %eax, %eax
418 je LMsgSendNilSelf
419
420 // receiver (in %eax) is non-nil: search the cache
421 LMsgSendReceiverOk:
422 movl isa(%eax), %edx // class = self->isa
423 CacheLookup WORD_RETURN, MSG_SEND, LMsgSendCacheMiss
424 xor %edx, %edx // set nonstret for msgForward_internal
425 jmp *%eax
426
427 // cache miss: go search the method lists
428 LMsgSendCacheMiss:
429 MethodTableLookup WORD_RETURN, MSG_SEND
430 xor %edx, %edx // set nonstret for msgForward_internal
431 jmp *%eax // goto *imp
432
433 // message sent to nil: redirect to nil receiver, if any
434 LMsgSendNilSelf:
435 call 1f // load new receiver
436 1: popl %edx
437 movl __objc_nilReceiver-1b(%edx),%eax
438 testl %eax, %eax // return nil if no new receiver
439 je LMsgSendReturnZero
440 movl %eax, self(%esp) // send to new receiver
441 jmp LMsgSendReceiverOk // receiver must be in %eax
442 LMsgSendReturnZero:
443 // %eax is already zero
444 movl $0,%edx
445 LMsgSendDone:
446 ret
447 LMsgSendExit:
448 END_ENTRY _objc_msgSend
449
450 /********************************************************************
451 *
452 * id objc_msgSendSuper(struct objc_super *super, SEL _cmd,...);
453 *
454 * struct objc_super {
455 * id receiver;
456 * Class class;
457 * };
458 ********************************************************************/
459
460 ENTRY _objc_msgSendSuper
461
462 // load selector and class to search
463 movl super(%esp), %eax // struct objc_super
464 movl selector(%esp), %ecx
465 movl class(%eax), %edx // struct objc_super->class
466
467 #if SUPPORT_IGNORED_SELECTOR_CONSTANT
468 // check whether selector is ignored
469 cmpl $ kIgnore, %ecx
470 je LMsgSendSuperIgnored // return self from %eax
471 #endif
472
473 // search the cache (class in %edx)
474 CacheLookup WORD_RETURN, MSG_SENDSUPER, LMsgSendSuperCacheMiss
475 xor %edx, %edx // set nonstret for msgForward_internal
476 jmp *%eax // goto *imp
477
478 // cache miss: go search the method lists
479 LMsgSendSuperCacheMiss:
480 MethodTableLookup WORD_RETURN, MSG_SENDSUPER
481 xor %edx, %edx // set nonstret for msgForward_internal
482 jmp *%eax // goto *imp
483
484 // ignored selector: return self
485 LMsgSendSuperIgnored:
486 movl super(%esp), %eax
487 movl receiver(%eax), %eax
488 ret
489
490 LMsgSendSuperExit:
491 END_ENTRY _objc_msgSendSuper
492
493
494 ENTRY _objc_msgSendSuper2
495
496 // load selector and class to search
497 movl super(%esp), %eax // struct objc_super
498 movl selector(%esp), %ecx
499 movl class(%eax), %eax // struct objc_super->class
500 mov superclass(%eax), %edx // edx = objc_super->class->super_class
501
502 #if SUPPORT_IGNORED_SELECTOR_CONSTANT
503 // check whether selector is ignored
504 cmpl $ kIgnore, %ecx
505 je LMsgSendSuperIgnored // return self from %eax
506 #endif
507
508 // search the cache (class in %edx)
509 CacheLookup WORD_RETURN, MSG_SENDSUPER2, LMsgSendSuper2CacheMiss
510 xor %edx, %edx // set nonstret for msgForward_internal
511 jmp *%eax // goto *imp
512
513 // cache miss: go search the method lists
514 LMsgSendSuper2CacheMiss:
515 MethodTableLookup WORD_RETURN, MSG_SENDSUPER2
516 xor %edx, %edx // set nonstret for msgForward_internal
517 jmp *%eax // goto *imp
518
519 // ignored selector: return self
520 LMsgSendSuper2Ignored:
521 movl super(%esp), %eax
522 movl receiver(%eax), %eax
523 ret
524
525 LMsgSendSuper2Exit:
526 END_ENTRY _objc_msgSendSuper2
527
528
529 /********************************************************************
530 *
531 * double objc_msgSend_fpret(id self, SEL _cmd,...);
532 *
533 ********************************************************************/
534
535 ENTRY _objc_msgSend_fpret
536
537 // load receiver and selector
538 movl selector(%esp), %ecx
539 movl self(%esp), %eax
540
541 #if SUPPORT_IGNORED_SELECTOR_CONSTANT
542 // check whether selector is ignored
543 cmpl $ kIgnore, %ecx
544 je LMsgSendFpretDone // return self from %eax
545 #endif
546
547 // check whether receiver is nil
548 testl %eax, %eax
549 je LMsgSendFpretNilSelf
550
551 // receiver (in %eax) is non-nil: search the cache
552 LMsgSendFpretReceiverOk:
553 movl isa(%eax), %edx // class = self->isa
554 CacheLookup WORD_RETURN, MSG_SEND, LMsgSendFpretCacheMiss
555 xor %edx, %edx // set nonstret for msgForward_internal
556 jmp *%eax // goto *imp
557
558 // cache miss: go search the method lists
559 LMsgSendFpretCacheMiss:
560 MethodTableLookup WORD_RETURN, MSG_SEND
561 xor %edx, %edx // set nonstret for msgForward_internal
562 jmp *%eax // goto *imp
563
564 // message sent to nil: redirect to nil receiver, if any
565 LMsgSendFpretNilSelf:
566 call 1f // load new receiver
567 1: popl %edx
568 movl __objc_nilReceiver-1b(%edx),%eax
569 testl %eax, %eax // return zero if no new receiver
570 je LMsgSendFpretReturnZero
571 movl %eax, self(%esp) // send to new receiver
572 jmp LMsgSendFpretReceiverOk // receiver must be in %eax
573 LMsgSendFpretReturnZero:
574 fldz
575 LMsgSendFpretDone:
576 ret
577
578 LMsgSendFpretExit:
579 END_ENTRY _objc_msgSend_fpret
580
581
582 /********************************************************************
583 *
584 * void objc_msgSend_stret(void *st_addr , id self, SEL _cmd, ...);
585 *
586 *
587 * objc_msgSend_stret is the struct-return form of msgSend.
588 * The ABI calls for (sp+4) to be used as the address of the structure
589 * being returned, with the parameters in the succeeding locations.
590 *
591 * On entry: (sp+4)is the address where the structure is returned,
592 * (sp+8) is the message receiver,
593 * (sp+12) is the selector
594 ********************************************************************/
595
596 ENTRY _objc_msgSend_stret
597
598 // load receiver and selector
599 movl self_stret(%esp), %eax
600 movl (selector_stret)(%esp), %ecx
601
602 // check whether receiver is nil
603 testl %eax, %eax
604 je LMsgSendStretNilSelf
605
606 // receiver (in %eax) is non-nil: search the cache
607 LMsgSendStretReceiverOk:
608 movl isa(%eax), %edx // class = self->isa
609 CacheLookup STRUCT_RETURN, MSG_SEND, LMsgSendStretCacheMiss
610 movl $1, %edx // set stret for objc_msgForward
611 jmp *%eax // goto *imp
612
613 // cache miss: go search the method lists
614 LMsgSendStretCacheMiss:
615 MethodTableLookup STRUCT_RETURN, MSG_SEND
616 movl $1, %edx // set stret for objc_msgForward
617 jmp *%eax // goto *imp
618
619 // message sent to nil: redirect to nil receiver, if any
620 LMsgSendStretNilSelf:
621 call 1f // load new receiver
622 1: popl %edx
623 movl __objc_nilReceiver-1b(%edx),%eax
624 testl %eax, %eax // return nil if no new receiver
625 je LMsgSendStretDone
626 movl %eax, self_stret(%esp) // send to new receiver
627 jmp LMsgSendStretReceiverOk // receiver must be in %eax
628 LMsgSendStretDone:
629 ret $4 // pop struct return address (#2995932)
630 LMsgSendStretExit:
631 END_ENTRY _objc_msgSend_stret
632
633 /********************************************************************
634 *
635 * void objc_msgSendSuper_stret(void *st_addr, struct objc_super *super, SEL _cmd, ...);
636 *
637 * struct objc_super {
638 * id receiver;
639 * Class class;
640 * };
641 *
642 * objc_msgSendSuper_stret is the struct-return form of msgSendSuper.
643 * The ABI calls for (sp+4) to be used as the address of the structure
644 * being returned, with the parameters in the succeeding registers.
645 *
646 * On entry: (sp+4)is the address where the structure is returned,
647 * (sp+8) is the address of the objc_super structure,
648 * (sp+12) is the selector
649 *
650 ********************************************************************/
651
652 ENTRY _objc_msgSendSuper_stret
653
654 // load selector and class to search
655 movl super_stret(%esp), %eax // struct objc_super
656 movl (selector_stret)(%esp), %ecx // get selector
657 movl class(%eax), %edx // struct objc_super->class
658
659 // search the cache (class in %edx)
660 CacheLookup STRUCT_RETURN, MSG_SENDSUPER, LMsgSendSuperStretCacheMiss
661 movl $1, %edx // set stret for objc_msgForward
662 jmp *%eax // goto *imp
663
664 // cache miss: go search the method lists
665 LMsgSendSuperStretCacheMiss:
666 MethodTableLookup STRUCT_RETURN, MSG_SENDSUPER
667 movl $1, %edx // set stret for objc_msgForward
668 jmp *%eax // goto *imp
669
670 LMsgSendSuperStretExit:
671 END_ENTRY _objc_msgSendSuper_stret
672
673
674 ENTRY _objc_msgSendSuper2_stret
675
676 // load selector and class to search
677 movl super_stret(%esp), %eax // struct objc_super
678 movl (selector_stret)(%esp), %ecx // get selector
679 movl class(%eax), %eax // struct objc_super->class
680 mov superclass(%eax), %edx // edx = objc_super->class->super_class
681
682 // search the cache (class in %edx)
683 CacheLookup STRUCT_RETURN, MSG_SENDSUPER2, LMsgSendSuper2StretCacheMiss
684 movl $1, %edx // set stret for objc_msgForward
685 jmp *%eax // goto *imp
686
687 // cache miss: go search the method lists
688 LMsgSendSuper2StretCacheMiss:
689 MethodTableLookup STRUCT_RETURN, MSG_SENDSUPER2
690 movl $1, %edx // set stret for objc_msgForward
691 jmp *%eax // goto *imp
692
693 LMsgSendSuper2StretExit:
694 END_ENTRY _objc_msgSendSuper2_stret
695
696
697 /********************************************************************
698 *
699 * id _objc_msgForward(id self, SEL _cmd,...);
700 *
701 ********************************************************************/
702
703 // _FwdSel is @selector(forward::), set up in map_images().
704 // ALWAYS dereference _FwdSel to get to "forward::" !!
705 .data
706 .align 2
707 .private_extern _FwdSel
708 _FwdSel: .long 0
709
710
711 .cstring
712 .align 2
713 LUnkSelStr: .ascii "Does not recognize selector %s\0"
714
715 .data
716 .align 2
717 .private_extern __objc_forward_handler
718 __objc_forward_handler: .long 0
719
720 .data
721 .align 2
722 .private_extern __objc_forward_stret_handler
723 __objc_forward_stret_handler: .long 0
724
725 ENTRY __objc_msgForward_internal
726 .private_extern __objc_msgForward_internal
727 // Method cache version
728
729 // THIS IS NOT A CALLABLE C FUNCTION
730 // Out-of-band register %edx is nonzero for stret, zero otherwise
731
732 // Check return type (stret or not)
733 testl %edx, %edx
734 jnz __objc_msgForward_stret
735 jmp __objc_msgForward
736
737 END_ENTRY _objc_msgForward_internal
738
739
740 ENTRY __objc_msgForward
741 // Non-struct return version
742
743 // Get PIC base into %edx
744 call L__objc_msgForward$pic_base
745 L__objc_msgForward$pic_base:
746 popl %edx
747
748 // Call user handler, if any
749 movl __objc_forward_handler-L__objc_msgForward$pic_base(%edx),%ecx
750 testl %ecx, %ecx // if not NULL
751 je 1f // skip to default handler
752 jmp *%ecx // call __objc_forward_handler
753 1:
754 // No user handler
755 // Push stack frame
756 pushl %ebp
757 movl %esp, %ebp
758
759 // Die if forwarding "forward::"
760 movl (selector+4)(%ebp), %eax
761 movl _FwdSel-L__objc_msgForward$pic_base(%edx),%ecx
762 cmpl %ecx, %eax
763 je LMsgForwardError
764
765 // Call [receiver forward:sel :margs]
766 subl $8, %esp // 16-byte align the stack
767 leal (self+4)(%ebp), %ecx
768 pushl %ecx // &margs
769 pushl %eax // sel
770 movl _FwdSel-L__objc_msgForward$pic_base(%edx),%ecx
771 pushl %ecx // forward::
772 pushl (self+4)(%ebp) // receiver
773
774 call _objc_msgSend
775
776 movl %ebp, %esp
777 popl %ebp
778 ret
779
780 LMsgForwardError:
781 // Call __objc_error(receiver, "unknown selector %s", "forward::")
782 subl $12, %esp // 16-byte align the stack
783 movl _FwdSel-L__objc_msgForward$pic_base(%edx),%eax
784 pushl %eax
785 leal LUnkSelStr-L__objc_msgForward$pic_base(%edx),%eax
786 pushl %eax
787 pushl (self+4)(%ebp)
788 call ___objc_error // never returns
789
790 END_ENTRY __objc_msgForward
791
792
793 ENTRY __objc_msgForward_stret
794 // Struct return version
795
796 // Get PIC base into %edx
797 call L__objc_msgForwardStret$pic_base
798 L__objc_msgForwardStret$pic_base:
799 popl %edx
800
801 // Call user handler, if any
802 movl __objc_forward_stret_handler-L__objc_msgForwardStret$pic_base(%edx), %ecx
803 testl %ecx, %ecx // if not NULL
804 je 1f // skip to default handler
805 jmp *%ecx // call __objc_forward_stret_handler
806 1:
807 // No user handler
808 // Push stack frame
809 pushl %ebp
810 movl %esp, %ebp
811
812 // Die if forwarding "forward::"
813 movl (selector_stret+4)(%ebp), %eax
814 movl _FwdSel-L__objc_msgForwardStret$pic_base(%edx), %ecx
815 cmpl %ecx, %eax
816 je LMsgForwardStretError
817
818 // Call [receiver forward:sel :margs]
819 subl $8, %esp // 16-byte align the stack
820 leal (self_stret+4)(%ebp), %ecx
821 pushl %ecx // &margs
822 pushl %eax // sel
823 movl _FwdSel-L__objc_msgForwardStret$pic_base(%edx),%ecx
824 pushl %ecx // forward::
825 pushl (self_stret+4)(%ebp) // receiver
826
827 call _objc_msgSend
828
829 movl %ebp, %esp
830 popl %ebp
831 ret $4 // pop struct return address (#2995932)
832
833 LMsgForwardStretError:
834 // Call __objc_error(receiver, "unknown selector %s", "forward::")
835 subl $12, %esp // 16-byte align the stack
836 leal _FwdSel-L__objc_msgForwardStret$pic_base(%edx),%eax
837 pushl %eax
838 leal LUnkSelStr-L__objc_msgForwardStret$pic_base(%edx),%eax
839 pushl %eax
840 pushl (self_stret+4)(%ebp)
841 call ___objc_error // never returns
842
843 END_ENTRY __objc_msgForward_stret
844
845
846 ENTRY _objc_msgSend_debug
847 jmp _objc_msgSend
848 END_ENTRY _objc_msgSend_debug
849
850 ENTRY _objc_msgSendSuper2_debug
851 jmp _objc_msgSendSuper2
852 END_ENTRY _objc_msgSendSuper2_debug
853
854 ENTRY _objc_msgSend_stret_debug
855 jmp _objc_msgSend_stret
856 END_ENTRY _objc_msgSend_stret_debug
857
858 ENTRY _objc_msgSendSuper2_stret_debug
859 jmp _objc_msgSendSuper2_stret
860 END_ENTRY _objc_msgSendSuper2_stret_debug
861
862 ENTRY _objc_msgSend_fpret_debug
863 jmp _objc_msgSend_fpret
864 END_ENTRY _objc_msgSend_fpret_debug
865
866
867 ENTRY _objc_msgSend_noarg
868 jmp _objc_msgSend
869 END_ENTRY _objc_msgSend_noarg
870
871
872 ENTRY _method_invoke
873
874 movl selector(%esp), %ecx
875 movl method_name(%ecx), %edx
876 movl method_imp(%ecx), %eax
877 movl %edx, selector(%esp)
878 jmp *%eax
879
880 END_ENTRY _method_invoke
881
882
883 ENTRY _method_invoke_stret
884
885 movl selector_stret(%esp), %ecx
886 movl method_name(%ecx), %edx
887 movl method_imp(%ecx), %eax
888 movl %edx, selector_stret(%esp)
889 jmp *%eax
890
891 END_ENTRY _method_invoke_stret
892
893 #if !defined(NDEBUG)
894 STATIC_ENTRY __objc_ignored_method
895
896 movl self(%esp), %eax
897 ret
898
899 END_ENTRY __objc_ignored_method
900 #endif
901
902 #endif