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