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