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