objc-msg-i386.s 30 KB

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