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