objc-msg-win32.m 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525
  1. #include "objc-private.h"
  2. // out-of-band parameter to objc_msgForward
  3. #define kFwdMsgSend 1
  4. #define kFwdMsgSendStret 0
  5. // objc_msgSend parameters
  6. #define SELF 8[ebp]
  7. #define SUPER 8[ebp]
  8. #define SELECTOR 12[ebp]
  9. #define FIRST_ARG 16[ebp]
  10. // objc_msgSend_stret parameters
  11. #define STRUCT_ADDR 8[ebp]
  12. #define SELF_STRET 12[ebp]
  13. #define SUPER_STRET 12[ebp]
  14. #define SELECTOR_STRET 16[ebp]
  15. // objc_super parameter to sendSuper
  16. #define super_receiver 0
  17. #define super_class 4
  18. // struct objc_class fields
  19. #define isa 0
  20. #define cache 32
  21. // struct objc_method fields
  22. #define method_name 0
  23. #define method_imp 8
  24. // struct objc_cache fields
  25. #define mask 0
  26. #define occupied 4
  27. #define buckets 8
  28. void *_objc_forward_handler = NULL;
  29. void *_objc_forward_stret_handler = NULL;
  30. __declspec(naked) Method _cache_getMethod(Class cls, SEL sel, IMP objc_msgForward_imp)
  31. {
  32. __asm {
  33. push ebp
  34. mov ebp, esp
  35. mov ecx, SELECTOR
  36. mov edx, SELF
  37. // CacheLookup WORD_RETURN, CACHE_GET
  38. push edi
  39. mov edi, cache[edx]
  40. push esi
  41. mov esi, mask[edi]
  42. mov edx, ecx
  43. shr edx, 2
  44. SCAN:
  45. and edx, esi
  46. mov eax, buckets[edi][edx*4]
  47. test eax, eax
  48. je MISS
  49. cmp ecx, method_name[eax]
  50. je HIT
  51. add edx, 1
  52. jmp SCAN
  53. MISS:
  54. xor eax, eax
  55. pop esi
  56. pop edi
  57. leave
  58. ret
  59. HIT:
  60. mov ecx, FIRST_ARG
  61. cmp ecx, method_imp[eax]
  62. je MISS
  63. pop esi
  64. pop edi
  65. leave
  66. ret
  67. }
  68. }
  69. __declspec(naked) IMP _cache_getImp(Class cls, SEL sel)
  70. {
  71. __asm {
  72. push ebp
  73. mov ebp, esp
  74. mov ecx, SELECTOR
  75. mov edx, SELF
  76. // CacheLookup WORD_RETURN, CACHE_GET
  77. push edi
  78. mov edi, cache[edx]
  79. push esi
  80. mov esi, mask[edi]
  81. mov edx, ecx
  82. shr edx, 2
  83. SCAN:
  84. and edx, esi
  85. mov eax, buckets[edi][edx*4]
  86. test eax, eax
  87. je MISS
  88. cmp ecx, method_name[eax]
  89. je HIT
  90. add edx, 1
  91. jmp SCAN
  92. MISS:
  93. pop esi
  94. pop edi
  95. xor eax, eax
  96. leave
  97. ret
  98. HIT:
  99. pop esi
  100. pop edi
  101. mov eax, method_imp[eax]
  102. leave
  103. ret
  104. }
  105. }
  106. OBJC_EXPORT __declspec(naked) id objc_msgSend(id a, SEL b, ...)
  107. {
  108. __asm {
  109. push ebp
  110. mov ebp, esp
  111. // load receiver and selector
  112. mov ecx, SELECTOR
  113. mov eax, SELF
  114. // check whether receiver is nil
  115. test eax, eax
  116. je NIL
  117. // receiver (in eax) is non-nil: search the cache
  118. mov edx, isa[eax]
  119. // CacheLookup WORD_RETURN, MSG_SEND
  120. push edi
  121. mov edi, cache[edx]
  122. push esi
  123. mov esi, mask[edi]
  124. mov edx, ecx
  125. shr edx, 2
  126. SCAN:
  127. and edx, esi
  128. mov eax, buckets[edi][edx*4]
  129. test eax, eax
  130. je MISS
  131. cmp ecx, method_name[eax]
  132. je HIT
  133. add edx, 1
  134. jmp SCAN
  135. HIT:
  136. mov eax, method_imp[eax]
  137. pop esi
  138. pop edi
  139. mov edx, kFwdMsgSend
  140. leave
  141. jmp eax
  142. // cache miss: search method lists
  143. MISS:
  144. pop esi
  145. pop edi
  146. mov edx, SELF
  147. mov eax, isa[edx]
  148. // MethodTableLookup WORD_RETURN, MSG_SEND
  149. push $3
  150. push eax
  151. push ecx
  152. push edx
  153. call lookUpImpOrFoward
  154. mov edx, kFwdMsgSend
  155. leave
  156. jmp eax
  157. // message send to nil: return zero
  158. NIL:
  159. // eax is already zero
  160. mov edx, 0
  161. leave
  162. ret
  163. }
  164. }
  165. OBJC_EXPORT __declspec(naked) double objc_msgSend_fpret(id a, SEL b, ...)
  166. {
  167. __asm {
  168. push ebp
  169. mov ebp, esp
  170. // load receiver and selector
  171. mov ecx, SELECTOR
  172. mov eax, SELF
  173. // check whether receiver is nil
  174. test eax, eax
  175. je NIL
  176. // receiver (in eax) is non-nil: search the cache
  177. mov edx, isa[eax]
  178. // CacheLookup WORD_RETURN, MSG_SEND
  179. push edi
  180. mov edi, cache[edx]
  181. push esi
  182. mov esi, mask[edi]
  183. mov edx, ecx
  184. shr edx, 2
  185. SCAN:
  186. and edx, esi
  187. mov eax, buckets[edi][edx*4]
  188. test eax, eax
  189. je MISS
  190. cmp ecx, method_name[eax]
  191. je HIT
  192. add edx, 1
  193. jmp SCAN
  194. HIT:
  195. mov eax, method_imp[eax]
  196. pop esi
  197. pop edi
  198. mov edx, kFwdMsgSend
  199. leave
  200. jmp eax
  201. // cache miss: search method lists
  202. MISS:
  203. pop esi
  204. pop edi
  205. mov edx, SELF
  206. mov eax, isa[edx]
  207. // MethodTableLookup WORD_RETURN, MSG_SEND
  208. push $3
  209. push eax
  210. push ecx
  211. push edx
  212. call lookUpImpOrFoward
  213. mov edx, kFwdMsgSend
  214. leave
  215. jmp eax
  216. // message send to nil: return zero
  217. NIL:
  218. fldz
  219. leave
  220. ret
  221. }
  222. }
  223. OBJC_EXPORT __declspec(naked) id objc_msgSendSuper(struct objc_super *a, SEL b, ...)
  224. {
  225. __asm {
  226. push ebp
  227. mov ebp, esp
  228. // load class and selector
  229. mov eax, SUPER
  230. mov ecx, SELECTOR
  231. mov edx, super_class[eax]
  232. // search the cache (class in edx)
  233. // CacheLookup WORD_RETURN, MSG_SENDSUPER
  234. push edi
  235. mov edi, cache[edx]
  236. push esi
  237. mov esi, mask[edi]
  238. mov edx, ecx
  239. shr edx, 2
  240. SCAN:
  241. and edx, esi
  242. mov eax, buckets[edi][edx*4]
  243. test eax, eax
  244. je MISS
  245. cmp ecx, method_name[eax]
  246. je HIT
  247. add edx, 1
  248. jmp SCAN
  249. HIT:
  250. mov eax, method_imp[eax]
  251. pop esi
  252. pop edi
  253. mov edx, SUPER
  254. mov edx, super_receiver[edx]
  255. mov SUPER, edx
  256. mov edx, kFwdMsgSend
  257. leave
  258. jmp eax
  259. // cache miss: search method lists
  260. MISS:
  261. pop esi
  262. pop edi
  263. mov eax, SUPER
  264. mov edx, super_receiver[eax]
  265. mov SUPER, edx
  266. mov eax, super_class[eax]
  267. // MethodTableLookup WORD_RETURN, MSG_SENDSUPER
  268. push $3
  269. push eax
  270. push ecx
  271. push edx
  272. call lookUpImpOrFoward
  273. mov edx, kFwdMsgSend
  274. leave
  275. jmp eax
  276. }
  277. }
  278. OBJC_EXPORT __declspec(naked) void objc_msgSend_stret(void)
  279. {
  280. __asm {
  281. push ebp
  282. mov ebp, esp
  283. // load receiver and selector
  284. mov ecx, SELECTOR_STRET
  285. mov eax, SELF_STRET
  286. // check whether receiver is nil
  287. test eax, eax
  288. je NIL
  289. // receiver (in eax) is non-nil: search the cache
  290. mov edx, isa[eax]
  291. // CacheLookup WORD_RETURN, MSG_SEND
  292. push edi
  293. mov edi, cache[edx]
  294. push esi
  295. mov esi, mask[edi]
  296. mov edx, ecx
  297. shr edx, 2
  298. SCAN:
  299. and edx, esi
  300. mov eax, buckets[edi][edx*4]
  301. test eax, eax
  302. je MISS
  303. cmp ecx, method_name[eax]
  304. je HIT
  305. add edx, 1
  306. jmp SCAN
  307. HIT:
  308. mov eax, method_imp[eax]
  309. pop esi
  310. pop edi
  311. mov edx, kFwdMsgSendStret
  312. leave
  313. jmp eax
  314. // cache miss: search method lists
  315. MISS:
  316. pop esi
  317. pop edi
  318. mov edx, SELF_STRET
  319. mov eax, isa[edx]
  320. // MethodTableLookup WORD_RETURN, MSG_SEND
  321. push $3
  322. push eax
  323. push ecx
  324. push edx
  325. call lookUpImpOrFoward
  326. mov edx, kFwdMsgSendStret
  327. leave
  328. jmp eax
  329. // message send to nil: return zero
  330. NIL:
  331. // eax is already zero
  332. mov edx, 0
  333. leave
  334. ret
  335. }
  336. }
  337. OBJC_EXPORT __declspec(naked) id objc_msgSendSuper_stret(struct objc_super *a, SEL b, ...)
  338. {
  339. __asm {
  340. push ebp
  341. mov ebp, esp
  342. // load class and selector
  343. mov eax, SUPER_STRET
  344. mov ecx, SELECTOR_STRET
  345. mov edx, super_class[eax]
  346. // search the cache (class in edx)
  347. // CacheLookup WORD_RETURN, MSG_SENDSUPER
  348. push edi
  349. mov edi, cache[edx]
  350. push esi
  351. mov esi, mask[edi]
  352. mov edx, ecx
  353. shr edx, 2
  354. SCAN:
  355. and edx, esi
  356. mov eax, buckets[edi][edx*4]
  357. test eax, eax
  358. je MISS
  359. cmp ecx, method_name[eax]
  360. je HIT
  361. add edx, 1
  362. jmp SCAN
  363. HIT:
  364. mov eax, method_imp[eax]
  365. pop esi
  366. pop edi
  367. mov edx, SUPER_STRET
  368. mov edx, super_receiver[edx]
  369. mov SUPER_STRET, edx
  370. mov edx, kFwdMsgSendStret
  371. leave
  372. jmp eax
  373. // cache miss: search method lists
  374. MISS:
  375. pop esi
  376. pop edi
  377. mov eax, SUPER_STRET
  378. mov edx, super_receiver[eax]
  379. mov SUPER_STRET, edx
  380. mov eax, super_class[eax]
  381. // MethodTableLookup WORD_RETURN, MSG_SENDSUPER
  382. push $3
  383. push eax
  384. push ecx
  385. push edx
  386. call lookUpImpOrFoward
  387. mov edx, kFwdMsgSendStret
  388. leave
  389. jmp eax
  390. }
  391. }
  392. OBJC_EXPORT __declspec(naked) id _objc_msgForward(id a, SEL b, ...)
  393. {
  394. __asm {
  395. mov ecx, _objc_forward_handler
  396. jmp ecx
  397. }
  398. }
  399. OBJC_EXPORT __declspec(naked) id _objc_msgForward_stret(id a, SEL b, ...)
  400. {
  401. __asm {
  402. mov ecx, _objc_forward_stret_handler
  403. jmp ecx
  404. }
  405. }
  406. __declspec(naked) id _objc_msgForward_cached(id a, SEL b, ...)
  407. {
  408. __asm {
  409. cmp edx, kFwdMsgSendStret
  410. je STRET
  411. jmp _objc_msgForward
  412. STRET:
  413. jmp _objc_msgForward_stret
  414. }
  415. }
  416. OBJC_EXPORT __declspec(naked) void method_invoke(void)
  417. {
  418. __asm {
  419. push ebp
  420. mov ebp, esp
  421. mov ecx, SELECTOR
  422. mov edx, method_name[ecx]
  423. mov eax, method_imp[ecx]
  424. mov SELECTOR, edx
  425. leave
  426. jmp eax
  427. }
  428. }
  429. OBJC_EXPORT __declspec(naked) void method_invoke_stret(void)
  430. {
  431. __asm {
  432. push ebp
  433. mov ebp, esp
  434. mov ecx, SELECTOR_STRET
  435. mov edx, method_name[ecx]
  436. mov eax, method_imp[ecx]
  437. mov SELECTOR_STRET, edx
  438. leave
  439. jmp eax
  440. }
  441. }