objc-msg-simulator-x86_64.s 26 KB

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