|
|
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: /*
25: * objc-dispatch.c
26: * Copyright 1988, NeXT, Inc.
27: * Author: s.naroff & s.stone
28: *
29: * Purpose: Compute implementation for method, and dispatch there,
30: * leaving all arguments undisturbed on the stack.
31: *
32: * Implementation:
33: *
34: * - caches are maintained on a `per-class' basis.
35: * - caches are allocated dynamically, sized proportional to all the
36: * methods that the class can respond to.
37: * - cache entries cost 4 bytes each. This saves memory and enables
38: * a cache load to be accomplished in an atomic assignment operation,
39: * removing the expensive `tas' operation. Because a cache load in the
40: * Stepstone messager consisted of 3 assignment operations <cls,sel,imp>
41: * they needed this instruction to enforce concurrency lockouts on
42: * cache slot access. This insured the `integrity' of the cache
43: * when sending messages from interrupt handlers. This makes the
44: * dispatcher more portable, considering many machines do not have or
45: * support (i.e. apollo) this instruction.
46: * - this cache supports collision resolution. Because we can estimate
47: * the number of elements in the cache (and are concerned about data
48: * space overhead), we use a simple open-addressing method called
49: * `linear probing'. If all probes are filled, we replace one of them.
50: * In this implementation, the length of a chain will be 8.
51: * - _msgSuper DOES NOT depend on retreiving `self' from the previous
52: * stack frame.
53: */
54:
55: #ifdef SHLIB
56: #import "shlib.h"
57: #endif SHLIB
58:
59: #include "objc.h"
60: #include "objc-private.h"
61: #include "objc-dispatch.h"
62: extern id (*_objc_msgPreop)(MSG, int, int);
63:
64: #define JMP(imp) \
65: /* load function address */ \
66: asm ("movel %0,a0" : "=m" (imp)); \
67: /* restore a1...for methods that return > 8 bytes quantities */ \
68: asm ("movel %0,a1" : "=m" (save_a1)); \
69: /* unlink stack frame */ \
70: asm ("unlk a6"); \
71: /* go to method */ \
72: asm ("jmp a0@");
73:
74: #if 0
75: /*
76: * Implement [anObject aSelector]
77: */
78: id objc_msgSend(id self, SEL sel, ...)
79: {
80: Class cls;
81: Method *buckets;
82: int index, mask, i;
83: IMP imp;
84: void *save_a1;
85:
86: asm ("movel a1,%0" : "=m" (save_a1));
87:
88: /* This provides the innocuous semantics for nil messages.
89: * Changing this to an error would reliably trap messages
90: * to nil objects.
91: */
92: if (self == nil)
93: return nil;
94:
95: cls = self->isa;
96:
97: mask = cls->cache->mask;
98: buckets = cls->cache->buckets;
99:
100: index = sel & mask;
101: for (;;) {
102: if (buckets[index] && (buckets[index]->method_name == sel))
103: goto cacheHit;
104: if (! buckets[index]) goto cacheMiss;
105: index++;
106: index &= mask;
107: }
108: cacheMiss:
109: imp = _class_lookupMethodAndLoadCache(cls, sel);
110:
111: if (_objc_msgPreop)
112: (*_objc_msgPreop)(GETFRAME(self), NO, NO);
113:
114: JMP(imp);
115:
116: cacheHit:
117: imp = buckets[index]->method_imp;
118:
119: if (_objc_msgPreop)
120: (*_objc_msgPreop)(GETFRAME(self), NO, YES);
121:
122: JMP(imp);
123: }
124: #endif
125: /*
126: * Implement [super aSelector]
127: */
128: id objc_msgSendSuper(struct objc_super *caller, SEL sel, ...)
129: {
130: id self; Class cls;
131: Method *buckets;
132: int index, mask, i;
133: IMP imp;
134: void *save_a1;
135:
136: asm ("movel a1,%0" : "=m" (save_a1));
137:
138: /* Fetch the caller's value for "self". */
139: cls = caller->class;
140:
141: /* replace `caller' with the real receiver */
142: caller = (struct objc_super *)self = caller->receiver;
143:
144: /* Unlikely, but not impossible */
145: if (self == nil)
146: return nil;
147:
148: mask = cls->cache->mask;
149: buckets = cls->cache->buckets;
150:
151: index = sel & mask;
152: for (;;) {
153: if (buckets[index] && (buckets[index]->method_name == sel))
154: goto cacheHit;
155: if (! buckets[index]) goto cacheMiss;
156: index++;
157: index &= mask;
158: }
159:
160: cacheMiss:
161: imp = _class_lookupMethodAndLoadCache(cls, sel);
162:
163: if (_objc_msgPreop)
164: (*_objc_msgPreop)(GETFRAME(self), YES, NO);
165:
166: JMP(imp);
167:
168: cacheHit:
169: imp = buckets[index]->method_imp;
170:
171: if (_objc_msgPreop)
172: (*_objc_msgPreop)(GETFRAME(self), YES, YES);
173:
174: JMP(imp);
175: }
176:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.