|
|
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: #ifdef DYLIB ! 25: #error Building of SPARC dynashlib not supported yet! ! 26: #endif ! 27: ! 28: #ifdef KERNEL ! 29: #define OBJC_LOCK_ROUTINE _simple_lock ! 30: #else ! 31: #define OBJC_LOCK_ROUTINE _spin_lock ! 32: #endif /* KERNEL */ ! 33: ! 34: #define CLEARLOW22 0xffc00000 /* mask to clear off low 22 bits */ ! 35: ! 36: ! 37: #define isa 0 ! 38: #define cache 32 ! 39: #define mask 0 ! 40: #define buckets 8 ! 41: #define method_name 0 ! 42: #define method_imp 8 ! 43: #define receiver 0 ! 44: #define class 4 ! 45: ! 46: ! optimized for sparc: 26 clocks (best case) + 7 clocks/probe ! 47: ! 48: .text ! 49: .globl _objc_msgSend ! 50: ! 51: ! ObjC message send: ! 52: ! Arguments: %i0 - receiver (self) ! 53: ! %i1 - selector ! 54: ! %i2.. - arguments ! 55: ! 56: _objc_msgSend: ! 57: save %sp,-96,%sp ! save register windows ! 58: ! 59: ! test for nil argument and locking requirements ! 60: sethi %hi(__objc_multithread_mask),%l1 ! 61: ld [%l1+%lo(__objc_multithread_mask)],%l1 ! 62: andcc %l1,%i0,%l1 ! if (self & multi) ! 63: bnz,a L_normalCase ! then normalcase ! 64: ld [%i0+isa],%o0 ! class = self->isa (class arg) ! 65: ! 66: tst %i0 ! if (self) ! 67: bnz L_sendLocking ! lockingcase ! 68: nop ! 69: ! self is NIL, return ! 70: ld [%i7+8],%g3 // load instruction ! 71: sethi %hi(CLEARLOW22),%g2 // mask off low 22 bits ! 72: andcc %g3,%g2,%g0 // if 0, then its an UNIMP inst ! 73: bz L_struct_returnSend0 // and we will return a structure ! 74: nop // ! 75: ret // Get back, JoJo ! 76: restore // <ds> ! 77: L_struct_returnSend0: ! 78: jmp %i7 + 12 // convention for returning structs ! 79: restore // <ds> ! 80: ! 81: ! Init pointers to class and cache ! 82: L_normalCase: ! 83: ld [%o0+cache],%l4 ! cache <- class->cache ! 84: ld [%l4+mask],%l3 ! mask <- cache->mask ! 85: add %l4,buckets,%l2 ! buckets <- cache->buckets ! 86: and %i1,%l3,%l1 ! index <- selector & mask ! 87: ! 88: ! Try to find a method in the cache ! 89: L_loop: ! 90: sll %l1,2,%l6 ! adjust to word index ! 91: ld [%l2+%l6],%l4 ! method = buckets[index] ! 92: tst %l4 ! if (method == NULL) ! 93: bz,a L_cacheMiss ! handle cacheMiss case ! 94: mov %i1,%o1 ! (DS) selector arg for LoadCache ! 95: ! 96: ld [%l4+method_name],%l5! name = method->method_name ! 97: cmp %l5,%i1 ! if (name == selector) ! 98: be,a L_cacheHit ! goto hit ! 99: ld [%l4+method_imp],%o0! load method_imp pointer to call ! 100: ! 101: inc %l1 ! index++ ! 102: b L_loop ! check next cache entry ! 103: and %l1,%l3,%l1 ! index = index & mask ! 104: L_cacheMiss: ! 105: call __class_lookupMethodAndLoadCache ! 106: nop ! 107: L_cacheHit: ! 108: jmp %o0 ! ! 109: restore ! 110: ! 111: ! Locking version of objc_msgSend ! 112: ! spins on the mutex lock. ! 113: ! 114: L_sendLocking: ! 115: set (_messageLock),%l7! get the lock addr ! 116: set 1,%l1 ! lock code (1) ! 117: L_lockspin: ! 118: swap [%l7],%l1 ! try to set the lock ! 119: tst %l1 ! if lock was already set ! 120: bnz L_lockspin ! try again ! 121: set 1,%l1 ! lock code (1) ! 122: ! 123: ! got the lock, ready to proceed ! 124: ! 125: ld [%i0+isa],%o0 ! class = self->isa ! 126: ld [%o0+cache],%l4 ! cache = class->cache ! 127: ld [%l4+mask],%l3 ! mask = cache->mask ! 128: add %l4,buckets,%l2 ! buckets = cache->buckets ! 129: and %i1,%l3,%l1 ! index = selector & mask ! 130: ! 131: L_loop_lk: ! 132: sll %l1,2,%l6 ! adjust to word index ! 133: ld [%l2+%l6],%l4 ! method = buckets[index] ! 134: tst %l4 ! if (method == NULL) ! 135: bz,a L_cacheMiss_lk ! handle cacheMiss case ! 136: mov %i1,%o1 ! (DS) selector arg for LoadCache ! 137: ! 138: ld [%l4+method_name],%l5! name = method->method_name ! 139: cmp %l5,%i1 ! if (name == selector) ! 140: be,a L_cacheHit_lk ! goto hit ! 141: ld [%l4+method_imp],%o0 ! impl = method->method_imp ! 142: ! 143: inc %l1 ! index++ ! 144: b L_loop_lk ! check next cache entry ! 145: and %l1,%l3,%l1 ! index = index & mask ! 146: ! 147: L_cacheMiss_lk: ! 148: call __class_lookupMethodAndLoadCache ! 149: nop ! 150: L_cacheHit_lk: ! 151: swap [%l7],%g0 ! clear the lock ! 152: jmp %o0 ! 153: restore ! 154: ! 155: ! 156: .globl _objc_msgSendSuper ! 157: _objc_msgSendSuper: ! 158: save %sp,-120,%sp ! save register window ! 159: ld [%i0+receiver],%l0 ! receiver = caller->receiver ! 160: tst %l0 ! if (receiver) ! 161: bnz L_receiver ! work on it ! 162: st %l0,[%fp+68] ! <delay slot> save a copy ! 163: L_noreceiver: ! return on NULL receiver ! 164: ld [%i7+8],%g3 // load instruction ! 165: sethi %hi(CLEARLOW22),%g2 // mask off low 22 bits ! 166: andcc %g3,%g2,%g0 // if 0, then its an UNIMP inst ! 167: bz L_struct_returnSend1 // and we will return a structure ! 168: nop // ! 169: ret // Get back, JoJo ! 170: restore // <ds> ! 171: L_struct_returnSend1: ! 172: jmp %i7 + 12 // convention for returning structs ! 173: restore // <ds> ! 174: ! 175: L_receiver: ! 176: sethi %hi(__objc_multithread_mask),%l1 ! 177: ld [%l1+%lo(__objc_multithread_mask)],%l1 ! 178: tst %l1 ! 179: bz L_superLock ! 180: ld [%i0+class],%o0 ! class = caller->class ! 181: ld [%o0+cache],%l4 ! cache = class->cache ! 182: ld [%l4+mask],%l3 ! mask = cache->mask ! 183: add %l4,buckets,%l2 ! buckets = cache->buckets ! 184: and %i1,%l3,%l1 ! index = selector & mask ! 185: ! 186: L_super_loop: ! 187: sll %l1,2,%l6 ! adjust to word index ! 188: ld [%l2+%l6],%l4 ! method = buckets[index] ! 189: tst %l4 ! if (method == NULL) ! 190: bz,a L_super_cacheMiss ! handle cacheMiss case ! 191: mov %i1,%o1 ! (DS) selector arg for LoadCache ! 192: ! 193: ld [%l4+method_name],%l5! name = method->method_name ! 194: cmp %l5,%i1 ! if (name == selector) ! 195: be L_super_cacheHit ! goto hit ! 196: ld [%l4+method_imp],%g1 ! method = buckets[index] ! 197: ! 198: inc %l1 ! index++ ! 199: b L_super_loop ! check next cache entry ! 200: and %l1,%l3,%l1 ! index = index & mask ! 201: ! 202: L_super_cacheMiss: ! 203: call __class_lookupMethodAndLoadCache ! 204: nop ! 205: mov %o0,%g1 ! save result from Loadcache ! 206: restore ! 207: jmp %g1 ! 208: ld [%sp+68],%o0 ! restore receiver ! 209: ! 210: ! 211: L_super_cacheHit: ! 212: restore ! 213: jmp %g1 ! 214: ld [%sp+68],%o0 ! restore receiver ! 215: ! 216: ! 217: ! locking version of objc_msgSendSuper ! 218: ! spins on the mutex lock ! 219: ! 220: L_superLock: ! 221: sethi %hi(_messageLock),%l1! aquire the lock addr ! 222: or %l1,%lo(_messageLock),%l7 ! 223: L_super_lockspin: ! 224: ldstub [%l7],%l1 ! try to set the lock ! 225: tst %l1 ! if lock was already set ! 226: bne L_super_lockspin ! try again ! 227: nop ! 228: ! 229: ! got the lock, ready to proceed ! 230: ! %o0 = class [set above] ! 231: ld [%o0+cache],%l4 ! cache = class->cache ! 232: ld [%l4+mask],%l3 ! mask = cache->mask ! 233: add %l4,buckets,%l2 ! buckets = cache->buckets ! 234: and %i1,%l3,%l1 ! index = selector & mask ! 235: ! 236: L_super_loop_lk: ! 237: sll %l1,2,%l6 ! adjust to word index ! 238: ld [%l2+%l6],%l4 ! method = buckets[index] ! 239: tst %l4 ! if (method == NULL) ! 240: bz,a L_super_cacheMiss_lk ! handle cacheMiss case ! 241: mov %i1,%o1 ! (DS) selector arg for LoadCache ! 242: ! 243: ld [%l4+method_name],%l5! name = method->method_name ! 244: cmp %l5,%i1 ! if (name == selector) ! 245: be L_super_cacheHit_lk ! goto hit ! 246: ld [%l4+method_imp],%g1 ! impl = method->method_imp ! 247: ! 248: inc %l1 ! index++ ! 249: b L_super_loop_lk ! check next cache entry ! 250: and %l1,%l3,%l1 ! index = index & mask ! 251: ! 252: L_super_cacheMiss_lk: ! 253: call __class_lookupMethodAndLoadCache ! 254: nop ! 255: mov %o0,%g1 ! save result from Loadcache ! 256: st %g0,[%l7] ! clear lock ! 257: restore ! 258: jmp %g1 ! 259: ld [%sp+68],%o0 ! restore receiver ! 260: ! 261: L_super_cacheHit_lk: ! 262: st %g0,[%l7] ! clear the lock ! 263: restore ! 264: jmp %g1 ! 265: ld [%sp+68],%o0 ! restore receiver ! 266: ! 267: ! 268: .objc_meth_var_names ! 269: .align 1 ! 270: L30: .ascii "forward::\0" ! 271: ! 272: .objc_message_refs ! 273: .align 2 ! 274: L31: .long L30 ! 275: ! 276: .cstring ! 277: .align 1 ! 278: L32: .ascii "Does not recognize selector %s\0" ! 279: ! 280: .text ! 281: .align 2 ! 282: ! 283: .globl __objc_msgForward ! 284: __objc_msgForward: ! 285: save %sp,-96,%sp ! 286: sethi %hi(L31),%g2 ! 287: ld [%g2+%lo(L31)],%g2 ! 288: cmp %i1,%g2 ! if (selector == @selector(forward::)) ! 289: be L_error ! 290: nop ! 291: add %fp,68,%g1 ! ptr to stack area ! 292: st %i0,[%g1] ! 293: st %i1,[%g1+4] ! 294: st %i2,[%g1+8] ! 295: st %i3,[%g1+12] ! 296: st %i4,[%g1+16] ! 297: st %i5,[%g1+20] ! 298: mov %i1,%o2 ! 299: mov %g2,%o1 ! 300: mov %g1,%o3 ! 301: call _objc_msgSend ! 302: mov %i0,%o0 ! 303: ret ! 304: restore %g0,%o0,%o0 ! 305: ! 306: L_error: ! 307: mov %i1, %o2 ! 308: set L32,%i1 ! 309: ba __objc_error ! never returns ! 310: nop ! 311: ! 312: ! 313: ! id objc_msgSendv(id self, SEL sel, unsigned size, marg_list args) ! 314: ! 315: .globl _objc_msgSendv ! 316: _objc_msgSendv: ! 317: add %g0,-96,%g1 ! Get min stack size + 4 (rounded by 8) ! 318: subcc %o2,28,%g2 ! Get size of non reg params + 4 ! 319: ble Lsave_stack ! None or 1, so skip making stack larger ! 320: sub %g1,%g2,%g2 ! Add local size to minimum stack ! 321: and %g2,-8,%g1 ! Need to round to 8 bit boundary ! 322: Lsave_stack: ! 323: save %sp,%g1,%sp ! Save min stack + 4 for 8 byte bound! ... ! 324: mov %i0,%o0 ! 325: mov %i1,%o1 ! 326: addcc %i2,-8,%i2 ! adjust for first 2 args (self & sel) ! 327: be L_send_msg ! 328: nop ! 329: ! 330: ld [%i3+8],%o2 ! get 3rd arg ! 331: addcc %i2,-4,%i2 ! size-- ! 332: be L_send_msg ! 333: nop ! 334: ! 335: ld [%i3+12],%o3 ! arg 4 ! 336: addcc %i2,-4,%i2 ! size-- ! 337: be L_send_msg ! 338: nop ! 339: ! 340: ld [%i3+16],%o4 ! arg 5 ! 341: addcc %i2,-4,%i2 ! size-- ! 342: be L_send_msg ! 343: nop ! 344: ! 345: ld [%i3+20],%o5 ! arg 6 ! 346: addcc %i2,-4,%i2 ! size-- ! 347: be L_send_msg ! 348: nop ! 349: add %i3,24,%i1 ! %i1 = args + 24 ! 350: add %sp,92,%i5 ! 351: L_loopv: ! deal with remaining args ! 352: ld [%i1],%i3 ! 353: addcc %i2,-4,%i2 ! size-- ! 354: st %i3,[%i5] ! 355: add %i5,4,%i5 ! 356: bnz L_loopv ! 357: add %i1,4,%i1 ! arg++ ! 358: ! 359: L_send_msg: ! 360: ld [%i7+8],%g3 ! load instruction ! 361: sethi %hi(CLEARLOW22),%g2 ! 362: andcc %g3,%g2,%g0 ! if 0 it is an UNIMP inst ! 363: be L_struct_returnSendv! return a structure ! 364: nop ! 365: ! 366: ! Case of no struct returned ! 367: ! 368: call _objc_msgSend ! 369: nop ! 370: mov %o0,%i0 ! Ret int, 1st half ! 371: ret ! ... of long long ! 372: restore %o1,0,%o1 ! 2nd half of ll ! 373: ! 374: L_struct_returnSendv: ! 375: ld [%fp+64],%g2 ! 376: st %g2,[%sp+64] ! 377: call _objc_msgSend ! 378: nop ! 379: unimp 0 ! 380: jmp %i7+12 ! 381: restore
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.