]> git.saurik.com Git - apple/objc4.git/blame - runtime/Messengers.subproj/objc-msg-win32.m
objc4-532.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
8972963c 138#if SUPPORT_GC\r
7af964d1
A
139 // check whether selector is ignored\r
140#error oops\r
141#endif\r
142\r
143 // check whether receiver is nil\r
144 test eax, eax\r
145 je NIL\r
146\r
147 // receiver (in eax) is non-nil: search the cache\r
148 mov edx, isa[eax]\r
149\r
150 // CacheLookup WORD_RETURN, MSG_SEND\r
151 push edi\r
152 mov edi, cache[edx]\r
153 push esi\r
154 mov esi, mask[edi]\r
155 mov edx, ecx\r
156 shr edx, 2\r
157SCAN:\r
158 and edx, esi\r
159 mov eax, buckets[edi][edx*4]\r
160 test eax, eax\r
161 je MISS\r
162 cmp ecx, method_name[eax]\r
163 je HIT\r
164 add edx, 1\r
165 jmp SCAN\r
166\r
167HIT:\r
168 mov eax, method_imp[eax]\r
169 pop esi\r
170 pop edi\r
171 mov edx, kFwdMsgSend\r
8972963c 172 leave\r
7af964d1
A
173 jmp eax\r
174\r
175 // cache miss: search method lists\r
176MISS:\r
177 pop esi\r
178 pop edi\r
cd5f04f5
A
179 mov edx, SELF\r
180 mov eax, isa[edx]\r
7af964d1
A
181\r
182 // MethodTableLookup WORD_RETURN, MSG_SEND\r
7af964d1 183 push eax\r
cd5f04f5
A
184 push ecx\r
185 push edx\r
186 call _class_lookupMethodAndLoadCache3\r
7af964d1
A
187\r
188 mov edx, kFwdMsgSend\r
8972963c 189 leave\r
7af964d1
A
190 jmp eax\r
191\r
192 // message send to nil: return zero\r
193NIL:\r
194 // eax is already zero\r
195 mov edx, 0\r
8972963c 196 leave\r
7af964d1
A
197 ret\r
198 }\r
199}\r
200\r
201\r
202OBJC_EXPORT __declspec(naked) double objc_msgSend_fpret(id a, SEL b, ...)\r
203{\r
204 __asm {\r
8972963c
A
205 push ebp\r
206 mov ebp, esp\r
207\r
7af964d1 208 // load receiver and selector\r
8972963c
A
209 mov ecx, SELECTOR\r
210 mov eax, SELF\r
7af964d1 211\r
8972963c 212#if SUPPORT_GC\r
7af964d1
A
213 // check whether selector is ignored\r
214#error oops\r
215#endif\r
216\r
217 // check whether receiver is nil\r
218 test eax, eax\r
219 je NIL\r
220\r
221 // receiver (in eax) is non-nil: search the cache\r
222 mov edx, isa[eax]\r
223\r
224 // CacheLookup WORD_RETURN, MSG_SEND\r
225 push edi\r
226 mov edi, cache[edx]\r
227 push esi\r
228 mov esi, mask[edi]\r
229 mov edx, ecx\r
230 shr edx, 2\r
231SCAN:\r
232 and edx, esi\r
233 mov eax, buckets[edi][edx*4]\r
234 test eax, eax\r
235 je MISS\r
236 cmp ecx, method_name[eax]\r
237 je HIT\r
238 add edx, 1\r
239 jmp SCAN\r
240\r
241HIT:\r
242 mov eax, method_imp[eax]\r
243 pop esi\r
244 pop edi\r
245 mov edx, kFwdMsgSend\r
8972963c 246 leave\r
7af964d1
A
247 jmp eax\r
248\r
249 // cache miss: search method lists\r
250MISS:\r
251 pop esi\r
252 pop edi\r
cd5f04f5
A
253 mov edx, SELF\r
254 mov eax, isa[edx]\r
7af964d1
A
255\r
256 // MethodTableLookup WORD_RETURN, MSG_SEND\r
7af964d1 257 push eax\r
cd5f04f5
A
258 push ecx\r
259 push edx\r
260 call _class_lookupMethodAndLoadCache3\r
7af964d1
A
261\r
262 mov edx, kFwdMsgSend\r
8972963c 263 leave\r
7af964d1
A
264 jmp eax\r
265\r
266 // message send to nil: return zero\r
267NIL:\r
268 fldz\r
8972963c 269 leave\r
7af964d1
A
270 ret\r
271 }\r
272}\r
273\r
274\r
275OBJC_EXPORT __declspec(naked) id objc_msgSendSuper(struct objc_super *a, SEL b, ...)\r
276{\r
277 __asm {\r
8972963c
A
278 push ebp\r
279 mov ebp, esp\r
280\r
7af964d1 281 // load class and selector\r
8972963c
A
282 mov eax, SUPER\r
283 mov ecx, SELECTOR\r
7af964d1
A
284 mov edx, super_class[eax]\r
285\r
8972963c 286#if SUPPORT_GC\r
7af964d1
A
287 // check whether selector is ignored\r
288#error oops\r
289#endif\r
290\r
291 // search the cache (class in edx)\r
292 // CacheLookup WORD_RETURN, MSG_SENDSUPER\r
293 push edi\r
294 mov edi, cache[edx]\r
295 push esi\r
296 mov esi, mask[edi]\r
297 mov edx, ecx\r
298 shr edx, 2\r
299SCAN:\r
300 and edx, esi\r
301 mov eax, buckets[edi][edx*4]\r
302 test eax, eax\r
303 je MISS\r
304 cmp ecx, method_name[eax]\r
305 je HIT\r
306 add edx, 1\r
307 jmp SCAN\r
308\r
309HIT:\r
310 mov eax, method_imp[eax]\r
311 pop esi\r
312 pop edi\r
8972963c 313 mov edx, SUPER\r
7af964d1 314 mov edx, super_receiver[edx]\r
8972963c 315 mov SUPER, edx\r
7af964d1 316 mov edx, kFwdMsgSend\r
8972963c 317 leave\r
7af964d1
A
318 jmp eax\r
319\r
320 // cache miss: search method lists\r
321MISS:\r
322\r
323 pop esi\r
324 pop edi\r
cd5f04f5
A
325 mov eax, SUPER\r
326 mov edx, super_receiver[eax]\r
327 mov SUPER, edx\r
328 mov eax, super_class[eax]\r
7af964d1
A
329\r
330 // MethodTableLookup WORD_RETURN, MSG_SENDSUPER\r
7af964d1 331 push eax\r
cd5f04f5
A
332 push ecx\r
333 push edx\r
334 call _class_lookupMethodAndLoadCache3\r
7af964d1
A
335\r
336 mov edx, kFwdMsgSend\r
8972963c 337 leave\r
7af964d1
A
338 jmp eax\r
339 }\r
340}\r
341\r
342\r
343OBJC_EXPORT __declspec(naked) void objc_msgSend_stret(void)\r
344{\r
345 __asm {\r
8972963c
A
346 push ebp\r
347 mov ebp, esp\r
348\r
7af964d1 349 // load receiver and selector\r
8972963c
A
350 mov ecx, SELECTOR_STRET\r
351 mov eax, SELF_STRET\r
7af964d1 352\r
8972963c 353#if SUPPORT_GC\r
7af964d1
A
354 // check whether selector is ignored\r
355#error oops\r
356#endif\r
357\r
358 // check whether receiver is nil\r
359 test eax, eax\r
360 je NIL\r
361\r
362 // receiver (in eax) is non-nil: search the cache\r
363 mov edx, isa[eax]\r
364\r
365 // CacheLookup WORD_RETURN, MSG_SEND\r
366 push edi\r
367 mov edi, cache[edx]\r
368 push esi\r
369 mov esi, mask[edi]\r
370 mov edx, ecx\r
371 shr edx, 2\r
372SCAN:\r
373 and edx, esi\r
374 mov eax, buckets[edi][edx*4]\r
375 test eax, eax\r
376 je MISS\r
377 cmp ecx, method_name[eax]\r
378 je HIT\r
379 add edx, 1\r
380 jmp SCAN\r
381\r
382HIT:\r
383 mov eax, method_imp[eax]\r
384 pop esi\r
385 pop edi\r
386 mov edx, kFwdMsgSendStret\r
8972963c 387 leave\r
7af964d1
A
388 jmp eax\r
389\r
390 // cache miss: search method lists\r
391MISS:\r
392 pop esi\r
393 pop edi\r
cd5f04f5
A
394 mov edx, SELF_STRET\r
395 mov eax, isa[edx]\r
7af964d1
A
396\r
397 // MethodTableLookup WORD_RETURN, MSG_SEND\r
7af964d1 398 push eax\r
cd5f04f5
A
399 push ecx\r
400 push edx\r
401 call _class_lookupMethodAndLoadCache3\r
7af964d1
A
402\r
403 mov edx, kFwdMsgSendStret\r
8972963c 404 leave\r
7af964d1
A
405 jmp eax\r
406\r
407 // message send to nil: return zero\r
408NIL:\r
409 // eax is already zero\r
410 mov edx, 0\r
8972963c 411 leave\r
7af964d1
A
412 ret\r
413 }\r
414}\r
415\r
416\r
417OBJC_EXPORT __declspec(naked) id objc_msgSendSuper_stret(struct objc_super *a, SEL b, ...)\r
418{\r
419 __asm {\r
8972963c
A
420 push ebp\r
421 mov ebp, esp\r
422\r
7af964d1 423 // load class and selector\r
8972963c
A
424 mov eax, SUPER_STRET\r
425 mov ecx, SELECTOR_STRET\r
7af964d1
A
426 mov edx, super_class[eax]\r
427\r
8972963c 428#if SUPPORT_GC\r
7af964d1
A
429 // check whether selector is ignored\r
430#error oops\r
431#endif\r
432\r
433 // search the cache (class in edx)\r
434 // CacheLookup WORD_RETURN, MSG_SENDSUPER\r
435 push edi\r
436 mov edi, cache[edx]\r
437 push esi\r
438 mov esi, mask[edi]\r
439 mov edx, ecx\r
440 shr edx, 2\r
441SCAN:\r
442 and edx, esi\r
443 mov eax, buckets[edi][edx*4]\r
444 test eax, eax\r
445 je MISS\r
446 cmp ecx, method_name[eax]\r
447 je HIT\r
448 add edx, 1\r
449 jmp SCAN\r
450\r
451HIT:\r
452 mov eax, method_imp[eax]\r
453 pop esi\r
454 pop edi\r
8972963c 455 mov edx, SUPER_STRET\r
7af964d1 456 mov edx, super_receiver[edx]\r
8972963c 457 mov SUPER_STRET, edx\r
7af964d1 458 mov edx, kFwdMsgSendStret\r
8972963c 459 leave\r
7af964d1
A
460 jmp eax\r
461\r
462 // cache miss: search method lists\r
463MISS:\r
464\r
465 pop esi\r
466 pop edi\r
cd5f04f5
A
467 mov eax, SUPER_STRET\r
468 mov edx, super_receiver[eax]\r
469 mov SUPER_STRET, edx\r
470 mov eax, super_class[eax]\r
7af964d1
A
471\r
472 // MethodTableLookup WORD_RETURN, MSG_SENDSUPER\r
7af964d1 473 push eax\r
cd5f04f5
A
474 push ecx\r
475 push edx\r
476 call _class_lookupMethodAndLoadCache3\r
7af964d1
A
477\r
478 mov edx, kFwdMsgSendStret\r
8972963c 479 leave\r
7af964d1
A
480 jmp eax\r
481 }\r
482}\r
483\r
484\r
485OBJC_EXPORT __declspec(naked) id _objc_msgForward(id a, SEL b, ...)\r
486{\r
487 __asm {\r
488 mov ecx, _objc_forward_handler\r
489 // forward:: support omitted here\r
490 jmp ecx\r
491 }\r
492}\r
493\r
494OBJC_EXPORT __declspec(naked) id _objc_msgForward_stret(id a, SEL b, ...)\r
495{\r
496 __asm {\r
497 mov ecx, _objc_forward_stret_handler\r
498 // forward:: support omitted here\r
499 jmp ecx\r
500 }\r
501}\r
502\r
503\r
504__declspec(naked) id _objc_msgForward_internal(id a, SEL b, ...)\r
505{\r
506 __asm {\r
507 cmp edx, kFwdMsgSendStret\r
508 je STRET\r
509 jmp _objc_msgForward\r
510STRET:\r
511 jmp _objc_msgForward_stret\r
512 }\r
513}\r
514\r
515\r
516OBJC_EXPORT __declspec(naked) void method_invoke(void)\r
517{\r
518 __asm {\r
8972963c
A
519 push ebp\r
520 mov ebp, esp\r
521\r
522 mov ecx, SELECTOR\r
7af964d1
A
523 mov edx, method_name[ecx]\r
524 mov eax, method_imp[ecx]\r
8972963c
A
525 mov SELECTOR, edx\r
526\r
527 leave\r
7af964d1
A
528 jmp eax\r
529 }\r
530}\r
531\r
532\r
533OBJC_EXPORT __declspec(naked) void method_invoke_stret(void)\r
534{\r
535 __asm {\r
8972963c
A
536 push ebp\r
537 mov ebp, esp\r
538\r
539 mov ecx, SELECTOR_STRET\r
7af964d1
A
540 mov edx, method_name[ecx]\r
541 mov eax, method_imp[ecx]\r
8972963c
A
542 mov SELECTOR_STRET, edx\r
543\r
544 leave\r
7af964d1
A
545 jmp eax\r
546 }\r
547}\r
8972963c
A
548\r
549\r
550__declspec(naked) id _objc_ignored_method(id obj, SEL sel)\r
551{\r
552 return obj;\r
553}\r