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