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