objc-msg-x86_64.s 29 KB

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