|
|
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, 0x90
68: _objc_msgSend:
69: movl self(%esp), %eax // (1) self = arg[0]
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) selector = arg[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: movl %eax,%eax // (1) NOP
87: .align 2, 0x90 // (0) would be 2
88:
89: L1probe_cache:
90: andl %esi, %edx // (1) index &= mask;
91: movl (%edi, %edx, 8), %eax // (2) method_name = buckets[index].sel;
92: cmpl %eax, %ecx // (1) if (method_name == selector)
93: je L1cache_hit // (1) goto cache_hit;
94: orl %eax, %eax // (1) if (method_name == NULL)
95: je L1cache_miss // (1) goto cache_miss;
96: inc %edx // (1) index++;
97: jmp L1probe_cache // (1)
98:
99: .align 2, 0x90
100: L1cache_hit:
101: movl 4(%edi, %edx, 8), %eax // (1) imp = buckets[index].imp
102: popl %esi // (1)
103: popl %edi // (1)
104:
105: Lexit1: jmp *%eax // (1) goto *imp;
106: .space 17, 0x90 // area for moninitobjc to write
107:
108: .align 4, 0x90
109: L1cache_miss:
110: // restore caller registers
111: popl %esi // (1)
112: popl %edi // (1)
113:
114: movl self(%esp), %eax // (1)
115: movl isa(%eax), %eax // (1)
116: pushl %ecx // (1)
117: pushl %eax
118: call __class_lookupMethodAndLoadCache
119: addl $8, %esp
120: Lexit2: jmp *%eax
121: .space 17, 0x90 // area for moninitobjc to write
122:
123:
124: L1nil_or_multi:
125: orl %eax,%eax
126: jne L1multi_msgSend
127: ret
128:
129:
130: // locking version of send - its the same except for the lock/clear
131: .align 4, 0x90
132: L1multi_msgSend:
133: // spin lock
134: movl $1, %ecx
135: leal _messageLock, %eax
136: L11spin:
137: xchgl %ecx, (%eax)
138: cmpl $0, %ecx
139: jne L11spin
140:
141: // load variables and save caller registers.
142: // Overlapped to prevent AGI
143: movl self(%esp), %eax // (1)
144: movl selector(%esp), %ecx // (1)
145: movl isa(%eax), %eax // (1) class = self->isa;
146: pushl %edi // (1)
147: movl cache(%eax), %eax // (1) cache = class->cache;
148: pushl %esi // (1)
149:
150: lea buckets(%eax), %edi // (1) buckets = &cache->buckets;
151: movl mask(%eax), %esi // (1) mask = cache->mask;
152: movl %ecx, %edx // (1) index = selector;
153:
154: movl %eax,%eax // (1) NOP
155: .align 2, 0x90 // (0) would be 2
156:
157: L11probe_cache:
158: andl %esi, %edx // (1) index &= mask;
159: movl (%edi, %edx, 8), %eax // (2) method_name = buckets[index].sel;
160: cmpl %eax, %ecx // (1) if (method_name == selector)
161: je L11cache_hit // (1) goto cache_hit;
162: orl %eax, %eax // (1) if (method_name == NULL)
163: je L11cache_miss // (1) goto cache_miss;
164: inc %edx // (1) index++;
165: jmp L11probe_cache // (1)
166:
167: .align 2, 0x90
168: L11cache_hit:
169: movl 4(%edi, %edx, 8), %eax // (1) imp = buckets[index].imp
170:
171: // restore registers
172: popl %esi // (1)
173: popl %edi // (1)
174:
175: movl $0, _messageLock // (1) unlock
176: Lexit3: jmp *%eax // (1) goto *imp;
177: .space 17, 0x90 // area for moninitobjc to write
178: // }
179: .align 4, 0x90
180: L11cache_miss:
181: // restore caller registers
182: popl %esi // (1)
183: popl %edi // (1)
184:
185: movl self(%esp), %eax // (1)
186: movl isa(%eax), %eax // (1)
187: pushl %ecx // (1)
188: pushl %eax
189: call __class_lookupMethodAndLoadCache
190: addl $8, %esp
191: movl $0, _messageLock // (1) unlock
192: Lexit4: jmp *%eax
193: .space 17, 0x90 // area for moninitobjc to write
194:
195:
196:
197:
198: // Objective-C Super Send
199:
200: // arguments
201: caller = 4
202: // structure elements
203: reciever = 0
204: class = 4
205:
206: .globl _objc_msgSendSuper
207: .align 4, 0x90
208: _objc_msgSendSuper:
209: movl __objc_multithread_mask, %eax // (1)
210: andl %eax, %eax // (1) if (multi)
211: je L2multi_msgSuperSend // (1) goto locking version
212:
213: movl caller(%esp), %eax // (1)
214: movl selector(%esp), %ecx // (1)
215:
216: // load variables and save caller registers.
217: // Overlapped to prevent AGI
218: movl class(%eax), %eax // (1) class = caller->class;
219: pushl %edi // (1)
220: movl cache(%eax), %eax // (1) cache = class->cache;
221: pushl %esi // (1)
222:
223: lea buckets(%eax), %edi // (1) buckets = &cache->buckets;
224: movl mask(%eax), %esi // (1) mask = cache->mask;
225: movl %ecx, %edx // (1) index = selector;
226:
227: leal 0(%eax),%eax // (1) NOP
228: .align 2, 0x90 // (0) would be 3
229:
230: L2probe_cache:
231: andl %esi, %edx // (1) index &= mask;
232: movl (%edi, %edx, 8), %eax // (2) method_name = buckets[index].sel;
233: cmpl %eax, %ecx // (1) if (method_name == selector)
234: je L2cache_hit // (1) goto cache_hit;
235: orl %eax, %eax // (1) if (method_name == NULL)
236: je L2cache_miss // (1) goto cache_miss;
237: inc %edx // (1) index++;
238: jmp L2probe_cache // (1)
239:
240: .align 2, 0x90
241:
242: L2cache_hit:
243: movl 4(%edi, %edx, 8), %eax // (1) imp = buckets[index].imp
244:
245: // clobber "caller" arg with "self" and get method pointer
246: movl caller+8(%esp), %edi // (1)
247: movl reciever(%edi), %esi // (1)
248: movl %esi, caller+8(%esp) // (1)
249:
250: // restore caller registers
251: popl %esi // (1)
252: popl %edi // (1)
253:
254: Lexit5: jmp *%eax // (1) goto *imp;
255: .space 17, 0x90 // area for moninitobjc to write
256: // }
257:
258: .align 4, 0x90
259: L2cache_miss:
260: // clobber "caller" arg with "reciever"
261: movl caller+8(%esp), %edi // (1)
262: movl reciever(%edi), %esi // (1)
263: movl %esi, caller+8(%esp) // (1)
264:
265: // get class argument
266: movl class(%edi), %eax // (1)
267:
268: // restore caller registers
269: popl %esi // (1)
270: popl %edi // (1)
271:
272: // push args (class, selector)
273: pushl %ecx // (1)
274: pushl %eax
275: call __class_lookupMethodAndLoadCache
276: addl $8, %esp
277: Lexit6: jmp *%eax
278: .space 17, 0x90 // area for moninitobjc to write
279:
280:
281:
282: // locking version of super send
283:
284: .align 4, 0x90
285: L2multi_msgSuperSend:
286: // spin lock
287: movl $1, %ecx
288: leal _messageLock, %eax
289: L22spin:
290: xchgl %ecx, (%eax)
291: cmpl $0, %ecx
292: jne L22spin
293:
294: movl caller(%esp), %eax // (1)
295: movl selector(%esp), %ecx // (1)
296:
297: // load variables and save caller registers.
298: // Overlapped to prevent AGI
299: movl class(%eax), %eax // (1) class = caller->class;
300: pushl %edi // (1)
301: movl cache(%eax), %eax // (1) cache = class->cache;
302: pushl %esi // (1)
303:
304: lea buckets(%eax), %edi // (1) buckets = &cache->buckets;
305: movl mask(%eax), %esi // (1) mask = cache->mask;
306: movl %ecx, %edx // (1) index = selector;
307:
308: movl %eax,%eax // (1) NOP
309: .align 2, 0x90 // (0) would be 2
310:
311: L22probe_cache:
312: andl %esi, %edx // (1) index &= mask;
313: movl (%edi, %edx, 8), %eax // (2) method_name = buckets[index].sel;
314: cmpl %eax, %ecx // (1) if (method_name == selector)
315: je L22cache_hit // (1) goto cache_hit;
316: orl %eax, %eax // (1) if (method_name == NULL)
317: je L22cache_miss // (1) goto cache_miss;
318: inc %edx // (1) index++;
319: jmp L22probe_cache // (1)
320:
321: .align 2, 0x90
322:
323: L22cache_hit:
324: movl 4(%edi, %edx, 8), %eax // (1) imp = buckets[index].imp
325:
326: // clobber "caller" arg with "self" and get method pointer
327: movl caller+8(%esp), %edi // (1)
328: movl reciever(%edi), %esi // (1)
329: movl %esi, caller+8(%esp) // (1)
330:
331: // restore caller registers
332: popl %esi // (1)
333: popl %edi // (1)
334:
335: movl $0, _messageLock // (1) unlock
336: Lexit7: jmp *%eax // (1) goto *imp;
337: .space 17, 0x90 // area for moninitobjc to write
338: // }
339:
340:
341: .align 4, 0x90
342: L22cache_miss:
343: // clobber "caller" arg with "reciever"
344: movl caller+8(%esp), %edi // (1)
345: movl reciever(%edi), %esi // (1)
346: movl %esi, caller+8(%esp) // (1)
347:
348: // get class argument
349: movl class(%edi), %eax // (1)
350:
351: // restore caller registers
352: popl %esi // (1)
353: popl %edi // (1)
354:
355: // push args (class, selector)
356: pushl %ecx // (1)
357: pushl %eax
358: call __class_lookupMethodAndLoadCache
359: addl $8, %esp
360: movl $0, _messageLock // (1) unlock
361: Lexit8: jmp *%eax
362: .space 17, 0x90 // area for moninitobjc to write
363:
364:
365: // Objective-C message forwarder
366:
367: .objc_meth_var_names
368: .align 2
369: L30: .ascii "forward::\0"
370:
371: .objc_message_refs
372: .align 2
373: L31: .long L30
374:
375: .cstring
376: .align 2
377: L32: .ascii "Does not recognize selector %s\0"
378:
379: .text
380: .align 4
381: .globl __objc_msgForward
382: __objc_msgForward:
383: pushl %ebp
384: movl %esp,%ebp
385: movl (selector+4)(%esp), %eax
386: cmpl L31, %eax
387: je L33
388:
389: leal (self+4)(%esp), %ecx
390: pushl %ecx
391: pushl %eax
392: movl L31, %ecx
393: pushl %ecx
394: pushl (self + 16)(%esp)
395: call _objc_msgSend
396: movl %ebp,%esp
397: popl %ebp
398: ret
399:
400: .align 4
401: L33:
402: pushl $L30
403: pushl $L32
404: pushl (self + 12)(%esp)
405: call ___objc_error // volatile, will not return
406:
407:
408:
409: // Objective-C vararg message send
410:
411: // arguments
412: args = 16
413: size = 12
414: sel = 8
415: self = 4
416:
417: .text
418: .align 4
419: .globl _objc_msgSendv
420: _objc_msgSendv:
421: pushl %ebp
422: movl %esp, %ebp
423: movl (args + 4)(%ebp), %edx
424: addl $8, %edx // skip self & selector
425: movl (size + 4)(%ebp), %ecx
426: shrl $2, %ecx
427: subl $2, %ecx // skip self & selector
428: jle L42
429: L41:
430: decl %ecx
431: movl 0(%edx, %ecx, 4), %eax
432: pushl %eax
433: jg L41
434:
435: L42:
436: movl (sel + 4)(%ebp), %ecx
437: pushl %ecx
438: movl (self + 4)(%ebp),%ecx
439: pushl %ecx
440: call _objc_msgSend
441: movl %ebp,%esp
442: popl %ebp
443: ret
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.