objc-msg-x86_64.s 28 KB

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