|
|
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 objc ! 26: # to get the critical egions for which method caches ! 27: # cannot be garbage collected. ! 28: ! 29: .data ! 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 Lexit5 ! 41: .long Lexit9 ! 42: .long 0 ! 43: #endif /* KERNEL */ ! 44: ! 45: // Objective-C message dispatching for the i386 ! 46: ! 47: // arguments ! 48: self = 4 ! 49: selector = 8 ! 50: // structure indices ! 51: isa = 0 ! 52: cache = 32 ! 53: buckets = 8 ! 54: mask = 0 ! 55: method_name = 0 ! 56: method_imp = 8 ! 57: ! 58: // Objective-C method send ! 59: ! 60: .text ! 61: .globl _objc_msgSend ! 62: .align 4 ! 63: _objc_msgSend: ! 64: #ifdef PROFILE ! 65: pushl %ebp ! 66: movl %esp,%ebp ! 67: movl $LP0,%eax ! 68: call mcount ! 69: .data ! 70: .align 2 ! 71: LP0: ! 72: .long 0 ! 73: .text ! 74: movl %ebp,%esp ! 75: popl %ebp ! 76: #endif ! 77: movl self(%esp), %eax ! 78: ! 79: // if receiver is nil ! 80: orl %eax, %eax ! 81: je L1nil_or_multi ! 82: ! 83: // load variables and save caller registers. ! 84: // Overlapped to prevent AGI ! 85: movl selector(%esp), %ecx // (1) ! 86: movl isa(%eax), %eax // (1) class = self->isa; ! 87: pushl %edi // (1) ! 88: movl cache(%eax), %eax // (1) cache = class->cache; ! 89: pushl %esi // (1) ! 90: ! 91: lea buckets(%eax), %edi // (1) buckets = &cache->buckets; ! 92: movl mask(%eax), %esi // (1) mask = cache->mask; ! 93: movl %ecx, %edx // (1) index = selector; ! 94: ! 95: L1probe_cache: ! 96: andl %esi, %edx // (1) index &= mask; ! 97: movl (%edi, %edx, 4), %eax // (2) method_name = buckets[index]; ! 98: ! 99: orl %eax, %eax // (1) if (method != NULL) { ! 100: je L1cache_miss // (1) ! 101: cmpl method_name(%eax), %ecx // (1) method_name = method->name; ! 102: jne L1not_the_method // (1) if (method_name == selector) { ! 103: movl method_imp(%eax), %eax // (1) imp = method->method_imp; ! 104: popl %esi // (1) ! 105: popl %edi // (1) ! 106: Lexit1: jmp *%eax // (1) goto *imp; ! 107: .space 17 // area for moninitobjc to write ! 108: // } ! 109: L1not_the_method: ! 110: inc %edx // (1) index++; ! 111: jmp L1probe_cache // (1) } ! 112: ! 113: .align 4, 0x90 ! 114: L1cache_miss: ! 115: // restore caller registers ! 116: popl %esi // (1) ! 117: popl %edi // (1) ! 118: ! 119: movl self(%esp), %eax // (1) ! 120: movl isa(%eax), %eax // (1) ! 121: pushl %ecx // (1) ! 122: pushl %eax ! 123: call __class_lookupMethodAndLoadCache ! 124: addl $8, %esp ! 125: Lexit2: jmp *%eax ! 126: .space 17 // area for moninitobjc to write ! 127: ! 128: ! 129: L1nil_or_multi: ! 130: ret ! 131: ! 132: ! 133: ! 134: ! 135: // Objective-C Super Send ! 136: ! 137: // arguments ! 138: caller = 4 ! 139: // structure elements ! 140: reciever = 0 ! 141: class = 4 ! 142: ! 143: .globl _objc_msgSendSuper ! 144: .align 4 ! 145: _objc_msgSendSuper: ! 146: #ifdef PROFILE ! 147: pushl %ebp ! 148: movl %esp,%ebp ! 149: movl $LP1,%eax ! 150: call mcount ! 151: .data ! 152: .align 2 ! 153: LP1: ! 154: .long 0 ! 155: .text ! 156: movl %ebp,%esp ! 157: popl %ebp ! 158: #endif ! 159: ! 160: movl caller(%esp), %eax // (1) ! 161: movl selector(%esp), %ecx // (1) ! 162: ! 163: // load variables and save caller registers. ! 164: // Overlapped to prevent AGI ! 165: movl class(%eax), %eax // (1) class = caller->class; ! 166: pushl %edi // (1) ! 167: movl cache(%eax), %eax // (1) cache = class->cache; ! 168: pushl %esi // (1) ! 169: ! 170: lea buckets(%eax), %edi // (1) buckets = &cache->buckets; ! 171: movl mask(%eax), %esi // (1) mask = cache->mask; ! 172: movl %ecx, %edx // (1) index = selector; ! 173: ! 174: L2probe_cache: ! 175: andl %esi, %edx // (1) index &= mask; ! 176: movl (%edi, %edx, 4), %eax // (2) method_name = buckets[index]; ! 177: ! 178: orl %eax, %eax // (1) if (method != NULL) { ! 179: je L2cache_miss // (1) ! 180: cmpl method_name(%eax), %ecx // (1) method_name = method->name; ! 181: jne L2not_the_method // (1) if (method_name == selector) { ! 182: ! 183: // clobber "caller" arg with "self" and get method pointer ! 184: movl caller+8(%esp), %edi // (1) ! 185: movl method_imp(%eax), %eax // (1) imp = method->method_imp; ! 186: movl reciever(%edi), %esi // (1) ! 187: movl %esi, caller+8(%esp) // (1) ! 188: ! 189: // restore caller registers ! 190: popl %esi // (1) ! 191: popl %edi // (1) ! 192: Lexit5: jmp *%eax // (1) goto *imp; ! 193: .space 17 // area for moninitobjc to write ! 194: // } ! 195: // .align 4, 0x90 ! 196: L2not_the_method: ! 197: inc %edx // (1) index++; ! 198: jmp L2probe_cache // (1) } ! 199: ! 200: .align 4, 0x90 ! 201: L2cache_miss: ! 202: // clobber "caller" arg with "reciever" ! 203: movl caller+8(%esp), %edi // (1) ! 204: movl reciever(%edi), %esi // (1) ! 205: movl %esi, caller+8(%esp) // (1) ! 206: ! 207: // get class argument ! 208: movl class(%edi), %eax // (1) ! 209: ! 210: // restore caller registers ! 211: popl %esi // (1) ! 212: popl %edi // (1) ! 213: ! 214: // push args (class, selector) ! 215: pushl %ecx // (1) ! 216: pushl %eax ! 217: call __class_lookupMethodAndLoadCache ! 218: addl $8, %esp ! 219: Lexit6: jmp *%eax ! 220: .space 17 // area for moninitobjc to write ! 221: ! 222: ! 223: ! 224: // Objective-C message forwarder ! 225: ! 226: .objc_meth_var_names ! 227: .align 2 ! 228: L30: .ascii "forward::\0" ! 229: ! 230: .objc_message_refs ! 231: .align 2 ! 232: L31: .long L30 ! 233: ! 234: .cstring ! 235: .align 2 ! 236: L32: .ascii "Does not recognize selector %s\0" ! 237: ! 238: .text ! 239: .align 4 ! 240: .globl __objc_msgForward ! 241: __objc_msgForward: ! 242: pushl %ebp ! 243: movl %esp,%ebp ! 244: movl (selector+4)(%esp), %eax ! 245: cmpl L31, %eax ! 246: je L33 ! 247: ! 248: leal (self+4)(%esp), %ecx ! 249: pushl %ecx ! 250: pushl %eax ! 251: movl L31, %ecx ! 252: pushl %ecx ! 253: pushl (self + 16)(%esp) ! 254: call _objc_msgSend ! 255: movl %ebp,%esp ! 256: popl %ebp ! 257: ret ! 258: ! 259: .align 4 ! 260: L33: ! 261: pushl $L30 ! 262: pushl $L32 ! 263: pushl (self + 12)(%esp) ! 264: call ___objc_error // volatile, will not return ! 265: ! 266: ! 267: ! 268: // Objective-C vararg message send ! 269: ! 270: // arguments ! 271: args = 16 ! 272: size = 12 ! 273: sel = 8 ! 274: self = 4 ! 275: ! 276: .text ! 277: .align 4 ! 278: .globl _objc_msgSendv ! 279: _objc_msgSendv: ! 280: pushl %ebp ! 281: movl %esp, %ebp ! 282: movl (args + 4)(%ebp), %edx ! 283: addl $8, %edx // skip self & selector ! 284: movl (size + 4)(%ebp), %ecx ! 285: shrl $2, %ecx ! 286: subl $2, %ecx // skip self & selector ! 287: jle L42 ! 288: L41: ! 289: decl %ecx ! 290: movl 0(%edx, %ecx, 4), %eax ! 291: pushl %eax ! 292: jg L41 ! 293: ! 294: L42: ! 295: movl (sel + 4)(%ebp), %ecx ! 296: pushl %ecx ! 297: movl (self + 4)(%ebp),%ecx ! 298: pushl %ecx ! 299: call _objc_msgSend ! 300: movl %ebp,%esp ! 301: popl %ebp ! 302: Lexit9: ! 303: ret
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.