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#ifdef __x86_64__ 25 26/******************************************************************** 27 ******************************************************************** 28 ** 29 ** objc-msg-x86_64.s - x86-64 code to support objc messaging. 30 ** 31 ******************************************************************** 32 ********************************************************************/ 33 34/******************************************************************** 35* Data used by the ObjC runtime. 36* 37********************************************************************/ 38 39.data 40// Substitute receiver for messages sent to nil (usually also nil) 41// id _objc_nilReceiver 42.align 4 43.private_extern __objc_nilReceiver 44__objc_nilReceiver: 45 .quad 0 46 47// _objc_entryPoints and _objc_exitPoints are used by objc 48// to get the critical regions for which method caches 49// cannot be garbage collected. 50 51.private_extern _objc_entryPoints 52_objc_entryPoints: 53 .quad _cache_getImp 54 .quad _objc_msgSend 55 .quad _objc_msgSend_fpret 56 .quad _objc_msgSend_fp2ret 57 .quad _objc_msgSend_stret 58 .quad _objc_msgSendSuper 59 .quad _objc_msgSendSuper_stret 60 .quad _objc_msgSendSuper2 61 .quad _objc_msgSendSuper2_stret 62 .quad 0 63 64.private_extern _objc_exitPoints 65_objc_exitPoints: 66 .quad LExit_cache_getImp 67 .quad LExit_objc_msgSend 68 .quad LExit_objc_msgSend_fpret 69 .quad LExit_objc_msgSend_fp2ret 70 .quad LExit_objc_msgSend_stret 71 .quad LExit_objc_msgSendSuper 72 .quad LExit_objc_msgSendSuper_stret 73 .quad LExit_objc_msgSendSuper2 74 .quad LExit_objc_msgSendSuper2_stret 75 .quad 0 76 77 78/******************************************************************** 79* List every exit insn from every messenger for debugger use. 80* Format: 81* ( 82* 1 word instruction's address 83* 1 word type (ENTER or FAST_EXIT or SLOW_EXIT or NIL_EXIT) 84* ) 85* 1 word zero 86* 87* ENTER is the start of a dispatcher 88* FAST_EXIT is method dispatch 89* SLOW_EXIT is uncached method lookup 90* NIL_EXIT is returning zero from a message sent to nil 91* These must match objc-gdb.h. 92********************************************************************/ 93 94#define ENTER 1 95#define FAST_EXIT 2 96#define SLOW_EXIT 3 97#define NIL_EXIT 4 98 99.section __DATA,__objc_msg_break 100.globl _gdb_objc_messenger_breakpoints 101_gdb_objc_messenger_breakpoints: 102// contents populated by the macros below 103 104.macro MESSENGER_START 1054: 106 .section __DATA,__objc_msg_break 107 .quad 4b 108 .quad ENTER 109 .text 110.endmacro 111.macro MESSENGER_END_FAST 1124: 113 .section __DATA,__objc_msg_break 114 .quad 4b 115 .quad FAST_EXIT 116 .text 117.endmacro 118.macro MESSENGER_END_SLOW 1194: 120 .section __DATA,__objc_msg_break 121 .quad 4b 122 .quad SLOW_EXIT 123 .text 124.endmacro 125.macro MESSENGER_END_NIL 1264: 127 .section __DATA,__objc_msg_break 128 .quad 4b 129 .quad NIL_EXIT 130 .text 131.endmacro 132 133 134/******************************************************************** 135 * Recommended multi-byte NOP instructions 136 * (Intel 64 and IA-32 Architectures Software Developer's Manual Volume 2B) 137 ********************************************************************/ 138#define nop1 .byte 0x90 139#define nop2 .byte 0x66,0x90 140#define nop3 .byte 0x0F,0x1F,0x00 141#define nop4 .byte 0x0F,0x1F,0x40,0x00 142#define nop5 .byte 0x0F,0x1F,0x44,0x00,0x00 143#define nop6 .byte 0x66,0x0F,0x1F,0x44,0x00,0x00 144#define nop7 .byte 0x0F,0x1F,0x80,0x00,0x00,0x00,0x00 145#define nop8 .byte 0x0F,0x1F,0x84,0x00,0x00,0x00,0x00,0x00 146#define nop9 .byte 0x66,0x0F,0x1F,0x84,0x00,0x00,0x00,0x00,0x00 147 148 149/******************************************************************** 150 * Harmless branch prefix hint for instruction alignment 151 ********************************************************************/ 152 153#define PN .byte 0x2e 154 155 156/******************************************************************** 157 * Names for parameter registers. 158 ********************************************************************/ 159 160#define a1 rdi 161#define a1d edi 162#define a1b dil 163#define a2 rsi 164#define a2d esi 165#define a2b sil 166#define a3 rdx 167#define a3d edx 168#define a4 rcx 169#define a4d ecx 170#define a5 r8 171#define a5d r8d 172#define a6 r9 173#define a6d r9d 174 175 176/******************************************************************** 177 * Names for relative labels 178 * DO NOT USE THESE LABELS ELSEWHERE 179 * Reserved labels: 5: 6: 7: 8: 9: 180 ********************************************************************/ 181#define LCacheMiss 5 182#define LCacheMiss_f 5f 183#define LCacheMiss_b 5b 184#define LNilTestDone 6 185#define LNilTestDone_f 6f 186#define LNilTestDone_b 6b 187#define LNilTestSlow 7 188#define LNilTestSlow_f 7f 189#define LNilTestSlow_b 7b 190#define LGetIsaDone 8 191#define LGetIsaDone_f 8f 192#define LGetIsaDone_b 8b 193#define LGetIsaSlow 9 194#define LGetIsaSlow_f 9f 195#define LGetIsaSlow_b 9b 196 197/******************************************************************** 198 * Macro parameters 199 ********************************************************************/ 200 201#define NORMAL 0 202#define FPRET 1 203#define FP2RET 2 204#define GETIMP 3 205#define STRET 4 206#define SUPER 5 207#define SUPER_STRET 6 208#define SUPER2 7 209#define SUPER2_STRET 8 210 211 212/******************************************************************** 213 * 214 * Structure definitions. 215 * 216 ********************************************************************/ 217 218// objc_super parameter to sendSuper 219#define receiver 0 220#define class 8 221 222// Selected field offsets in class structure 223// #define isa 0 USE GetIsa INSTEAD 224 225// Method descriptor 226#define method_name 0 227#define method_imp 16 228 229// typedef struct { 230// uint128_t floatingPointArgs[8]; // xmm0..xmm7 231// long linkageArea[4]; // r10, rax, ebp, ret 232// long registerArgs[6]; // a1..a6 233// long stackArgs[0]; // variable-size 234// } *marg_list; 235#define FP_AREA 0 236#define LINK_AREA (FP_AREA+8*16) 237#define REG_AREA (LINK_AREA+4*8) 238#define STACK_AREA (REG_AREA+6*8) 239 240 241////////////////////////////////////////////////////////////////////// 242// 243// ENTRY functionName 244// 245// Assembly directives to begin an exported function. 246// 247// Takes: functionName - name of the exported function 248////////////////////////////////////////////////////////////////////// 249 250.macro ENTRY 251 .text 252 .globl $0 253 .align 6, 0x90 254$0: 255.endmacro 256 257.macro STATIC_ENTRY 258 .text 259 .private_extern $0 260 .align 2, 0x90 261$0: 262.endmacro 263 264////////////////////////////////////////////////////////////////////// 265// 266// END_ENTRY functionName 267// 268// Assembly directives to end an exported function. Just a placeholder, 269// a close-parenthesis for ENTRY, until it is needed for something. 270// 271// Takes: functionName - name of the exported function 272////////////////////////////////////////////////////////////////////// 273 274.macro END_ENTRY 275LExit$0: 276.endmacro 277 278 279/* DWARF support 280 These macros work for objc_msgSend variants and others that call 281 CacheLookup/MethodTableLookup or SaveRegisters/RestoreRegisters 282 without otherwise building a frame or clobbering callee-save registers 283 284 The macros build appropriate FDEs and tie them to the CIE. 285*/ 286 287#define DW_CFA_offset 0x80 288#define DW_CFA_restore 0xc0 289#define DW_CFA_advance_loc4 0x4 290#define DW_CFA_same_value 0x8 291#define DW_CFA_def_cfa 0xc 292#define DW_CFA_def_cfa_register 0xd 293#define DW_CFA_def_cfa_offset 0xe 294#define DW_CFA_offset_extended_sf 0x11 295#define DW_CFA_def_cfa_offset_sf 0x13 296#define DW_rax 0 297#define DW_rdx 1 298#define DW_rcx 2 299#define DW_rsi 4 300#define DW_rdi 5 301#define DW_rbp 6 302#define DW_rsp 7 303#define DW_r8 8 304#define DW_r9 9 305#define DW_r10 10 306#define DW_ra 16 307#define DW_xmm0 17 308#define DW_xmm1 18 309#define DW_xmm2 19 310#define DW_xmm3 20 311#define DW_xmm4 21 312#define DW_xmm5 22 313#define DW_xmm6 23 314#define DW_xmm7 24 315#define DW_a1 DW_rdi 316#define DW_a2 DW_rsi 317#define DW_a3 DW_rdx 318#define DW_a4 DW_rcx 319#define DW_a5 DW_r8 320#define DW_a6 DW_r9 321 322// CIE 323// 8-byte data multiplier 324// 1-byte insn multiplier 325// PC-relative everything 326// No prologue 327 328 .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support 329CIE: 330 .set L$set$0,LECIE1-LSCIE1 331 .long L$set$0 # Length of Common Information Entry 332LSCIE1: 333 .long 0 # CIE Identifier Tag 334 .byte 0x3 # CIE Version 335 .ascii "zPR\0" # CIE Augmentation: size + personality + FDE encoding 336 .byte 0x1 # uleb128 0x1; CIE Code Alignment Factor 337 .byte 0x78 # sleb128 -0x8; CIE Data Alignment Factor 338 .byte 0x10 # CIE RA Column 339 .byte 0x6 # uleb128 0x1; Augmentation size 340 // Personality augmentation 341 .byte 0x9b 342 .long ___objc_personality_v0+4@GOTPCREL 343 // FDE-encoding augmentation 344 .byte 0x10 345 // Prefix instructions 346 // CFA is %rsp+8 347 .byte DW_CFA_def_cfa 348 .byte DW_rsp 349 .byte 8 350 // RA is at 0(%rsp) aka 1*-8(CFA) 351 .byte DW_CFA_offset | DW_ra 352 .byte 1 353 354 .align 3 355LECIE1: 356 357 358.macro EMIT_FDE 359 360 .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support 361 362// FDE header 363.globl $0.eh 364$0.eh: 365LSFDE$0: 366 .set LLENFDE$0, LEFDE$0-LASFDE$0 367 .long LLENFDE$0 # FDE Length 368LASFDE$0: 369 .long LASFDE$0-CIE # FDE CIE offset 370 .quad L_dw_start_$0-. # FDE address start 371 .quad L_dw_len_$0 # FDE address range 372 .byte 0x0 # uleb128 0x0; Augmentation size 373 374 // DW_START: set by CIE 375 376.if $1 == 1 377 // Save/RestoreRegisters or MethodTableLookup 378 379 // enter 380 .byte DW_CFA_advance_loc4 381 .long L_dw_enter_$0 - L_dw_start_$0 382 .byte DW_CFA_def_cfa_offset 383 .byte 16 384 .byte DW_CFA_offset | DW_rbp // rbp => 2*-8(CFA) 385 .byte 2 386 .byte DW_CFA_def_cfa_register // CFA = rbp+16 (offset unchanged) 387 .byte DW_rbp 388 389 // leave 390 .byte DW_CFA_advance_loc4 391 .long L_dw_leave_$0 - L_dw_enter_$0 392 393 .byte DW_CFA_same_value // rbp = original value 394 .byte DW_rbp 395 .byte DW_CFA_def_cfa // CFA = rsp+8 396 .byte DW_rsp 397 .byte 8 398 399.endif 400 401 .align 3 402LEFDE$0: 403 .text 404 405.endmacro 406 407 408// Start of function 409.macro DW_START 410L_dw_start_$0: 411.endmacro 412 413// After `enter` in SaveRegisters 414.macro DW_ENTER 415L_dw_enter_$0: 416.endmacro 417 418// After `leave` in RestoreRegisters 419.macro DW_LEAVE 420L_dw_leave_$0: 421.endmacro 422 423// End of function 424// $1 == 1 iff you called MethodTableLookup or Save/RestoreRegsters 425.macro DW_END 426 .set L_dw_len_$0, . - L_dw_start_$0 427 EMIT_FDE $0, $1 428.endmacro 429 430 431///////////////////////////////////////////////////////////////////// 432// 433// SaveRegisters caller 434// 435// Pushes a stack frame and saves all registers that might contain 436// parameter values. 437// 438// On entry: %0 = caller's symbol name for DWARF 439// stack = ret 440// 441// On exit: 442// %rsp is 16-byte aligned 443// 444///////////////////////////////////////////////////////////////////// 445 446.macro SaveRegisters 447 // These instructions must match the DWARF data in EMIT_FDE. 448 449 enter $$0x80+8, $$0 // +8 for alignment 450 DW_ENTER $0 451 452 movdqa %xmm0, -0x80(%rbp) 453 push %rax // might be xmm parameter count 454 movdqa %xmm1, -0x70(%rbp) 455 push %a1 456 movdqa %xmm2, -0x60(%rbp) 457 push %a2 458 movdqa %xmm3, -0x50(%rbp) 459 push %a3 460 movdqa %xmm4, -0x40(%rbp) 461 push %a4 462 movdqa %xmm5, -0x30(%rbp) 463 push %a5 464 movdqa %xmm6, -0x20(%rbp) 465 push %a6 466 movdqa %xmm7, -0x10(%rbp) 467 468 // These instructions must match the DWARF data in EMIT_FDE. 469.endmacro 470 471///////////////////////////////////////////////////////////////////// 472// 473// RestoreRegisters 474// 475// Pops a stack frame pushed by SaveRegisters 476// 477// On entry: $0 = caller's symbol name for DWARF 478// %rbp unchanged since SaveRegisters 479// 480// On exit: 481// stack = ret 482// 483///////////////////////////////////////////////////////////////////// 484 485.macro RestoreRegisters 486 // These instructions must match the DWARF data in EMIT_FDE. 487 488 movdqa -0x80(%rbp), %xmm0 489 pop %a6 490 movdqa -0x70(%rbp), %xmm1 491 pop %a5 492 movdqa -0x60(%rbp), %xmm2 493 pop %a4 494 movdqa -0x50(%rbp), %xmm3 495 pop %a3 496 movdqa -0x40(%rbp), %xmm4 497 pop %a2 498 movdqa -0x30(%rbp), %xmm5 499 pop %a1 500 movdqa -0x20(%rbp), %xmm6 501 pop %rax 502 movdqa -0x10(%rbp), %xmm7 503 504 leave 505 DW_LEAVE $0 506 507 // These instructions must match the DWARF data in EMIT_FDE. 508.endmacro 509 510 511///////////////////////////////////////////////////////////////////// 512// 513// CacheLookup return-type, caller 514// 515// Locate the implementation for a class in a selector's method cache. 516// 517// Takes: 518// $0 = NORMAL, FPRET, FP2RET, STRET, SUPER, SUPER_STRET, SUPER2, SUPER2_STRET, GETIMP 519// a2 or a3 (STRET) = selector a.k.a. cache 520// r11 = class to search 521// 522// On exit: r10 clobbered 523// (found) calls or returns IMP, eq/ne/r11 set for forwarding 524// (not found) jumps to LCacheMiss, class still in r11 525// 526///////////////////////////////////////////////////////////////////// 527 528.macro CacheHit 529 530 // CacheHit must always be preceded by a not-taken `jne` instruction 531 // in order to set the correct flags for _objc_msgForward_impcache. 532 533 // r10 = found bucket 534 535.if $0 == GETIMP 536 movq 8(%r10), %rax // return imp 537 leaq __objc_msgSend_uncached_impcache(%rip), %r11 538 cmpq %rax, %r11 539 jne 4f 540 xorl %eax, %eax // don't return msgSend_uncached 5414: ret 542.elseif $0 == NORMAL || $0 == FPRET || $0 == FP2RET 543 // eq already set for forwarding by `jne` 544 MESSENGER_END_FAST 545 jmp *8(%r10) // call imp 546 547.elseif $0 == SUPER 548 movq receiver(%a1), %a1 // load real receiver 549 cmp %r10, %r10 // set eq for non-stret forwarding 550 MESSENGER_END_FAST 551 jmp *8(%r10) // call imp 552 553.elseif $0 == SUPER2 554 movq receiver(%a1), %a1 // load real receiver 555 cmp %r10, %r10 // set eq for non-stret forwarding 556 MESSENGER_END_FAST 557 jmp *8(%r10) // call imp 558 559.elseif $0 == STRET 560 test %r10, %r10 // set ne for stret forwarding 561 MESSENGER_END_FAST 562 jmp *8(%r10) // call imp 563 564.elseif $0 == SUPER_STRET 565 movq receiver(%a2), %a2 // load real receiver 566 test %r10, %r10 // set ne for stret forwarding 567 MESSENGER_END_FAST 568 jmp *8(%r10) // call imp 569 570.elseif $0 == SUPER2_STRET 571 movq receiver(%a2), %a2 // load real receiver 572 test %r10, %r10 // set ne for stret forwarding 573 MESSENGER_END_FAST 574 jmp *8(%r10) // call imp 575.else 576.abort oops 577.endif 578 579.endmacro 580 581 582.macro CacheLookup 583.if $0 != STRET && $0 != SUPER_STRET && $0 != SUPER2_STRET 584 movq %a2, %r10 // r10 = _cmd 585.else 586 movq %a3, %r10 // r10 = _cmd 587.endif 588 andl 24(%r11), %r10d // r10 = _cmd & class->cache.mask 589 shlq $$4, %r10 // r10 = offset = (_cmd & mask)<<4 590 addq 16(%r11), %r10 // r10 = class->cache.buckets + offset 591 592.if $0 != STRET && $0 != SUPER_STRET && $0 != SUPER2_STRET 593 cmpq (%r10), %a2 // if (bucket->sel != _cmd) 594.else 595 cmpq (%r10), %a3 // if (bucket->sel != _cmd) 596.endif 597 jne 1f // scan more 598 // CacheHit must always be preceded by a not-taken `jne` instruction 599 CacheHit $0 // call or return imp 600 6011: 602 // loop 603 cmpq $$0, (%r10) 604 je LCacheMiss_f // if (bucket->sel == 0) cache miss 605 cmpq 16(%r11), %r10 606 je 3f // if (bucket == cache->buckets) wrap 607 608 subq $$16, %r10 // bucket-- 609.if $0 != STRET && $0 != SUPER_STRET && $0 != SUPER2_STRET 610 cmpq (%r10), %a2 // if (bucket->sel != _cmd) 611.else 612 cmpq (%r10), %a3 // if (bucket->sel != _cmd) 613.endif 614 jne 1b // scan more 615 // CacheHit must always be preceded by a not-taken `jne` instruction 616 CacheHit $0 // call or return imp 617 6183: 619 // wrap 620 movl 24(%r11), %r10d // r10 = mask a.k.a. last bucket index 621 shlq $$4, %r10 // r10 = offset = mask<<4 622 addq 16(%r11), %r10 // r10 = &cache->buckets[mask] 623 jmp 2f 624 625 // clone scanning loop to crash instead of hang when cache is corrupt 626 6271: 628 // loop 629 cmpq $$0, (%r10) 630 je LCacheMiss_f // if (bucket->sel == 0) cache miss 631 cmpq 16(%r11), %r10 632 je 3f // if (bucket == cache->buckets) wrap 633 634 subq $$16, %r10 // bucket-- 6352: 636.if $0 != STRET && $0 != SUPER_STRET && $0 != SUPER2_STRET 637 cmpq (%r10), %a2 // if (bucket->sel != _cmd) 638.else 639 cmpq (%r10), %a3 // if (bucket->sel != _cmd) 640.endif 641 jne 1b // scan more 642 // CacheHit must always be preceded by a not-taken `jne` instruction 643 CacheHit $0 // call or return imp 644 6453: 646 // double wrap - busted 647.if $0 == STRET || $0 == SUPER_STRET || $0 == SUPER2_STRET 648 movq %a2, %a1 649 movq %a3, %a2 650.elseif $0 == GETIMP 651 movq $$0, %a1 652.endif 653 // a1 = receiver 654 // a2 = SEL 655 movq %r11, %a3 // a3 = isa 656 movq %r10, %a4 // a4 = bucket 657.if $0 == GETIMP 658 jmp _cache_getImp_corrupt_cache_error 659.else 660 jmp _objc_msgSend_corrupt_cache_error 661.endif 662.endmacro 663 664 665///////////////////////////////////////////////////////////////////// 666// 667// MethodTableLookup classRegister, selectorRegister, caller 668// 669// Takes: $0 = class to search (a1 or a2 or r10 ONLY) 670// $1 = selector to search for (a2 or a3 ONLY) 671// $2 = caller's symbol name for DWARF 672// r11 = class to search 673// 674// On exit: imp in %r11 675// 676///////////////////////////////////////////////////////////////////// 677.macro MethodTableLookup 678 679 MESSENGER_END_SLOW 680 681 SaveRegisters $2 682 683 // _class_lookupMethodAndLoadCache3(receiver, selector, class) 684 685 movq $0, %a1 686 movq $1, %a2 687 movq %r11, %a3 688 call __class_lookupMethodAndLoadCache3 689 690 // IMP is now in %rax 691 movq %rax, %r11 692 693 RestoreRegisters $2 694 695.endmacro 696 697///////////////////////////////////////////////////////////////////// 698// 699// GetIsaFast return-type 700// GetIsaSupport return-type 701// 702// Sets r11 = obj->isa. Consults the tagged isa table if necessary. 703// 704// Takes: $0 = NORMAL or FPRET or FP2RET or STRET 705// a1 or a2 (STRET) = receiver 706// 707// On exit: r11 = receiver->isa 708// r10 is clobbered 709// 710///////////////////////////////////////////////////////////////////// 711 712.macro GetIsaFast 713.if $0 != STRET 714 testb $$1, %a1b 715 PN 716 jnz LGetIsaSlow_f 717 movq (%a1), %r11 718.else 719 testb $$1, %a2b 720 PN 721 jnz LGetIsaSlow_f 722 movq (%a2), %r11 723.endif 724LGetIsaDone: 725.endmacro 726 727.macro GetIsaSupport2 728LGetIsaSlow: 729 leaq _objc_debug_taggedpointer_classes(%rip), %r11 730.if $0 != STRET 731 movl %a1d, %r10d 732.else 733 movl %a2d, %r10d 734.endif 735 andl $$0xF, %r10d 736 movq (%r11, %r10, 8), %r11 // read isa from table 737.endmacro 738 739.macro GetIsaSupport 740 GetIsaSupport2 $0 741 jmp LGetIsaDone_b 742.endmacro 743 744.macro GetIsa 745 GetIsaFast $0 746 jmp LGetIsaDone_f 747 GetIsaSupport2 $0 748LGetIsaDone: 749.endmacro 750 751 752///////////////////////////////////////////////////////////////////// 753// 754// NilTest return-type 755// 756// Takes: $0 = NORMAL or FPRET or FP2RET or STRET 757// %a1 or %a2 (STRET) = receiver 758// 759// On exit: Loads non-nil receiver in %a1 or %a2 (STRET), or returns zero. 760// 761// NilTestSupport return-type 762// 763// Takes: $0 = NORMAL or FPRET or FP2RET or STRET 764// %a1 or %a2 (STRET) = receiver 765// 766// On exit: Loads non-nil receiver in %a1 or %a2 (STRET), or returns zero. 767// 768///////////////////////////////////////////////////////////////////// 769 770.macro NilTest 771.if $0 == SUPER || $0 == SUPER_STRET 772 error super dispatch does not test for nil 773.endif 774 775.if $0 != STRET 776 testq %a1, %a1 777.else 778 testq %a2, %a2 779.endif 780 PN 781 jz LNilTestSlow_f 782LNilTestDone: 783.endmacro 784 785.macro NilTestSupport 786 .align 3 787LNilTestSlow: 788.if $0 != STRET 789 movq __objc_nilReceiver(%rip), %a1 790 testq %a1, %a1 // if (receiver != nil) 791.else 792 movq __objc_nilReceiver(%rip), %a2 793 testq %a2, %a2 // if (receiver != nil) 794.endif 795 jne LNilTestDone_b // send to new receiver 796 797.if $0 == FPRET 798 fldz 799.elseif $0 == FP2RET 800 fldz 801 fldz 802.endif 803.if $0 == STRET 804 movq %rdi, %rax 805.else 806 xorl %eax, %eax 807 xorl %edx, %edx 808 xorps %xmm0, %xmm0 809 xorps %xmm1, %xmm1 810.endif 811 MESSENGER_END_NIL 812 ret 813.endmacro 814 815 816/******************************************************************** 817 * IMP cache_getImp(Class cls, SEL sel) 818 * 819 * On entry: a1 = class whose cache is to be searched 820 * a2 = selector to search for 821 * 822 * If found, returns method implementation. 823 * If not found, returns NULL. 824 ********************************************************************/ 825 826 STATIC_ENTRY _cache_getImp 827 DW_START _cache_getImp 828 829// do lookup 830 movq %a1, %r11 // move class to r11 for CacheLookup 831 CacheLookup GETIMP // returns IMP on success 832 833LCacheMiss: 834// cache miss, return nil 835 xorl %eax, %eax 836 ret 837 838LGetImpExit: 839 DW_END _cache_getImp, 0 840 END_ENTRY _cache_getImp 841 842 843/******************************************************************** 844 * 845 * id objc_msgSend(id self, SEL _cmd,...); 846 * 847 ********************************************************************/ 848 849 .data 850 .align 3 851 .globl _objc_debug_taggedpointer_classes 852_objc_debug_taggedpointer_classes: 853 .fill 16, 8, 0 854 855 ENTRY _objc_msgSend 856 DW_START _objc_msgSend 857 MESSENGER_START 858 859 NilTest NORMAL 860 861 GetIsaFast NORMAL // r11 = self->isa 862 CacheLookup NORMAL // calls IMP on success 863 864 NilTestSupport NORMAL 865 866 GetIsaSupport NORMAL 867 868// cache miss: go search the method lists 869LCacheMiss: 870 // isa still in r11 871 MethodTableLookup %a1, %a2, _objc_msgSend // r11 = IMP 872 cmp %r11, %r11 // set eq (nonstret) for forwarding 873 jmp *%r11 // goto *imp 874 875 DW_END _objc_msgSend, 1 876 END_ENTRY _objc_msgSend 877 878 879 ENTRY _objc_msgSend_fixup 880 int3 881 END_ENTRY _objc_msgSend_fixup 882 883 884 STATIC_ENTRY _objc_msgSend_fixedup 885 // Load _cmd from the message_ref 886 movq 8(%a2), %a2 887 jmp _objc_msgSend 888 END_ENTRY _objc_msgSend_fixedup 889 890 891/******************************************************************** 892 * 893 * id objc_msgSendSuper(struct objc_super *super, SEL _cmd,...); 894 * 895 * struct objc_super { 896 * id receiver; 897 * Class class; 898 * }; 899 ********************************************************************/ 900 901 ENTRY _objc_msgSendSuper 902 DW_START _objc_msgSendSuper 903 MESSENGER_START 904 905// search the cache (objc_super in %a1) 906 movq class(%a1), %r11 // class = objc_super->class 907 CacheLookup SUPER // calls IMP on success 908 909// cache miss: go search the method lists 910LCacheMiss: 911 // class still in r11 912 movq receiver(%a1), %r10 913 MethodTableLookup %r10, %a2, _objc_msgSendSuper // r11 = IMP 914 movq receiver(%a1), %a1 // load real receiver 915 cmp %r11, %r11 // set eq (nonstret) for forwarding 916 jmp *%r11 // goto *imp 917 918 DW_END _objc_msgSendSuper, 1 919 END_ENTRY _objc_msgSendSuper 920 921 922/******************************************************************** 923 * id objc_msgSendSuper2 924 ********************************************************************/ 925 926 ENTRY _objc_msgSendSuper2 927 DW_START _objc_msgSendSuper2 928 MESSENGER_START 929 930 // objc_super->class is superclass of class to search 931 932// search the cache (objc_super in %a1) 933 movq class(%a1), %r11 // cls = objc_super->class 934 movq 8(%r11), %r11 // cls = class->superclass 935 CacheLookup SUPER2 // calls IMP on success 936 937// cache miss: go search the method lists 938LCacheMiss: 939 // superclass still in r11 940 movq receiver(%a1), %r10 941 MethodTableLookup %r10, %a2, _objc_msgSendSuper2 // r11 = IMP 942 movq receiver(%a1), %a1 // load real receiver 943 cmp %r11, %r11 // set eq (nonstret) for forwarding 944 jmp *%r11 // goto *imp 945 946 DW_END _objc_msgSendSuper2, 1 947 END_ENTRY _objc_msgSendSuper2 948 949 950 ENTRY _objc_msgSendSuper2_fixup 951 int3 952 END_ENTRY _objc_msgSendSuper2_fixup 953 954 955 STATIC_ENTRY _objc_msgSendSuper2_fixedup 956 // Load _cmd from the message_ref 957 movq 8(%a2), %a2 958 jmp _objc_msgSendSuper2 959 END_ENTRY _objc_msgSendSuper2_fixedup 960 961 962/******************************************************************** 963 * 964 * double objc_msgSend_fpret(id self, SEL _cmd,...); 965 * Used for `long double` return only. `float` and `double` use objc_msgSend. 966 * 967 ********************************************************************/ 968 969 ENTRY _objc_msgSend_fpret 970 DW_START _objc_msgSend_fpret 971 MESSENGER_START 972 973 NilTest FPRET 974 975 GetIsaFast FPRET // r11 = self->isa 976 CacheLookup FPRET // calls IMP on success 977 978 NilTestSupport FPRET 979 980 GetIsaSupport FPRET 981 982// cache miss: go search the method lists 983LCacheMiss: 984 // isa still in r11 985 MethodTableLookup %a1, %a2, _objc_msgSend_fpret // r11 = IMP 986 cmp %r11, %r11 // set eq (nonstret) for forwarding 987 jmp *%r11 // goto *imp 988 989 DW_END _objc_msgSend_fpret, 1 990 END_ENTRY _objc_msgSend_fpret 991 992 993 ENTRY _objc_msgSend_fpret_fixup 994 int3 995 END_ENTRY _objc_msgSend_fpret_fixup 996 997 998 STATIC_ENTRY _objc_msgSend_fpret_fixedup 999 // Load _cmd from the message_ref 1000 movq 8(%a2), %a2 1001 jmp _objc_msgSend_fpret 1002 END_ENTRY _objc_msgSend_fpret_fixedup 1003 1004 1005/******************************************************************** 1006 * 1007 * double objc_msgSend_fp2ret(id self, SEL _cmd,...); 1008 * Used for `complex long double` return only. 1009 * 1010 ********************************************************************/ 1011 1012 ENTRY _objc_msgSend_fp2ret 1013 DW_START _objc_msgSend_fp2ret 1014 MESSENGER_START 1015 1016 NilTest FP2RET 1017 1018 GetIsaFast FP2RET // r11 = self->isa 1019 CacheLookup FP2RET // calls IMP on success 1020 1021 NilTestSupport FP2RET 1022 1023 GetIsaSupport FP2RET 1024 1025// cache miss: go search the method lists 1026LCacheMiss: 1027 // isa still in r11 1028 MethodTableLookup %a1, %a2, _objc_msgSend_fp2ret // r11 = IMP 1029 cmp %r11, %r11 // set eq (nonstret) for forwarding 1030 jmp *%r11 // goto *imp 1031 1032 DW_END _objc_msgSend_fp2ret, 1 1033 END_ENTRY _objc_msgSend_fp2ret 1034 1035 1036 ENTRY _objc_msgSend_fp2ret_fixup 1037 int3 1038 END_ENTRY _objc_msgSend_fp2ret_fixup 1039 1040 1041 STATIC_ENTRY _objc_msgSend_fp2ret_fixedup 1042 // Load _cmd from the message_ref 1043 movq 8(%a2), %a2 1044 jmp _objc_msgSend_fp2ret 1045 END_ENTRY _objc_msgSend_fp2ret_fixedup 1046 1047 1048/******************************************************************** 1049 * 1050 * void objc_msgSend_stret(void *st_addr, id self, SEL _cmd, ...); 1051 * 1052 * objc_msgSend_stret is the struct-return form of msgSend. 1053 * The ABI calls for %a1 to be used as the address of the structure 1054 * being returned, with the parameters in the succeeding locations. 1055 * 1056 * On entry: %a1 is the address where the structure is returned, 1057 * %a2 is the message receiver, 1058 * %a3 is the selector 1059 ********************************************************************/ 1060 1061 ENTRY _objc_msgSend_stret 1062 DW_START _objc_msgSend_stret 1063 MESSENGER_START 1064 1065 NilTest STRET 1066 1067 GetIsaFast STRET // r11 = self->isa 1068 CacheLookup STRET // calls IMP on success 1069 1070 NilTestSupport STRET 1071 1072 GetIsaSupport STRET 1073 1074// cache miss: go search the method lists 1075LCacheMiss: 1076 // isa still in r11 1077 MethodTableLookup %a2, %a3, _objc_msgSend_stret // r11 = IMP 1078 test %r11, %r11 // set ne (stret) for forward; r11!=0 1079 jmp *%r11 // goto *imp 1080 1081 DW_END _objc_msgSend_stret, 1 1082 END_ENTRY _objc_msgSend_stret 1083 1084 1085 ENTRY _objc_msgSend_stret_fixup 1086 int3 1087 END_ENTRY _objc_msgSend_stret_fixup 1088 1089 1090 STATIC_ENTRY _objc_msgSend_stret_fixedup 1091 // Load _cmd from the message_ref 1092 movq 8(%a3), %a3 1093 jmp _objc_msgSend_stret 1094 END_ENTRY _objc_msgSend_stret_fixedup 1095 1096 1097/******************************************************************** 1098 * 1099 * void objc_msgSendSuper_stret(void *st_addr, struct objc_super *super, SEL _cmd, ...); 1100 * 1101 * struct objc_super { 1102 * id receiver; 1103 * Class class; 1104 * }; 1105 * 1106 * objc_msgSendSuper_stret is the struct-return form of msgSendSuper. 1107 * The ABI calls for (sp+4) to be used as the address of the structure 1108 * being returned, with the parameters in the succeeding registers. 1109 * 1110 * On entry: %a1 is the address where the structure is returned, 1111 * %a2 is the address of the objc_super structure, 1112 * %a3 is the selector 1113 * 1114 ********************************************************************/ 1115 1116 ENTRY _objc_msgSendSuper_stret 1117 DW_START _objc_msgSendSuper_stret 1118 MESSENGER_START 1119 1120// search the cache (objc_super in %a2) 1121 movq class(%a2), %r11 // class = objc_super->class 1122 CacheLookup SUPER_STRET // calls IMP on success 1123 1124// cache miss: go search the method lists 1125LCacheMiss: 1126 // class still in r11 1127 movq receiver(%a2), %r10 1128 MethodTableLookup %r10, %a3, _objc_msgSendSuper_stret // r11 = IMP 1129 movq receiver(%a2), %a2 // load real receiver 1130 test %r11, %r11 // set ne (stret) for forward; r11!=0 1131 jmp *%r11 // goto *imp 1132 1133 DW_END _objc_msgSendSuper_stret, 1 1134 END_ENTRY _objc_msgSendSuper_stret 1135 1136 1137/******************************************************************** 1138 * id objc_msgSendSuper2_stret 1139 ********************************************************************/ 1140 1141 ENTRY _objc_msgSendSuper2_stret 1142 DW_START _objc_msgSendSuper2_stret 1143 MESSENGER_START 1144 1145// search the cache (objc_super in %a2) 1146 movq class(%a2), %r11 // class = objc_super->class 1147 movq 8(%r11), %r11 // class = class->superclass 1148 CacheLookup SUPER2_STRET // calls IMP on success 1149 1150// cache miss: go search the method lists 1151LCacheMiss: 1152 // superclass still in r11 1153 movq receiver(%a2), %r10 1154 MethodTableLookup %r10, %a3, _objc_msgSendSuper2_stret // r11 = IMP 1155 movq receiver(%a2), %a2 // load real receiver 1156 test %r11, %r11 // set ne (stret) for forward; r11!=0 1157 jmp *%r11 // goto *imp 1158 1159 DW_END _objc_msgSendSuper2_stret, 1 1160 END_ENTRY _objc_msgSendSuper2_stret 1161 1162 1163 ENTRY _objc_msgSendSuper2_stret_fixup 1164 int3 1165 END_ENTRY _objc_msgSendSuper2_stret_fixup 1166 1167 1168 STATIC_ENTRY _objc_msgSendSuper2_stret_fixedup 1169 // Load _cmd from the message_ref 1170 movq 8(%a3), %a3 1171 jmp _objc_msgSendSuper2_stret 1172 END_ENTRY _objc_msgSendSuper2_stret_fixedup 1173 1174 1175/******************************************************************** 1176 * 1177 * _objc_msgSend_uncached_impcache 1178 * _objc_msgSend_uncached 1179 * _objc_msgSend_stret_uncached 1180 * 1181 * Used to erase method cache entries in-place by 1182 * bouncing them to the uncached lookup. 1183 * 1184 ********************************************************************/ 1185 1186 STATIC_ENTRY __objc_msgSend_uncached_impcache 1187 // Method cache version 1188 1189 // THIS IS NOT A CALLABLE C FUNCTION 1190 // Out-of-band condition register is NE for stret, EQ otherwise. 1191 // Out-of-band r11 is the searched class 1192 1193 MESSENGER_START 1194 nop 1195 MESSENGER_END_SLOW 1196 1197 jne __objc_msgSend_stret_uncached 1198 jmp __objc_msgSend_uncached 1199 1200 END_ENTRY __objc_msgSend_uncached_impcache 1201 1202 1203 STATIC_ENTRY __objc_msgSend_uncached 1204 DW_START __objc_msgSend_uncached 1205 1206 // THIS IS NOT A CALLABLE C FUNCTION 1207 // Out-of-band r11 is the searched class 1208 1209 // r11 is already the class to search 1210 MethodTableLookup %a1, %a2, __objc_msgSend_uncached // r11 = IMP 1211 cmp %r11, %r11 // set eq (nonstret) for forwarding 1212 jmp *%r11 // goto *imp 1213 1214 DW_END __objc_msgSend_uncached, 1 1215 END_ENTRY __objc_msgSend_uncached 1216 1217 1218 STATIC_ENTRY __objc_msgSend_stret_uncached 1219 DW_START __objc_msgSend_stret_uncached 1220 // THIS IS NOT A CALLABLE C FUNCTION 1221 // Out-of-band r11 is the searched class 1222 1223 // r11 is already the class to search 1224 MethodTableLookup %a2, %a3, __objc_msgSend_stret_uncached // r11 = IMP 1225 test %r11, %r11 // set ne (stret) for forward; r11!=0 1226 jmp *%r11 // goto *imp 1227 1228 DW_END __objc_msgSend_stret_uncached, 1 1229 END_ENTRY __objc_msgSend_stret_uncached 1230 1231 1232/******************************************************************** 1233 * 1234 * id _objc_msgForward(id self, SEL _cmd,...); 1235 * 1236 ********************************************************************/ 1237 1238// _FwdSel is @selector(forward::), set up in map_images(). 1239// ALWAYS dereference _FwdSel to get to "forward::" !! 1240 .data 1241 .align 3 1242 .private_extern _FwdSel 1243_FwdSel: .quad 0 1244 1245 .cstring 1246 .align 3 1247LUnkSelStr: .ascii "Does not recognize selector %s (while forwarding %s)\0" 1248 1249 .data 1250 .align 3 1251 .private_extern __objc_forward_handler 1252__objc_forward_handler: .quad 0 1253 1254 .data 1255 .align 3 1256 .private_extern __objc_forward_stret_handler 1257__objc_forward_stret_handler: .quad 0 1258 1259 1260 STATIC_ENTRY __objc_msgForward_impcache 1261 // Method cache version 1262 1263 // THIS IS NOT A CALLABLE C FUNCTION 1264 // Out-of-band condition register is NE for stret, EQ otherwise. 1265 1266 MESSENGER_START 1267 nop 1268 MESSENGER_END_SLOW 1269 1270 jne __objc_msgForward_stret 1271 jmp __objc_msgForward 1272 1273 END_ENTRY __objc_msgForward_impcache 1274 1275 1276 ENTRY __objc_msgForward 1277 // Non-stret version 1278 1279 // Call user handler, if any 1280 movq __objc_forward_handler(%rip), %r11 1281 testq %r11, %r11 // if (handler == NULL) 1282 je 1f // skip handler 1283 jmp *%r11 // else goto handler 12841: 1285 // No user handler 1286 1287 // Die if forwarding "forward::" 1288 cmpq %a2, _FwdSel(%rip) 1289 je LMsgForwardError 1290 1291 // Record current return address. It will be copied elsewhere in 1292 // the marg_list because this location is needed for register args 1293 movq (%rsp), %r11 1294 1295 // Push stack frame 1296 // Space for: fpArgs + regArgs + linkage - ret (already on stack) 1297 subq $ 8*16 + 6*8 + (4-1)*8, %rsp 1298 1299 // Save return address in linkage area. 1300 movq %r11, 16+LINK_AREA(%rsp) 1301 1302 // Save parameter registers 1303 movq %a1, 0+REG_AREA(%rsp) 1304 movq %a2, 8+REG_AREA(%rsp) 1305 movq %a3, 16+REG_AREA(%rsp) 1306 movq %a4, 24+REG_AREA(%rsp) 1307 movq %a5, 32+REG_AREA(%rsp) 1308 movq %a6, 40+REG_AREA(%rsp) 1309 1310 // Save side parameter registers 1311 // movq %r10, 0+LINK_AREA(%rsp) // static chain pointer == Pascal 1312 movq %rax, 8+LINK_AREA(%rsp) // xmm count 1313 // 16+LINK_AREA is return address 1314 1315 // Save xmm registers 1316 movdqa %xmm0, 0+FP_AREA(%rsp) 1317 movdqa %xmm1, 16+FP_AREA(%rsp) 1318 movdqa %xmm2, 32+FP_AREA(%rsp) 1319 movdqa %xmm3, 48+FP_AREA(%rsp) 1320 movdqa %xmm4, 64+FP_AREA(%rsp) 1321 movdqa %xmm5, 80+FP_AREA(%rsp) 1322 movdqa %xmm6, 96+FP_AREA(%rsp) 1323 movdqa %xmm7, 112+FP_AREA(%rsp) 1324 1325 // Call [receiver forward:sel :margs] 1326 movq %rsp, %a4 // marg_list 1327 movq %a2, %a3 // sel 1328 movq _FwdSel(%rip), %a2 // forward:: 1329 // %a1 is already the receiver 1330 1331 call _objc_msgSend 1332 1333 // Retrieve return address from linkage area 1334 movq 16+LINK_AREA(%rsp), %r11 1335 // Pop stack frame 1336 addq $ 8*16 + 6*8 + (4-1)*8, %rsp 1337 // Put return address back 1338 movq %r11, (%rsp) 1339 ret 1340 1341LMsgForwardError: 1342 // Tail-call __objc_error(receiver, "unknown selector %s %s", "forward::", forwardedSel) 1343 // %a1 is already the receiver 1344 movq %a3, %a4 // the forwarded selector 1345 leaq LUnkSelStr(%rip), %a2 // "unknown selector %s %s" 1346 movq _FwdSel(%rip), %a3 // forward:: 1347 jmp ___objc_error // never returns 1348 1349 END_ENTRY __objc_msgForward 1350 1351 1352 ENTRY __objc_msgForward_stret 1353 // Struct-return version 1354 1355 // Call user handler, if any 1356 movq __objc_forward_stret_handler(%rip), %r11 1357 testq %r11, %r11 // if (handler == NULL) 1358 je 1f // skip handler 1359 jmp *%r11 // else goto handler 13601: 1361 // No user handler 1362 // Die if forwarding "forward::" 1363 cmpq %a3, _FwdSel(%rip) 1364 je LMsgForwardStretError 1365 1366 // Record current return address. It will be copied elsewhere in 1367 // the marg_list because this location is needed for register args 1368 movq (%rsp), %r11 1369 1370 // Push stack frame 1371 // Space for: fpArgs + regArgs + linkage - ret (already on stack) 1372 subq $ 8*16 + 6*8 + (4-1)*8, %rsp 1373 1374 // Save return address in linkage area. 1375 movq %r11, 16+LINK_AREA(%rsp) 1376 1377 // Save parameter registers 1378 movq %a1, 0+REG_AREA(%rsp) // note: used again below 1379 movq %a2, 8+REG_AREA(%rsp) 1380 movq %a3, 16+REG_AREA(%rsp) 1381 movq %a4, 24+REG_AREA(%rsp) 1382 movq %a5, 32+REG_AREA(%rsp) 1383 movq %a6, 40+REG_AREA(%rsp) 1384 1385 // Save side parameter registers 1386 // movq %r10, 0+LINK_AREA(%rsp) // static chain pointer == Pascal 1387 movq %rax, 8+LINK_AREA(%rsp) // xmm count 1388 // 16+LINK_AREA is return address 1389 1390 // Save xmm registers 1391 movdqa %xmm0, 0+FP_AREA(%rsp) 1392 movdqa %xmm1, 16+FP_AREA(%rsp) 1393 movdqa %xmm2, 32+FP_AREA(%rsp) 1394 movdqa %xmm3, 48+FP_AREA(%rsp) 1395 movdqa %xmm4, 64+FP_AREA(%rsp) 1396 movdqa %xmm5, 80+FP_AREA(%rsp) 1397 movdqa %xmm6, 96+FP_AREA(%rsp) 1398 movdqa %xmm7, 112+FP_AREA(%rsp) 1399 1400 // Call [receiver forward:sel :margs] 1401 movq %a2, %a1 // receiver 1402 movq _FwdSel(%rip), %a2 // forward:: 1403 // %a3 is already the selector 1404 movq %rsp, %a4 // marg_list 1405 1406 call _objc_msgSend // forward:: is NOT struct-return 1407 1408 // Set return value register to the passed-in struct address 1409 movq 0+REG_AREA(%rsp), %rax 1410 // Retrieve return address from linkage area 1411 movq 16+LINK_AREA(%rsp), %r11 1412 // Pop stack frame 1413 addq $ 8*16 + 6*8 + (4-1)*8, %rsp 1414 // Put return address back 1415 movq %r11, (%rsp) 1416 ret 1417 1418LMsgForwardStretError: 1419 // Tail-call __objc_error(receiver, "unknown selector %s %s", "forward::", forwardedSel) 1420 // %a4 is already the forwarded selector 1421 movq %a2, %a1 // receiver 1422 leaq LUnkSelStr(%rip), %a2 // "unknown selector %s %s" 1423 movq _FwdSel(%rip), %a3 // forward:: 1424 jmp ___objc_error // never returns 1425 1426 END_ENTRY __objc_msgForward_stret 1427 1428 1429 ENTRY _objc_msgSend_debug 1430 jmp _objc_msgSend 1431 END_ENTRY _objc_msgSend_debug 1432 1433 ENTRY _objc_msgSendSuper2_debug 1434 jmp _objc_msgSendSuper2 1435 END_ENTRY _objc_msgSendSuper2_debug 1436 1437 ENTRY _objc_msgSend_stret_debug 1438 jmp _objc_msgSend_stret 1439 END_ENTRY _objc_msgSend_stret_debug 1440 1441 ENTRY _objc_msgSendSuper2_stret_debug 1442 jmp _objc_msgSendSuper2_stret 1443 END_ENTRY _objc_msgSendSuper2_stret_debug 1444 1445 ENTRY _objc_msgSend_fpret_debug 1446 jmp _objc_msgSend_fpret 1447 END_ENTRY _objc_msgSend_fpret_debug 1448 1449 ENTRY _objc_msgSend_fp2ret_debug 1450 jmp _objc_msgSend_fp2ret 1451 END_ENTRY _objc_msgSend_fp2ret_debug 1452 1453 1454 ENTRY _objc_msgSend_noarg 1455 jmp _objc_msgSend 1456 END_ENTRY _objc_msgSend_noarg 1457 1458 1459 ENTRY _method_invoke 1460 1461 movq method_imp(%a2), %r11 1462 movq method_name(%a2), %a2 1463 jmp *%r11 1464 1465 END_ENTRY _method_invoke 1466 1467 1468 ENTRY _method_invoke_stret 1469 1470 movq method_imp(%a3), %r11 1471 movq method_name(%a3), %a3 1472 jmp *%r11 1473 1474 END_ENTRY _method_invoke_stret 1475 1476 1477 STATIC_ENTRY __objc_ignored_method 1478 1479 movq %a1, %rax 1480 ret 1481 1482 END_ENTRY __objc_ignored_method 1483 1484 1485.section __DATA,__objc_msg_break 1486.quad 0 1487.quad 0 1488 1489#endif 1490