objc-msg-simulator-x86_64.s 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140
  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. #include <TargetConditionals.h>
  24. #if __x86_64__ && TARGET_OS_SIMULATOR && !TARGET_OS_IOSMAC
  25. /********************************************************************
  26. ********************************************************************
  27. **
  28. ** objc-msg-x86_64.s - x86-64 code to support objc messaging.
  29. **
  30. ********************************************************************
  31. ********************************************************************/
  32. .data
  33. // _objc_entryPoints and _objc_exitPoints are used by objc
  34. // to get the critical regions for which method caches
  35. // cannot be garbage collected.
  36. .align 4
  37. .private_extern _objc_entryPoints
  38. _objc_entryPoints:
  39. .quad _cache_getImp
  40. .quad _objc_msgSend
  41. .quad _objc_msgSend_fpret
  42. .quad _objc_msgSend_fp2ret
  43. .quad _objc_msgSend_stret
  44. .quad _objc_msgSendSuper
  45. .quad _objc_msgSendSuper_stret
  46. .quad _objc_msgSendSuper2
  47. .quad _objc_msgSendSuper2_stret
  48. .quad _objc_msgLookup
  49. .quad _objc_msgLookup_fpret
  50. .quad _objc_msgLookup_fp2ret
  51. .quad _objc_msgLookup_stret
  52. .quad _objc_msgLookupSuper2
  53. .quad _objc_msgLookupSuper2_stret
  54. .quad 0
  55. .private_extern _objc_exitPoints
  56. _objc_exitPoints:
  57. .quad LExit_cache_getImp
  58. .quad LExit_objc_msgSend
  59. .quad LExit_objc_msgSend_fpret
  60. .quad LExit_objc_msgSend_fp2ret
  61. .quad LExit_objc_msgSend_stret
  62. .quad LExit_objc_msgSendSuper
  63. .quad LExit_objc_msgSendSuper_stret
  64. .quad LExit_objc_msgSendSuper2
  65. .quad LExit_objc_msgSendSuper2_stret
  66. .quad LExit_objc_msgLookup
  67. .quad LExit_objc_msgLookup_fpret
  68. .quad LExit_objc_msgLookup_fp2ret
  69. .quad LExit_objc_msgLookup_stret
  70. .quad LExit_objc_msgLookupSuper2
  71. .quad LExit_objc_msgLookupSuper2_stret
  72. .quad 0
  73. /********************************************************************
  74. * Recommended multi-byte NOP instructions
  75. * (Intel 64 and IA-32 Architectures Software Developer's Manual Volume 2B)
  76. ********************************************************************/
  77. #define nop1 .byte 0x90
  78. #define nop2 .byte 0x66,0x90
  79. #define nop3 .byte 0x0F,0x1F,0x00
  80. #define nop4 .byte 0x0F,0x1F,0x40,0x00
  81. #define nop5 .byte 0x0F,0x1F,0x44,0x00,0x00
  82. #define nop6 .byte 0x66,0x0F,0x1F,0x44,0x00,0x00
  83. #define nop7 .byte 0x0F,0x1F,0x80,0x00,0x00,0x00,0x00
  84. #define nop8 .byte 0x0F,0x1F,0x84,0x00,0x00,0x00,0x00,0x00
  85. #define nop9 .byte 0x66,0x0F,0x1F,0x84,0x00,0x00,0x00,0x00,0x00
  86. /********************************************************************
  87. * Names for parameter registers.
  88. ********************************************************************/
  89. #define a1 rdi
  90. #define a1d edi
  91. #define a1b dil
  92. #define a2 rsi
  93. #define a2d esi
  94. #define a2b sil
  95. #define a3 rdx
  96. #define a3d edx
  97. #define a4 rcx
  98. #define a4d ecx
  99. #define a5 r8
  100. #define a5d r8d
  101. #define a6 r9
  102. #define a6d r9d
  103. /********************************************************************
  104. * Names for relative labels
  105. * DO NOT USE THESE LABELS ELSEWHERE
  106. * Reserved labels: 6: 7: 8: 9:
  107. ********************************************************************/
  108. #define LCacheMiss 6
  109. #define LCacheMiss_f 6f
  110. #define LCacheMiss_b 6b
  111. #define LGetIsaDone 7
  112. #define LGetIsaDone_f 7f
  113. #define LGetIsaDone_b 7b
  114. #define LNilOrTagged 8
  115. #define LNilOrTagged_f 8f
  116. #define LNilOrTagged_b 8b
  117. #define LNil 9
  118. #define LNil_f 9f
  119. #define LNil_b 9b
  120. /********************************************************************
  121. * Macro parameters
  122. ********************************************************************/
  123. #define NORMAL 0
  124. #define FPRET 1
  125. #define FP2RET 2
  126. #define STRET 3
  127. #define CALL 100
  128. #define GETIMP 101
  129. #define LOOKUP 102
  130. /********************************************************************
  131. *
  132. * Structure definitions.
  133. *
  134. ********************************************************************/
  135. // objc_super parameter to sendSuper
  136. #define receiver 0
  137. #define class 8
  138. // Selected field offsets in class structure
  139. // #define isa 0 USE GetIsa INSTEAD
  140. // Method descriptor
  141. #define method_name 0
  142. #define method_imp 16
  143. // Method cache
  144. #define cached_sel 0
  145. #define cached_imp 8
  146. //////////////////////////////////////////////////////////////////////
  147. //
  148. // ENTRY functionName
  149. //
  150. // Assembly directives to begin an exported function.
  151. //
  152. // Takes: functionName - name of the exported function
  153. //////////////////////////////////////////////////////////////////////
  154. .macro ENTRY
  155. .text
  156. .globl $0
  157. .align 6, 0x90
  158. $0:
  159. .endmacro
  160. .macro STATIC_ENTRY
  161. .text
  162. .private_extern $0
  163. .align 2, 0x90
  164. $0:
  165. .endmacro
  166. //////////////////////////////////////////////////////////////////////
  167. //
  168. // END_ENTRY functionName
  169. //
  170. // Assembly directives to end an exported function. Just a placeholder,
  171. // a close-parenthesis for ENTRY, until it is needed for something.
  172. //
  173. // Takes: functionName - name of the exported function
  174. //////////////////////////////////////////////////////////////////////
  175. .macro END_ENTRY
  176. LExit$0:
  177. .endmacro
  178. /********************************************************************
  179. * UNWIND name, flags
  180. * Unwind info generation
  181. ********************************************************************/
  182. .macro UNWIND
  183. .section __LD,__compact_unwind,regular,debug
  184. .quad $0
  185. .set LUnwind$0, LExit$0 - $0
  186. .long LUnwind$0
  187. .long $1
  188. .quad 0 /* no personality */
  189. .quad 0 /* no LSDA */
  190. .text
  191. .endmacro
  192. #define NoFrame 0x02010000 // no frame, no SP adjustment except return address
  193. #define FrameWithNoSaves 0x01000000 // frame, no non-volatile saves
  194. /////////////////////////////////////////////////////////////////////
  195. //
  196. // CacheLookup return-type, caller
  197. //
  198. // Locate the implementation for a class in a selector's method cache.
  199. //
  200. // Takes:
  201. // $0 = NORMAL, FPRET, FP2RET, STRET
  202. // $1 = CALL, LOOKUP, GETIMP
  203. // a1 or a2 (STRET) = receiver
  204. // a2 or a3 (STRET) = selector
  205. // r10 = class to search
  206. //
  207. // On exit: r10 clobbered
  208. // (found) calls or returns IMP in r11, eq/ne set for forwarding
  209. // (not found) jumps to LCacheMiss, class still in r10
  210. //
  211. /////////////////////////////////////////////////////////////////////
  212. .macro CacheHit
  213. // CacheHit must always be preceded by a not-taken `jne` instruction
  214. // in order to set the correct flags for _objc_msgForward_impcache.
  215. // r11 = found bucket
  216. .if $1 == GETIMP
  217. movq cached_imp(%r11), %rax // return imp
  218. ret
  219. .else
  220. .if $0 != STRET
  221. // eq already set for forwarding by `jne`
  222. .else
  223. test %r11, %r11 // set ne for stret forwarding
  224. .endif
  225. .if $1 == CALL
  226. jmp *cached_imp(%r11) // call imp
  227. .elseif $1 == LOOKUP
  228. movq cached_imp(%r11), %r11 // return imp
  229. ret
  230. .else
  231. .abort oops
  232. .endif
  233. .endif
  234. .endmacro
  235. .macro CacheLookup
  236. .if $0 != STRET
  237. movq %a2, %r11 // r11 = _cmd
  238. .else
  239. movq %a3, %r11 // r11 = _cmd
  240. .endif
  241. andl 24(%r10), %r11d // r11 = _cmd & class->cache.mask
  242. shlq $$4, %r11 // r11 = offset = (_cmd & mask)<<4
  243. addq 16(%r10), %r11 // r11 = class->cache.buckets + offset
  244. .if $0 != STRET
  245. cmpq cached_sel(%r11), %a2 // if (bucket->sel != _cmd)
  246. .else
  247. cmpq cached_sel(%r11), %a3 // if (bucket->sel != _cmd)
  248. .endif
  249. jne 1f // scan more
  250. // CacheHit must always be preceded by a not-taken `jne` instruction
  251. CacheHit $0, $1 // call or return imp
  252. 1:
  253. // loop
  254. cmpq $$1, cached_sel(%r11)
  255. jbe 3f // if (bucket->sel <= 1) wrap or miss
  256. addq $$16, %r11 // bucket++
  257. 2:
  258. .if $0 != STRET
  259. cmpq cached_sel(%r11), %a2 // if (bucket->sel != _cmd)
  260. .else
  261. cmpq cached_sel(%r11), %a3 // if (bucket->sel != _cmd)
  262. .endif
  263. jne 1b // scan more
  264. // CacheHit must always be preceded by a not-taken `jne` instruction
  265. CacheHit $0, $1 // call or return imp
  266. 3:
  267. // wrap or miss
  268. jb LCacheMiss_f // if (bucket->sel < 1) cache miss
  269. // wrap
  270. movq cached_imp(%r11), %r11 // bucket->imp is really first bucket
  271. jmp 2f
  272. // Clone scanning loop to miss instead of hang when cache is corrupt.
  273. // The slow path may detect any corruption and halt later.
  274. 1:
  275. // loop
  276. cmpq $$1, cached_sel(%r11)
  277. jbe 3f // if (bucket->sel <= 1) wrap or miss
  278. addq $$16, %r11 // bucket++
  279. 2:
  280. .if $0 != STRET
  281. cmpq cached_sel(%r11), %a2 // if (bucket->sel != _cmd)
  282. .else
  283. cmpq cached_sel(%r11), %a3 // if (bucket->sel != _cmd)
  284. .endif
  285. jne 1b // scan more
  286. // CacheHit must always be preceded by a not-taken `jne` instruction
  287. CacheHit $0, $1 // call or return imp
  288. 3:
  289. // double wrap or miss
  290. jmp LCacheMiss_f
  291. .endmacro
  292. /////////////////////////////////////////////////////////////////////
  293. //
  294. // MethodTableLookup NORMAL|STRET
  295. //
  296. // Takes: a1 or a2 (STRET) = receiver
  297. // a2 or a3 (STRET) = selector to search for
  298. // r10 = class to search
  299. //
  300. // On exit: imp in %r11, eq/ne set for forwarding
  301. //
  302. /////////////////////////////////////////////////////////////////////
  303. .macro MethodTableLookup
  304. push %rbp
  305. mov %rsp, %rbp
  306. sub $$0x80+8, %rsp // +8 for alignment
  307. movdqa %xmm0, -0x80(%rbp)
  308. push %rax // might be xmm parameter count
  309. movdqa %xmm1, -0x70(%rbp)
  310. push %a1
  311. movdqa %xmm2, -0x60(%rbp)
  312. push %a2
  313. movdqa %xmm3, -0x50(%rbp)
  314. push %a3
  315. movdqa %xmm4, -0x40(%rbp)
  316. push %a4
  317. movdqa %xmm5, -0x30(%rbp)
  318. push %a5
  319. movdqa %xmm6, -0x20(%rbp)
  320. push %a6
  321. movdqa %xmm7, -0x10(%rbp)
  322. // _class_lookupMethodAndLoadCache3(receiver, selector, class)
  323. .if $0 == NORMAL
  324. // receiver already in a1
  325. // selector already in a2
  326. .else
  327. movq %a2, %a1
  328. movq %a3, %a2
  329. .endif
  330. movq %r10, %a3
  331. call __class_lookupMethodAndLoadCache3
  332. // IMP is now in %rax
  333. movq %rax, %r11
  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. .if $0 == NORMAL
  350. cmp %r11, %r11 // set eq for nonstret forwarding
  351. .else
  352. test %r11, %r11 // set ne for stret forwarding
  353. .endif
  354. leave
  355. .endmacro
  356. /////////////////////////////////////////////////////////////////////
  357. //
  358. // GetIsaCheckNil return-type
  359. // GetIsaSupport return-type
  360. // NilTestReturnZero return-type
  361. // NilTestReturnIMP return-type
  362. //
  363. // Sets r10 = obj->isa.
  364. // Looks up the real class if receiver is a tagged pointer object.
  365. // Returns zero or a zero-returning IMP if obj is nil.
  366. //
  367. // Takes: $0 = NORMAL or FPRET or FP2RET or STRET
  368. // a1 or a2 (STRET) = receiver
  369. //
  370. // On exit from GetIsaCheckNil:
  371. // r10 = receiver->isa
  372. // r11 is clobbered
  373. //
  374. /////////////////////////////////////////////////////////////////////
  375. .macro ZeroReturn
  376. xorl %eax, %eax
  377. xorl %edx, %edx
  378. xorps %xmm0, %xmm0
  379. xorps %xmm1, %xmm1
  380. .endmacro
  381. .macro ZeroReturnFPRET
  382. fldz
  383. ZeroReturn
  384. .endmacro
  385. .macro ZeroReturnFP2RET
  386. fldz
  387. fldz
  388. ZeroReturn
  389. .endmacro
  390. .macro ZeroReturnSTRET
  391. // rax gets the struct-return address as passed in rdi
  392. movq %rdi, %rax
  393. .endmacro
  394. STATIC_ENTRY __objc_msgNil
  395. ZeroReturn
  396. ret
  397. END_ENTRY __objc_msgNil
  398. STATIC_ENTRY __objc_msgNil_fpret
  399. ZeroReturnFPRET
  400. ret
  401. END_ENTRY __objc_msgNil_fpret
  402. STATIC_ENTRY __objc_msgNil_fp2ret
  403. ZeroReturnFP2RET
  404. ret
  405. END_ENTRY __objc_msgNil_fp2ret
  406. STATIC_ENTRY __objc_msgNil_stret
  407. ZeroReturnSTRET
  408. ret
  409. END_ENTRY __objc_msgNil_stret
  410. .macro GetIsaCheckNil
  411. .if $0 != STRET
  412. testq %a1, %a1
  413. .else
  414. testq %a2, %a2
  415. .endif
  416. jle LNilOrTagged_f // MSB tagged pointer looks negative
  417. .if $0 != STRET
  418. movq (%a1), %r10 // r10 = isa
  419. .else
  420. movq (%a2), %r10 // r10 = isa
  421. .endif
  422. LGetIsaDone:
  423. .endmacro
  424. .macro GetIsaSupport
  425. .align 3
  426. LNilOrTagged:
  427. jz LNil_f // flags set by GetIsaCheckNil
  428. .if $0 != STRET
  429. movq %a1, %r11
  430. .else
  431. movq %a2, %r11
  432. .endif
  433. // basic tagged
  434. shrq $$60, %r11
  435. leaq _objc_debug_taggedpointer_classes(%rip), %r10
  436. movq (%r10, %r11, 8), %r10 // read isa from table
  437. leaq _OBJC_CLASS_$___NSUnrecognizedTaggedPointer(%rip), %r11
  438. cmp %r10, %r11
  439. jne LGetIsaDone_b
  440. // ext tagged
  441. .if $0 != STRET
  442. movq %a1, %r11
  443. .else
  444. movq %a2, %r11
  445. .endif
  446. shrq $$52, %r11
  447. andl $$0xff, %r11d
  448. leaq _objc_debug_taggedpointer_ext_classes(%rip), %r10
  449. movq (%r10, %r11, 8), %r10 // read isa from table
  450. jmp LGetIsaDone_b
  451. .endmacro
  452. .macro NilTestReturnZero
  453. LNil:
  454. .if $0 == NORMAL
  455. ZeroReturn
  456. .elseif $0 == FPRET
  457. ZeroReturnFPRET
  458. .elseif $0 == FP2RET
  459. ZeroReturnFP2RET
  460. .elseif $0 == STRET
  461. ZeroReturnSTRET
  462. .else
  463. .abort oops
  464. .endif
  465. ret
  466. .endmacro
  467. .macro NilTestReturnIMP
  468. LNil:
  469. .if $0 == NORMAL
  470. leaq __objc_msgNil(%rip), %r11
  471. .elseif $0 == FPRET
  472. leaq __objc_msgNil_fpret(%rip), %r11
  473. .elseif $0 == FP2RET
  474. leaq __objc_msgNil_fp2ret(%rip), %r11
  475. .elseif $0 == STRET
  476. leaq __objc_msgNil_stret(%rip), %r11
  477. .else
  478. .abort oops
  479. .endif
  480. ret
  481. .endmacro
  482. /********************************************************************
  483. * IMP cache_getImp(Class cls, SEL sel)
  484. *
  485. * On entry: a1 = class whose cache is to be searched
  486. * a2 = selector to search for
  487. *
  488. * If found, returns method implementation.
  489. * If not found, returns NULL.
  490. ********************************************************************/
  491. STATIC_ENTRY _cache_getImp
  492. // do lookup
  493. movq %a1, %r10 // move class to r10 for CacheLookup
  494. CacheLookup NORMAL, GETIMP // returns IMP on success
  495. LCacheMiss:
  496. // cache miss, return nil
  497. xorl %eax, %eax
  498. ret
  499. END_ENTRY _cache_getImp
  500. /********************************************************************
  501. *
  502. * id objc_msgSend(id self, SEL _cmd,...);
  503. * IMP objc_msgLookup(id self, SEL _cmd, ...);
  504. *
  505. * objc_msgLookup ABI:
  506. * IMP returned in r11
  507. * Forwarding returned in Z flag
  508. * r10 reserved for our use but not used
  509. *
  510. ********************************************************************/
  511. .data
  512. .align 3
  513. .globl _objc_debug_taggedpointer_classes
  514. _objc_debug_taggedpointer_classes:
  515. .fill 16, 8, 0
  516. .globl _objc_debug_taggedpointer_ext_classes
  517. _objc_debug_taggedpointer_ext_classes:
  518. .fill 256, 8, 0
  519. ENTRY _objc_msgSend
  520. UNWIND _objc_msgSend, NoFrame
  521. GetIsaCheckNil NORMAL // r10 = self->isa, or return zero
  522. CacheLookup NORMAL, CALL // calls IMP on success
  523. GetIsaSupport NORMAL
  524. NilTestReturnZero NORMAL
  525. // cache miss: go search the method lists
  526. LCacheMiss:
  527. // isa still in r10
  528. jmp __objc_msgSend_uncached
  529. END_ENTRY _objc_msgSend
  530. ENTRY _objc_msgLookup
  531. GetIsaCheckNil NORMAL // r10 = self->isa, or return zero IMP
  532. CacheLookup NORMAL, LOOKUP // returns IMP on success
  533. GetIsaSupport NORMAL
  534. NilTestReturnIMP NORMAL
  535. // cache miss: go search the method lists
  536. LCacheMiss:
  537. // isa still in r10
  538. jmp __objc_msgLookup_uncached
  539. END_ENTRY _objc_msgLookup
  540. ENTRY _objc_msgSend_fixup
  541. int3
  542. END_ENTRY _objc_msgSend_fixup
  543. STATIC_ENTRY _objc_msgSend_fixedup
  544. // Load _cmd from the message_ref
  545. movq 8(%a2), %a2
  546. jmp _objc_msgSend
  547. END_ENTRY _objc_msgSend_fixedup
  548. /********************************************************************
  549. *
  550. * id objc_msgSendSuper(struct objc_super *super, SEL _cmd,...);
  551. *
  552. * struct objc_super {
  553. * id receiver;
  554. * Class class;
  555. * };
  556. ********************************************************************/
  557. ENTRY _objc_msgSendSuper
  558. UNWIND _objc_msgSendSuper, NoFrame
  559. // search the cache (objc_super in %a1)
  560. movq class(%a1), %r10 // class = objc_super->class
  561. movq receiver(%a1), %a1 // load real receiver
  562. CacheLookup NORMAL, CALL // calls IMP on success
  563. // cache miss: go search the method lists
  564. LCacheMiss:
  565. // class still in r10
  566. jmp __objc_msgSend_uncached
  567. END_ENTRY _objc_msgSendSuper
  568. /********************************************************************
  569. * id objc_msgSendSuper2
  570. ********************************************************************/
  571. ENTRY _objc_msgSendSuper2
  572. UNWIND _objc_msgSendSuper2, NoFrame
  573. // objc_super->class is superclass of class to search
  574. // search the cache (objc_super in %a1)
  575. movq class(%a1), %r10 // cls = objc_super->class
  576. movq receiver(%a1), %a1 // load real receiver
  577. movq 8(%r10), %r10 // cls = class->superclass
  578. CacheLookup NORMAL, CALL // calls IMP on success
  579. // cache miss: go search the method lists
  580. LCacheMiss:
  581. // superclass still in r10
  582. jmp __objc_msgSend_uncached
  583. END_ENTRY _objc_msgSendSuper2
  584. ENTRY _objc_msgLookupSuper2
  585. // objc_super->class is superclass of class to search
  586. // search the cache (objc_super in %a1)
  587. movq class(%a1), %r10 // cls = objc_super->class
  588. movq receiver(%a1), %a1 // load real receiver
  589. movq 8(%r10), %r10 // cls = class->superclass
  590. CacheLookup NORMAL, LOOKUP // returns IMP on success
  591. // cache miss: go search the method lists
  592. LCacheMiss:
  593. // superclass still in r10
  594. jmp __objc_msgLookup_uncached
  595. END_ENTRY _objc_msgLookupSuper2
  596. ENTRY _objc_msgSendSuper2_fixup
  597. int3
  598. END_ENTRY _objc_msgSendSuper2_fixup
  599. STATIC_ENTRY _objc_msgSendSuper2_fixedup
  600. // Load _cmd from the message_ref
  601. movq 8(%a2), %a2
  602. jmp _objc_msgSendSuper2
  603. END_ENTRY _objc_msgSendSuper2_fixedup
  604. /********************************************************************
  605. *
  606. * double objc_msgSend_fpret(id self, SEL _cmd,...);
  607. * Used for `long double` return only. `float` and `double` use objc_msgSend.
  608. *
  609. ********************************************************************/
  610. ENTRY _objc_msgSend_fpret
  611. UNWIND _objc_msgSend_fpret, NoFrame
  612. GetIsaCheckNil FPRET // r10 = self->isa, or return zero
  613. CacheLookup FPRET, CALL // calls IMP on success
  614. GetIsaSupport FPRET
  615. NilTestReturnZero FPRET
  616. // cache miss: go search the method lists
  617. LCacheMiss:
  618. // isa still in r10
  619. jmp __objc_msgSend_uncached
  620. END_ENTRY _objc_msgSend_fpret
  621. ENTRY _objc_msgLookup_fpret
  622. GetIsaCheckNil FPRET // r10 = self->isa, or return zero IMP
  623. CacheLookup FPRET, LOOKUP // returns IMP on success
  624. GetIsaSupport FPRET
  625. NilTestReturnIMP FPRET
  626. // cache miss: go search the method lists
  627. LCacheMiss:
  628. // isa still in r10
  629. jmp __objc_msgLookup_uncached
  630. END_ENTRY _objc_msgLookup_fpret
  631. ENTRY _objc_msgSend_fpret_fixup
  632. int3
  633. END_ENTRY _objc_msgSend_fpret_fixup
  634. STATIC_ENTRY _objc_msgSend_fpret_fixedup
  635. // Load _cmd from the message_ref
  636. movq 8(%a2), %a2
  637. jmp _objc_msgSend_fpret
  638. END_ENTRY _objc_msgSend_fpret_fixedup
  639. /********************************************************************
  640. *
  641. * double objc_msgSend_fp2ret(id self, SEL _cmd,...);
  642. * Used for `complex long double` return only.
  643. *
  644. ********************************************************************/
  645. ENTRY _objc_msgSend_fp2ret
  646. UNWIND _objc_msgSend_fp2ret, NoFrame
  647. GetIsaCheckNil FP2RET // r10 = self->isa, or return zero
  648. CacheLookup FP2RET, CALL // calls IMP on success
  649. GetIsaSupport FP2RET
  650. NilTestReturnZero FP2RET
  651. // cache miss: go search the method lists
  652. LCacheMiss:
  653. // isa still in r10
  654. jmp __objc_msgSend_uncached
  655. END_ENTRY _objc_msgSend_fp2ret
  656. ENTRY _objc_msgLookup_fp2ret
  657. GetIsaCheckNil FP2RET // r10 = self->isa, or return zero IMP
  658. CacheLookup FP2RET, LOOKUP // returns IMP on success
  659. GetIsaSupport FP2RET
  660. NilTestReturnIMP FP2RET
  661. // cache miss: go search the method lists
  662. LCacheMiss:
  663. // isa still in r10
  664. jmp __objc_msgLookup_uncached
  665. END_ENTRY _objc_msgLookup_fp2ret
  666. ENTRY _objc_msgSend_fp2ret_fixup
  667. int3
  668. END_ENTRY _objc_msgSend_fp2ret_fixup
  669. STATIC_ENTRY _objc_msgSend_fp2ret_fixedup
  670. // Load _cmd from the message_ref
  671. movq 8(%a2), %a2
  672. jmp _objc_msgSend_fp2ret
  673. END_ENTRY _objc_msgSend_fp2ret_fixedup
  674. /********************************************************************
  675. *
  676. * void objc_msgSend_stret(void *st_addr, id self, SEL _cmd, ...);
  677. *
  678. * objc_msgSend_stret is the struct-return form of msgSend.
  679. * The ABI calls for %a1 to be used as the address of the structure
  680. * being returned, with the parameters in the succeeding locations.
  681. *
  682. * On entry: %a1 is the address where the structure is returned,
  683. * %a2 is the message receiver,
  684. * %a3 is the selector
  685. ********************************************************************/
  686. ENTRY _objc_msgSend_stret
  687. UNWIND _objc_msgSend_stret, NoFrame
  688. GetIsaCheckNil STRET // r10 = self->isa, or return zero
  689. CacheLookup STRET, CALL // calls IMP on success
  690. GetIsaSupport STRET
  691. NilTestReturnZero STRET
  692. // cache miss: go search the method lists
  693. LCacheMiss:
  694. // isa still in r10
  695. jmp __objc_msgSend_stret_uncached
  696. END_ENTRY _objc_msgSend_stret
  697. ENTRY _objc_msgLookup_stret
  698. GetIsaCheckNil STRET // r10 = self->isa, or return zero IMP
  699. CacheLookup STRET, LOOKUP // returns IMP on success
  700. GetIsaSupport STRET
  701. NilTestReturnIMP STRET
  702. // cache miss: go search the method lists
  703. LCacheMiss:
  704. // isa still in r10
  705. jmp __objc_msgLookup_stret_uncached
  706. END_ENTRY _objc_msgLookup_stret
  707. ENTRY _objc_msgSend_stret_fixup
  708. int3
  709. END_ENTRY _objc_msgSend_stret_fixup
  710. STATIC_ENTRY _objc_msgSend_stret_fixedup
  711. // Load _cmd from the message_ref
  712. movq 8(%a3), %a3
  713. jmp _objc_msgSend_stret
  714. END_ENTRY _objc_msgSend_stret_fixedup
  715. /********************************************************************
  716. *
  717. * void objc_msgSendSuper_stret(void *st_addr, struct objc_super *super, SEL _cmd, ...);
  718. *
  719. * struct objc_super {
  720. * id receiver;
  721. * Class class;
  722. * };
  723. *
  724. * objc_msgSendSuper_stret is the struct-return form of msgSendSuper.
  725. * The ABI calls for (sp+4) to be used as the address of the structure
  726. * being returned, with the parameters in the succeeding registers.
  727. *
  728. * On entry: %a1 is the address where the structure is returned,
  729. * %a2 is the address of the objc_super structure,
  730. * %a3 is the selector
  731. *
  732. ********************************************************************/
  733. ENTRY _objc_msgSendSuper_stret
  734. UNWIND _objc_msgSendSuper_stret, NoFrame
  735. // search the cache (objc_super in %a2)
  736. movq class(%a2), %r10 // class = objc_super->class
  737. movq receiver(%a2), %a2 // load real receiver
  738. CacheLookup STRET, CALL // calls IMP on success
  739. // cache miss: go search the method lists
  740. LCacheMiss:
  741. // class still in r10
  742. jmp __objc_msgSend_stret_uncached
  743. END_ENTRY _objc_msgSendSuper_stret
  744. /********************************************************************
  745. * id objc_msgSendSuper2_stret
  746. ********************************************************************/
  747. ENTRY _objc_msgSendSuper2_stret
  748. UNWIND _objc_msgSendSuper2_stret, NoFrame
  749. // search the cache (objc_super in %a2)
  750. movq class(%a2), %r10 // class = objc_super->class
  751. movq receiver(%a2), %a2 // load real receiver
  752. movq 8(%r10), %r10 // class = class->superclass
  753. CacheLookup STRET, CALL // calls IMP on success
  754. // cache miss: go search the method lists
  755. LCacheMiss:
  756. // superclass still in r10
  757. jmp __objc_msgSend_stret_uncached
  758. END_ENTRY _objc_msgSendSuper2_stret
  759. ENTRY _objc_msgLookupSuper2_stret
  760. // search the cache (objc_super in %a2)
  761. movq class(%a2), %r10 // class = objc_super->class
  762. movq receiver(%a2), %a2 // load real receiver
  763. movq 8(%r10), %r10 // class = class->superclass
  764. CacheLookup STRET, LOOKUP // returns IMP on success
  765. // cache miss: go search the method lists
  766. LCacheMiss:
  767. // superclass still in r10
  768. jmp __objc_msgLookup_stret_uncached
  769. END_ENTRY _objc_msgLookupSuper2_stret
  770. ENTRY _objc_msgSendSuper2_stret_fixup
  771. int3
  772. END_ENTRY _objc_msgSendSuper2_stret_fixup
  773. STATIC_ENTRY _objc_msgSendSuper2_stret_fixedup
  774. // Load _cmd from the message_ref
  775. movq 8(%a3), %a3
  776. jmp _objc_msgSendSuper2_stret
  777. END_ENTRY _objc_msgSendSuper2_stret_fixedup
  778. /********************************************************************
  779. *
  780. * _objc_msgSend_uncached
  781. * _objc_msgSend_stret_uncached
  782. * The uncached method lookup.
  783. *
  784. ********************************************************************/
  785. STATIC_ENTRY __objc_msgSend_uncached
  786. UNWIND __objc_msgSend_uncached, FrameWithNoSaves
  787. // THIS IS NOT A CALLABLE C FUNCTION
  788. // Out-of-band r10 is the searched class
  789. // r10 is already the class to search
  790. MethodTableLookup NORMAL // r11 = IMP
  791. jmp *%r11 // goto *imp
  792. END_ENTRY __objc_msgSend_uncached
  793. STATIC_ENTRY __objc_msgSend_stret_uncached
  794. UNWIND __objc_msgSend_stret_uncached, FrameWithNoSaves
  795. // THIS IS NOT A CALLABLE C FUNCTION
  796. // Out-of-band r10 is the searched class
  797. // r10 is already the class to search
  798. MethodTableLookup STRET // r11 = IMP
  799. jmp *%r11 // goto *imp
  800. END_ENTRY __objc_msgSend_stret_uncached
  801. STATIC_ENTRY __objc_msgLookup_uncached
  802. UNWIND __objc_msgLookup_uncached, FrameWithNoSaves
  803. // THIS IS NOT A CALLABLE C FUNCTION
  804. // Out-of-band r10 is the searched class
  805. // r10 is already the class to search
  806. MethodTableLookup NORMAL // r11 = IMP
  807. ret
  808. END_ENTRY __objc_msgLookup_uncached
  809. STATIC_ENTRY __objc_msgLookup_stret_uncached
  810. UNWIND __objc_msgLookup_stret_uncached, FrameWithNoSaves
  811. // THIS IS NOT A CALLABLE C FUNCTION
  812. // Out-of-band r10 is the searched class
  813. // r10 is already the class to search
  814. MethodTableLookup STRET // r11 = IMP
  815. ret
  816. END_ENTRY __objc_msgLookup_stret_uncached
  817. /********************************************************************
  818. *
  819. * id _objc_msgForward(id self, SEL _cmd,...);
  820. *
  821. * _objc_msgForward and _objc_msgForward_stret are the externally-callable
  822. * functions returned by things like method_getImplementation().
  823. * _objc_msgForward_impcache is the function pointer actually stored in
  824. * method caches.
  825. *
  826. ********************************************************************/
  827. STATIC_ENTRY __objc_msgForward_impcache
  828. // Method cache version
  829. // THIS IS NOT A CALLABLE C FUNCTION
  830. // Out-of-band condition register is NE for stret, EQ otherwise.
  831. jne __objc_msgForward_stret
  832. jmp __objc_msgForward
  833. END_ENTRY __objc_msgForward_impcache
  834. ENTRY __objc_msgForward
  835. // Non-stret version
  836. movq __objc_forward_handler(%rip), %r11
  837. jmp *%r11
  838. END_ENTRY __objc_msgForward
  839. ENTRY __objc_msgForward_stret
  840. // Struct-return version
  841. movq __objc_forward_stret_handler(%rip), %r11
  842. jmp *%r11
  843. END_ENTRY __objc_msgForward_stret
  844. ENTRY _objc_msgSend_debug
  845. jmp _objc_msgSend
  846. END_ENTRY _objc_msgSend_debug
  847. ENTRY _objc_msgSendSuper2_debug
  848. jmp _objc_msgSendSuper2
  849. END_ENTRY _objc_msgSendSuper2_debug
  850. ENTRY _objc_msgSend_stret_debug
  851. jmp _objc_msgSend_stret
  852. END_ENTRY _objc_msgSend_stret_debug
  853. ENTRY _objc_msgSendSuper2_stret_debug
  854. jmp _objc_msgSendSuper2_stret
  855. END_ENTRY _objc_msgSendSuper2_stret_debug
  856. ENTRY _objc_msgSend_fpret_debug
  857. jmp _objc_msgSend_fpret
  858. END_ENTRY _objc_msgSend_fpret_debug
  859. ENTRY _objc_msgSend_fp2ret_debug
  860. jmp _objc_msgSend_fp2ret
  861. END_ENTRY _objc_msgSend_fp2ret_debug
  862. ENTRY _objc_msgSend_noarg
  863. jmp _objc_msgSend
  864. END_ENTRY _objc_msgSend_noarg
  865. ENTRY _method_invoke
  866. movq method_imp(%a2), %r11
  867. movq method_name(%a2), %a2
  868. jmp *%r11
  869. END_ENTRY _method_invoke
  870. ENTRY _method_invoke_stret
  871. movq method_imp(%a3), %r11
  872. movq method_name(%a3), %a3
  873. jmp *%r11
  874. END_ENTRY _method_invoke_stret
  875. .section __DATA,__objc_msg_break
  876. .quad 0
  877. .quad 0
  878. #endif