objc-msg-i386.s 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087
  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 defined(__i386__) && !TARGET_OS_SIMULATOR
  25. /********************************************************************
  26. ********************************************************************
  27. **
  28. ** objc-msg-i386.s - i386 code to support objc messaging.
  29. **
  30. ********************************************************************
  31. ********************************************************************/
  32. /********************************************************************
  33. * Data used by the ObjC runtime.
  34. *
  35. ********************************************************************/
  36. .data
  37. // _objc_restartableRanges is used by method dispatch
  38. // to get the critical regions for which method caches
  39. // cannot be garbage collected.
  40. .macro RestartableEntry
  41. .long $0
  42. .long 0
  43. .short $1 - $0
  44. .short 0xffff // The old runtime doesn't support kernel based recovery
  45. .long 0
  46. .endmacro
  47. .align 4
  48. .private_extern _objc_restartableRanges
  49. _objc_restartableRanges:
  50. RestartableEntry __cache_getImp, LGetImpExit
  51. RestartableEntry __cache_getMethod, LGetMethodExit
  52. RestartableEntry _objc_msgSend, LMsgSendExit
  53. RestartableEntry _objc_msgSend_fpret, LMsgSendFpretExit
  54. RestartableEntry _objc_msgSend_stret, LMsgSendStretExit
  55. RestartableEntry _objc_msgSendSuper, LMsgSendSuperExit
  56. RestartableEntry _objc_msgSendSuper_stret, LMsgSendSuperStretExit
  57. .fill 16, 1, 0
  58. /********************************************************************
  59. *
  60. * Common offsets.
  61. *
  62. ********************************************************************/
  63. self = 4
  64. super = 4
  65. selector = 8
  66. marg_size = 12
  67. marg_list = 16
  68. first_arg = 12
  69. struct_addr = 4
  70. self_stret = 8
  71. super_stret = 8
  72. selector_stret = 12
  73. marg_size_stret = 16
  74. marg_list_stret = 20
  75. /********************************************************************
  76. *
  77. * Structure definitions.
  78. *
  79. ********************************************************************/
  80. // objc_super parameter to sendSuper
  81. receiver = 0
  82. class = 4
  83. // Selected field offsets in class structure
  84. isa = 0
  85. cache = 32
  86. // Method descriptor
  87. method_name = 0
  88. method_imp = 8
  89. // Cache header
  90. mask = 0
  91. occupied = 4
  92. buckets = 8 // variable length array
  93. #if defined(OBJC_INSTRUMENTED)
  94. // Cache instrumentation data, follows buckets
  95. hitCount = 0
  96. hitProbes = hitCount + 4
  97. maxHitProbes = hitProbes + 4
  98. missCount = maxHitProbes + 4
  99. missProbes = missCount + 4
  100. maxMissProbes = missProbes + 4
  101. flushCount = maxMissProbes + 4
  102. flushedEntries = flushCount + 4
  103. // Buckets in CacheHitHistogram and CacheMissHistogram
  104. CACHE_HISTOGRAM_SIZE = 512
  105. #endif
  106. //////////////////////////////////////////////////////////////////////
  107. //
  108. // ENTRY functionName
  109. //
  110. // Assembly directives to begin an exported function.
  111. //
  112. // Takes: functionName - name of the exported function
  113. //////////////////////////////////////////////////////////////////////
  114. .macro ENTRY
  115. .text
  116. .globl $0
  117. .align 4, 0x90
  118. $0:
  119. .endmacro
  120. .macro STATIC_ENTRY
  121. .text
  122. .private_extern $0
  123. .align 4, 0x90
  124. $0:
  125. .endmacro
  126. //////////////////////////////////////////////////////////////////////
  127. //
  128. // END_ENTRY functionName
  129. //
  130. // Assembly directives to end an exported function. Just a placeholder,
  131. // a close-parenthesis for ENTRY, until it is needed for something.
  132. //
  133. // Takes: functionName - name of the exported function
  134. //////////////////////////////////////////////////////////////////////
  135. .macro END_ENTRY
  136. .endmacro
  137. //////////////////////////////////////////////////////////////////////
  138. //
  139. // CALL_MCOUNTER
  140. //
  141. // Calls mcount() profiling routine. Must be called immediately on
  142. // function entry, before any prologue executes.
  143. //
  144. //////////////////////////////////////////////////////////////////////
  145. .macro CALL_MCOUNTER
  146. #ifdef PROFILE
  147. // Current stack contents: ret
  148. pushl %ebp
  149. movl %esp,%ebp
  150. subl $$8,%esp
  151. // Current stack contents: ret, ebp, pad, pad
  152. call mcount
  153. movl %ebp,%esp
  154. popl %ebp
  155. #endif
  156. .endmacro
  157. /////////////////////////////////////////////////////////////////////
  158. //
  159. //
  160. // CacheLookup WORD_RETURN | STRUCT_RETURN, MSG_SEND | MSG_SENDSUPER | CACHE_GET, cacheMissLabel
  161. //
  162. // Locate the implementation for a selector in a class method cache.
  163. //
  164. // Takes: WORD_RETURN (first parameter is at sp+4)
  165. // STRUCT_RETURN (struct address is at sp+4, first parameter at sp+8)
  166. // MSG_SEND (first parameter is receiver)
  167. // MSG_SENDSUPER (first parameter is address of objc_super structure)
  168. // CACHE_GET (first parameter is class; return method triplet)
  169. // selector in %ecx
  170. // class to search in %edx
  171. //
  172. // cacheMissLabel = label to branch to iff method is not cached
  173. //
  174. // On exit: (found) MSG_SEND and MSG_SENDSUPER: return imp in eax
  175. // (found) CACHE_GET: return method triplet in eax
  176. // (not found) jumps to cacheMissLabel
  177. //
  178. /////////////////////////////////////////////////////////////////////
  179. // Values to specify to method lookup macros whether the return type of
  180. // the method is word or structure.
  181. WORD_RETURN = 0
  182. STRUCT_RETURN = 1
  183. // Values to specify to method lookup macros whether the first argument
  184. // is an object/class reference or a 'objc_super' structure.
  185. MSG_SEND = 0 // first argument is receiver, search the isa
  186. MSG_SENDSUPER = 1 // first argument is objc_super, search the class
  187. CACHE_GET = 2 // first argument is class, search that class
  188. .macro CacheLookup
  189. // load variables and save caller registers.
  190. pushl %edi // save scratch register
  191. movl cache(%edx), %edi // cache = class->cache
  192. pushl %esi // save scratch register
  193. #if defined(OBJC_INSTRUMENTED)
  194. pushl %ebx // save non-volatile register
  195. pushl %eax // save cache pointer
  196. xorl %ebx, %ebx // probeCount = 0
  197. #endif
  198. movl mask(%edi), %esi // mask = cache->mask
  199. movl %ecx, %edx // index = selector
  200. shrl $$2, %edx // index = selector >> 2
  201. // search the receiver's cache
  202. // ecx = selector
  203. // edi = cache
  204. // esi = mask
  205. // edx = index
  206. // eax = method (soon)
  207. LMsgSendProbeCache_$0_$1_$2:
  208. #if defined(OBJC_INSTRUMENTED)
  209. addl $$1, %ebx // probeCount += 1
  210. #endif
  211. andl %esi, %edx // index &= mask
  212. movl buckets(%edi, %edx, 4), %eax // meth = cache->buckets[index]
  213. testl %eax, %eax // check for end of bucket
  214. je LMsgSendCacheMiss_$0_$1_$2 // go to cache miss code
  215. cmpl method_name(%eax), %ecx // check for method name match
  216. je LMsgSendCacheHit_$0_$1_$2 // go handle cache hit
  217. addl $$1, %edx // bump index ...
  218. jmp LMsgSendProbeCache_$0_$1_$2 // ... and loop
  219. // not found in cache: restore state and go to callers handler
  220. LMsgSendCacheMiss_$0_$1_$2:
  221. #if defined(OBJC_INSTRUMENTED)
  222. popl %edx // retrieve cache pointer
  223. movl mask(%edx), %esi // mask = cache->mask
  224. testl %esi, %esi // a mask of zero is only for the...
  225. je LMsgSendMissInstrumentDone_$0_$1_$2 // ... emptyCache, do not record anything
  226. // locate and update the CacheInstrumentation structure
  227. addl $$1, %esi // entryCount = mask + 1
  228. shll $$2, %esi // tableSize = entryCount * sizeof(entry)
  229. addl $buckets, %esi // offset = buckets + tableSize
  230. addl %edx, %esi // cacheData = &cache->buckets[mask+1]
  231. movl missCount(%esi), %edi //
  232. addl $$1, %edi //
  233. movl %edi, missCount(%esi) // cacheData->missCount += 1
  234. movl missProbes(%esi), %edi //
  235. addl %ebx, %edi //
  236. movl %edi, missProbes(%esi) // cacheData->missProbes += probeCount
  237. movl maxMissProbes(%esi), %edi// if (cacheData->maxMissProbes < probeCount)
  238. cmpl %ebx, %edi //
  239. jge LMsgSendMaxMissProbeOK_$0_$1_$2 //
  240. movl %ebx, maxMissProbes(%esi)// cacheData->maxMissProbes = probeCount
  241. LMsgSendMaxMissProbeOK_$0_$1_$2:
  242. // update cache miss probe histogram
  243. cmpl $CACHE_HISTOGRAM_SIZE, %ebx // pin probeCount to max index
  244. jl LMsgSendMissHistoIndexSet_$0_$1_$2
  245. movl $(CACHE_HISTOGRAM_SIZE-1), %ebx
  246. LMsgSendMissHistoIndexSet_$0_$1_$2:
  247. LEA_STATIC_DATA %esi, _CacheMissHistogram, EXTERNAL_SYMBOL
  248. shll $$2, %ebx // convert probeCount to histogram index
  249. addl %ebx, %esi // calculate &CacheMissHistogram[probeCount<<2]
  250. movl 0(%esi), %edi // get current tally
  251. addl $$1, %edi //
  252. movl %edi, 0(%esi) // tally += 1
  253. LMsgSendMissInstrumentDone_$0_$1_$2:
  254. popl %ebx // restore non-volatile register
  255. #endif
  256. .if $0 == WORD_RETURN // Regular word return
  257. .if $1 == MSG_SEND // MSG_SEND
  258. popl %esi // restore callers register
  259. popl %edi // restore callers register
  260. movl self(%esp), %edx // get messaged object
  261. movl isa(%edx), %eax // get objects class
  262. .elseif $1 == MSG_SENDSUPER // MSG_SENDSUPER
  263. // replace "super" arg with "receiver"
  264. movl super+8(%esp), %edi // get super structure
  265. movl receiver(%edi), %edx // get messaged object
  266. movl %edx, super+8(%esp) // make it the first argument
  267. movl class(%edi), %eax // get messaged class
  268. popl %esi // restore callers register
  269. popl %edi // restore callers register
  270. .else // CACHE_GET
  271. popl %esi // restore callers register
  272. popl %edi // restore callers register
  273. .endif
  274. .else // Struct return
  275. .if $1 == MSG_SEND // MSG_SEND (stret)
  276. popl %esi // restore callers register
  277. popl %edi // restore callers register
  278. movl self_stret(%esp), %edx // get messaged object
  279. movl isa(%edx), %eax // get objects class
  280. .elseif $1 == MSG_SENDSUPER // MSG_SENDSUPER (stret)
  281. // replace "super" arg with "receiver"
  282. movl super_stret+8(%esp), %edi// get super structure
  283. movl receiver(%edi), %edx // get messaged object
  284. movl %edx, super_stret+8(%esp)// make it the first argument
  285. movl class(%edi), %eax // get messaged class
  286. popl %esi // restore callers register
  287. popl %edi // restore callers register
  288. .else // CACHE_GET
  289. !! This should not happen.
  290. .endif
  291. .endif
  292. // edx = receiver
  293. // ecx = selector
  294. // eax = class
  295. jmp $2 // go to callers handler
  296. // eax points to matching cache entry
  297. .align 4, 0x90
  298. LMsgSendCacheHit_$0_$1_$2:
  299. #if defined(OBJC_INSTRUMENTED)
  300. popl %edx // retrieve cache pointer
  301. movl mask(%edx), %esi // mask = cache->mask
  302. testl %esi, %esi // a mask of zero is only for the...
  303. je LMsgSendHitInstrumentDone_$0_$1_$2 // ... emptyCache, do not record anything
  304. // locate and update the CacheInstrumentation structure
  305. addl $$1, %esi // entryCount = mask + 1
  306. shll $$2, %esi // tableSize = entryCount * sizeof(entry)
  307. addl $buckets, %esi // offset = buckets + tableSize
  308. addl %edx, %esi // cacheData = &cache->buckets[mask+1]
  309. movl hitCount(%esi), %edi
  310. addl $$1, %edi
  311. movl %edi, hitCount(%esi) // cacheData->hitCount += 1
  312. movl hitProbes(%esi), %edi
  313. addl %ebx, %edi
  314. movl %edi, hitProbes(%esi) // cacheData->hitProbes += probeCount
  315. movl maxHitProbes(%esi), %edi// if (cacheData->maxHitProbes < probeCount)
  316. cmpl %ebx, %edi
  317. jge LMsgSendMaxHitProbeOK_$0_$1_$2
  318. movl %ebx, maxHitProbes(%esi)// cacheData->maxHitProbes = probeCount
  319. LMsgSendMaxHitProbeOK_$0_$1_$2:
  320. // update cache hit probe histogram
  321. cmpl $CACHE_HISTOGRAM_SIZE, %ebx // pin probeCount to max index
  322. jl LMsgSendHitHistoIndexSet_$0_$1_$2
  323. movl $(CACHE_HISTOGRAM_SIZE-1), %ebx
  324. LMsgSendHitHistoIndexSet_$0_$1_$2:
  325. LEA_STATIC_DATA %esi, _CacheHitHistogram, EXTERNAL_SYMBOL
  326. shll $$2, %ebx // convert probeCount to histogram index
  327. addl %ebx, %esi // calculate &CacheHitHistogram[probeCount<<2]
  328. movl 0(%esi), %edi // get current tally
  329. addl $$1, %edi //
  330. movl %edi, 0(%esi) // tally += 1
  331. LMsgSendHitInstrumentDone_$0_$1_$2:
  332. popl %ebx // restore non-volatile register
  333. #endif
  334. // load implementation address, restore state, and we're done
  335. .if $1 == CACHE_GET
  336. // method triplet is already in eax
  337. .else
  338. movl method_imp(%eax), %eax // imp = method->method_imp
  339. .endif
  340. .if $0 == WORD_RETURN // Regular word return
  341. .if $1 == MSG_SENDSUPER // MSG_SENDSUPER
  342. // replace "super" arg with "self"
  343. movl super+8(%esp), %edi
  344. movl receiver(%edi), %esi
  345. movl %esi, super+8(%esp)
  346. .endif
  347. .else // Struct return
  348. .if $1 == MSG_SENDSUPER // MSG_SENDSUPER (stret)
  349. // replace "super" arg with "self"
  350. movl super_stret+8(%esp), %edi
  351. movl receiver(%edi), %esi
  352. movl %esi, super_stret+8(%esp)
  353. .endif
  354. .endif
  355. // restore caller registers
  356. popl %esi
  357. popl %edi
  358. .endmacro
  359. /////////////////////////////////////////////////////////////////////
  360. //
  361. // MethodTableLookup WORD_RETURN | STRUCT_RETURN, MSG_SEND | MSG_SENDSUPER
  362. //
  363. // Takes: WORD_RETURN (first parameter is at sp+4)
  364. // STRUCT_RETURN (struct address is at sp+4, first parameter at sp+8)
  365. // MSG_SEND (first parameter is receiver)
  366. // MSG_SENDSUPER (first parameter is address of objc_super structure)
  367. //
  368. // edx = receiver
  369. // ecx = selector
  370. // eax = class
  371. // (all set by CacheLookup's miss case)
  372. //
  373. // Stack must be at 0xXXXXXXXc on entrance.
  374. //
  375. // On exit: esp unchanged
  376. // imp in eax
  377. //
  378. /////////////////////////////////////////////////////////////////////
  379. .macro MethodTableLookup
  380. // stack has return address and nothing else
  381. subl $$(12+5*16), %esp
  382. movdqa %xmm3, 4*16(%esp)
  383. movdqa %xmm2, 3*16(%esp)
  384. movdqa %xmm1, 2*16(%esp)
  385. movdqa %xmm0, 1*16(%esp)
  386. // lookUpImpOrForward(obj, sel, cls, LOOKUP_INITIALIZE | LOOKUP_RESOLVER)
  387. movl $$3, 12(%esp) // LOOKUP_INITIALIZE | LOOKUP_RESOLVER
  388. movl %eax, 8(%esp) // class
  389. movl %ecx, 4(%esp) // selector
  390. movl %edx, 0(%esp) // receiver
  391. call _lookUpImpOrForward
  392. movdqa 4*16(%esp), %xmm3
  393. movdqa 3*16(%esp), %xmm2
  394. movdqa 2*16(%esp), %xmm1
  395. movdqa 1*16(%esp), %xmm0
  396. addl $$(12+5*16), %esp // pop parameters
  397. .endmacro
  398. /********************************************************************
  399. * Method _cache_getMethod(Class cls, SEL sel, IMP msgForward_internal_imp)
  400. *
  401. * If found, returns method triplet pointer.
  402. * If not found, returns NULL.
  403. *
  404. * NOTE: _cache_getMethod never returns any cache entry whose implementation
  405. * is _objc_msgForward_impcache. It returns 1 instead. This prevents thread-
  406. * safety and memory management bugs in _class_lookupMethodAndLoadCache.
  407. * See _class_lookupMethodAndLoadCache for details.
  408. *
  409. * _objc_msgForward_impcache is passed as a parameter because it's more
  410. * efficient to do the (PIC) lookup once in the caller than repeatedly here.
  411. ********************************************************************/
  412. STATIC_ENTRY __cache_getMethod
  413. // load the class and selector
  414. movl selector(%esp), %ecx
  415. movl self(%esp), %edx
  416. // do lookup
  417. CacheLookup WORD_RETURN, CACHE_GET, LGetMethodMiss
  418. // cache hit, method triplet in %eax
  419. movl first_arg(%esp), %ecx // check for _objc_msgForward_impcache
  420. cmpl method_imp(%eax), %ecx // if (imp==_objc_msgForward_impcache)
  421. je 1f // return (Method)1
  422. ret // else return method triplet address
  423. 1: movl $1, %eax
  424. ret
  425. LGetMethodMiss:
  426. // cache miss, return nil
  427. xorl %eax, %eax // zero %eax
  428. ret
  429. LGetMethodExit:
  430. END_ENTRY __cache_getMethod
  431. /********************************************************************
  432. * IMP _cache_getImp(Class cls, SEL sel)
  433. *
  434. * If found, returns method implementation.
  435. * If not found, returns NULL.
  436. ********************************************************************/
  437. STATIC_ENTRY __cache_getImp
  438. // load the class and selector
  439. movl selector(%esp), %ecx
  440. movl self(%esp), %edx
  441. // do lookup
  442. CacheLookup WORD_RETURN, CACHE_GET, LGetImpMiss
  443. // cache hit, method triplet in %eax
  444. movl method_imp(%eax), %eax // return method imp
  445. ret
  446. LGetImpMiss:
  447. // cache miss, return nil
  448. xorl %eax, %eax // zero %eax
  449. ret
  450. LGetImpExit:
  451. END_ENTRY __cache_getImp
  452. /********************************************************************
  453. *
  454. * id objc_msgSend(id self, SEL _cmd,...);
  455. *
  456. ********************************************************************/
  457. ENTRY _objc_msgSend
  458. CALL_MCOUNTER
  459. // load receiver and selector
  460. movl selector(%esp), %ecx
  461. movl self(%esp), %eax
  462. // check whether receiver is nil
  463. testl %eax, %eax
  464. je LMsgSendNilSelf
  465. // receiver (in %eax) is non-nil: search the cache
  466. LMsgSendReceiverOk:
  467. movl isa(%eax), %edx // class = self->isa
  468. CacheLookup WORD_RETURN, MSG_SEND, LMsgSendCacheMiss
  469. xor %edx, %edx // set nonstret for msgForward_internal
  470. jmp *%eax
  471. // cache miss: go search the method lists
  472. LMsgSendCacheMiss:
  473. MethodTableLookup WORD_RETURN, MSG_SEND
  474. xor %edx, %edx // set nonstret for msgForward_internal
  475. jmp *%eax // goto *imp
  476. // message sent to nil: redirect to nil receiver, if any
  477. LMsgSendNilSelf:
  478. // %eax is already zero
  479. movl $0,%edx
  480. xorps %xmm0, %xmm0
  481. LMsgSendDone:
  482. ret
  483. // guaranteed non-nil entry point (disabled for now)
  484. // .globl _objc_msgSendNonNil
  485. // _objc_msgSendNonNil:
  486. // movl self(%esp), %eax
  487. // jmp LMsgSendReceiverOk
  488. LMsgSendExit:
  489. END_ENTRY _objc_msgSend
  490. /********************************************************************
  491. *
  492. * id objc_msgSendSuper(struct objc_super *super, SEL _cmd,...);
  493. *
  494. * struct objc_super {
  495. * id receiver;
  496. * Class class;
  497. * };
  498. ********************************************************************/
  499. ENTRY _objc_msgSendSuper
  500. CALL_MCOUNTER
  501. // load selector and class to search
  502. movl super(%esp), %eax // struct objc_super
  503. movl selector(%esp), %ecx
  504. movl class(%eax), %edx // struct objc_super->class
  505. // search the cache (class in %edx)
  506. CacheLookup WORD_RETURN, MSG_SENDSUPER, LMsgSendSuperCacheMiss
  507. xor %edx, %edx // set nonstret for msgForward_internal
  508. jmp *%eax // goto *imp
  509. // cache miss: go search the method lists
  510. LMsgSendSuperCacheMiss:
  511. MethodTableLookup WORD_RETURN, MSG_SENDSUPER
  512. xor %edx, %edx // set nonstret for msgForward_internal
  513. jmp *%eax // goto *imp
  514. // ignored selector: return self
  515. LMsgSendSuperIgnored:
  516. movl super(%esp), %eax
  517. movl receiver(%eax), %eax
  518. ret
  519. LMsgSendSuperExit:
  520. END_ENTRY _objc_msgSendSuper
  521. /********************************************************************
  522. * id objc_msgSendv(id self, SEL _cmd, unsigned size, marg_list frame);
  523. *
  524. * On entry:
  525. * (sp+4) is the message receiver,
  526. * (sp+8) is the selector,
  527. * (sp+12) is the size of the marg_list, in bytes,
  528. * (sp+16) is the address of the marg_list
  529. *
  530. ********************************************************************/
  531. ENTRY _objc_msgSendv
  532. #if defined(KERNEL)
  533. trap // _objc_msgSendv is not for the kernel
  534. #else
  535. pushl %ebp
  536. movl %esp, %ebp
  537. // stack is currently aligned assuming no extra arguments
  538. movl (marg_list+4)(%ebp), %edx
  539. addl $8, %edx // skip self & selector
  540. movl (marg_size+4)(%ebp), %ecx
  541. subl $8, %ecx // skip self & selector
  542. shrl $2, %ecx
  543. je LMsgSendvArgsOK
  544. // %esp = %esp - (16 - ((numVariableArguments & 3) << 2))
  545. movl %ecx, %eax // 16-byte align stack
  546. andl $3, %eax
  547. shll $2, %eax
  548. subl $16, %esp
  549. addl %eax, %esp
  550. LMsgSendvArgLoop:
  551. decl %ecx
  552. movl 0(%edx, %ecx, 4), %eax
  553. pushl %eax
  554. jg LMsgSendvArgLoop
  555. LMsgSendvArgsOK:
  556. movl (selector+4)(%ebp), %ecx
  557. pushl %ecx
  558. movl (self+4)(%ebp),%ecx
  559. pushl %ecx
  560. call _objc_msgSend
  561. movl %ebp,%esp
  562. popl %ebp
  563. ret
  564. #endif
  565. END_ENTRY _objc_msgSendv
  566. /********************************************************************
  567. *
  568. * double objc_msgSend_fpret(id self, SEL _cmd,...);
  569. *
  570. ********************************************************************/
  571. ENTRY _objc_msgSend_fpret
  572. CALL_MCOUNTER
  573. // load receiver and selector
  574. movl selector(%esp), %ecx
  575. movl self(%esp), %eax
  576. // check whether receiver is nil
  577. testl %eax, %eax
  578. je LMsgSendFpretNilSelf
  579. // receiver (in %eax) is non-nil: search the cache
  580. LMsgSendFpretReceiverOk:
  581. movl isa(%eax), %edx // class = self->isa
  582. CacheLookup WORD_RETURN, MSG_SEND, LMsgSendFpretCacheMiss
  583. xor %edx, %edx // set nonstret for msgForward_internal
  584. jmp *%eax // goto *imp
  585. // cache miss: go search the method lists
  586. LMsgSendFpretCacheMiss:
  587. MethodTableLookup WORD_RETURN, MSG_SEND
  588. xor %edx, %edx // set nonstret for msgForward_internal
  589. jmp *%eax // goto *imp
  590. // message sent to nil: redirect to nil receiver, if any
  591. LMsgSendFpretNilSelf:
  592. // %eax is already zero
  593. fldz
  594. LMsgSendFpretDone:
  595. ret
  596. LMsgSendFpretExit:
  597. END_ENTRY _objc_msgSend_fpret
  598. /********************************************************************
  599. * double objc_msgSendv_fpret(id self, SEL _cmd, unsigned size, marg_list frame);
  600. *
  601. * On entry:
  602. * (sp+4) is the message receiver,
  603. * (sp+8) is the selector,
  604. * (sp+12) is the size of the marg_list, in bytes,
  605. * (sp+16) is the address of the marg_list
  606. *
  607. ********************************************************************/
  608. ENTRY _objc_msgSendv_fpret
  609. #if defined(KERNEL)
  610. trap // _objc_msgSendv is not for the kernel
  611. #else
  612. pushl %ebp
  613. movl %esp, %ebp
  614. // stack is currently aligned assuming no extra arguments
  615. movl (marg_list+4)(%ebp), %edx
  616. addl $8, %edx // skip self & selector
  617. movl (marg_size+4)(%ebp), %ecx
  618. subl $8, %ecx // skip self & selector
  619. shrl $2, %ecx
  620. je LMsgSendvFpretArgsOK
  621. // %esp = %esp - (16 - ((numVariableArguments & 3) << 2))
  622. movl %ecx, %eax // 16-byte align stack
  623. andl $3, %eax
  624. shll $2, %eax
  625. subl $16, %esp
  626. addl %eax, %esp
  627. LMsgSendvFpretArgLoop:
  628. decl %ecx
  629. movl 0(%edx, %ecx, 4), %eax
  630. pushl %eax
  631. jg LMsgSendvFpretArgLoop
  632. LMsgSendvFpretArgsOK:
  633. movl (selector+4)(%ebp), %ecx
  634. pushl %ecx
  635. movl (self+4)(%ebp),%ecx
  636. pushl %ecx
  637. call _objc_msgSend_fpret
  638. movl %ebp,%esp
  639. popl %ebp
  640. ret
  641. #endif
  642. END_ENTRY _objc_msgSendv_fpret
  643. /********************************************************************
  644. *
  645. * void objc_msgSend_stret(void *st_addr , id self, SEL _cmd, ...);
  646. *
  647. *
  648. * objc_msgSend_stret is the struct-return form of msgSend.
  649. * The ABI calls for (sp+4) to be used as the address of the structure
  650. * being returned, with the parameters in the succeeding locations.
  651. *
  652. * On entry: (sp+4)is the address where the structure is returned,
  653. * (sp+8) is the message receiver,
  654. * (sp+12) is the selector
  655. ********************************************************************/
  656. ENTRY _objc_msgSend_stret
  657. CALL_MCOUNTER
  658. // load receiver and selector
  659. movl self_stret(%esp), %eax
  660. movl (selector_stret)(%esp), %ecx
  661. // check whether receiver is nil
  662. testl %eax, %eax
  663. je LMsgSendStretNilSelf
  664. // receiver (in %eax) is non-nil: search the cache
  665. LMsgSendStretReceiverOk:
  666. movl isa(%eax), %edx // class = self->isa
  667. CacheLookup STRUCT_RETURN, MSG_SEND, LMsgSendStretCacheMiss
  668. movl $1, %edx // set stret for objc_msgForward
  669. jmp *%eax // goto *imp
  670. // cache miss: go search the method lists
  671. LMsgSendStretCacheMiss:
  672. MethodTableLookup STRUCT_RETURN, MSG_SEND
  673. movl $1, %edx // set stret for objc_msgForward
  674. jmp *%eax // goto *imp
  675. // message sent to nil: redirect to nil receiver, if any
  676. LMsgSendStretNilSelf:
  677. ret $4 // pop struct return address (#2995932)
  678. // guaranteed non-nil entry point (disabled for now)
  679. // .globl _objc_msgSendNonNil_stret
  680. // _objc_msgSendNonNil_stret:
  681. // CALL_MCOUNTER
  682. // movl self_stret(%esp), %eax
  683. // jmp LMsgSendStretReceiverOk
  684. LMsgSendStretExit:
  685. END_ENTRY _objc_msgSend_stret
  686. /********************************************************************
  687. *
  688. * void objc_msgSendSuper_stret(void *st_addr, struct objc_super *super, SEL _cmd, ...);
  689. *
  690. * struct objc_super {
  691. * id receiver;
  692. * Class class;
  693. * };
  694. *
  695. * objc_msgSendSuper_stret is the struct-return form of msgSendSuper.
  696. * The ABI calls for (sp+4) to be used as the address of the structure
  697. * being returned, with the parameters in the succeeding registers.
  698. *
  699. * On entry: (sp+4)is the address where the structure is returned,
  700. * (sp+8) is the address of the objc_super structure,
  701. * (sp+12) is the selector
  702. *
  703. ********************************************************************/
  704. ENTRY _objc_msgSendSuper_stret
  705. CALL_MCOUNTER
  706. // load selector and class to search
  707. movl super_stret(%esp), %eax // struct objc_super
  708. movl (selector_stret)(%esp), %ecx // get selector
  709. movl class(%eax), %edx // struct objc_super->class
  710. // search the cache (class in %edx)
  711. CacheLookup STRUCT_RETURN, MSG_SENDSUPER, LMsgSendSuperStretCacheMiss
  712. movl $1, %edx // set stret for objc_msgForward
  713. jmp *%eax // goto *imp
  714. // cache miss: go search the method lists
  715. LMsgSendSuperStretCacheMiss:
  716. MethodTableLookup STRUCT_RETURN, MSG_SENDSUPER
  717. movl $1, %edx // set stret for objc_msgForward
  718. jmp *%eax // goto *imp
  719. LMsgSendSuperStretExit:
  720. END_ENTRY _objc_msgSendSuper_stret
  721. /********************************************************************
  722. * void objc_msgSendv_stret(void *st_addr, id self, SEL _cmd, unsigned size, marg_list frame);
  723. *
  724. * objc_msgSendv_stret is the struct-return form of msgSendv.
  725. * This function does not use the struct-return ABI; instead, the
  726. * structure return address is passed as a normal parameter.
  727. *
  728. * On entry: (sp+4) is the address in which the returned struct is put,
  729. * (sp+8) is the message receiver,
  730. * (sp+12) is the selector,
  731. * (sp+16) is the size of the marg_list, in bytes,
  732. * (sp+20) is the address of the marg_list
  733. *
  734. ********************************************************************/
  735. ENTRY _objc_msgSendv_stret
  736. #if defined(KERNEL)
  737. trap // _objc_msgSendv_stret is not for the kernel
  738. #else
  739. pushl %ebp
  740. movl %esp, %ebp
  741. subl $12, %esp // align stack assuming no extra arguments
  742. movl (marg_list_stret+4)(%ebp), %edx
  743. addl $8, %edx // skip self & selector
  744. movl (marg_size_stret+4)(%ebp), %ecx
  745. subl $5, %ecx // skip self & selector
  746. shrl $2, %ecx
  747. jle LMsgSendvStretArgsOK
  748. // %esp = %esp - (16 - ((numVariableArguments & 3) << 2))
  749. movl %ecx, %eax // 16-byte align stack
  750. andl $3, %eax
  751. shll $2, %eax
  752. subl $16, %esp
  753. addl %eax, %esp
  754. LMsgSendvStretArgLoop:
  755. decl %ecx
  756. movl 0(%edx, %ecx, 4), %eax
  757. pushl %eax
  758. jg LMsgSendvStretArgLoop
  759. LMsgSendvStretArgsOK:
  760. movl (selector_stret+4)(%ebp), %ecx
  761. pushl %ecx
  762. movl (self_stret+4)(%ebp),%ecx
  763. pushl %ecx
  764. movl (struct_addr+4)(%ebp),%ecx
  765. pushl %ecx
  766. call _objc_msgSend_stret
  767. movl %ebp,%esp
  768. popl %ebp
  769. ret
  770. #endif
  771. END_ENTRY _objc_msgSendv_stret
  772. /********************************************************************
  773. *
  774. * id _objc_msgForward(id self, SEL _cmd,...);
  775. *
  776. ********************************************************************/
  777. // _FwdSel is @selector(forward::), set up in map_images().
  778. // ALWAYS dereference _FwdSel to get to "forward::" !!
  779. .data
  780. .align 2
  781. .private_extern _FwdSel
  782. _FwdSel: .long 0
  783. .cstring
  784. .align 2
  785. LUnkSelStr: .ascii "Does not recognize selector %s (while forwarding %s)\0"
  786. .non_lazy_symbol_pointer
  787. L_forward_handler:
  788. .indirect_symbol __objc_forward_handler
  789. .long 0
  790. L_forward_stret_handler:
  791. .indirect_symbol __objc_forward_stret_handler
  792. .long 0
  793. STATIC_ENTRY __objc_msgForward_impcache
  794. // Method cache version
  795. // THIS IS NOT A CALLABLE C FUNCTION
  796. // Out-of-band register %edx is nonzero for stret, zero otherwise
  797. // Check return type (stret or not)
  798. testl %edx, %edx
  799. jnz __objc_msgForward_stret
  800. jmp __objc_msgForward
  801. END_ENTRY _objc_msgForward_impcache
  802. ENTRY __objc_msgForward
  803. // Non-struct return version
  804. // Get PIC base into %edx
  805. call L__objc_msgForward$pic_base
  806. L__objc_msgForward$pic_base:
  807. popl %edx
  808. // Call user handler, if any
  809. movl L_forward_handler-L__objc_msgForward$pic_base(%edx),%ecx
  810. movl (%ecx), %ecx
  811. testl %ecx, %ecx // if not NULL
  812. je 1f // skip to default handler
  813. jmp *%ecx // call __objc_forward_handler
  814. 1:
  815. // No user handler
  816. // Push stack frame
  817. pushl %ebp
  818. movl %esp, %ebp
  819. // Die if forwarding "forward::"
  820. movl (selector+4)(%ebp), %eax
  821. movl _FwdSel-L__objc_msgForward$pic_base(%edx),%ecx
  822. cmpl %ecx, %eax
  823. je LMsgForwardError
  824. // Call [receiver forward:sel :margs]
  825. subl $8, %esp // 16-byte align the stack
  826. leal (self+4)(%ebp), %ecx
  827. pushl %ecx // &margs
  828. pushl %eax // sel
  829. movl _FwdSel-L__objc_msgForward$pic_base(%edx),%ecx
  830. pushl %ecx // forward::
  831. pushl (self+4)(%ebp) // receiver
  832. call _objc_msgSend
  833. movl %ebp, %esp
  834. popl %ebp
  835. ret
  836. LMsgForwardError:
  837. // Call __objc_error(receiver, "unknown selector %s %s", "forward::", forwardedSel)
  838. subl $8, %esp // 16-byte align the stack
  839. pushl (selector+4+4)(%ebp) // the forwarded selector
  840. movl _FwdSel-L__objc_msgForward$pic_base(%edx),%eax
  841. pushl %eax
  842. leal LUnkSelStr-L__objc_msgForward$pic_base(%edx),%eax
  843. pushl %eax
  844. pushl (self+4)(%ebp)
  845. call ___objc_error // never returns
  846. END_ENTRY __objc_msgForward
  847. ENTRY __objc_msgForward_stret
  848. // Struct return version
  849. // Get PIC base into %edx
  850. call L__objc_msgForwardStret$pic_base
  851. L__objc_msgForwardStret$pic_base:
  852. popl %edx
  853. // Call user handler, if any
  854. movl L_forward_stret_handler-L__objc_msgForwardStret$pic_base(%edx), %ecx
  855. movl (%ecx), %ecx
  856. testl %ecx, %ecx // if not NULL
  857. je 1f // skip to default handler
  858. jmp *%ecx // call __objc_forward_stret_handler
  859. 1:
  860. // No user handler
  861. // Push stack frame
  862. pushl %ebp
  863. movl %esp, %ebp
  864. // Die if forwarding "forward::"
  865. movl (selector_stret+4)(%ebp), %eax
  866. movl _FwdSel-L__objc_msgForwardStret$pic_base(%edx), %ecx
  867. cmpl %ecx, %eax
  868. je LMsgForwardStretError
  869. // Call [receiver forward:sel :margs]
  870. subl $8, %esp // 16-byte align the stack
  871. leal (self_stret+4)(%ebp), %ecx
  872. pushl %ecx // &margs
  873. pushl %eax // sel
  874. movl _FwdSel-L__objc_msgForwardStret$pic_base(%edx),%ecx
  875. pushl %ecx // forward::
  876. pushl (self_stret+4)(%ebp) // receiver
  877. call _objc_msgSend
  878. movl %ebp, %esp
  879. popl %ebp
  880. ret $4 // pop struct return address (#2995932)
  881. LMsgForwardStretError:
  882. // Call __objc_error(receiver, "unknown selector %s %s", "forward::", forwardedSelector)
  883. subl $8, %esp // 16-byte align the stack
  884. pushl (selector_stret+4+4)(%ebp) // the forwarded selector
  885. leal _FwdSel-L__objc_msgForwardStret$pic_base(%edx),%eax
  886. pushl %eax
  887. leal LUnkSelStr-L__objc_msgForwardStret$pic_base(%edx),%eax
  888. pushl %eax
  889. pushl (self_stret+4)(%ebp)
  890. call ___objc_error // never returns
  891. END_ENTRY __objc_msgForward_stret
  892. ENTRY _method_invoke
  893. movl selector(%esp), %ecx
  894. movl method_name(%ecx), %edx
  895. movl method_imp(%ecx), %eax
  896. movl %edx, selector(%esp)
  897. jmp *%eax
  898. END_ENTRY _method_invoke
  899. ENTRY _method_invoke_stret
  900. movl selector_stret(%esp), %ecx
  901. movl method_name(%ecx), %edx
  902. movl method_imp(%ecx), %eax
  903. movl %edx, selector_stret(%esp)
  904. jmp *%eax
  905. END_ENTRY _method_invoke_stret
  906. .section __DATA,__objc_msg_break
  907. .long 0
  908. .long 0
  909. #endif