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