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