2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.1 (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
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
22 * @APPLE_LICENSE_HEADER_END@
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
28 .reference _moninitobjc
30 .globl _objc_entryPoints
33 .long _objc_msgSendSuper
37 .globl _objc_exitPoints
56 | optimized for 68040: 27 clocks (best case) + 16 clocks / probe
62 movel sp@(self),d0 | (1)
64 andl __objc_multithread_mask,d0 | (1) if (_objc_multithread_mask == 0)
65 jne L1 | (2) goto lock;
66 tstl a0 | if (self != nil)
67 jne L11 | continue with objc_msgSend
68 movel __objc_msgNil,a0 | (?) load nil object handler
69 tstl a0 | (?) If NULL just return and dont do anything
71 jbsr a0@ | (?) call __objc_msgNil;
72 clrl d0 | (1) zero d0, just in case nil handler changed them
73 movel d0,a0 | (1) zero a0, just in case nil handler changed them
75 L1: movel a0@,a0 | (1) class = self->isa;
76 movel a1,sp@- | (2) (save a1)
77 movel a0@(cache),a1 | (1) cache = class->cache;
78 movel sp@(selector+4),d1 | (1) index = selector;
79 L2: andl a1@,d1 | (1) index &= cache->mask;
80 movel a1@(buckets,d1:l:4),d0 | (4) method = cache->buckets[index];
81 movel d0,a0 | (1) if (method == NULL)
82 jne L3 | (2) goto cache_miss;
84 L3: movel sp@(selector+4),d0 | (1)
85 cmpl a0@,d0 | (1) if (method_name == selector)
86 jeq L4 | (2) goto cache_hit;
89 L4: movel a0@(method_imp),a0 | (1) imp = method->method_imp;
90 movel sp@+,a1 | (1) (restore a1)
91 Lexit1: jmp a0@ | (3) goto *imp;
92 .space 22 | /* area for moninitobjc to write */
93 L5: movel sp@(self+4),a0 | cache_miss:
94 movel sp@(selector+4),sp@- | imp =
95 movel a0@,sp@- | _class_lookupMethodAndLoadCache
96 CALL_EXTERN(__class_lookupMethodAndLoadCache) | (class, selector);
99 movel sp@+,a1 | (restore a1)
100 Lexit2: jmp a0@ | goto *imp;
101 .space 22 | /* area for moninitobjc to write */
105 | locking version of objc_msgSend:
107 L11: clrb _messageLock+1 | (workaround 040 bug)
108 tas _messageLock | mutex_lock (messageLock);
111 L24: movel a0@,a0 | class = self->isa;
112 movel a1,sp@- | (save a1)
113 movel a0@(cache),a1 | cache = class->cache;
114 movel sp@(selector+4),d1 | index = selector;
115 L12: andl a1@,d1 | index &= cache->mask;
116 movel a1@(buckets,d1:l:4),d0 | method = cache->buckets[index];
117 movel d0,a0 | if (method == NULL)
118 jne L13 | goto cache_miss;
120 L13: movel sp@(selector+4),d0 |
121 cmpl a0@,d0 | if (method_name == selector)
122 jeq L14 | goto cache_hit;
123 addql #1,d1 | index++
125 L14: movel a0@(method_imp),a0 | imp = method->method_imp;
126 movel sp@+,a1 | (restore a1)
127 clrb _messageLock | mutex_unlock (messageLock);
128 Lexit3: jmp a0@ | goto *imp;
129 .space 22 | /* area for moninitobjc to write */
130 L15: movel sp@(self+4),a0 | cache_miss:
131 movel sp@(selector+4),sp@- | imp =
132 movel a0@,sp@- | _class_lookupMethodAndLoadCache
133 CALL_EXTERN_AGAIN(__class_lookupMethodAndLoadCache) | (class, selector);
136 movel sp@+,a1 | (restore a1)
137 clrb _messageLock | mutex_unlock (messageLock);
138 Lexit4: jmp a0@ | goto *imp;
139 .space 22 | /* area for moninitobjc to write */
145 | optimized for 68040: 31 clocks (best case) + 16 clocks / probe
148 .globl _objc_msgSendSuper
150 tstl __objc_multithread_mask | (1) if (_objc_multithread_mask == 0)
151 jne L20 | (2) goto lock;
153 L20: movel sp@(caller),a0 | (1)
154 movel a2,sp@- | (2) (save a2)
155 movel a0@+,sp@(self+4) | (2) self = caller->receiver;
156 movel a0@,a2 | (1) class = caller->class;
157 movel a1,sp@- | (2) (save a1)
158 movel a2@(cache),a1 | (1) cache = class->cache;
159 movel sp@(selector+8),d1 | (1) index = selector;
160 L6: andl a1@,d1 | (1) index &= cache->mask;
161 movel a1@(buckets,d1:l:4),d0 | (4) method = cache->buckets[index];
162 movel d0,a0 | (1) if (method == NULL)
163 jne L7 | (2) goto cache_miss;
165 L7: movel sp@(selector+8),d0 | (1)
166 cmpl a0@,d0 | (1) if (method_name == selector)
167 jeq L8 | (2) goto cache_hit;
168 addql #1,d1 | index++
170 L8: movel a0@(method_imp),a0 | (1) imp = method->method_imp;
171 movel sp@+,a1 | (1) (restore a1)
172 movel sp@+,a2 | (1) (restore a2)
173 Lexit5: jmp a0@ | (3) goto *imp;
174 .space 22 | /* area for moninitobjc to write */
175 L9: movel sp@(selector+8),sp@- | imp =
176 movel a2,sp@- | _class_lookupMethodAndLoadCache
177 CALL_EXTERN_AGAIN(__class_lookupMethodAndLoadCache) | (class, selector);
180 movel sp@+,a1 | (restore a1)
181 movel sp@+,a2 | (restore a2)
182 Lexit6: jmp a0@ | goto *imp;
183 .space 22 | /* area for moninitobjc to write */
187 | locking version of objc_msgSendSuper:
189 L21: clrb _messageLock+1 | (workaround 040 bug)
190 tas _messageLock | mutex_lock (messageLock);
193 L27: movel sp@(caller),a0 |
194 movel a2,sp@- | (save a2)
195 movel a0@+,sp@(self+4) | self = caller->receiver;
196 movel a0@,a2 | class = caller->class;
197 movel a1,sp@- | (save a1)
198 movel a2@(cache),a1 | cache = class->cache;
199 movel sp@(selector+8),d1 | index = selector;
200 L16: andl a1@,d1 | index &= cache->mask;
201 movel a1@(buckets,d1:l:4),d0 | method = cache->buckets[index];
202 movel d0,a0 | if (method == NULL)
203 jne L17 | goto cache_miss;
205 L17: movel sp@(selector+8),d0 |
206 cmpl a0@,d0 | if (method_name == selector)
207 jeq L18 | goto cache_hit;
208 addql #1,d1 | index++
210 L18: movel a0@(method_imp),a0 | imp = method->method_imp;
211 movel sp@+,a1 | (restore a1)
212 movel sp@+,a2 | (restore a2)
213 clrb _messageLock | mutex_unlock (messageLock);
214 Lexit7: jmp a0@ | goto *imp;
215 .space 22 | /* area for moninitobjc to write */
216 L19: movel sp@(selector+8),sp@- | imp =
217 movel a2,sp@- | _class_lookupMethodAndLoadCache
218 CALL_EXTERN_AGAIN(__class_lookupMethodAndLoadCache) | (class, selector);
221 movel sp@+,a1 | (restore a1)
222 movel sp@+,a2 | (restore a2)
223 clrb _messageLock | mutex_unlock (messageLock);
224 Lexit8: jmp a0@ | goto *imp;
225 .space 22 | /* area for moninitobjc to write */
230 L30: .ascii "forward::\0"
238 L32: .ascii "Does not recognize selector %s\0"
242 .globl __objc_msgForward
244 linkw a6,#0x0 | set up frame pointer
245 movel sp@(selector+4),d0 | +n accounts for sp pushes
246 cmpl L31,d0 | if (sel == @selector (forward::))
248 pea L30 | __objc_error (self,
249 pea L32 | _errDoesntRecognize
250 movel sp@(self+12),sp@- | "forward::");
251 BRANCH_EXTERN(___objc_error) |
252 L33: pea sp@(self+4) | return [self forward: sel : &self];
255 movel sp@(self+16),sp@- |
257 unlk a6 | clear frame pointer
266 .globl _objc_msgSendv
269 movel a6@(size+4),d0 |
270 addql #3,d0 | size = round_up (size, 4);
271 andl #0xfffffffc,d0 |
272 movel a6@(args+4),a0 |
273 addl d0,a0 | arg_ptr = &args[size];
274 subql #8,d0 | size -= 8;
275 ble L35 | while (size > 0)
276 L34: movel a0@-,sp@- | *--sp = *--arg_ptr;
277 subql #4,d0 | size -= 4;
279 L35: movel a6@(selector+4),sp@- |
280 movel a6@(self+4),sp@- | objc_msgSend (self, selector, ...);
282 unlk a6 | (deallocate variable storage)