1/* 2 * Copyright (c) 1999-2007 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24/* 25 * Utilities for registering and looking up selectors. The sole 26 * purpose of the selector tables is a registry whereby there is 27 * exactly one address (selector) associated with a given string 28 * (method name). 29 */ 30 31#if !__OBJC2__ 32 33#include "objc-private.h" 34#include "objc-sel-set.h" 35 36#if SUPPORT_PREOPT 37#include <objc-shared-cache.h> 38static const objc_selopt_t *builtins = NULL; 39#endif 40 41__BEGIN_DECLS 42 43static size_t SelrefCount = 0; 44 45static const char *_objc_empty_selector = ""; 46static struct __objc_sel_set *_objc_selectors = NULL; 47 48 49static SEL _objc_search_builtins(const char *key) 50{ 51#if defined(DUMP_SELECTORS) 52 if (NULL != key) printf("\t\"%s\",\n", key); 53#endif 54 55 if (!key) return (SEL)0; 56#if SUPPORT_IGNORED_SELECTOR_CONSTANT 57 if ((uintptr_t)key == kIgnore) return (SEL)kIgnore; 58 if (ignoreSelectorNamed(key)) return (SEL)kIgnore; 59#endif 60 if ('\0' == *key) return (SEL)_objc_empty_selector; 61 62#if SUPPORT_PREOPT 63 if (builtins) return (SEL)builtins->get(key); 64#endif 65 66 return (SEL)0; 67} 68 69 70const char *sel_getName(SEL sel) { 71#if SUPPORT_IGNORED_SELECTOR_CONSTANT 72 if ((uintptr_t)sel == kIgnore) return "<ignored selector>"; 73#endif 74 return sel ? (const char *)sel : "<null selector>"; 75} 76 77 78BOOL sel_isMapped(SEL name) 79{ 80 SEL result; 81 82 if (!name) return NO; 83#if SUPPORT_IGNORED_SELECTOR_CONSTANT 84 if ((uintptr_t)name == kIgnore) return YES; 85#endif 86 87 result = _objc_search_builtins((const char *)name); 88 if (result) return YES; 89 90 rwlock_read(&selLock); 91 if (_objc_selectors) { 92 result = __objc_sel_set_get(_objc_selectors, name); 93 } 94 rwlock_unlock_read(&selLock); 95 return result ? YES : NO; 96} 97 98static SEL __sel_registerName(const char *name, int lock, int copy) 99{ 100 SEL result = 0; 101 102 if (lock) rwlock_assert_unlocked(&selLock); 103 else rwlock_assert_writing(&selLock); 104 105 if (!name) return (SEL)0; 106 result = _objc_search_builtins(name); 107 if (result) return result; 108 109 if (lock) rwlock_read(&selLock); 110 if (_objc_selectors) { 111 result = __objc_sel_set_get(_objc_selectors, (SEL)name); 112 } 113 if (lock) rwlock_unlock_read(&selLock); 114 if (result) return result; 115 116 // No match. Insert. 117 118 if (lock) rwlock_write(&selLock); 119 120 if (!_objc_selectors) { 121 _objc_selectors = __objc_sel_set_create(SelrefCount); 122 } 123 if (lock) { 124 // Rescan in case it was added while we dropped the lock 125 result = __objc_sel_set_get(_objc_selectors, (SEL)name); 126 } 127 if (!result) { 128 result = (SEL)(copy ? _strdup_internal(name) : name); 129 __objc_sel_set_add(_objc_selectors, result); 130#if defined(DUMP_UNKNOWN_SELECTORS) 131 printf("\t\"%s\",\n", name); 132#endif 133 } 134 135 if (lock) rwlock_unlock_write(&selLock); 136 return result; 137} 138 139 140SEL sel_registerName(const char *name) { 141 return __sel_registerName(name, 1, 1); // YES lock, YES copy 142} 143 144SEL sel_registerNameNoLock(const char *name, BOOL copy) { 145 return __sel_registerName(name, 0, copy); // NO lock, maybe copy 146} 147 148void sel_lock(void) 149{ 150 rwlock_write(&selLock); 151} 152 153void sel_unlock(void) 154{ 155 rwlock_unlock_write(&selLock); 156} 157 158 159// 2001/1/24 160// the majority of uses of this function (which used to return NULL if not found) 161// did not check for NULL, so, in fact, never return NULL 162// 163SEL sel_getUid(const char *name) { 164 return __sel_registerName(name, 2, 1); // YES lock, YES copy 165} 166 167 168BOOL sel_isEqual(SEL lhs, SEL rhs) 169{ 170 return (lhs == rhs) ? YES : NO; 171} 172 173 174/*********************************************************************** 175* sel_preoptimizationValid 176* Return YES if this image's selector fixups are valid courtesy 177* of the dyld shared cache. 178**********************************************************************/ 179BOOL sel_preoptimizationValid(const header_info *hi) 180{ 181#if !SUPPORT_PREOPT 182 183 return NO; 184 185#else 186 187# if SUPPORT_IGNORED_SELECTOR_CONSTANT 188 // shared cache can't fix constant ignored selectors 189 if (UseGC) return NO; 190# endif 191 192 // preoptimization disabled for some reason 193 if (!isPreoptimized()) return NO; 194 195 // image not from shared cache, or not fixed inside shared cache 196 if (!_objcHeaderOptimizedByDyld(hi)) return NO; 197 198 return YES; 199 200#endif 201} 202 203 204/*********************************************************************** 205* sel_init 206* Initialize selector tables and register selectors used internally. 207**********************************************************************/ 208void sel_init(BOOL wantsGC, size_t selrefCount) 209{ 210 // save this value for later 211 SelrefCount = selrefCount; 212 213#if SUPPORT_PREOPT 214 builtins = preoptimizedSelectors(); 215#endif 216 217 // Register selectors used by libobjc 218 219 if (wantsGC) { 220 // Registering retain/release/autorelease requires GC decision first. 221 // sel_init doesn't actually need the wantsGC parameter, it just 222 // helps enforce the initialization order. 223 } 224 225#define s(x) SEL_##x = sel_registerNameNoLock(#x, NO) 226#define t(x,y) SEL_##y = sel_registerNameNoLock(#x, NO) 227 228 sel_lock(); 229 230 s(load); 231 s(initialize); 232 t(resolveInstanceMethod:, resolveInstanceMethod); 233 t(resolveClassMethod:, resolveClassMethod); 234 t(.cxx_construct, cxx_construct); 235 t(.cxx_destruct, cxx_destruct); 236 s(retain); 237 s(release); 238 s(autorelease); 239 s(retainCount); 240 s(alloc); 241 t(allocWithZone:, allocWithZone); 242 s(dealloc); 243 s(copy); 244 s(new); 245 s(finalize); 246 t(forwardInvocation:, forwardInvocation); 247 t(_tryRetain, tryRetain); 248 t(_isDeallocating, isDeallocating); 249 s(retainWeakReference); 250 s(allowsWeakReference); 251 252 extern SEL FwdSel; 253 FwdSel = sel_registerNameNoLock("forward::", NO); 254 255 sel_unlock(); 256 257#undef s 258#undef t 259} 260 261__END_DECLS 262 263#endif 264