|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.0 (the 'License'). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License."
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24: #ifndef KERNEL
25: # _objc_entryPoints and _objc_exitPoints are used by moninitobjc() to setup
26: # objective-C messages for profiling. The are made private_externs when in
27: # a shared library.
28: .reference _moninitobjc
29: .const
30: .globl _objc_entryPoints
31: _objc_entryPoints:
32: .long _objc_msgSend
33: .long _objc_msgSendSuper
34: .long _objc_msgSendv
35: .long 0
36:
37: .globl _objc_exitPoints
38: _objc_exitPoints:
39: .long Lexit1
40: .long Lexit2
41: .long Lexit3
42: .long Lexit4
43: .long Lexit5
44: .long Lexit6
45: .long Lexit7
46: .long Lexit8
47: .long 0
48: #endif /* KERNEL */
49:
50: // Objective-C message dispatching for the i386
51:
52: // arguments
53: self = 4
54: selector = 8
55: // structure indices
56: isa = 0
57: cache = 32
58: buckets = 8
59: mask = 0
60: method_name = 0
61: method_imp = 8
62:
63: // Objective-C method send
64:
65: .text
66: .globl _objc_msgSend
67: .align 4
68: _objc_msgSend:
69: movl self(%esp), %eax
70: movl %eax, %ecx
71: andl __objc_multithread_mask, %ecx
72: je L1nil_or_multi
73:
74: // load variables and save caller registers.
75: // Overlapped to prevent AGI
76: movl selector(%esp), %ecx // (1)
77: movl isa(%eax), %eax // (1) class = self->isa;
78: pushl %edi // (1)
79: movl cache(%eax), %eax // (1) cache = class->cache;
80: pushl %esi // (1)
81:
82: lea buckets(%eax), %edi // (1) buckets = &cache->buckets;
83: movl mask(%eax), %esi // (1) mask = cache->mask;
84: movl %ecx, %edx // (1) index = selector;
85:
86: L1probe_cache:
87: andl %esi, %edx // (1) index &= mask;
88: movl (%edi, %edx, 4), %eax // (2) method_name = buckets[index];
89:
90: orl %eax, %eax // (1) if (method != NULL) {
91: je L1cache_miss // (1)
92: cmpl method_name(%eax), %ecx // (1) method_name = method->name;
93: jne L1not_the_method // (1) if (method_name == selector) {
94: movl method_imp(%eax), %eax // (1) imp = method->method_imp;
95: popl %esi // (1)
96: popl %edi // (1)
97: Lexit1: jmp *%eax // (1) goto *imp;
98: .space 17 // area for moninitobjc to write
99: // }
100: L1not_the_method:
101: inc %edx // (1) index++;
102: jmp L1probe_cache // (1) }
103:
104: .align 4, 0x90
105: L1cache_miss:
106: // restore caller registers
107: popl %esi // (1)
108: popl %edi // (1)
109:
110: movl self(%esp), %eax // (1)
111: movl isa(%eax), %eax // (1)
112: pushl %ecx // (1)
113: pushl %eax
114: call __class_lookupMethodAndLoadCache
115: addl $8, %esp
116: Lexit2: jmp *%eax
117: .space 17 // area for moninitobjc to write
118:
119:
120: L1nil_or_multi:
121: orl %eax,%eax
122: jne L1multi_msgSend
123: ret
124:
125:
126: // locking version of send - its the same except for the lock/clear
127: .align 4
128: L1multi_msgSend:
129: // spin lock
130: movl $1, %ecx
131: leal _messageLock, %eax
132: L11spin:
133: xchgl %ecx, (%eax)
134: cmpl $0, %ecx
135: jne L11spin
136:
137: // load variables and save caller registers.
138: // Overlapped to prevent AGI
139: movl self(%esp), %eax // (1)
140: movl selector(%esp), %ecx // (1)
141: movl isa(%eax), %eax // (1) class = self->isa;
142: pushl %edi // (1)
143: movl cache(%eax), %eax // (1) cache = class->cache;
144: pushl %esi // (1)
145:
146: lea buckets(%eax), %edi // (1) buckets = &cache->buckets;
147: movl mask(%eax), %esi // (1) mask = cache->mask;
148: movl %ecx, %edx // (1) index = selector;
149:
150: L11probe_cache:
151: andl %esi, %edx // (1) index &= mask;
152: movl (%edi, %edx, 4), %eax // (2) method_name = buckets[index];
153:
154: orl %eax, %eax // (1) if (method != NULL) {
155: je L11cache_miss // (1)
156: cmpl method_name(%eax), %ecx // (1) method_name = method->name;
157: jne L11not_the_method // (1) if (method_name == selector) {
158: movl method_imp(%eax), %eax // (1) imp = method->method_imp;
159: popl %esi // (1)
160: popl %edi // (1)
161: movl $0, _messageLock // (1) unlock
162: Lexit3: jmp *%eax // (1) goto *imp;
163: .space 17 // area for moninitobjc to write
164: // }
165: L11not_the_method:
166: inc %edx // (1) index++;
167: jmp L11probe_cache // (1) }
168:
169: .align 4, 0x90
170: L11cache_miss:
171: // restore caller registers
172: popl %esi // (1)
173: popl %edi // (1)
174:
175: movl self(%esp), %eax // (1)
176: movl isa(%eax), %eax // (1)
177: pushl %ecx // (1)
178: pushl %eax
179: call __class_lookupMethodAndLoadCache
180: addl $8, %esp
181: movl $0, _messageLock // (1) unlock
182: Lexit4: jmp *%eax
183: .space 17 // area for moninitobjc to write
184:
185:
186:
187:
188: // Objective-C Super Send
189:
190: // arguments
191: caller = 4
192: // structure elements
193: reciever = 0
194: class = 4
195:
196: .globl _objc_msgSendSuper
197: .align 4
198: _objc_msgSendSuper:
199: movl __objc_multithread_mask, %eax // (1)
200: andl %eax, %eax // (1) if (multi)
201: je L2multi_msgSuperSend // (1) goto locking version
202:
203: movl caller(%esp), %eax // (1)
204: movl selector(%esp), %ecx // (1)
205:
206: // load variables and save caller registers.
207: // Overlapped to prevent AGI
208: movl class(%eax), %eax // (1) class = caller->class;
209: pushl %edi // (1)
210: movl cache(%eax), %eax // (1) cache = class->cache;
211: pushl %esi // (1)
212:
213: lea buckets(%eax), %edi // (1) buckets = &cache->buckets;
214: movl mask(%eax), %esi // (1) mask = cache->mask;
215: movl %ecx, %edx // (1) index = selector;
216:
217: L2probe_cache:
218: andl %esi, %edx // (1) index &= mask;
219: movl (%edi, %edx, 4), %eax // (2) method_name = buckets[index];
220:
221: orl %eax, %eax // (1) if (method != NULL) {
222: je L2cache_miss // (1)
223: cmpl method_name(%eax), %ecx // (1) method_name = method->name;
224: jne L2not_the_method // (1) if (method_name == selector) {
225:
226: // clobber "caller" arg with "self" and get method pointer
227: movl caller+8(%esp), %edi // (1)
228: movl method_imp(%eax), %eax // (1) imp = method->method_imp;
229: movl reciever(%edi), %esi // (1)
230: movl %esi, caller+8(%esp) // (1)
231:
232: // restore caller registers
233: popl %esi // (1)
234: popl %edi // (1)
235: Lexit5: jmp *%eax // (1) goto *imp;
236: .space 17 // area for moninitobjc to write
237: // }
238: // .align 4, 0x90
239: L2not_the_method:
240: inc %edx // (1) index++;
241: jmp L2probe_cache // (1) }
242:
243: .align 4, 0x90
244: L2cache_miss:
245: // clobber "caller" arg with "reciever"
246: movl caller+8(%esp), %edi // (1)
247: movl reciever(%edi), %esi // (1)
248: movl %esi, caller+8(%esp) // (1)
249:
250: // get class argument
251: movl class(%edi), %eax // (1)
252:
253: // restore caller registers
254: popl %esi // (1)
255: popl %edi // (1)
256:
257: // push args (class, selector)
258: pushl %ecx // (1)
259: pushl %eax
260: call __class_lookupMethodAndLoadCache
261: addl $8, %esp
262: Lexit6: jmp *%eax
263: .space 17 // area for moninitobjc to write
264:
265:
266:
267: // locking version of super send
268:
269: .align 4
270: L2multi_msgSuperSend:
271: // spin lock
272: movl $1, %ecx
273: leal _messageLock, %eax
274: L22spin:
275: xchgl %ecx, (%eax)
276: cmpl $0, %ecx
277: jne L22spin
278:
279: movl caller(%esp), %eax // (1)
280: movl selector(%esp), %ecx // (1)
281:
282: // load variables and save caller registers.
283: // Overlapped to prevent AGI
284: movl class(%eax), %eax // (1) class = caller->class;
285: pushl %edi // (1)
286: movl cache(%eax), %eax // (1) cache = class->cache;
287: pushl %esi // (1)
288:
289: lea buckets(%eax), %edi // (1) buckets = &cache->buckets;
290: movl mask(%eax), %esi // (1) mask = cache->mask;
291: movl %ecx, %edx // (1) index = selector;
292:
293: L22probe_cache:
294: andl %esi, %edx // (1) index &= mask;
295: movl (%edi, %edx, 4), %eax // (2) method_name = buckets[index];
296:
297: orl %eax, %eax // (1) if (method != NULL) {
298: je L22cache_miss // (1)
299: cmpl method_name(%eax), %ecx // (1) method_name = method->name;
300: jne L22not_the_method // (1) if (method_name == selector) {
301:
302: // clobber "caller" arg with "self" and load method pointer
303: movl caller+8(%esp), %edi // (1)
304: movl method_imp(%eax), %eax // (1) imp = method->method_imp;
305: movl reciever(%edi), %esi // (1)
306: movl %esi, caller+8(%esp) // (1)
307:
308: // restore caller registers
309: popl %esi // (1)
310: popl %edi // (1)
311: movl $0, _messageLock // (1) unlock
312: Lexit7: jmp *%eax // (1) goto *imp;
313: .space 17 // area for moninitobjc to write
314: // }
315: // .align 4, 0x90
316: L22not_the_method:
317: inc %edx // (1) index++;
318: jmp L22probe_cache // (1) }
319:
320: .align 4, 0x90
321: L22cache_miss:
322: // clobber "caller" arg with "reciever"
323: movl caller+8(%esp), %edi // (1)
324: movl reciever(%edi), %esi // (1)
325: movl %esi, caller+8(%esp) // (1)
326:
327: // get class argument
328: movl class(%edi), %eax // (1)
329:
330: // restore caller registers
331: popl %esi // (1)
332: popl %edi // (1)
333:
334: // push args (class, selector)
335: pushl %ecx // (1)
336: pushl %eax
337: call __class_lookupMethodAndLoadCache
338: addl $8, %esp
339: movl $0, _messageLock // (1) unlock
340: Lexit8: jmp *%eax
341: .space 17 // area for moninitobjc to write
342:
343:
344: // Objective-C message forwarder
345:
346: .objc_meth_var_names
347: .align 2
348: L30: .ascii "forward::\0"
349:
350: .objc_message_refs
351: .align 2
352: L31: .long L30
353:
354: .cstring
355: .align 2
356: L32: .ascii "Does not recognize selector %s\0"
357:
358: .text
359: .align 4
360: .globl __objc_msgForward
361: __objc_msgForward:
362: pushl %ebp
363: movl %esp,%ebp
364: movl (selector+4)(%esp), %eax
365: cmpl L31, %eax
366: je L33
367:
368: leal (self+4)(%esp), %ecx
369: pushl %ecx
370: pushl %eax
371: movl L31, %ecx
372: pushl %ecx
373: pushl (self + 16)(%esp)
374: call _objc_msgSend
375: movl %ebp,%esp
376: popl %ebp
377: ret
378:
379: .align 4
380: L33:
381: pushl $L30
382: pushl $L32
383: pushl (self + 12)(%esp)
384: call ___objc_error // volatile, will not return
385:
386:
387:
388: // Objective-C vararg message send
389:
390: // arguments
391: args = 16
392: size = 12
393: sel = 8
394: self = 4
395:
396: .text
397: .align 4
398: .globl _objc_msgSendv
399: _objc_msgSendv:
400: pushl %ebp
401: movl %esp, %ebp
402: movl (args + 4)(%ebp), %edx
403: addl $8, %edx // skip self & selector
404: movl (size + 4)(%ebp), %ecx
405: shrl $2, %ecx
406: subl $2, %ecx // skip self & selector
407: jle L42
408: L41:
409: decl %ecx
410: movl 0(%edx, %ecx, 4), %eax
411: pushl %eax
412: jg L41
413:
414: L42:
415: movl (sel + 4)(%ebp), %ecx
416: pushl %ecx
417: movl (self + 4)(%ebp),%ecx
418: pushl %ecx
419: call _objc_msgSend
420: movl %ebp,%esp
421: popl %ebp
422: ret
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.