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