objc-sel.mm 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. /*
  2. * Copyright (c) 2012 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. #if __OBJC2__
  24. #include "objc-private.h"
  25. #include "objc-cache.h"
  26. #if SUPPORT_PREOPT
  27. static const objc_selopt_t *builtins = NULL;
  28. #endif
  29. static size_t SelrefCount = 0;
  30. static NXMapTable *namedSelectors;
  31. static SEL search_builtins(const char *key);
  32. /***********************************************************************
  33. * sel_init
  34. * Initialize selector tables and register selectors used internally.
  35. **********************************************************************/
  36. void sel_init(size_t selrefCount)
  37. {
  38. // save this value for later
  39. SelrefCount = selrefCount;
  40. #if SUPPORT_PREOPT
  41. builtins = preoptimizedSelectors();
  42. if (PrintPreopt && builtins) {
  43. uint32_t occupied = builtins->occupied;
  44. uint32_t capacity = builtins->capacity;
  45. _objc_inform("PREOPTIMIZATION: using selopt at %p", builtins);
  46. _objc_inform("PREOPTIMIZATION: %u selectors", occupied);
  47. _objc_inform("PREOPTIMIZATION: %u/%u (%u%%) hash table occupancy",
  48. occupied, capacity,
  49. (unsigned)(occupied/(double)capacity*100));
  50. }
  51. #endif
  52. // Register selectors used by libobjc
  53. #define s(x) SEL_##x = sel_registerNameNoLock(#x, NO)
  54. #define t(x,y) SEL_##y = sel_registerNameNoLock(#x, NO)
  55. mutex_locker_t lock(selLock);
  56. s(load);
  57. s(initialize);
  58. t(resolveInstanceMethod:, resolveInstanceMethod);
  59. t(resolveClassMethod:, resolveClassMethod);
  60. t(.cxx_construct, cxx_construct);
  61. t(.cxx_destruct, cxx_destruct);
  62. s(retain);
  63. s(release);
  64. s(autorelease);
  65. s(retainCount);
  66. s(alloc);
  67. t(allocWithZone:, allocWithZone);
  68. s(dealloc);
  69. s(copy);
  70. s(new);
  71. t(forwardInvocation:, forwardInvocation);
  72. t(_tryRetain, tryRetain);
  73. t(_isDeallocating, isDeallocating);
  74. s(retainWeakReference);
  75. s(allowsWeakReference);
  76. #undef s
  77. #undef t
  78. }
  79. static SEL sel_alloc(const char *name, bool copy)
  80. {
  81. selLock.assertLocked();
  82. return (SEL)(copy ? strdupIfMutable(name) : name);
  83. }
  84. const char *sel_getName(SEL sel)
  85. {
  86. if (!sel) return "<null selector>";
  87. return (const char *)(const void*)sel;
  88. }
  89. BOOL sel_isMapped(SEL sel)
  90. {
  91. if (!sel) return NO;
  92. const char *name = (const char *)(void *)sel;
  93. if (sel == search_builtins(name)) return YES;
  94. mutex_locker_t lock(selLock);
  95. if (namedSelectors) {
  96. return (sel == (SEL)NXMapGet(namedSelectors, name));
  97. }
  98. return false;
  99. }
  100. static SEL search_builtins(const char *name)
  101. {
  102. #if SUPPORT_PREOPT
  103. if (builtins) return (SEL)builtins->get(name);
  104. #endif
  105. return nil;
  106. }
  107. static SEL __sel_registerName(const char *name, bool shouldLock, bool copy)
  108. {
  109. SEL result = 0;
  110. if (shouldLock) selLock.assertUnlocked();
  111. else selLock.assertLocked();
  112. if (!name) return (SEL)0;
  113. result = search_builtins(name);
  114. if (result) return result;
  115. conditional_mutex_locker_t lock(selLock, shouldLock);
  116. if (namedSelectors) {
  117. result = (SEL)NXMapGet(namedSelectors, name);
  118. }
  119. if (result) return result;
  120. // No match. Insert.
  121. if (!namedSelectors) {
  122. namedSelectors = NXCreateMapTable(NXStrValueMapPrototype,
  123. (unsigned)SelrefCount);
  124. }
  125. if (!result) {
  126. result = sel_alloc(name, copy);
  127. // fixme choose a better container (hash not map for starters)
  128. NXMapInsert(namedSelectors, sel_getName(result), result);
  129. }
  130. return result;
  131. }
  132. SEL sel_registerName(const char *name) {
  133. return __sel_registerName(name, 1, 1); // YES lock, YES copy
  134. }
  135. SEL sel_registerNameNoLock(const char *name, bool copy) {
  136. return __sel_registerName(name, 0, copy); // NO lock, maybe copy
  137. }
  138. // 2001/1/24
  139. // the majority of uses of this function (which used to return NULL if not found)
  140. // did not check for NULL, so, in fact, never return NULL
  141. //
  142. SEL sel_getUid(const char *name) {
  143. return __sel_registerName(name, 2, 1); // YES lock, YES copy
  144. }
  145. BOOL sel_isEqual(SEL lhs, SEL rhs)
  146. {
  147. return bool(lhs == rhs);
  148. }
  149. #endif