]> git.saurik.com Git - apple/objc4.git/blob - runtime/Messengers.subproj/objc-msg-x86_64.s
objc4-709.tar.gz
[apple/objc4.git] / runtime / Messengers.subproj / objc-msg-x86_64.s
1 /*
2 * Copyright (c) 1999-2007 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 __x86_64__ && !TARGET_OS_SIMULATOR
26
27 /********************************************************************
28 ********************************************************************
29 **
30 ** objc-msg-x86_64.s - x86-64 code to support objc messaging.
31 **
32 ********************************************************************
33 ********************************************************************/
34
35 .data
36
37 // _objc_entryPoints and _objc_exitPoints are used by objc
38 // to get the critical regions for which method caches
39 // cannot be garbage collected.
40
41 .align 4
42 .private_extern _objc_entryPoints
43 _objc_entryPoints:
44 .quad _cache_getImp
45 .quad _objc_msgSend
46 .quad _objc_msgSend_fpret
47 .quad _objc_msgSend_fp2ret
48 .quad _objc_msgSend_stret
49 .quad _objc_msgSendSuper
50 .quad _objc_msgSendSuper_stret
51 .quad _objc_msgSendSuper2
52 .quad _objc_msgSendSuper2_stret
53 .quad _objc_msgLookup
54 .quad _objc_msgLookup_fpret
55 .quad _objc_msgLookup_fp2ret
56 .quad _objc_msgLookup_stret
57 .quad _objc_msgLookupSuper2
58 .quad _objc_msgLookupSuper2_stret
59 .quad 0
60
61 .private_extern _objc_exitPoints
62 _objc_exitPoints:
63 .quad LExit_cache_getImp
64 .quad LExit_objc_msgSend
65 .quad LExit_objc_msgSend_fpret
66 .quad LExit_objc_msgSend_fp2ret
67 .quad LExit_objc_msgSend_stret
68 .quad LExit_objc_msgSendSuper
69 .quad LExit_objc_msgSendSuper_stret
70 .quad LExit_objc_msgSendSuper2
71 .quad LExit_objc_msgSendSuper2_stret
72 .quad LExit_objc_msgLookup
73 .quad LExit_objc_msgLookup_fpret
74 .quad LExit_objc_msgLookup_fp2ret
75 .quad LExit_objc_msgLookup_stret
76 .quad LExit_objc_msgLookupSuper2
77 .quad LExit_objc_msgLookupSuper2_stret
78 .quad 0
79
80
81 /********************************************************************
82 * List every exit insn from every messenger for debugger use.
83 * Format:
84 * (
85 * 1 word instruction's address
86 * 1 word type (ENTER or FAST_EXIT or SLOW_EXIT or NIL_EXIT)
87 * )
88 * 1 word zero
89 *
90 * ENTER is the start of a dispatcher
91 * FAST_EXIT is method dispatch
92 * SLOW_EXIT is uncached method lookup
93 * NIL_EXIT is returning zero from a message sent to nil
94 * These must match objc-gdb.h.
95 ********************************************************************/
96
97 #define ENTER 1
98 #define FAST_EXIT 2
99 #define SLOW_EXIT 3
100 #define NIL_EXIT 4
101
102 .section __DATA,__objc_msg_break
103 .globl _gdb_objc_messenger_breakpoints
104 _gdb_objc_messenger_breakpoints:
105 // contents populated by the macros below
106
107 .macro MESSENGER_START
108 4:
109 .section __DATA,__objc_msg_break
110 .quad 4b
111 .quad ENTER
112 .text
113 .endmacro
114 .macro MESSENGER_END_FAST
115 4:
116 .section __DATA,__objc_msg_break
117 .quad 4b
118 .quad FAST_EXIT
119 .text
120 .endmacro
121 .macro MESSENGER_END_SLOW
122 4:
123 .section __DATA,__objc_msg_break
124 .quad 4b
125 .quad SLOW_EXIT
126 .text
127 .endmacro
128 .macro MESSENGER_END_NIL
129 4:
130 .section __DATA,__objc_msg_break
131 .quad 4b
132 .quad NIL_EXIT
133 .text
134 .endmacro
135
136
137 /********************************************************************
138 * Recommended multi-byte NOP instructions
139 * (Intel 64 and IA-32 Architectures Software Developer's Manual Volume 2B)
140 ********************************************************************/
141 #define nop1 .byte 0x90
142 #define nop2 .byte 0x66,0x90
143 #define nop3 .byte 0x0F,0x1F,0x00
144 #define nop4 .byte 0x0F,0x1F,0x40,0x00
145 #define nop5 .byte 0x0F,0x1F,0x44,0x00,0x00
146 #define nop6 .byte 0x66,0x0F,0x1F,0x44,0x00,0x00
147 #define nop7 .byte 0x0F,0x1F,0x80,0x00,0x00,0x00,0x00
148 #define nop8 .byte 0x0F,0x1F,0x84,0x00,0x00,0x00,0x00,0x00
149 #define nop9 .byte 0x66,0x0F,0x1F,0x84,0x00,0x00,0x00,0x00,0x00
150
151
152 /********************************************************************
153 * Harmless branch prefix hint for instruction alignment
154 ********************************************************************/
155
156 #define PN .byte 0x2e
157
158
159 /********************************************************************
160 * Names for parameter registers.
161 ********************************************************************/
162
163 #define a1 rdi
164 #define a1d edi
165 #define a1b dil
166 #define a2 rsi
167 #define a2d esi
168 #define a2b sil
169 #define a3 rdx
170 #define a3d edx
171 #define a4 rcx
172 #define a4d ecx
173 #define a5 r8
174 #define a5d r8d
175 #define a6 r9
176 #define a6d r9d
177
178
179 /********************************************************************
180 * Names for relative labels
181 * DO NOT USE THESE LABELS ELSEWHERE
182 * Reserved labels: 6: 7: 8: 9:
183 ********************************************************************/
184 #define LCacheMiss 6
185 #define LCacheMiss_f 6f
186 #define LCacheMiss_b 6b
187 #define LNilTestSlow 7
188 #define LNilTestSlow_f 7f
189 #define LNilTestSlow_b 7b
190 #define LGetIsaDone 8
191 #define LGetIsaDone_f 8f
192 #define LGetIsaDone_b 8b
193 #define LGetIsaSlow 9
194 #define LGetIsaSlow_f 9f
195 #define LGetIsaSlow_b 9b
196
197 /********************************************************************
198 * Macro parameters
199 ********************************************************************/
200
201 #define NORMAL 0
202 #define FPRET 1
203 #define FP2RET 2
204 #define STRET 3
205
206 #define CALL 100
207 #define GETIMP 101
208 #define LOOKUP 102
209
210
211 /********************************************************************
212 *
213 * Structure definitions.
214 *
215 ********************************************************************/
216
217 // objc_super parameter to sendSuper
218 #define receiver 0
219 #define class 8
220
221 // Selected field offsets in class structure
222 // #define isa 0 USE GetIsa INSTEAD
223
224 // Method descriptor
225 #define method_name 0
226 #define method_imp 16
227
228
229 //////////////////////////////////////////////////////////////////////
230 //
231 // ENTRY functionName
232 //
233 // Assembly directives to begin an exported function.
234 //
235 // Takes: functionName - name of the exported function
236 //////////////////////////////////////////////////////////////////////
237
238 .macro ENTRY
239 .text
240 .globl $0
241 .align 6, 0x90
242 $0:
243 .endmacro
244
245 .macro STATIC_ENTRY
246 .text
247 .private_extern $0
248 .align 2, 0x90
249 $0:
250 .endmacro
251
252 //////////////////////////////////////////////////////////////////////
253 //
254 // END_ENTRY functionName
255 //
256 // Assembly directives to end an exported function. Just a placeholder,
257 // a close-parenthesis for ENTRY, until it is needed for something.
258 //
259 // Takes: functionName - name of the exported function
260 //////////////////////////////////////////////////////////////////////
261
262 .macro END_ENTRY
263 LExit$0:
264 .endmacro
265
266
267 /********************************************************************
268 * UNWIND name, flags
269 * Unwind info generation
270 ********************************************************************/
271 .macro UNWIND
272 .section __LD,__compact_unwind,regular,debug
273 .quad $0
274 .set LUnwind$0, LExit$0 - $0
275 .long LUnwind$0
276 .long $1
277 .quad 0 /* no personality */
278 .quad 0 /* no LSDA */
279 .text
280 .endmacro
281
282 #define NoFrame 0x02010000 // no frame, no SP adjustment except return address
283 #define FrameWithNoSaves 0x01000000 // frame, no non-volatile saves
284
285
286 /////////////////////////////////////////////////////////////////////
287 //
288 // CacheLookup return-type, caller
289 //
290 // Locate the implementation for a class in a selector's method cache.
291 //
292 // Takes:
293 // $0 = NORMAL, FPRET, FP2RET, STRET
294 // $1 = CALL, LOOKUP, GETIMP
295 // a1 or a2 (STRET) = receiver
296 // a2 or a3 (STRET) = selector
297 // r10 = class to search
298 //
299 // On exit: r10 clobbered
300 // (found) calls or returns IMP in r11, eq/ne set for forwarding
301 // (not found) jumps to LCacheMiss, class still in r10
302 //
303 /////////////////////////////////////////////////////////////////////
304
305 .macro CacheHit
306
307 // CacheHit must always be preceded by a not-taken `jne` instruction
308 // in order to set the correct flags for _objc_msgForward_impcache.
309
310 // r11 = found bucket
311
312 .if $1 == GETIMP
313 movq 8(%r11), %rax // return imp
314 ret
315
316 .else
317
318 .if $0 != STRET
319 // eq already set for forwarding by `jne`
320 .else
321 test %r11, %r11 // set ne for stret forwarding
322 .endif
323
324 .if $1 == CALL
325 MESSENGER_END_FAST
326 jmp *8(%r11) // call imp
327
328 .elseif $1 == LOOKUP
329 movq 8(%r11), %r11 // return imp
330 ret
331
332 .else
333 .abort oops
334 .endif
335
336 .endif
337
338 .endmacro
339
340
341 .macro CacheLookup
342 .if $0 != STRET
343 movq %a2, %r11 // r11 = _cmd
344 .else
345 movq %a3, %r11 // r11 = _cmd
346 .endif
347 andl 24(%r10), %r11d // r11 = _cmd & class->cache.mask
348 shlq $$4, %r11 // r11 = offset = (_cmd & mask)<<4
349 addq 16(%r10), %r11 // r11 = class->cache.buckets + offset
350
351 .if $0 != STRET
352 cmpq (%r11), %a2 // if (bucket->sel != _cmd)
353 .else
354 cmpq (%r11), %a3 // if (bucket->sel != _cmd)
355 .endif
356 jne 1f // scan more
357 // CacheHit must always be preceded by a not-taken `jne` instruction
358 CacheHit $0, $1 // call or return imp
359
360 1:
361 // loop
362 cmpq $$1, (%r11)
363 jbe 3f // if (bucket->sel <= 1) wrap or miss
364
365 addq $$16, %r11 // bucket++
366 2:
367 .if $0 != STRET
368 cmpq (%r11), %a2 // if (bucket->sel != _cmd)
369 .else
370 cmpq (%r11), %a3 // if (bucket->sel != _cmd)
371 .endif
372 jne 1b // scan more
373 // CacheHit must always be preceded by a not-taken `jne` instruction
374 CacheHit $0, $1 // call or return imp
375
376 3:
377 // wrap or miss
378 jb LCacheMiss_f // if (bucket->sel < 1) cache miss
379 // wrap
380 movq 8(%r11), %r11 // bucket->imp is really first bucket
381 jmp 2f
382
383 // Clone scanning loop to miss instead of hang when cache is corrupt.
384 // The slow path may detect any corruption and halt later.
385
386 1:
387 // loop
388 cmpq $$1, (%r11)
389 jbe 3f // if (bucket->sel <= 1) wrap or miss
390
391 addq $$16, %r11 // bucket++
392 2:
393 .if $0 != STRET
394 cmpq (%r11), %a2 // if (bucket->sel != _cmd)
395 .else
396 cmpq (%r11), %a3 // if (bucket->sel != _cmd)
397 .endif
398 jne 1b // scan more
399 // CacheHit must always be preceded by a not-taken `jne` instruction
400 CacheHit $0, $1 // call or return imp
401
402 3:
403 // double wrap or miss
404 jmp LCacheMiss_f
405
406 .endmacro
407
408
409 /////////////////////////////////////////////////////////////////////
410 //
411 // MethodTableLookup NORMAL|STRET
412 //
413 // Takes: a1 or a2 (STRET) = receiver
414 // a2 or a3 (STRET) = selector to search for
415 // r10 = class to search
416 //
417 // On exit: imp in %r11, eq/ne set for forwarding
418 //
419 /////////////////////////////////////////////////////////////////////
420
421 .macro MethodTableLookup
422
423 push %rbp
424 mov %rsp, %rbp
425
426 sub $$0x80+8, %rsp // +8 for alignment
427
428 movdqa %xmm0, -0x80(%rbp)
429 push %rax // might be xmm parameter count
430 movdqa %xmm1, -0x70(%rbp)
431 push %a1
432 movdqa %xmm2, -0x60(%rbp)
433 push %a2
434 movdqa %xmm3, -0x50(%rbp)
435 push %a3
436 movdqa %xmm4, -0x40(%rbp)
437 push %a4
438 movdqa %xmm5, -0x30(%rbp)
439 push %a5
440 movdqa %xmm6, -0x20(%rbp)
441 push %a6
442 movdqa %xmm7, -0x10(%rbp)
443
444 // _class_lookupMethodAndLoadCache3(receiver, selector, class)
445
446 .if $0 == NORMAL
447 // receiver already in a1
448 // selector already in a2
449 .else
450 movq %a2, %a1
451 movq %a3, %a2
452 .endif
453 movq %r10, %a3
454 call __class_lookupMethodAndLoadCache3
455
456 // IMP is now in %rax
457 movq %rax, %r11
458
459 movdqa -0x80(%rbp), %xmm0
460 pop %a6
461 movdqa -0x70(%rbp), %xmm1
462 pop %a5
463 movdqa -0x60(%rbp), %xmm2
464 pop %a4
465 movdqa -0x50(%rbp), %xmm3
466 pop %a3
467 movdqa -0x40(%rbp), %xmm4
468 pop %a2
469 movdqa -0x30(%rbp), %xmm5
470 pop %a1
471 movdqa -0x20(%rbp), %xmm6
472 pop %rax
473 movdqa -0x10(%rbp), %xmm7
474
475 .if $0 == NORMAL
476 cmp %r11, %r11 // set eq for nonstret forwarding
477 .else
478 test %r11, %r11 // set ne for stret forwarding
479 .endif
480
481 leave
482
483 .endmacro
484
485
486 /////////////////////////////////////////////////////////////////////
487 //
488 // GetIsaFast return-type
489 // GetIsaSupport return-type
490 //
491 // Sets r10 = obj->isa. Consults the tagged isa table if necessary.
492 //
493 // Takes: $0 = NORMAL or FPRET or FP2RET or STRET
494 // a1 or a2 (STRET) = receiver
495 //
496 // On exit: r10 = receiver->isa
497 // r11 is clobbered
498 //
499 /////////////////////////////////////////////////////////////////////
500
501 .macro GetIsaFast
502 .if $0 != STRET
503 testb $$1, %a1b
504 PN
505 jnz LGetIsaSlow_f
506 movq $$0x00007ffffffffff8, %r10
507 andq (%a1), %r10
508 .else
509 testb $$1, %a2b
510 PN
511 jnz LGetIsaSlow_f
512 movq $$0x00007ffffffffff8, %r10
513 andq (%a2), %r10
514 .endif
515 LGetIsaDone:
516 .endmacro
517
518 .macro GetIsaSupport
519 LGetIsaSlow:
520 .if $0 != STRET
521 movl %a1d, %r11d
522 .else
523 movl %a2d, %r11d
524 .endif
525 andl $$0xF, %r11d
526 cmp $$0xF, %r11d
527 je 1f
528 // basic tagged
529 leaq _objc_debug_taggedpointer_classes(%rip), %r10
530 movq (%r10, %r11, 8), %r10 // read isa from table
531 jmp LGetIsaDone_b
532 1:
533 // extended tagged
534 .if $0 != STRET
535 movl %a1d, %r11d
536 .else
537 movl %a2d, %r11d
538 .endif
539 shrl $$4, %r11d
540 andl $$0xFF, %r11d
541 leaq _objc_debug_taggedpointer_ext_classes(%rip), %r10
542 movq (%r10, %r11, 8), %r10 // read isa from table
543 jmp LGetIsaDone_b
544 .endmacro
545
546
547 /////////////////////////////////////////////////////////////////////
548 //
549 // NilTest return-type
550 //
551 // Takes: $0 = NORMAL or FPRET or FP2RET or STRET
552 // %a1 or %a2 (STRET) = receiver
553 //
554 // On exit: Loads non-nil receiver in %a1 or %a2 (STRET)
555 // or returns.
556 //
557 // NilTestReturnZero return-type
558 //
559 // Takes: $0 = NORMAL or FPRET or FP2RET or STRET
560 // %a1 or %a2 (STRET) = receiver
561 //
562 // On exit: Loads non-nil receiver in %a1 or %a2 (STRET)
563 // or returns zero.
564 //
565 // NilTestReturnIMP return-type
566 //
567 // Takes: $0 = NORMAL or FPRET or FP2RET or STRET
568 // %a1 or %a2 (STRET) = receiver
569 //
570 // On exit: Loads non-nil receiver in %a1 or %a2 (STRET)
571 // or returns an IMP in r11 that returns zero.
572 //
573 /////////////////////////////////////////////////////////////////////
574
575 .macro ZeroReturn
576 xorl %eax, %eax
577 xorl %edx, %edx
578 xorps %xmm0, %xmm0
579 xorps %xmm1, %xmm1
580 .endmacro
581
582 .macro ZeroReturnFPRET
583 fldz
584 ZeroReturn
585 .endmacro
586
587 .macro ZeroReturnFP2RET
588 fldz
589 fldz
590 ZeroReturn
591 .endmacro
592
593 .macro ZeroReturnSTRET
594 // rax gets the struct-return address as passed in rdi
595 movq %rdi, %rax
596 .endmacro
597
598 STATIC_ENTRY __objc_msgNil
599 ZeroReturn
600 ret
601 END_ENTRY __objc_msgNil
602
603 STATIC_ENTRY __objc_msgNil_fpret
604 ZeroReturnFPRET
605 ret
606 END_ENTRY __objc_msgNil_fpret
607
608 STATIC_ENTRY __objc_msgNil_fp2ret
609 ZeroReturnFP2RET
610 ret
611 END_ENTRY __objc_msgNil_fp2ret
612
613 STATIC_ENTRY __objc_msgNil_stret
614 ZeroReturnSTRET
615 ret
616 END_ENTRY __objc_msgNil_stret
617
618
619 .macro NilTest
620 .if $0 != STRET
621 testq %a1, %a1
622 .else
623 testq %a2, %a2
624 .endif
625 PN
626 jz LNilTestSlow_f
627 .endmacro
628
629
630 .macro NilTestReturnZero
631 .align 3
632 LNilTestSlow:
633
634 .if $0 == NORMAL
635 ZeroReturn
636 .elseif $0 == FPRET
637 ZeroReturnFPRET
638 .elseif $0 == FP2RET
639 ZeroReturnFP2RET
640 .elseif $0 == STRET
641 ZeroReturnSTRET
642 .else
643 .abort oops
644 .endif
645 MESSENGER_END_NIL
646 ret
647 .endmacro
648
649
650 .macro NilTestReturnIMP
651 .align 3
652 LNilTestSlow:
653
654 .if $0 == NORMAL
655 leaq __objc_msgNil(%rip), %r11
656 .elseif $0 == FPRET
657 leaq __objc_msgNil_fpret(%rip), %r11
658 .elseif $0 == FP2RET
659 leaq __objc_msgNil_fp2ret(%rip), %r11
660 .elseif $0 == STRET
661 leaq __objc_msgNil_stret(%rip), %r11
662 .else
663 .abort oops
664 .endif
665 ret
666 .endmacro
667
668
669 /********************************************************************
670 * IMP cache_getImp(Class cls, SEL sel)
671 *
672 * On entry: a1 = class whose cache is to be searched
673 * a2 = selector to search for
674 *
675 * If found, returns method implementation.
676 * If not found, returns NULL.
677 ********************************************************************/
678
679 STATIC_ENTRY _cache_getImp
680
681 // do lookup
682 movq %a1, %r10 // move class to r10 for CacheLookup
683 CacheLookup NORMAL, GETIMP // returns IMP on success
684
685 LCacheMiss:
686 // cache miss, return nil
687 xorl %eax, %eax
688 ret
689
690 END_ENTRY _cache_getImp
691
692
693 /********************************************************************
694 *
695 * id objc_msgSend(id self, SEL _cmd,...);
696 * IMP objc_msgLookup(id self, SEL _cmd, ...);
697 *
698 * objc_msgLookup ABI:
699 * IMP returned in r11
700 * Forwarding returned in Z flag
701 * r10 reserved for our use but not used
702 *
703 ********************************************************************/
704
705 .data
706 .align 3
707 .globl _objc_debug_taggedpointer_classes
708 _objc_debug_taggedpointer_classes:
709 .fill 16, 8, 0
710 .globl _objc_debug_taggedpointer_ext_classes
711 _objc_debug_taggedpointer_ext_classes:
712 .fill 256, 8, 0
713
714 ENTRY _objc_msgSend
715 UNWIND _objc_msgSend, NoFrame
716 MESSENGER_START
717
718 NilTest NORMAL
719
720 GetIsaFast NORMAL // r10 = self->isa
721 CacheLookup NORMAL, CALL // calls IMP on success
722
723 NilTestReturnZero NORMAL
724
725 GetIsaSupport NORMAL
726
727 // cache miss: go search the method lists
728 LCacheMiss:
729 // isa still in r10
730 MESSENGER_END_SLOW
731 jmp __objc_msgSend_uncached
732
733 END_ENTRY _objc_msgSend
734
735
736 ENTRY _objc_msgLookup
737
738 NilTest NORMAL
739
740 GetIsaFast NORMAL // r10 = self->isa
741 CacheLookup NORMAL, LOOKUP // returns IMP on success
742
743 NilTestReturnIMP NORMAL
744
745 GetIsaSupport NORMAL
746
747 // cache miss: go search the method lists
748 LCacheMiss:
749 // isa still in r10
750 jmp __objc_msgLookup_uncached
751
752 END_ENTRY _objc_msgLookup
753
754
755 ENTRY _objc_msgSend_fixup
756 int3
757 END_ENTRY _objc_msgSend_fixup
758
759
760 STATIC_ENTRY _objc_msgSend_fixedup
761 // Load _cmd from the message_ref
762 movq 8(%a2), %a2
763 jmp _objc_msgSend
764 END_ENTRY _objc_msgSend_fixedup
765
766
767 /********************************************************************
768 *
769 * id objc_msgSendSuper(struct objc_super *super, SEL _cmd,...);
770 *
771 * struct objc_super {
772 * id receiver;
773 * Class class;
774 * };
775 ********************************************************************/
776
777 ENTRY _objc_msgSendSuper
778 UNWIND _objc_msgSendSuper, NoFrame
779 MESSENGER_START
780
781 // search the cache (objc_super in %a1)
782 movq class(%a1), %r10 // class = objc_super->class
783 movq receiver(%a1), %a1 // load real receiver
784 CacheLookup NORMAL, CALL // calls IMP on success
785
786 // cache miss: go search the method lists
787 LCacheMiss:
788 // class still in r10
789 MESSENGER_END_SLOW
790 jmp __objc_msgSend_uncached
791
792 END_ENTRY _objc_msgSendSuper
793
794
795 /********************************************************************
796 * id objc_msgSendSuper2
797 ********************************************************************/
798
799 ENTRY _objc_msgSendSuper2
800 UNWIND _objc_msgSendSuper2, NoFrame
801 MESSENGER_START
802
803 // objc_super->class is superclass of class to search
804
805 // search the cache (objc_super in %a1)
806 movq class(%a1), %r10 // cls = objc_super->class
807 movq receiver(%a1), %a1 // load real receiver
808 movq 8(%r10), %r10 // cls = class->superclass
809 CacheLookup NORMAL, CALL // calls IMP on success
810
811 // cache miss: go search the method lists
812 LCacheMiss:
813 // superclass still in r10
814 MESSENGER_END_SLOW
815 jmp __objc_msgSend_uncached
816
817 END_ENTRY _objc_msgSendSuper2
818
819
820 ENTRY _objc_msgLookupSuper2
821
822 // objc_super->class is superclass of class to search
823
824 // search the cache (objc_super in %a1)
825 movq class(%a1), %r10 // cls = objc_super->class
826 movq receiver(%a1), %a1 // load real receiver
827 movq 8(%r10), %r10 // cls = class->superclass
828 CacheLookup NORMAL, LOOKUP // returns IMP on success
829
830 // cache miss: go search the method lists
831 LCacheMiss:
832 // superclass still in r10
833 jmp __objc_msgLookup_uncached
834
835 END_ENTRY _objc_msgLookupSuper2
836
837
838 ENTRY _objc_msgSendSuper2_fixup
839 int3
840 END_ENTRY _objc_msgSendSuper2_fixup
841
842
843 STATIC_ENTRY _objc_msgSendSuper2_fixedup
844 // Load _cmd from the message_ref
845 movq 8(%a2), %a2
846 jmp _objc_msgSendSuper2
847 END_ENTRY _objc_msgSendSuper2_fixedup
848
849
850 /********************************************************************
851 *
852 * double objc_msgSend_fpret(id self, SEL _cmd,...);
853 * Used for `long double` return only. `float` and `double` use objc_msgSend.
854 *
855 ********************************************************************/
856
857 ENTRY _objc_msgSend_fpret
858 UNWIND _objc_msgSend_fpret, NoFrame
859 MESSENGER_START
860
861 NilTest FPRET
862
863 GetIsaFast FPRET // r10 = self->isa
864 CacheLookup FPRET, CALL // calls IMP on success
865
866 NilTestReturnZero FPRET
867
868 GetIsaSupport FPRET
869
870 // cache miss: go search the method lists
871 LCacheMiss:
872 // isa still in r10
873 MESSENGER_END_SLOW
874 jmp __objc_msgSend_uncached
875
876 END_ENTRY _objc_msgSend_fpret
877
878
879 ENTRY _objc_msgLookup_fpret
880
881 NilTest FPRET
882
883 GetIsaFast FPRET // r10 = self->isa
884 CacheLookup FPRET, LOOKUP // returns IMP on success
885
886 NilTestReturnIMP FPRET
887
888 GetIsaSupport FPRET
889
890 // cache miss: go search the method lists
891 LCacheMiss:
892 // isa still in r10
893 jmp __objc_msgLookup_uncached
894
895 END_ENTRY _objc_msgLookup_fpret
896
897
898 ENTRY _objc_msgSend_fpret_fixup
899 int3
900 END_ENTRY _objc_msgSend_fpret_fixup
901
902
903 STATIC_ENTRY _objc_msgSend_fpret_fixedup
904 // Load _cmd from the message_ref
905 movq 8(%a2), %a2
906 jmp _objc_msgSend_fpret
907 END_ENTRY _objc_msgSend_fpret_fixedup
908
909
910 /********************************************************************
911 *
912 * double objc_msgSend_fp2ret(id self, SEL _cmd,...);
913 * Used for `complex long double` return only.
914 *
915 ********************************************************************/
916
917 ENTRY _objc_msgSend_fp2ret
918 UNWIND _objc_msgSend_fp2ret, NoFrame
919 MESSENGER_START
920
921 NilTest FP2RET
922
923 GetIsaFast FP2RET // r10 = self->isa
924 CacheLookup FP2RET, CALL // calls IMP on success
925
926 NilTestReturnZero FP2RET
927
928 GetIsaSupport FP2RET
929
930 // cache miss: go search the method lists
931 LCacheMiss:
932 // isa still in r10
933 MESSENGER_END_SLOW
934 jmp __objc_msgSend_uncached
935
936 END_ENTRY _objc_msgSend_fp2ret
937
938
939 ENTRY _objc_msgLookup_fp2ret
940
941 NilTest FP2RET
942
943 GetIsaFast FP2RET // r10 = self->isa
944 CacheLookup FP2RET, LOOKUP // returns IMP on success
945
946 NilTestReturnIMP FP2RET
947
948 GetIsaSupport FP2RET
949
950 // cache miss: go search the method lists
951 LCacheMiss:
952 // isa still in r10
953 jmp __objc_msgLookup_uncached
954
955 END_ENTRY _objc_msgLookup_fp2ret
956
957
958 ENTRY _objc_msgSend_fp2ret_fixup
959 int3
960 END_ENTRY _objc_msgSend_fp2ret_fixup
961
962
963 STATIC_ENTRY _objc_msgSend_fp2ret_fixedup
964 // Load _cmd from the message_ref
965 movq 8(%a2), %a2
966 jmp _objc_msgSend_fp2ret
967 END_ENTRY _objc_msgSend_fp2ret_fixedup
968
969
970 /********************************************************************
971 *
972 * void objc_msgSend_stret(void *st_addr, id self, SEL _cmd, ...);
973 *
974 * objc_msgSend_stret is the struct-return form of msgSend.
975 * The ABI calls for %a1 to be used as the address of the structure
976 * being returned, with the parameters in the succeeding locations.
977 *
978 * On entry: %a1 is the address where the structure is returned,
979 * %a2 is the message receiver,
980 * %a3 is the selector
981 ********************************************************************/
982
983 ENTRY _objc_msgSend_stret
984 UNWIND _objc_msgSend_stret, NoFrame
985 MESSENGER_START
986
987 NilTest STRET
988
989 GetIsaFast STRET // r10 = self->isa
990 CacheLookup STRET, CALL // calls IMP on success
991
992 NilTestReturnZero STRET
993
994 GetIsaSupport STRET
995
996 // cache miss: go search the method lists
997 LCacheMiss:
998 // isa still in r10
999 MESSENGER_END_SLOW
1000 jmp __objc_msgSend_stret_uncached
1001
1002 END_ENTRY _objc_msgSend_stret
1003
1004
1005 ENTRY _objc_msgLookup_stret
1006
1007 NilTest STRET
1008
1009 GetIsaFast STRET // r10 = self->isa
1010 CacheLookup STRET, LOOKUP // returns IMP on success
1011
1012 NilTestReturnIMP STRET
1013
1014 GetIsaSupport STRET
1015
1016 // cache miss: go search the method lists
1017 LCacheMiss:
1018 // isa still in r10
1019 jmp __objc_msgLookup_stret_uncached
1020
1021 END_ENTRY _objc_msgLookup_stret
1022
1023
1024 ENTRY _objc_msgSend_stret_fixup
1025 int3
1026 END_ENTRY _objc_msgSend_stret_fixup
1027
1028
1029 STATIC_ENTRY _objc_msgSend_stret_fixedup
1030 // Load _cmd from the message_ref
1031 movq 8(%a3), %a3
1032 jmp _objc_msgSend_stret
1033 END_ENTRY _objc_msgSend_stret_fixedup
1034
1035
1036 /********************************************************************
1037 *
1038 * void objc_msgSendSuper_stret(void *st_addr, struct objc_super *super, SEL _cmd, ...);
1039 *
1040 * struct objc_super {
1041 * id receiver;
1042 * Class class;
1043 * };
1044 *
1045 * objc_msgSendSuper_stret is the struct-return form of msgSendSuper.
1046 * The ABI calls for (sp+4) to be used as the address of the structure
1047 * being returned, with the parameters in the succeeding registers.
1048 *
1049 * On entry: %a1 is the address where the structure is returned,
1050 * %a2 is the address of the objc_super structure,
1051 * %a3 is the selector
1052 *
1053 ********************************************************************/
1054
1055 ENTRY _objc_msgSendSuper_stret
1056 UNWIND _objc_msgSendSuper_stret, NoFrame
1057 MESSENGER_START
1058
1059 // search the cache (objc_super in %a2)
1060 movq class(%a2), %r10 // class = objc_super->class
1061 movq receiver(%a2), %a2 // load real receiver
1062 CacheLookup STRET, CALL // calls IMP on success
1063
1064 // cache miss: go search the method lists
1065 LCacheMiss:
1066 // class still in r10
1067 MESSENGER_END_SLOW
1068 jmp __objc_msgSend_stret_uncached
1069
1070 END_ENTRY _objc_msgSendSuper_stret
1071
1072
1073 /********************************************************************
1074 * id objc_msgSendSuper2_stret
1075 ********************************************************************/
1076
1077 ENTRY _objc_msgSendSuper2_stret
1078 UNWIND _objc_msgSendSuper2_stret, NoFrame
1079 MESSENGER_START
1080
1081 // search the cache (objc_super in %a2)
1082 movq class(%a2), %r10 // class = objc_super->class
1083 movq receiver(%a2), %a2 // load real receiver
1084 movq 8(%r10), %r10 // class = class->superclass
1085 CacheLookup STRET, CALL // calls IMP on success
1086
1087 // cache miss: go search the method lists
1088 LCacheMiss:
1089 // superclass still in r10
1090 MESSENGER_END_SLOW
1091 jmp __objc_msgSend_stret_uncached
1092
1093 END_ENTRY _objc_msgSendSuper2_stret
1094
1095
1096 ENTRY _objc_msgLookupSuper2_stret
1097
1098 // search the cache (objc_super in %a2)
1099 movq class(%a2), %r10 // class = objc_super->class
1100 movq receiver(%a2), %a2 // load real receiver
1101 movq 8(%r10), %r10 // class = class->superclass
1102 CacheLookup STRET, LOOKUP // returns IMP on success
1103
1104 // cache miss: go search the method lists
1105 LCacheMiss:
1106 // superclass still in r10
1107 jmp __objc_msgLookup_stret_uncached
1108
1109 END_ENTRY _objc_msgLookupSuper2_stret
1110
1111
1112 ENTRY _objc_msgSendSuper2_stret_fixup
1113 int3
1114 END_ENTRY _objc_msgSendSuper2_stret_fixup
1115
1116
1117 STATIC_ENTRY _objc_msgSendSuper2_stret_fixedup
1118 // Load _cmd from the message_ref
1119 movq 8(%a3), %a3
1120 jmp _objc_msgSendSuper2_stret
1121 END_ENTRY _objc_msgSendSuper2_stret_fixedup
1122
1123
1124 /********************************************************************
1125 *
1126 * _objc_msgSend_uncached
1127 * _objc_msgSend_stret_uncached
1128 * _objc_msgLookup_uncached
1129 * _objc_msgLookup_stret_uncached
1130 *
1131 * The uncached method lookup.
1132 *
1133 ********************************************************************/
1134
1135 STATIC_ENTRY __objc_msgSend_uncached
1136 UNWIND __objc_msgSend_uncached, FrameWithNoSaves
1137
1138 // THIS IS NOT A CALLABLE C FUNCTION
1139 // Out-of-band r10 is the searched class
1140
1141 // r10 is already the class to search
1142 MethodTableLookup NORMAL // r11 = IMP
1143 jmp *%r11 // goto *imp
1144
1145 END_ENTRY __objc_msgSend_uncached
1146
1147
1148 STATIC_ENTRY __objc_msgSend_stret_uncached
1149 UNWIND __objc_msgSend_stret_uncached, FrameWithNoSaves
1150
1151 // THIS IS NOT A CALLABLE C FUNCTION
1152 // Out-of-band r10 is the searched class
1153
1154 // r10 is already the class to search
1155 MethodTableLookup STRET // r11 = IMP
1156 jmp *%r11 // goto *imp
1157
1158 END_ENTRY __objc_msgSend_stret_uncached
1159
1160
1161 STATIC_ENTRY __objc_msgLookup_uncached
1162 UNWIND __objc_msgLookup_uncached, FrameWithNoSaves
1163
1164 // THIS IS NOT A CALLABLE C FUNCTION
1165 // Out-of-band r10 is the searched class
1166
1167 // r10 is already the class to search
1168 MethodTableLookup NORMAL // r11 = IMP
1169 ret
1170
1171 END_ENTRY __objc_msgLookup_uncached
1172
1173
1174 STATIC_ENTRY __objc_msgLookup_stret_uncached
1175 UNWIND __objc_msgLookup_stret_uncached, FrameWithNoSaves
1176
1177 // THIS IS NOT A CALLABLE C FUNCTION
1178 // Out-of-band r10 is the searched class
1179
1180 // r10 is already the class to search
1181 MethodTableLookup STRET // r11 = IMP
1182 ret
1183
1184 END_ENTRY __objc_msgLookup_stret_uncached
1185
1186
1187 /********************************************************************
1188 *
1189 * id _objc_msgForward(id self, SEL _cmd,...);
1190 *
1191 * _objc_msgForward and _objc_msgForward_stret are the externally-callable
1192 * functions returned by things like method_getImplementation().
1193 * _objc_msgForward_impcache is the function pointer actually stored in
1194 * method caches.
1195 *
1196 ********************************************************************/
1197
1198 STATIC_ENTRY __objc_msgForward_impcache
1199 // Method cache version
1200
1201 // THIS IS NOT A CALLABLE C FUNCTION
1202 // Out-of-band condition register is NE for stret, EQ otherwise.
1203
1204 MESSENGER_START
1205 nop
1206 MESSENGER_END_SLOW
1207
1208 jne __objc_msgForward_stret
1209 jmp __objc_msgForward
1210
1211 END_ENTRY __objc_msgForward_impcache
1212
1213
1214 ENTRY __objc_msgForward
1215 // Non-stret version
1216
1217 movq __objc_forward_handler(%rip), %r11
1218 jmp *%r11
1219
1220 END_ENTRY __objc_msgForward
1221
1222
1223 ENTRY __objc_msgForward_stret
1224 // Struct-return version
1225
1226 movq __objc_forward_stret_handler(%rip), %r11
1227 jmp *%r11
1228
1229 END_ENTRY __objc_msgForward_stret
1230
1231
1232 ENTRY _objc_msgSend_debug
1233 jmp _objc_msgSend
1234 END_ENTRY _objc_msgSend_debug
1235
1236 ENTRY _objc_msgSendSuper2_debug
1237 jmp _objc_msgSendSuper2
1238 END_ENTRY _objc_msgSendSuper2_debug
1239
1240 ENTRY _objc_msgSend_stret_debug
1241 jmp _objc_msgSend_stret
1242 END_ENTRY _objc_msgSend_stret_debug
1243
1244 ENTRY _objc_msgSendSuper2_stret_debug
1245 jmp _objc_msgSendSuper2_stret
1246 END_ENTRY _objc_msgSendSuper2_stret_debug
1247
1248 ENTRY _objc_msgSend_fpret_debug
1249 jmp _objc_msgSend_fpret
1250 END_ENTRY _objc_msgSend_fpret_debug
1251
1252 ENTRY _objc_msgSend_fp2ret_debug
1253 jmp _objc_msgSend_fp2ret
1254 END_ENTRY _objc_msgSend_fp2ret_debug
1255
1256
1257 ENTRY _objc_msgSend_noarg
1258 jmp _objc_msgSend
1259 END_ENTRY _objc_msgSend_noarg
1260
1261
1262 ENTRY _method_invoke
1263
1264 movq method_imp(%a2), %r11
1265 movq method_name(%a2), %a2
1266 jmp *%r11
1267
1268 END_ENTRY _method_invoke
1269
1270
1271 ENTRY _method_invoke_stret
1272
1273 movq method_imp(%a3), %r11
1274 movq method_name(%a3), %a3
1275 jmp *%r11
1276
1277 END_ENTRY _method_invoke_stret
1278
1279
1280 .section __DATA,__objc_msg_break
1281 .quad 0
1282 .quad 0
1283
1284 #endif