]> git.saurik.com Git - apple/objc4.git/blob - runtime/Messengers.subproj/objc-msg-x86_64.s
343b300a8b309c992a195324d6a8b09d0874e064
[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
1285 // Workaround for Skype evil (rdar://19715989)
1286
1287 .text
1288 .align 4
1289 .private_extern _map_images
1290 .private_extern _map_2_images
1291 .private_extern _hax
1292 _hax:
1293 nop
1294 nop
1295 nop
1296 nop
1297 nop
1298 nop
1299 nop
1300 nop
1301 nop
1302 nop
1303 nop
1304 nop
1305 nop
1306 nop
1307 nop
1308 nop
1309 nop
1310 _map_images:
1311 nop
1312 nop
1313 nop
1314 nop
1315 nop
1316 nop
1317 nop
1318 nop
1319 nop
1320 nop
1321 nop
1322 nop
1323 nop
1324 nop
1325 nop
1326 nop
1327 jmp _map_2_images
1328
1329 #endif