Annotation of objc/objc-dispatch.c, revision 1.1.1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.