objc-sel.mm 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  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. #include "DenseMapExtras.h"
  27. #if SUPPORT_PREOPT
  28. static const objc_selopt_t *builtins = NULL;
  29. static bool useDyldSelectorLookup = false;
  30. #endif
  31. static objc::ExplicitInitDenseSet<const char *> namedSelectors;
  32. static SEL search_builtins(const char *key);
  33. /***********************************************************************
  34. * sel_init
  35. * Initialize selector tables and register selectors used internally.
  36. **********************************************************************/
  37. void sel_init(size_t selrefCount)
  38. {
  39. #if SUPPORT_PREOPT
  40. // If dyld finds a known shared cache selector, then it must be also looking
  41. // in the shared cache table.
  42. if (_dyld_get_objc_selector("retain") != nil)
  43. useDyldSelectorLookup = true;
  44. else
  45. builtins = preoptimizedSelectors();
  46. if (PrintPreopt && useDyldSelectorLookup) {
  47. _objc_inform("PREOPTIMIZATION: using dyld selector opt");
  48. }
  49. if (PrintPreopt && builtins) {
  50. uint32_t occupied = builtins->occupied;
  51. uint32_t capacity = builtins->capacity;
  52. _objc_inform("PREOPTIMIZATION: using selopt at %p", builtins);
  53. _objc_inform("PREOPTIMIZATION: %u selectors", occupied);
  54. _objc_inform("PREOPTIMIZATION: %u/%u (%u%%) hash table occupancy",
  55. occupied, capacity,
  56. (unsigned)(occupied/(double)capacity*100));
  57. }
  58. namedSelectors.init(useDyldSelectorLookup ? 0 : (unsigned)selrefCount);
  59. #else
  60. namedSelectors.init((unsigned)selrefCount);
  61. #endif
  62. // Register selectors used by libobjc
  63. mutex_locker_t lock(selLock);
  64. SEL_cxx_construct = sel_registerNameNoLock(".cxx_construct", NO);
  65. SEL_cxx_destruct = sel_registerNameNoLock(".cxx_destruct", NO);
  66. }
  67. static SEL sel_alloc(const char *name, bool copy)
  68. {
  69. selLock.assertLocked();
  70. return (SEL)(copy ? strdupIfMutable(name) : name);
  71. }
  72. const char *sel_getName(SEL sel)
  73. {
  74. if (!sel) return "<null selector>";
  75. return (const char *)(const void*)sel;
  76. }
  77. BOOL sel_isMapped(SEL sel)
  78. {
  79. if (!sel) return NO;
  80. const char *name = (const char *)(void *)sel;
  81. if (sel == search_builtins(name)) return YES;
  82. mutex_locker_t lock(selLock);
  83. auto it = namedSelectors.get().find(name);
  84. return it != namedSelectors.get().end() && (SEL)*it == sel;
  85. }
  86. static SEL search_builtins(const char *name)
  87. {
  88. #if SUPPORT_PREOPT
  89. if (builtins) {
  90. SEL result = 0;
  91. if ((result = (SEL)builtins->get(name)))
  92. return result;
  93. if ((result = (SEL)_dyld_get_objc_selector(name)))
  94. return result;
  95. } else if (useDyldSelectorLookup) {
  96. if (SEL result = (SEL)_dyld_get_objc_selector(name))
  97. return result;
  98. }
  99. #endif
  100. return nil;
  101. }
  102. static SEL __sel_registerName(const char *name, bool shouldLock, bool copy)
  103. {
  104. SEL result = 0;
  105. if (shouldLock) selLock.assertUnlocked();
  106. else selLock.assertLocked();
  107. if (!name) return (SEL)0;
  108. result = search_builtins(name);
  109. if (result) return result;
  110. conditional_mutex_locker_t lock(selLock, shouldLock);
  111. auto it = namedSelectors.get().insert(name);
  112. if (it.second) {
  113. // No match. Insert.
  114. *it.first = (const char *)sel_alloc(name, copy);
  115. }
  116. return (SEL)*it.first;
  117. }
  118. SEL sel_registerName(const char *name) {
  119. return __sel_registerName(name, 1, 1); // YES lock, YES copy
  120. }
  121. SEL sel_registerNameNoLock(const char *name, bool copy) {
  122. return __sel_registerName(name, 0, copy); // NO lock, maybe copy
  123. }
  124. // 2001/1/24
  125. // the majority of uses of this function (which used to return NULL if not found)
  126. // did not check for NULL, so, in fact, never return NULL
  127. //
  128. SEL sel_getUid(const char *name) {
  129. return __sel_registerName(name, 2, 1); // YES lock, YES copy
  130. }
  131. BOOL sel_isEqual(SEL lhs, SEL rhs)
  132. {
  133. return bool(lhs == rhs);
  134. }
  135. #endif