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