objc-msg-simulator-i386.s 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933
  1. /*
  2. * Copyright (c) 1999-2009 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 defined(__i386__) && TARGET_OS_SIMULATOR
  25. #include "objc-config.h"
  26. .data
  27. // _objc_restartableRanges is used by method dispatch
  28. // to get the critical regions for which method caches
  29. // cannot be garbage collected.
  30. .macro RestartableEntry
  31. .long $0
  32. .long 0
  33. .short LExit$0 - $0
  34. .short 0xffff // The simulator doesn't support kernel based recovery
  35. .long 0
  36. .endmacro
  37. .align 4
  38. .private_extern _objc_restartableRanges
  39. _objc_restartableRanges:
  40. RestartableEntry _cache_getImp
  41. RestartableEntry _objc_msgSend
  42. RestartableEntry _objc_msgSend_fpret
  43. RestartableEntry _objc_msgSend_stret
  44. RestartableEntry _objc_msgSendSuper
  45. RestartableEntry _objc_msgSendSuper2
  46. RestartableEntry _objc_msgSendSuper_stret
  47. RestartableEntry _objc_msgSendSuper2_stret
  48. RestartableEntry _objc_msgLookup
  49. RestartableEntry _objc_msgLookup_fpret
  50. RestartableEntry _objc_msgLookup_stret
  51. RestartableEntry _objc_msgLookupSuper2
  52. RestartableEntry _objc_msgLookupSuper2_stret
  53. .fill 16, 1, 0
  54. /********************************************************************
  55. * Names for relative labels
  56. * DO NOT USE THESE LABELS ELSEWHERE
  57. * Reserved labels: 5: 6: 7: 8: 9:
  58. ********************************************************************/
  59. #define LCacheMiss 5
  60. #define LCacheMiss_f 5f
  61. #define LCacheMiss_b 5b
  62. #define LNilTestDone 6
  63. #define LNilTestDone_f 6f
  64. #define LNilTestDone_b 6b
  65. #define LNilTestSlow 7
  66. #define LNilTestSlow_f 7f
  67. #define LNilTestSlow_b 7b
  68. #define LGetIsaDone 8
  69. #define LGetIsaDone_f 8f
  70. #define LGetIsaDone_b 8b
  71. #define LGetIsaSlow 9
  72. #define LGetIsaSlow_f 9f
  73. #define LGetIsaSlow_b 9b
  74. /********************************************************************
  75. * Macro parameters
  76. ********************************************************************/
  77. #define NORMAL 0
  78. #define FPRET 1
  79. #define STRET 2
  80. #define CALL 100
  81. #define GETIMP 101
  82. #define LOOKUP 102
  83. /********************************************************************
  84. *
  85. * Structure definitions.
  86. *
  87. ********************************************************************/
  88. // Offsets from %esp
  89. #define self 4
  90. #define super 4
  91. #define selector 8
  92. #define marg_size 12
  93. #define marg_list 16
  94. #define first_arg 12
  95. #define struct_addr 4
  96. #define self_stret 8
  97. #define super_stret 8
  98. #define selector_stret 12
  99. #define marg_size_stret 16
  100. #define marg_list_stret 20
  101. // objc_super parameter to sendSuper
  102. #define receiver 0
  103. #define class 4
  104. // Selected field offsets in class structure
  105. #define isa 0
  106. #define superclass 4
  107. #define cache_buckets 8
  108. #define cache_mask 12
  109. // Method cache
  110. #define cached_sel 0
  111. #define cached_imp 4
  112. // Method descriptor
  113. #define method_name 0
  114. #define method_imp 8
  115. //////////////////////////////////////////////////////////////////////
  116. //
  117. // ENTRY functionName
  118. //
  119. // Assembly directives to begin an exported function.
  120. //
  121. // Takes: functionName - name of the exported function
  122. //////////////////////////////////////////////////////////////////////
  123. .macro ENTRY
  124. .text
  125. .globl $0
  126. .align 2, 0x90
  127. $0:
  128. .endmacro
  129. .macro STATIC_ENTRY
  130. .text
  131. .private_extern $0
  132. .align 4, 0x90
  133. $0:
  134. .endmacro
  135. //////////////////////////////////////////////////////////////////////
  136. //
  137. // END_ENTRY functionName
  138. //
  139. // Assembly directives to end an exported function. Just a placeholder,
  140. // a close-parenthesis for ENTRY, until it is needed for something.
  141. //
  142. // Takes: functionName - name of the exported function
  143. //////////////////////////////////////////////////////////////////////
  144. .macro END_ENTRY
  145. LExit$0:
  146. .endmacro
  147. /********************************************************************
  148. * UNWIND name, flags
  149. * Unwind info generation
  150. ********************************************************************/
  151. .macro UNWIND
  152. .section __LD,__compact_unwind,regular,debug
  153. .long $0
  154. .set LUnwind$0, LExit$0 - $0
  155. .long LUnwind$0
  156. .long $1
  157. .long 0 /* no personality */
  158. .long 0 /* no LSDA */
  159. .text
  160. .endmacro
  161. #define NoFrame 0x02010000 // no frame, no SP adjustment except return address
  162. #define FrameWithNoSaves 0x01000000 // frame, no non-volatile saves
  163. /////////////////////////////////////////////////////////////////////
  164. //
  165. // CacheLookup return-type, caller
  166. //
  167. // Locate the implementation for a selector in a class method cache.
  168. //
  169. // Takes:
  170. // $0 = NORMAL, FPRET, STRET
  171. // $1 = CALL, LOOKUP, GETIMP
  172. // ecx = selector to search for
  173. // edx = class to search
  174. //
  175. // On exit: ecx clobbered
  176. // (found) calls or returns IMP in eax, eq/ne set for forwarding
  177. // (not found) jumps to LCacheMiss, class still in edx
  178. //
  179. /////////////////////////////////////////////////////////////////////
  180. .macro CacheHit
  181. // CacheHit must always be preceded by a not-taken `jne` instruction
  182. // in case the imp is _objc_msgForward_impcache.
  183. // eax = found bucket
  184. .if $1 == GETIMP
  185. movl cached_imp(%eax), %eax // return imp
  186. cmpl $$0, %eax
  187. jz 9f // don't xor a nil imp
  188. xorl %edx, %eax // xor the isa with the imp
  189. 9: ret
  190. .else
  191. .if $1 == CALL
  192. xorl cached_imp(%eax), %edx // xor imp and isa
  193. .if $0 != STRET
  194. // ne already set for forwarding by `xor`
  195. .else
  196. cmp %eax, %eax // set eq for stret forwarding
  197. .endif
  198. jmp *%edx // call imp
  199. .elseif $1 == LOOKUP
  200. movl cached_imp(%eax), %eax // return imp
  201. xorl %edx, %eax // xor isa into imp
  202. ret
  203. .else
  204. .abort oops
  205. .endif
  206. .endif
  207. .endmacro
  208. .macro CacheLookup
  209. movzwl cache_mask(%edx), %eax // eax = mask
  210. andl %ecx, %eax // eax = SEL & mask
  211. shll $$3, %eax // eax = offset = (SEL & mask) * 8
  212. addl cache_buckets(%edx), %eax // eax = bucket = buckets+offset
  213. cmpl cached_sel(%eax), %ecx // if (bucket->sel != SEL)
  214. jne 1f // scan more
  215. // The `jne` above sets flags for CacheHit
  216. CacheHit $0, $1 // call or return imp
  217. 1:
  218. // loop
  219. cmpl $$1, cached_sel(%eax)
  220. jbe 3f // if (bucket->sel <= 1) wrap or miss
  221. addl $$8, %eax // bucket++
  222. 2:
  223. cmpl cached_sel(%eax), %ecx // if (bucket->sel != sel)
  224. jne 1b // scan more
  225. // The `jne` above sets flags for CacheHit
  226. CacheHit $0, $1 // call or return imp
  227. 3:
  228. // wrap or miss
  229. jb LCacheMiss_f // if (bucket->sel < 1) cache miss
  230. // wrap
  231. movl cached_imp(%eax), %eax // bucket->imp is really first bucket
  232. jmp 2f
  233. // Clone scanning loop to miss instead of hang when cache is corrupt.
  234. // The slow path may detect any corruption and halt later.
  235. 1:
  236. // loop
  237. cmpl $$1, cached_sel(%eax)
  238. jbe 3f // if (bucket->sel <= 1) wrap or miss
  239. addl $$8, %eax // bucket++
  240. 2:
  241. cmpl cached_sel(%eax), %ecx // if (bucket->sel != sel)
  242. jne 1b // scan more
  243. // The `jne` above sets flags for CacheHit
  244. CacheHit $0, $1 // call or return imp
  245. 3:
  246. // double wrap or miss
  247. jmp LCacheMiss_f
  248. .endmacro
  249. /////////////////////////////////////////////////////////////////////
  250. //
  251. // MethodTableLookup NORMAL|STRET
  252. //
  253. // Takes:
  254. // receiver (not struct objc_super) and selector on stack
  255. // edx = class to search
  256. //
  257. // On exit: IMP in eax, eq/ne set for forwarding
  258. //
  259. /////////////////////////////////////////////////////////////////////
  260. .macro MethodTableLookup
  261. pushl %ebp
  262. movl %esp, %ebp
  263. subl $$(8+5*16), %esp
  264. .if $0 == NORMAL
  265. movl self+4(%ebp), %eax
  266. movl selector+4(%ebp), %ecx
  267. .else
  268. movl self_stret+4(%ebp), %eax
  269. movl selector_stret+4(%ebp), %ecx
  270. .endif
  271. movdqa %xmm3, 4*16(%esp)
  272. movdqa %xmm2, 3*16(%esp)
  273. movdqa %xmm1, 2*16(%esp)
  274. movdqa %xmm0, 1*16(%esp)
  275. // lookUpImpOrForward(obj, sel, cls, LOOKUP_INITIALIZE | LOOKUP_RESOLVER)
  276. movl $$3, 12(%esp) // LOOKUP_INITIALIZE | LOOKUP_RESOLVER
  277. movl %edx, 8(%esp) // class
  278. movl %ecx, 4(%esp) // selector
  279. movl %eax, 0(%esp) // receiver
  280. call _lookUpImpOrForward
  281. // imp in eax
  282. movdqa 4*16(%esp), %xmm3
  283. movdqa 3*16(%esp), %xmm2
  284. movdqa 2*16(%esp), %xmm1
  285. movdqa 1*16(%esp), %xmm0
  286. .if $0 == NORMAL
  287. test %eax, %eax // set ne for stret forwarding
  288. .else
  289. cmp %eax, %eax // set eq for nonstret forwarding
  290. .endif
  291. leave
  292. .endmacro
  293. /////////////////////////////////////////////////////////////////////
  294. //
  295. // NilTest return-type
  296. //
  297. // Takes: $0 = NORMAL or FPRET or STRET
  298. // eax = receiver
  299. //
  300. // On exit: Loads non-nil receiver in eax and self(esp) or self_stret(esp),
  301. // or returns zero.
  302. //
  303. // NilTestReturnZero return-type
  304. //
  305. // Takes: $0 = NORMAL or FPRET or STRET
  306. // eax = receiver
  307. //
  308. // On exit: Loads non-nil receiver in eax and self(esp) or self_stret(esp),
  309. // or returns zero.
  310. //
  311. // NilTestReturnIMP return-type
  312. //
  313. // Takes: $0 = NORMAL or FPRET or STRET
  314. // eax = receiver
  315. //
  316. // On exit: Loads non-nil receiver in eax and self(esp) or self_stret(esp),
  317. // or returns an IMP in eax that returns zero.
  318. //
  319. /////////////////////////////////////////////////////////////////////
  320. .macro ZeroReturn
  321. xorl %eax, %eax
  322. xorl %edx, %edx
  323. xorps %xmm0, %xmm0
  324. xorps %xmm1, %xmm1
  325. .endmacro
  326. .macro ZeroReturnFPRET
  327. fldz
  328. .endmacro
  329. .macro ZeroReturnSTRET
  330. // empty
  331. .endmacro
  332. STATIC_ENTRY __objc_msgNil
  333. ZeroReturn
  334. ret
  335. END_ENTRY __objc_msgNil
  336. STATIC_ENTRY __objc_msgNil_fpret
  337. ZeroReturnFPRET
  338. ret
  339. END_ENTRY __objc_msgNil_fpret
  340. STATIC_ENTRY __objc_msgNil_stret
  341. ZeroReturnSTRET
  342. ret $4
  343. END_ENTRY __objc_msgNil_stret
  344. .macro NilTest
  345. testl %eax, %eax
  346. jz LNilTestSlow_f
  347. LNilTestDone:
  348. .endmacro
  349. .macro NilTestReturnZero
  350. .align 3
  351. LNilTestSlow:
  352. .if $0 == NORMAL
  353. ZeroReturn
  354. ret
  355. .elseif $0 == FPRET
  356. ZeroReturnFPRET
  357. ret
  358. .elseif $0 == STRET
  359. ZeroReturnSTRET
  360. ret $$4
  361. .else
  362. .abort oops
  363. .endif
  364. .endmacro
  365. .macro NilTestReturnIMP
  366. .align 3
  367. LNilTestSlow:
  368. call 1f
  369. 1: pop %eax
  370. .if $0 == NORMAL
  371. leal __objc_msgNil-1b(%eax), %eax
  372. .elseif $0 == FPRET
  373. leal __objc_msgNil_fpret-1b(%eax), %eax
  374. .elseif $0 == STRET
  375. leal __objc_msgNil_stret-1b(%eax), %eax
  376. .else
  377. .abort oops
  378. .endif
  379. ret
  380. .endmacro
  381. /********************************************************************
  382. * IMP _cache_getImp(Class cls, SEL sel)
  383. *
  384. * If found, returns method implementation.
  385. * If not found, returns NULL.
  386. ********************************************************************/
  387. STATIC_ENTRY _cache_getImp
  388. // load the class and selector
  389. movl selector(%esp), %ecx
  390. movl self(%esp), %edx
  391. CacheLookup NORMAL, GETIMP // returns IMP on success
  392. LCacheMiss:
  393. // cache miss, return nil
  394. xorl %eax, %eax
  395. ret
  396. END_ENTRY _cache_getImp
  397. /********************************************************************
  398. *
  399. * id objc_msgSend(id self, SEL _cmd, ...);
  400. * IMP objc_msgLookup(id self, SEL _cmd, ...);
  401. *
  402. * objc_msgLookup ABI:
  403. * IMP returned in eax
  404. * Forwarding returned in Z flag
  405. * edx reserved for our use but not used
  406. *
  407. ********************************************************************/
  408. ENTRY _objc_msgSend
  409. UNWIND _objc_msgSend, NoFrame
  410. movl selector(%esp), %ecx
  411. movl self(%esp), %eax
  412. NilTest NORMAL
  413. movl isa(%eax), %edx // class = self->isa
  414. CacheLookup NORMAL, CALL // calls IMP on success
  415. NilTestReturnZero NORMAL
  416. LCacheMiss:
  417. // isa still in edx
  418. jmp __objc_msgSend_uncached
  419. END_ENTRY _objc_msgSend
  420. ENTRY _objc_msgLookup
  421. UNWIND _objc_msgLookup, NoFrame
  422. movl selector(%esp), %ecx
  423. movl self(%esp), %eax
  424. NilTest NORMAL
  425. movl isa(%eax), %edx // class = self->isa
  426. CacheLookup NORMAL, LOOKUP // returns IMP on success
  427. NilTestReturnIMP NORMAL
  428. LCacheMiss:
  429. // isa still in edx
  430. jmp __objc_msgLookup_uncached
  431. END_ENTRY _objc_msgLookup
  432. /********************************************************************
  433. *
  434. * id objc_msgSendSuper(struct objc_super *super, SEL _cmd, ...);
  435. *
  436. ********************************************************************/
  437. ENTRY _objc_msgSendSuper
  438. UNWIND _objc_msgSendSuper, NoFrame
  439. movl selector(%esp), %ecx
  440. movl super(%esp), %eax // struct objc_super
  441. movl class(%eax), %edx // struct objc_super->class
  442. movl receiver(%eax), %eax // struct objc_super->receiver
  443. movl %eax, super(%esp) // replace super arg with receiver
  444. CacheLookup NORMAL, CALL // calls IMP on success
  445. LCacheMiss:
  446. // class still in edx
  447. jmp __objc_msgSend_uncached
  448. END_ENTRY _objc_msgSendSuper
  449. /********************************************************************
  450. *
  451. * id objc_msgSendSuper2(struct objc_super *super, SEL _cmd, ...);
  452. * IMP objc_msgLookupSuper2(struct objc_super *super, SEL _cmd, ...);
  453. *
  454. ********************************************************************/
  455. ENTRY _objc_msgSendSuper2
  456. UNWIND _objc_msgSendSuper2, NoFrame
  457. movl selector(%esp), %ecx
  458. movl super(%esp), %eax // struct objc_super
  459. movl class(%eax), %edx // struct objc_super->class
  460. movl receiver(%eax), %eax // struct objc_super->receiver
  461. movl %eax, super(%esp) // replace super arg with receiver
  462. movl superclass(%edx), %edx // edx = objc_super->class->super_class
  463. CacheLookup NORMAL, CALL // calls IMP on success
  464. LCacheMiss:
  465. // class still in edx
  466. jmp __objc_msgSend_uncached
  467. END_ENTRY _objc_msgSendSuper2
  468. ENTRY _objc_msgLookupSuper2
  469. UNWIND _objc_msgLookupSuper2, NoFrame
  470. movl selector(%esp), %ecx
  471. movl super(%esp), %eax // struct objc_super
  472. movl class(%eax), %edx // struct objc_super->class
  473. movl receiver(%eax), %eax // struct objc_super->receiver
  474. movl %eax, super(%esp) // replace super arg with receiver
  475. movl superclass(%edx), %edx // edx = objc_super->class->super_class
  476. CacheLookup NORMAL, LOOKUP // returns IMP on success
  477. LCacheMiss:
  478. // class still in edx
  479. jmp __objc_msgLookup_uncached
  480. END_ENTRY _objc_msgLookupSuper2
  481. /********************************************************************
  482. *
  483. * double objc_msgSend_fpret(id self, SEL _cmd, ...);
  484. * IMP objc_msgLookup_fpret(id self, SEL _cmd, ...);
  485. *
  486. ********************************************************************/
  487. ENTRY _objc_msgSend_fpret
  488. UNWIND _objc_msgSend_fpret, NoFrame
  489. movl selector(%esp), %ecx
  490. movl self(%esp), %eax
  491. NilTest FPRET
  492. movl isa(%eax), %edx // class = self->isa
  493. CacheLookup FPRET, CALL // calls IMP on success
  494. NilTestReturnZero FPRET
  495. LCacheMiss:
  496. // class still in edx
  497. jmp __objc_msgSend_uncached
  498. END_ENTRY _objc_msgSend_fpret
  499. ENTRY _objc_msgLookup_fpret
  500. UNWIND _objc_msgLookup_fpret, NoFrame
  501. movl selector(%esp), %ecx
  502. movl self(%esp), %eax
  503. NilTest FPRET
  504. movl isa(%eax), %edx // class = self->isa
  505. CacheLookup FPRET, LOOKUP // returns IMP on success
  506. NilTestReturnIMP FPRET
  507. LCacheMiss:
  508. // class still in edx
  509. jmp __objc_msgLookup_uncached
  510. END_ENTRY _objc_msgLookup_fpret
  511. /********************************************************************
  512. *
  513. * void objc_msgSend_stret(void *st_addr, id self, SEL _cmd, ...);
  514. * IMP objc_msgLookup_stret(void *st_addr, id self, SEL _cmd, ...);
  515. *
  516. ********************************************************************/
  517. ENTRY _objc_msgSend_stret
  518. UNWIND _objc_msgSend_stret, NoFrame
  519. movl selector_stret(%esp), %ecx
  520. movl self_stret(%esp), %eax
  521. NilTest STRET
  522. movl isa(%eax), %edx // class = self->isa
  523. CacheLookup STRET, CALL // calls IMP on success
  524. NilTestReturnZero STRET
  525. LCacheMiss:
  526. // class still in edx
  527. jmp __objc_msgSend_stret_uncached
  528. END_ENTRY _objc_msgSend_stret
  529. ENTRY _objc_msgLookup_stret
  530. UNWIND _objc_msgLookup_stret, NoFrame
  531. movl selector_stret(%esp), %ecx
  532. movl self_stret(%esp), %eax
  533. NilTest STRET
  534. movl isa(%eax), %edx // class = self->isa
  535. CacheLookup STRET, LOOKUP // returns IMP on success
  536. NilTestReturnIMP STRET
  537. LCacheMiss:
  538. // class still in edx
  539. jmp __objc_msgLookup_stret_uncached
  540. END_ENTRY _objc_msgLookup_stret
  541. /********************************************************************
  542. *
  543. * void objc_msgSendSuper_stret(void *st_addr, struct objc_super *super, SEL _cmd, ...);
  544. *
  545. ********************************************************************/
  546. ENTRY _objc_msgSendSuper_stret
  547. UNWIND _objc_msgSendSuper_stret, NoFrame
  548. movl selector_stret(%esp), %ecx
  549. movl super_stret(%esp), %eax // struct objc_super
  550. movl class(%eax), %edx // struct objc_super->class
  551. movl receiver(%eax), %eax // struct objc_super->receiver
  552. movl %eax, super_stret(%esp) // replace super arg with receiver
  553. CacheLookup STRET, CALL // calls IMP on success
  554. LCacheMiss:
  555. // class still in edx
  556. jmp __objc_msgSend_stret_uncached
  557. END_ENTRY _objc_msgSendSuper_stret
  558. /********************************************************************
  559. *
  560. * void objc_msgSendSuper2_stret(void *st_addr, struct objc_super *super, SEL _cmd, ...);
  561. * IMP objc_msgLookupSuper2_stret(void *st_addr, struct objc_super *super, SEL _cmd, ...);
  562. *
  563. ********************************************************************/
  564. ENTRY _objc_msgSendSuper2_stret
  565. UNWIND _objc_msgSendSuper2_stret, NoFrame
  566. movl selector_stret(%esp), %ecx
  567. movl super_stret(%esp), %eax // struct objc_super
  568. movl class(%eax), %edx // struct objc_super->class
  569. movl receiver(%eax), %eax // struct objc_super->receiver
  570. movl %eax, super_stret(%esp) // replace super arg with receiver
  571. mov superclass(%edx), %edx // edx = objc_super->class->super_class
  572. CacheLookup STRET, CALL // calls IMP on success
  573. // cache miss: go search the method lists
  574. LCacheMiss:
  575. // class still in edx
  576. jmp __objc_msgSend_stret_uncached
  577. END_ENTRY _objc_msgSendSuper2_stret
  578. ENTRY _objc_msgLookupSuper2_stret
  579. UNWIND _objc_msgLookupSuper2_stret, NoFrame
  580. movl selector_stret(%esp), %ecx
  581. movl super_stret(%esp), %eax // struct objc_super
  582. movl class(%eax), %edx // struct objc_super->class
  583. movl receiver(%eax), %eax // struct objc_super->receiver
  584. movl %eax, super_stret(%esp) // replace super arg with receiver
  585. mov superclass(%edx), %edx // edx = objc_super->class->super_class
  586. CacheLookup STRET, LOOKUP // returns IMP on success
  587. // cache miss: go search the method lists
  588. LCacheMiss:
  589. // class still in edx
  590. jmp __objc_msgLookup_stret_uncached
  591. END_ENTRY _objc_msgLookupSuper2_stret
  592. /********************************************************************
  593. *
  594. * _objc_msgSend_uncached
  595. * _objc_msgSend_stret_uncached
  596. * _objc_msgLookup_uncached
  597. * _objc_msgLookup_stret_uncached
  598. *
  599. * The uncached method lookup.
  600. *
  601. ********************************************************************/
  602. STATIC_ENTRY __objc_msgSend_uncached
  603. UNWIND __objc_msgSend_uncached, FrameWithNoSaves
  604. // THIS IS NOT A CALLABLE C FUNCTION
  605. // Out-of-band edx is the searched class
  606. // edx is already the class to search
  607. MethodTableLookup NORMAL
  608. jmp *%eax // call imp
  609. END_ENTRY __objc_msgSend_uncached
  610. STATIC_ENTRY __objc_msgSend_stret_uncached
  611. UNWIND __objc_msgSend_stret_uncached, FrameWithNoSaves
  612. // THIS IS NOT A CALLABLE C FUNCTION
  613. // Out-of-band edx is the searched class
  614. // edx is already the class to search
  615. MethodTableLookup STRET
  616. jmp *%eax // call imp
  617. END_ENTRY __objc_msgSend_stret_uncached
  618. STATIC_ENTRY __objc_msgLookup_uncached
  619. UNWIND __objc_msgLookup_uncached, FrameWithNoSaves
  620. // THIS IS NOT A CALLABLE C FUNCTION
  621. // Out-of-band edx is the searched class
  622. // edx is already the class to search
  623. MethodTableLookup NORMAL // eax = IMP
  624. ret
  625. END_ENTRY __objc_msgLookup_uncached
  626. STATIC_ENTRY __objc_msgLookup_stret_uncached
  627. UNWIND __objc_msgLookup_stret_uncached, FrameWithNoSaves
  628. // THIS IS NOT A CALLABLE C FUNCTION
  629. // Out-of-band edx is the searched class
  630. // edx is already the class to search
  631. MethodTableLookup STRET // eax = IMP
  632. ret
  633. END_ENTRY __objc_msgLookup_stret_uncached
  634. /********************************************************************
  635. *
  636. * id _objc_msgForward(id self, SEL _cmd,...);
  637. *
  638. * _objc_msgForward and _objc_msgForward_stret are the externally-callable
  639. * functions returned by things like method_getImplementation().
  640. * _objc_msgForward_impcache is the function pointer actually stored in
  641. * method caches.
  642. *
  643. ********************************************************************/
  644. .non_lazy_symbol_pointer
  645. L_forward_handler:
  646. .indirect_symbol __objc_forward_handler
  647. .long 0
  648. L_forward_stret_handler:
  649. .indirect_symbol __objc_forward_stret_handler
  650. .long 0
  651. STATIC_ENTRY __objc_msgForward_impcache
  652. // Method cache version
  653. // THIS IS NOT A CALLABLE C FUNCTION
  654. // Out-of-band condition register is NE for stret, EQ otherwise.
  655. je __objc_msgForward_stret
  656. jmp __objc_msgForward
  657. END_ENTRY _objc_msgForward_impcache
  658. ENTRY __objc_msgForward
  659. // Non-struct return version
  660. call 1f
  661. 1: popl %edx
  662. movl L_forward_handler-1b(%edx), %edx
  663. jmp *(%edx)
  664. END_ENTRY __objc_msgForward
  665. ENTRY __objc_msgForward_stret
  666. // Struct return version
  667. call 1f
  668. 1: popl %edx
  669. movl L_forward_stret_handler-1b(%edx), %edx
  670. jmp *(%edx)
  671. END_ENTRY __objc_msgForward_stret
  672. ENTRY _objc_msgSend_debug
  673. jmp _objc_msgSend
  674. END_ENTRY _objc_msgSend_debug
  675. ENTRY _objc_msgSendSuper2_debug
  676. jmp _objc_msgSendSuper2
  677. END_ENTRY _objc_msgSendSuper2_debug
  678. ENTRY _objc_msgSend_stret_debug
  679. jmp _objc_msgSend_stret
  680. END_ENTRY _objc_msgSend_stret_debug
  681. ENTRY _objc_msgSendSuper2_stret_debug
  682. jmp _objc_msgSendSuper2_stret
  683. END_ENTRY _objc_msgSendSuper2_stret_debug
  684. ENTRY _objc_msgSend_fpret_debug
  685. jmp _objc_msgSend_fpret
  686. END_ENTRY _objc_msgSend_fpret_debug
  687. ENTRY _objc_msgSend_noarg
  688. jmp _objc_msgSend
  689. END_ENTRY _objc_msgSend_noarg
  690. ENTRY _method_invoke
  691. movl selector(%esp), %ecx
  692. movl method_name(%ecx), %edx
  693. movl method_imp(%ecx), %eax
  694. movl %edx, selector(%esp)
  695. jmp *%eax
  696. END_ENTRY _method_invoke
  697. ENTRY _method_invoke_stret
  698. movl selector_stret(%esp), %ecx
  699. movl method_name(%ecx), %edx
  700. movl method_imp(%ecx), %eax
  701. movl %edx, selector_stret(%esp)
  702. jmp *%eax
  703. END_ENTRY _method_invoke_stret
  704. .section __DATA,__objc_msg_break
  705. .long 0
  706. .long 0
  707. #endif