2 * @APPLE_LICENSE_HEADER_START@
4 * Copyright (c) 2011 Apple Inc. All Rights Reserved.
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
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.
21 * @APPLE_LICENSE_HEADER_END@
23 /********************************************************************
25 * objc-msg-arm64.s - ARM64 code to support objc messaging
27 ********************************************************************/
36 // _objc_entryPoints and _objc_exitPoints are used by method dispatch
37 // caching code to figure out whether any threads are actively
38 // in the cache for dispatching. The labels surround the asm code
39 // that do cache lookups. The tables are zero-terminated.
42 .private_extern _objc_entryPoints
46 .quad _objc_msgSendSuper
47 .quad _objc_msgSendSuper2
49 .quad _objc_msgLookupSuper2
52 .private_extern _objc_exitPoints
54 .quad LExit_cache_getImp
55 .quad LExit_objc_msgSend
56 .quad LExit_objc_msgSendSuper
57 .quad LExit_objc_msgSendSuper2
58 .quad LExit_objc_msgLookup
59 .quad LExit_objc_msgLookupSuper2
63 /********************************************************************
64 * List every exit insn from every messenger for debugger use.
67 * 1 word instruction's address
68 * 1 word type (ENTER or FAST_EXIT or SLOW_EXIT or NIL_EXIT)
72 * ENTER is the start of a dispatcher
73 * FAST_EXIT is method dispatch
74 * SLOW_EXIT is uncached method lookup
75 * NIL_EXIT is returning zero from a message sent to nil
76 * These must match objc-gdb.h.
77 ********************************************************************/
84 .section __DATA,__objc_msg_break
85 .globl _gdb_objc_messenger_breakpoints
86 _gdb_objc_messenger_breakpoints:
87 // contents populated by the macros below
89 .macro MESSENGER_START
91 .section __DATA,__objc_msg_break
96 .macro MESSENGER_END_FAST
98 .section __DATA,__objc_msg_break
103 .macro MESSENGER_END_SLOW
105 .section __DATA,__objc_msg_break
110 .macro MESSENGER_END_NIL
112 .section __DATA,__objc_msg_break
119 /* objc_super parameter to sendSuper */
123 /* Selected field offsets in class structure */
127 /* Selected field offsets in isa field */
128 #define ISA_MASK 0x0000000ffffffff8
130 /* Selected field offsets in method structure */
131 #define METHOD_NAME 0
132 #define METHOD_TYPES 8
133 #define METHOD_IMP 16
136 /********************************************************************
138 * STATIC_ENTRY functionName
139 * END_ENTRY functionName
140 ********************************************************************/
142 .macro ENTRY /* name */
149 .macro STATIC_ENTRY /*name*/
156 .macro END_ENTRY /* name */
161 /********************************************************************
163 * Unwind info generation
164 ********************************************************************/
166 .section __LD,__compact_unwind,regular,debug
168 .set LUnwind$0, LExit$0 - $0
171 .quad 0 /* no personality */
172 .quad 0 /* no LSDA */
176 #define NoFrame 0x02000000 // no frame, no SP adjustment
177 #define FrameWithNoSaves 0x04000000 // frame, no non-volatile saves
180 /********************************************************************
182 * CacheLookup NORMAL|GETIMP|LOOKUP
184 * Locate the implementation for a selector in a class method cache.
188 * x16 = class to be searched
191 * x9,x10,x11,x12, x17
193 * On exit: (found) calls or returns IMP
194 * with x16 = class, x17 = IMP
195 * (not found) jumps to LCacheMiss
197 ********************************************************************/
208 mov x0, x17 // return imp
211 ret // return imp via x17
218 // miss if bucket->sel == 0
222 cbz x9, __objc_msgSend_uncached
224 cbz x9, __objc_msgLookup_uncached
234 b __objc_msgSend_uncached
236 b __objc_msgLookup_uncached
243 // x1 = SEL, x16 = isa
244 ldp x10, x11, [x16, #CACHE] // x10 = buckets, x11 = occupied|mask
245 and w12, w1, w11 // x12 = _cmd & mask
246 add x12, x10, x12, LSL #4 // x12 = buckets + ((_cmd & mask)<<4)
248 ldp x9, x17, [x12] // {x9, x17} = *bucket
249 1: cmp x9, x1 // if (bucket->sel != _cmd)
251 CacheHit $0 // call or return imp
253 2: // not hit: x12 = not-hit bucket
254 CheckMiss $0 // miss if bucket->sel == 0
255 cmp x12, x10 // wrap if bucket == buckets
257 ldp x9, x17, [x12, #-16]! // {x9, x17} = *--bucket
260 3: // wrap: x12 = first bucket, w11 = mask
261 add x12, x12, w11, UXTW #4 // x12 = buckets+(mask<<4)
263 // Clone scanning loop to miss instead of hang when cache is corrupt.
264 // The slow path may detect any corruption and halt later.
266 ldp x9, x17, [x12] // {x9, x17} = *bucket
267 1: cmp x9, x1 // if (bucket->sel != _cmd)
269 CacheHit $0 // call or return imp
271 2: // not hit: x12 = not-hit bucket
272 CheckMiss $0 // miss if bucket->sel == 0
273 cmp x12, x10 // wrap if bucket == buckets
275 ldp x9, x17, [x12, #-16]! // {x9, x17} = *--bucket
284 /********************************************************************
286 * id objc_msgSend(id self, SEL _cmd, ...);
287 * IMP objc_msgLookup(id self, SEL _cmd, ...);
289 * objc_msgLookup ABI:
290 * IMP returned in x17
291 * x16 reserved for our use but not used
293 ********************************************************************/
297 .globl _objc_debug_taggedpointer_classes
298 _objc_debug_taggedpointer_classes:
300 .globl _objc_debug_taggedpointer_ext_classes
301 _objc_debug_taggedpointer_ext_classes:
305 UNWIND _objc_msgSend, NoFrame
308 cmp x0, #0 // nil check and tagged pointer check
309 b.le LNilOrTagged // (MSB tagged pointer looks negative)
310 ldr x13, [x0] // x13 = isa
311 and x16, x13, #ISA_MASK // x16 = class
313 CacheLookup NORMAL // calls imp or objc_msgSend_uncached
316 b.eq LReturnZero // nil check
319 mov x10, #0xf000000000000000
322 adrp x10, _objc_debug_taggedpointer_classes@PAGE
323 add x10, x10, _objc_debug_taggedpointer_classes@PAGEOFF
324 ubfx x11, x0, #60, #4
325 ldr x16, [x10, x11, LSL #3]
330 adrp x10, _objc_debug_taggedpointer_ext_classes@PAGE
331 add x10, x10, _objc_debug_taggedpointer_ext_classes@PAGEOFF
332 ubfx x11, x0, #52, #8
333 ldr x16, [x10, x11, LSL #3]
337 // x0 is already zero
346 END_ENTRY _objc_msgSend
349 ENTRY _objc_msgLookup
350 UNWIND _objc_msgLookup, NoFrame
352 cmp x0, #0 // nil check and tagged pointer check
353 b.le LLookup_NilOrTagged // (MSB tagged pointer looks negative)
354 ldr x13, [x0] // x13 = isa
355 and x16, x13, #ISA_MASK // x16 = class
357 CacheLookup LOOKUP // returns imp
360 b.eq LLookup_Nil // nil check
363 mov x10, #0xf000000000000000
366 adrp x10, _objc_debug_taggedpointer_classes@PAGE
367 add x10, x10, _objc_debug_taggedpointer_classes@PAGEOFF
368 ubfx x11, x0, #60, #4
369 ldr x16, [x10, x11, LSL #3]
373 adrp x10, _objc_debug_taggedpointer_ext_classes@PAGE
374 add x10, x10, _objc_debug_taggedpointer_ext_classes@PAGEOFF
375 ubfx x11, x0, #52, #8
376 ldr x16, [x10, x11, LSL #3]
380 adrp x17, __objc_msgNil@PAGE
381 add x17, x17, __objc_msgNil@PAGEOFF
384 END_ENTRY _objc_msgLookup
387 STATIC_ENTRY __objc_msgNil
389 // x0 is already zero
397 END_ENTRY __objc_msgNil
400 ENTRY _objc_msgSendSuper
401 UNWIND _objc_msgSendSuper, NoFrame
404 ldp x0, x16, [x0] // x0 = real receiver, x16 = class
405 CacheLookup NORMAL // calls imp or objc_msgSend_uncached
407 END_ENTRY _objc_msgSendSuper
409 // no _objc_msgLookupSuper
411 ENTRY _objc_msgSendSuper2
412 UNWIND _objc_msgSendSuper2, NoFrame
415 ldp x0, x16, [x0] // x0 = real receiver, x16 = class
416 ldr x16, [x16, #SUPERCLASS] // x16 = class->superclass
419 END_ENTRY _objc_msgSendSuper2
422 ENTRY _objc_msgLookupSuper2
423 UNWIND _objc_msgLookupSuper2, NoFrame
425 ldp x0, x16, [x0] // x0 = real receiver, x16 = class
426 ldr x16, [x16, #SUPERCLASS] // x16 = class->superclass
429 END_ENTRY _objc_msgLookupSuper2
432 .macro MethodTableLookup
435 stp fp, lr, [sp, #-16]!
438 // save parameter registers: x0..x8, q0..q7
439 sub sp, sp, #(10*8 + 8*16)
440 stp q0, q1, [sp, #(0*16)]
441 stp q2, q3, [sp, #(2*16)]
442 stp q4, q5, [sp, #(4*16)]
443 stp q6, q7, [sp, #(6*16)]
444 stp x0, x1, [sp, #(8*16+0*8)]
445 stp x2, x3, [sp, #(8*16+2*8)]
446 stp x4, x5, [sp, #(8*16+4*8)]
447 stp x6, x7, [sp, #(8*16+6*8)]
448 str x8, [sp, #(8*16+8*8)]
450 // receiver and selector already in x0 and x1
452 bl __class_lookupMethodAndLoadCache3
457 // restore registers and return
458 ldp q0, q1, [sp, #(0*16)]
459 ldp q2, q3, [sp, #(2*16)]
460 ldp q4, q5, [sp, #(4*16)]
461 ldp q6, q7, [sp, #(6*16)]
462 ldp x0, x1, [sp, #(8*16+0*8)]
463 ldp x2, x3, [sp, #(8*16+2*8)]
464 ldp x4, x5, [sp, #(8*16+4*8)]
465 ldp x6, x7, [sp, #(8*16+6*8)]
466 ldr x8, [sp, #(8*16+8*8)]
469 ldp fp, lr, [sp], #16
473 STATIC_ENTRY __objc_msgSend_uncached
474 UNWIND __objc_msgSend_uncached, FrameWithNoSaves
476 // THIS IS NOT A CALLABLE C FUNCTION
477 // Out-of-band x16 is the class to search
482 END_ENTRY __objc_msgSend_uncached
485 STATIC_ENTRY __objc_msgLookup_uncached
486 UNWIND __objc_msgLookup_uncached, FrameWithNoSaves
488 // THIS IS NOT A CALLABLE C FUNCTION
489 // Out-of-band x16 is the class to search
494 END_ENTRY __objc_msgLookup_uncached
497 STATIC_ENTRY _cache_getImp
499 and x16, x0, #ISA_MASK
506 END_ENTRY _cache_getImp
509 /********************************************************************
511 * id _objc_msgForward(id self, SEL _cmd,...);
513 * _objc_msgForward is the externally-callable
514 * function returned by things like method_getImplementation().
515 * _objc_msgForward_impcache is the function pointer actually stored in
518 ********************************************************************/
520 STATIC_ENTRY __objc_msgForward_impcache
526 // No stret specialization.
529 END_ENTRY __objc_msgForward_impcache
532 ENTRY __objc_msgForward
534 adrp x17, __objc_forward_handler@PAGE
535 ldr x17, [x17, __objc_forward_handler@PAGEOFF]
538 END_ENTRY __objc_msgForward
541 ENTRY _objc_msgSend_noarg
543 END_ENTRY _objc_msgSend_noarg
545 ENTRY _objc_msgSend_debug
547 END_ENTRY _objc_msgSend_debug
549 ENTRY _objc_msgSendSuper2_debug
550 b _objc_msgSendSuper2
551 END_ENTRY _objc_msgSendSuper2_debug
555 // x1 is method triplet instead of SEL
556 ldr x17, [x1, #METHOD_IMP]
557 ldr x1, [x1, #METHOD_NAME]
559 END_ENTRY _method_invoke