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