]> git.saurik.com Git - apple/objc4.git/blame - runtime/Messengers.subproj/objc-msg-simulator-x86_64.s
objc4-646.tar.gz
[apple/objc4.git] / runtime / Messengers.subproj / objc-msg-simulator-x86_64.s
CommitLineData
8070259c
A
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_IPHONE_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.private_extern _objc_entryPoints
42_objc_entryPoints:
43 .quad _cache_getImp
44 .quad _objc_msgSend
45 .quad _objc_msgSend_fpret
46 .quad _objc_msgSend_fp2ret
47 .quad _objc_msgSend_stret
48 .quad _objc_msgSendSuper
49 .quad _objc_msgSendSuper_stret
50 .quad _objc_msgSendSuper2
51 .quad _objc_msgSendSuper2_stret
52 .quad 0
53
54.private_extern _objc_exitPoints
55_objc_exitPoints:
56 .quad LExit_cache_getImp
57 .quad LExit_objc_msgSend
58 .quad LExit_objc_msgSend_fpret
59 .quad LExit_objc_msgSend_fp2ret
60 .quad LExit_objc_msgSend_stret
61 .quad LExit_objc_msgSendSuper
62 .quad LExit_objc_msgSendSuper_stret
63 .quad LExit_objc_msgSendSuper2
64 .quad LExit_objc_msgSendSuper2_stret
65 .quad 0
66
67
68/********************************************************************
69* List every exit insn from every messenger for debugger use.
70* Format:
71* (
72* 1 word instruction's address
73* 1 word type (ENTER or FAST_EXIT or SLOW_EXIT or NIL_EXIT)
74* )
75* 1 word zero
76*
77* ENTER is the start of a dispatcher
78* FAST_EXIT is method dispatch
79* SLOW_EXIT is uncached method lookup
80* NIL_EXIT is returning zero from a message sent to nil
81* These must match objc-gdb.h.
82********************************************************************/
83
84#define ENTER 1
85#define FAST_EXIT 2
86#define SLOW_EXIT 3
87#define NIL_EXIT 4
88
89.section __DATA,__objc_msg_break
90.globl _gdb_objc_messenger_breakpoints
91_gdb_objc_messenger_breakpoints:
92// contents populated by the macros below
93
94.macro MESSENGER_START
954:
96 .section __DATA,__objc_msg_break
97 .quad 4b
98 .quad ENTER
99 .text
100.endmacro
101.macro MESSENGER_END_FAST
1024:
103 .section __DATA,__objc_msg_break
104 .quad 4b
105 .quad FAST_EXIT
106 .text
107.endmacro
108.macro MESSENGER_END_SLOW
1094:
110 .section __DATA,__objc_msg_break
111 .quad 4b
112 .quad SLOW_EXIT
113 .text
114.endmacro
115.macro MESSENGER_END_NIL
1164:
117 .section __DATA,__objc_msg_break
118 .quad 4b
119 .quad NIL_EXIT
120 .text
121.endmacro
122
123
124/********************************************************************
125 * Recommended multi-byte NOP instructions
126 * (Intel 64 and IA-32 Architectures Software Developer's Manual Volume 2B)
127 ********************************************************************/
128#define nop1 .byte 0x90
129#define nop2 .byte 0x66,0x90
130#define nop3 .byte 0x0F,0x1F,0x00
131#define nop4 .byte 0x0F,0x1F,0x40,0x00
132#define nop5 .byte 0x0F,0x1F,0x44,0x00,0x00
133#define nop6 .byte 0x66,0x0F,0x1F,0x44,0x00,0x00
134#define nop7 .byte 0x0F,0x1F,0x80,0x00,0x00,0x00,0x00
135#define nop8 .byte 0x0F,0x1F,0x84,0x00,0x00,0x00,0x00,0x00
136#define nop9 .byte 0x66,0x0F,0x1F,0x84,0x00,0x00,0x00,0x00,0x00
137
138
139/********************************************************************
140 * Names for parameter registers.
141 ********************************************************************/
142
143#define a1 rdi
144#define a1d edi
145#define a1b dil
146#define a2 rsi
147#define a2d esi
148#define a2b sil
149#define a3 rdx
150#define a3d edx
151#define a4 rcx
152#define a4d ecx
153#define a5 r8
154#define a5d r8d
155#define a6 r9
156#define a6d r9d
157
158
159/********************************************************************
160 * Names for relative labels
161 * DO NOT USE THESE LABELS ELSEWHERE
162 * Reserved labels: 6: 7: 8: 9:
163 ********************************************************************/
164#define LCacheMiss 6
165#define LCacheMiss_f 6f
166#define LCacheMiss_b 6b
167#define LGetIsaDone 7
168#define LGetIsaDone_f 7f
169#define LGetIsaDone_b 7b
170#define LNilOrTagged 8
171#define LNilOrTagged_f 8f
172#define LNilOrTagged_b 8b
173#define LNil 9
174#define LNil_f 9f
175#define LNil_b 9b
176
177/********************************************************************
178 * Macro parameters
179 ********************************************************************/
180
181#define NORMAL 0
182#define FPRET 1
183#define FP2RET 2
184#define GETIMP 3
185#define STRET 4
186#define SUPER 5
187#define SUPER_STRET 6
188#define SUPER2 7
189#define SUPER2_STRET 8
190
191
192/********************************************************************
193 *
194 * Structure definitions.
195 *
196 ********************************************************************/
197
198// objc_super parameter to sendSuper
199#define receiver 0
200#define class 8
201
202// Selected field offsets in class structure
203// #define isa 0 USE GetIsa INSTEAD
204
205// Method descriptor
206#define method_name 0
207#define method_imp 16
208
209
210//////////////////////////////////////////////////////////////////////
211//
212// ENTRY functionName
213//
214// Assembly directives to begin an exported function.
215//
216// Takes: functionName - name of the exported function
217//////////////////////////////////////////////////////////////////////
218
219.macro ENTRY
220 .text
221 .globl $0
222 .align 6, 0x90
223$0:
224 .cfi_startproc
225.endmacro
226
227.macro STATIC_ENTRY
228 .text
229 .private_extern $0
230 .align 2, 0x90
231$0:
232 .cfi_startproc
233.endmacro
234
235//////////////////////////////////////////////////////////////////////
236//
237// END_ENTRY functionName
238//
239// Assembly directives to end an exported function. Just a placeholder,
240// a close-parenthesis for ENTRY, until it is needed for something.
241//
242// Takes: functionName - name of the exported function
243//////////////////////////////////////////////////////////////////////
244
245.macro END_ENTRY
246 .cfi_endproc
247LExit$0:
248.endmacro
249
250
251/////////////////////////////////////////////////////////////////////
252//
253// SaveRegisters
254//
255// Pushes a stack frame and saves all registers that might contain
256// parameter values.
257//
258// On entry:
259// stack = ret
260//
261// On exit:
262// %rsp is 16-byte aligned
263//
264/////////////////////////////////////////////////////////////////////
265
266.macro SaveRegisters
267
268 push %rbp
269 .cfi_def_cfa_offset 16
270 .cfi_offset rbp, -16
271
272 mov %rsp, %rbp
273 .cfi_def_cfa_register rbp
274
275 sub $$0x80+8, %rsp // +8 for alignment
276
277 movdqa %xmm0, -0x80(%rbp)
278 push %rax // might be xmm parameter count
279 movdqa %xmm1, -0x70(%rbp)
280 push %a1
281 movdqa %xmm2, -0x60(%rbp)
282 push %a2
283 movdqa %xmm3, -0x50(%rbp)
284 push %a3
285 movdqa %xmm4, -0x40(%rbp)
286 push %a4
287 movdqa %xmm5, -0x30(%rbp)
288 push %a5
289 movdqa %xmm6, -0x20(%rbp)
290 push %a6
291 movdqa %xmm7, -0x10(%rbp)
292
293.endmacro
294
295/////////////////////////////////////////////////////////////////////
296//
297// RestoreRegisters
298//
299// Pops a stack frame pushed by SaveRegisters
300//
301// On entry:
302// %rbp unchanged since SaveRegisters
303//
304// On exit:
305// stack = ret
306//
307/////////////////////////////////////////////////////////////////////
308
309.macro RestoreRegisters
310
311 movdqa -0x80(%rbp), %xmm0
312 pop %a6
313 movdqa -0x70(%rbp), %xmm1
314 pop %a5
315 movdqa -0x60(%rbp), %xmm2
316 pop %a4
317 movdqa -0x50(%rbp), %xmm3
318 pop %a3
319 movdqa -0x40(%rbp), %xmm4
320 pop %a2
321 movdqa -0x30(%rbp), %xmm5
322 pop %a1
323 movdqa -0x20(%rbp), %xmm6
324 pop %rax
325 movdqa -0x10(%rbp), %xmm7
326
327 leave
328 .cfi_def_cfa rsp, 8
329 .cfi_same_value rbp
330
331.endmacro
332
333
334/////////////////////////////////////////////////////////////////////
335//
336// CacheLookup return-type, caller
337//
338// Locate the implementation for a class in a selector's method cache.
339//
340// Takes:
341// $0 = NORMAL, FPRET, FP2RET, STRET, SUPER, SUPER_STRET, SUPER2, SUPER2_STRET, GETIMP
342// a2 or a3 (STRET) = selector a.k.a. cache
343// r11 = class to search
344//
345// On exit: r10 clobbered
346// (found) calls or returns IMP, eq/ne/r11 set for forwarding
347// (not found) jumps to LCacheMiss, class still in r11
348//
349/////////////////////////////////////////////////////////////////////
350
351.macro CacheHit
352
353 // CacheHit must always be preceded by a not-taken `jne` instruction
354 // in order to set the correct flags for _objc_msgForward_impcache.
355
356 // r10 = found bucket
357
358.if $0 == GETIMP
359 movq 8(%r10), %rax // return imp
360 leaq __objc_msgSend_uncached_impcache(%rip), %r11
361 cmpq %rax, %r11
362 jne 4f
363 xorl %eax, %eax // don't return msgSend_uncached
3644: ret
365.elseif $0 == NORMAL || $0 == FPRET || $0 == FP2RET
366 // eq already set for forwarding by `jne`
367 MESSENGER_END_FAST
368 jmp *8(%r10) // call imp
369
370.elseif $0 == SUPER
371 movq receiver(%a1), %a1 // load real receiver
372 cmp %r10, %r10 // set eq for non-stret forwarding
373 MESSENGER_END_FAST
374 jmp *8(%r10) // call imp
375
376.elseif $0 == SUPER2
377 movq receiver(%a1), %a1 // load real receiver
378 cmp %r10, %r10 // set eq for non-stret forwarding
379 MESSENGER_END_FAST
380 jmp *8(%r10) // call imp
381
382.elseif $0 == STRET
383 test %r10, %r10 // set ne for stret forwarding
384 MESSENGER_END_FAST
385 jmp *8(%r10) // call imp
386
387.elseif $0 == SUPER_STRET
388 movq receiver(%a2), %a2 // load real receiver
389 test %r10, %r10 // set ne for stret forwarding
390 MESSENGER_END_FAST
391 jmp *8(%r10) // call imp
392
393.elseif $0 == SUPER2_STRET
394 movq receiver(%a2), %a2 // load real receiver
395 test %r10, %r10 // set ne for stret forwarding
396 MESSENGER_END_FAST
397 jmp *8(%r10) // call imp
398.else
399.abort oops
400.endif
401
402.endmacro
403
404
405.macro CacheLookup
406.if $0 != STRET && $0 != SUPER_STRET && $0 != SUPER2_STRET
407 movq %a2, %r10 // r10 = _cmd
408.else
409 movq %a3, %r10 // r10 = _cmd
410.endif
411 andl 24(%r11), %r10d // r10 = _cmd & class->cache.mask
412 shlq $$4, %r10 // r10 = offset = (_cmd & mask)<<4
413 addq 16(%r11), %r10 // r10 = class->cache.buckets + offset
414
415.if $0 != STRET && $0 != SUPER_STRET && $0 != SUPER2_STRET
416 cmpq (%r10), %a2 // if (bucket->sel != _cmd)
417.else
418 cmpq (%r10), %a3 // if (bucket->sel != _cmd)
419.endif
420 jne 1f // scan more
421 // CacheHit must always be preceded by a not-taken `jne` instruction
422 CacheHit $0 // call or return imp
423
4241:
425 // loop
426 cmpq $$0, (%r10)
427 je LCacheMiss_f // if (bucket->sel == 0) cache miss
428 cmpq 16(%r11), %r10
429 je 3f // if (bucket == cache->buckets) wrap
430
431 subq $$16, %r10 // bucket--
4322:
433.if $0 != STRET && $0 != SUPER_STRET && $0 != SUPER2_STRET
434 cmpq (%r10), %a2 // if (bucket->sel != _cmd)
435.else
436 cmpq (%r10), %a3 // if (bucket->sel != _cmd)
437.endif
438 jne 1b // scan more
439 // CacheHit must always be preceded by a not-taken `jne` instruction
440 CacheHit $0 // call or return imp
441
4423:
443 // wrap
444 movl 24(%r11), %r10d // r10 = mask a.k.a. last bucket index
445 shlq $$4, %r10 // r10 = offset = mask<<4
446 addq 16(%r11), %r10 // r10 = &cache->buckets[mask]
447 jmp 2f
448
449 // clone scanning loop to crash instead of hang when cache is corrupt
450
4511:
452 // loop
453 cmpq $$0, (%r10)
454 je LCacheMiss_f // if (bucket->sel == 0) cache miss
455 cmpq 16(%r11), %r10
456 je 3f // if (bucket == cache->buckets) wrap
457
458 subq $$16, %r10 // bucket--
4592:
460.if $0 != STRET && $0 != SUPER_STRET && $0 != SUPER2_STRET
461 cmpq (%r10), %a2 // if (bucket->sel != _cmd)
462.else
463 cmpq (%r10), %a3 // if (bucket->sel != _cmd)
464.endif
465 jne 1b // scan more
466 // CacheHit must always be preceded by a not-taken `jne` instruction
467 CacheHit $0 // call or return imp
468
4693:
470 // double wrap - busted
471.if $0 == STRET || $0 == SUPER_STRET || $0 == SUPER2_STRET
472 movq %a2, %a1
473 movq %a3, %a2
474.elseif $0 == GETIMP
475 movq $$0, %a1
476.endif
477 // a1 = receiver
478 // a2 = SEL
479 movq %r11, %a3 // a3 = isa
480.if $0 == GETIMP
481 jmp _cache_getImp_corrupt_cache_error
482.else
483 jmp _objc_msgSend_corrupt_cache_error
484.endif
485
486.endmacro
487
488
489/////////////////////////////////////////////////////////////////////
490//
491// MethodTableLookup classRegister, selectorRegister
492//
493// Takes: $0 = class to search (a1 or a2 or r10 ONLY)
494// $1 = selector to search for (a2 or a3 ONLY)
495// r11 = class to search
496//
497// On exit: imp in %r11
498//
499/////////////////////////////////////////////////////////////////////
500.macro MethodTableLookup
501
502 MESSENGER_END_SLOW
503
504 SaveRegisters
505
506 // _class_lookupMethodAndLoadCache3(receiver, selector, class)
507
508 movq $0, %a1
509 movq $1, %a2
510 movq %r11, %a3
511 call __class_lookupMethodAndLoadCache3
512
513 // IMP is now in %rax
514 movq %rax, %r11
515
516 RestoreRegisters
517
518.endmacro
519
520
521/////////////////////////////////////////////////////////////////////
522//
523// GetIsaCheckNil return-type
524// GetIsaSupport return-type
525//
526// Sets r11 = receiver->isa.
527// Looks up the real class if receiver is a tagged pointer object.
528// Returns zero if obj is nil.
529//
530// Takes: $0 = NORMAL or FPRET or FP2RET or STRET
531// a1 or a2 (STRET) = receiver
532//
533// On exit: r11 = receiver->isa
534// r10 is clobbered
535//
536/////////////////////////////////////////////////////////////////////
537
538.macro GetIsaCheckNil
539.if $0 == SUPER || $0 == SUPER_STRET
540 error super dispatch does not test for nil
541.endif
542
543.if $0 != STRET
544 testq %a1, %a1
545.else
546 testq %a2, %a2
547.endif
548 jle LNilOrTagged_f // MSB tagged pointer looks negative
549
550.if $0 != STRET
551 movq (%a1), %r11 // r11 = isa
552.else
553 movq (%a2), %r11 // r11 = isa
554.endif
555
556LGetIsaDone:
557.endmacro
558
559
560.macro GetIsaSupport
561 .align 3
562LNilOrTagged:
563 jz LNil_f // flags set by NilOrTaggedTest
564
565 // tagged
566
567 leaq _objc_debug_taggedpointer_classes(%rip), %r11
568.if $0 != STRET
569 movq %a1, %r10
570.else
571 movq %a2, %r10
572.endif
573 shrq $$60, %r10
574 movq (%r11, %r10, 8), %r11 // read isa from table
575 jmp LGetIsaDone_b
576
577LNil:
578 // nil
579
580.if $0 == FPRET
581 fldz
582.elseif $0 == FP2RET
583 fldz
584 fldz
585.endif
586.if $0 == STRET
587 movq %rdi, %rax
588.else
589 xorl %eax, %eax
590 xorl %edx, %edx
591 xorps %xmm0, %xmm0
592 xorps %xmm1, %xmm1
593.endif
594 MESSENGER_END_NIL
595 ret
596.endmacro
597
598
599/********************************************************************
600 * IMP cache_getImp(Class cls, SEL sel)
601 *
602 * On entry: a1 = class whose cache is to be searched
603 * a2 = selector to search for
604 *
605 * If found, returns method implementation.
606 * If not found, returns NULL.
607 ********************************************************************/
608
609 STATIC_ENTRY _cache_getImp
610
611// do lookup
612 movq %a1, %r11 // move class to r11 for CacheLookup
613 CacheLookup GETIMP // returns IMP on success
614
615LCacheMiss:
616// cache miss, return nil
617 xorl %eax, %eax
618 ret
619
620LGetImpExit:
621 END_ENTRY _cache_getImp
622
623
624/********************************************************************
625 *
626 * id objc_msgSend(id self, SEL _cmd,...);
627 *
628 ********************************************************************/
629
630 .data
631 .align 3
632 .globl _objc_debug_taggedpointer_classes
633_objc_debug_taggedpointer_classes:
634 .fill 16, 8, 0
635
636 ENTRY _objc_msgSend
637 MESSENGER_START
638
639 GetIsaCheckNil NORMAL // r11 = self->isa, or return zero
640 CacheLookup NORMAL // calls IMP on success
641
642 GetIsaSupport NORMAL
643
644// cache miss: go search the method lists
645LCacheMiss:
646 // isa still in r11
647 MethodTableLookup %a1, %a2 // r11 = IMP
648 cmp %r11, %r11 // set eq (nonstret) for forwarding
649 jmp *%r11 // goto *imp
650
651 END_ENTRY _objc_msgSend
652
653
654 ENTRY _objc_msgSend_fixup
655 int3
656 END_ENTRY _objc_msgSend_fixup
657
658
659 STATIC_ENTRY _objc_msgSend_fixedup
660 // Load _cmd from the message_ref
661 movq 8(%a2), %a2
662 jmp _objc_msgSend
663 END_ENTRY _objc_msgSend_fixedup
664
665
666/********************************************************************
667 *
668 * id objc_msgSendSuper(struct objc_super *super, SEL _cmd,...);
669 *
670 * struct objc_super {
671 * id receiver;
672 * Class class;
673 * };
674 ********************************************************************/
675
676 ENTRY _objc_msgSendSuper
677 MESSENGER_START
678
679// search the cache (objc_super in %a1)
680 movq class(%a1), %r11 // class = objc_super->class
681 CacheLookup SUPER // calls IMP on success
682
683// cache miss: go search the method lists
684LCacheMiss:
685 // class still in r11
686 movq receiver(%a1), %r10
687 MethodTableLookup %r10, %a2 // r11 = IMP
688 movq receiver(%a1), %a1 // load real receiver
689 cmp %r11, %r11 // set eq (nonstret) for forwarding
690 jmp *%r11 // goto *imp
691
692 END_ENTRY _objc_msgSendSuper
693
694
695/********************************************************************
696 * id objc_msgSendSuper2
697 ********************************************************************/
698
699 ENTRY _objc_msgSendSuper2
700 MESSENGER_START
701
702 // objc_super->class is superclass of class to search
703
704// search the cache (objc_super in %a1)
705 movq class(%a1), %r11 // cls = objc_super->class
706 movq 8(%r11), %r11 // cls = class->superclass
707 CacheLookup SUPER2 // calls IMP on success
708
709// cache miss: go search the method lists
710LCacheMiss:
711 // superclass still in r11
712 movq receiver(%a1), %r10
713 MethodTableLookup %r10, %a2 // r11 = IMP
714 movq receiver(%a1), %a1 // load real receiver
715 cmp %r11, %r11 // set eq (nonstret) for forwarding
716 jmp *%r11 // goto *imp
717
718 END_ENTRY _objc_msgSendSuper2
719
720
721 ENTRY _objc_msgSendSuper2_fixup
722 int3
723 END_ENTRY _objc_msgSendSuper2_fixup
724
725
726 STATIC_ENTRY _objc_msgSendSuper2_fixedup
727 // Load _cmd from the message_ref
728 movq 8(%a2), %a2
729 jmp _objc_msgSendSuper2
730 END_ENTRY _objc_msgSendSuper2_fixedup
731
732
733/********************************************************************
734 *
735 * double objc_msgSend_fpret(id self, SEL _cmd,...);
736 * Used for `long double` return only. `float` and `double` use objc_msgSend.
737 *
738 ********************************************************************/
739
740 ENTRY _objc_msgSend_fpret
741 MESSENGER_START
742
743 GetIsaCheckNil FPRET // r11 = self->isa, or return zero
744 CacheLookup FPRET // calls IMP on success
745
746 GetIsaSupport FPRET
747
748// cache miss: go search the method lists
749LCacheMiss:
750 // isa still in r11
751 MethodTableLookup %a1, %a2 // r11 = IMP
752 cmp %r11, %r11 // set eq (nonstret) for forwarding
753 jmp *%r11 // goto *imp
754
755 END_ENTRY _objc_msgSend_fpret
756
757
758 ENTRY _objc_msgSend_fpret_fixup
759 int3
760 END_ENTRY _objc_msgSend_fpret_fixup
761
762
763 STATIC_ENTRY _objc_msgSend_fpret_fixedup
764 // Load _cmd from the message_ref
765 movq 8(%a2), %a2
766 jmp _objc_msgSend_fpret
767 END_ENTRY _objc_msgSend_fpret_fixedup
768
769
770/********************************************************************
771 *
772 * double objc_msgSend_fp2ret(id self, SEL _cmd,...);
773 * Used for `complex long double` return only.
774 *
775 ********************************************************************/
776
777 ENTRY _objc_msgSend_fp2ret
778 MESSENGER_START
779
780 GetIsaCheckNil FP2RET // r11 = self->isa, or return zero
781 CacheLookup FP2RET // calls IMP on success
782
783 GetIsaSupport FP2RET
784
785// cache miss: go search the method lists
786LCacheMiss:
787 // isa still in r11
788 MethodTableLookup %a1, %a2 // r11 = IMP
789 cmp %r11, %r11 // set eq (nonstret) for forwarding
790 jmp *%r11 // goto *imp
791
792 END_ENTRY _objc_msgSend_fp2ret
793
794
795 ENTRY _objc_msgSend_fp2ret_fixup
796 int3
797 END_ENTRY _objc_msgSend_fp2ret_fixup
798
799
800 STATIC_ENTRY _objc_msgSend_fp2ret_fixedup
801 // Load _cmd from the message_ref
802 movq 8(%a2), %a2
803 jmp _objc_msgSend_fp2ret
804 END_ENTRY _objc_msgSend_fp2ret_fixedup
805
806
807/********************************************************************
808 *
809 * void objc_msgSend_stret(void *st_addr, id self, SEL _cmd, ...);
810 *
811 * objc_msgSend_stret is the struct-return form of msgSend.
812 * The ABI calls for %a1 to be used as the address of the structure
813 * being returned, with the parameters in the succeeding locations.
814 *
815 * On entry: %a1 is the address where the structure is returned,
816 * %a2 is the message receiver,
817 * %a3 is the selector
818 ********************************************************************/
819
820 ENTRY _objc_msgSend_stret
821 MESSENGER_START
822
823 GetIsaCheckNil STRET // r11 = self->isa, or return zero
824 CacheLookup STRET // calls IMP on success
825
826 GetIsaSupport STRET
827
828// cache miss: go search the method lists
829LCacheMiss:
830 // isa still in r11
831 MethodTableLookup %a2, %a3 // r11 = IMP
832 test %r11, %r11 // set ne (stret) for forward; r11!=0
833 jmp *%r11 // goto *imp
834
835 END_ENTRY _objc_msgSend_stret
836
837
838 ENTRY _objc_msgSend_stret_fixup
839 int3
840 END_ENTRY _objc_msgSend_stret_fixup
841
842
843 STATIC_ENTRY _objc_msgSend_stret_fixedup
844 // Load _cmd from the message_ref
845 movq 8(%a3), %a3
846 jmp _objc_msgSend_stret
847 END_ENTRY _objc_msgSend_stret_fixedup
848
849
850/********************************************************************
851 *
852 * void objc_msgSendSuper_stret(void *st_addr, struct objc_super *super, SEL _cmd, ...);
853 *
854 * struct objc_super {
855 * id receiver;
856 * Class class;
857 * };
858 *
859 * objc_msgSendSuper_stret is the struct-return form of msgSendSuper.
860 * The ABI calls for (sp+4) to be used as the address of the structure
861 * being returned, with the parameters in the succeeding registers.
862 *
863 * On entry: %a1 is the address where the structure is returned,
864 * %a2 is the address of the objc_super structure,
865 * %a3 is the selector
866 *
867 ********************************************************************/
868
869 ENTRY _objc_msgSendSuper_stret
870 MESSENGER_START
871
872// search the cache (objc_super in %a2)
873 movq class(%a2), %r11 // class = objc_super->class
874 CacheLookup SUPER_STRET // calls IMP on success
875
876// cache miss: go search the method lists
877LCacheMiss:
878 // class still in r11
879 movq receiver(%a2), %r10
880 MethodTableLookup %r10, %a3 // r11 = IMP
881 movq receiver(%a2), %a2 // load real receiver
882 test %r11, %r11 // set ne (stret) for forward; r11!=0
883 jmp *%r11 // goto *imp
884
885 END_ENTRY _objc_msgSendSuper_stret
886
887
888/********************************************************************
889 * id objc_msgSendSuper2_stret
890 ********************************************************************/
891
892 ENTRY _objc_msgSendSuper2_stret
893 MESSENGER_START
894
895// search the cache (objc_super in %a2)
896 movq class(%a2), %r11 // class = objc_super->class
897 movq 8(%r11), %r11 // class = class->superclass
898 CacheLookup SUPER2_STRET // calls IMP on success
899
900// cache miss: go search the method lists
901LCacheMiss:
902 // superclass still in r11
903 movq receiver(%a2), %r10
904 MethodTableLookup %r10, %a3 // r11 = IMP
905 movq receiver(%a2), %a2 // load real receiver
906 test %r11, %r11 // set ne (stret) for forward; r11!=0
907 jmp *%r11 // goto *imp
908
909 END_ENTRY _objc_msgSendSuper2_stret
910
911
912 ENTRY _objc_msgSendSuper2_stret_fixup
913 int3
914 END_ENTRY _objc_msgSendSuper2_stret_fixup
915
916
917 STATIC_ENTRY _objc_msgSendSuper2_stret_fixedup
918 // Load _cmd from the message_ref
919 movq 8(%a3), %a3
920 jmp _objc_msgSendSuper2_stret
921 END_ENTRY _objc_msgSendSuper2_stret_fixedup
922
923
924/********************************************************************
925 *
926 * _objc_msgSend_uncached_impcache
927 * _objc_msgSend_uncached
928 * _objc_msgSend_stret_uncached
929 *
930 * Used to erase method cache entries in-place by
931 * bouncing them to the uncached lookup.
932 *
933 ********************************************************************/
934
935 STATIC_ENTRY __objc_msgSend_uncached_impcache
936 // Method cache version
937
938 // THIS IS NOT A CALLABLE C FUNCTION
939 // Out-of-band condition register is NE for stret, EQ otherwise.
940 // Out-of-band r11 is the searched class
941
942 MESSENGER_START
943 nop
944 MESSENGER_END_SLOW
945
946 jne __objc_msgSend_stret_uncached
947 jmp __objc_msgSend_uncached
948
949 END_ENTRY __objc_msgSend_uncached_impcache
950
951
952 STATIC_ENTRY __objc_msgSend_uncached
953
954 // THIS IS NOT A CALLABLE C FUNCTION
955 // Out-of-band r11 is the searched class
956
957 // r11 is already the class to search
958 MethodTableLookup %a1, %a2 // r11 = IMP
959 cmp %r11, %r11 // set eq (nonstret) for forwarding
960 jmp *%r11 // goto *imp
961
962 END_ENTRY __objc_msgSend_uncached
963
964
965 STATIC_ENTRY __objc_msgSend_stret_uncached
966 // THIS IS NOT A CALLABLE C FUNCTION
967 // Out-of-band r11 is the searched class
968
969 // r11 is already the class to search
970 MethodTableLookup %a2, %a3 // r11 = IMP
971 test %r11, %r11 // set ne (stret) for forward; r11!=0
972 jmp *%r11 // goto *imp
973
974 END_ENTRY __objc_msgSend_stret_uncached
975
976
977/********************************************************************
978*
979* id _objc_msgForward(id self, SEL _cmd,...);
980*
981* _objc_msgForward and _objc_msgForward_stret are the externally-callable
982* functions returned by things like method_getImplementation().
983* _objc_msgForward_impcache is the function pointer actually stored in
984* method caches.
985*
986********************************************************************/
987
988 STATIC_ENTRY __objc_msgForward_impcache
989 // Method cache version
990
991 // THIS IS NOT A CALLABLE C FUNCTION
992 // Out-of-band condition register is NE for stret, EQ otherwise.
993
994 MESSENGER_START
995 nop
996 MESSENGER_END_SLOW
997
998 jne __objc_msgForward_stret
999 jmp __objc_msgForward
1000
1001 END_ENTRY __objc_msgForward_impcache
1002
1003
1004 ENTRY __objc_msgForward
1005 // Non-stret version
1006
1007 movq __objc_forward_handler(%rip), %r11
1008 jmp *%r11
1009
1010 END_ENTRY __objc_msgForward
1011
1012
1013 ENTRY __objc_msgForward_stret
1014 // Struct-return version
1015
1016 movq __objc_forward_stret_handler(%rip), %r11
1017 jmp *%r11
1018
1019 END_ENTRY __objc_msgForward_stret
1020
1021
1022 ENTRY _objc_msgSend_debug
1023 jmp _objc_msgSend
1024 END_ENTRY _objc_msgSend_debug
1025
1026 ENTRY _objc_msgSendSuper2_debug
1027 jmp _objc_msgSendSuper2
1028 END_ENTRY _objc_msgSendSuper2_debug
1029
1030 ENTRY _objc_msgSend_stret_debug
1031 jmp _objc_msgSend_stret
1032 END_ENTRY _objc_msgSend_stret_debug
1033
1034 ENTRY _objc_msgSendSuper2_stret_debug
1035 jmp _objc_msgSendSuper2_stret
1036 END_ENTRY _objc_msgSendSuper2_stret_debug
1037
1038 ENTRY _objc_msgSend_fpret_debug
1039 jmp _objc_msgSend_fpret
1040 END_ENTRY _objc_msgSend_fpret_debug
1041
1042 ENTRY _objc_msgSend_fp2ret_debug
1043 jmp _objc_msgSend_fp2ret
1044 END_ENTRY _objc_msgSend_fp2ret_debug
1045
1046
1047 ENTRY _objc_msgSend_noarg
1048 jmp _objc_msgSend
1049 END_ENTRY _objc_msgSend_noarg
1050
1051
1052 ENTRY _method_invoke
1053
1054 movq method_imp(%a2), %r11
1055 movq method_name(%a2), %a2
1056 jmp *%r11
1057
1058 END_ENTRY _method_invoke
1059
1060
1061 ENTRY _method_invoke_stret
1062
1063 movq method_imp(%a3), %r11
1064 movq method_name(%a3), %a3
1065 jmp *%r11
1066
1067 END_ENTRY _method_invoke_stret
1068
1069
1070 STATIC_ENTRY __objc_ignored_method
1071
1072 movq %a1, %rax
1073 ret
1074
1075 END_ENTRY __objc_ignored_method
1076
1077
1078.section __DATA,__objc_msg_break
1079.quad 0
1080.quad 0
1081
1082#endif