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