|
|
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.