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