objc-class.mm 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138
  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. * objc-class.m
  25. * Copyright 1988-1997, Apple Computer, Inc.
  26. * Author: s. naroff
  27. **********************************************************************/
  28. /***********************************************************************
  29. * Lazy method list arrays and method list locking (2004-10-19)
  30. *
  31. * cls->methodLists may be in one of three forms:
  32. * 1. nil: The class has no methods.
  33. * 2. non-nil, with CLS_NO_METHOD_ARRAY set: cls->methodLists points
  34. * to a single method list, which is the class's only method list.
  35. * 3. non-nil, with CLS_NO_METHOD_ARRAY clear: cls->methodLists points to
  36. * an array of method list pointers. The end of the array's block
  37. * is set to -1. If the actual number of method lists is smaller
  38. * than that, the rest of the array is nil.
  39. *
  40. * Attaching categories and adding and removing classes may change
  41. * the form of the class list. In addition, individual method lists
  42. * may be reallocated when fixed up.
  43. *
  44. * Classes are initially read as #1 or #2. If a category is attached
  45. * or other methods added, the class is changed to #3. Once in form #3,
  46. * the class is never downgraded to #1 or #2, even if methods are removed.
  47. * Classes added with objc_addClass are initially either #1 or #3.
  48. *
  49. * Accessing and manipulating a class's method lists are synchronized,
  50. * to prevent races when one thread restructures the list. However,
  51. * if the class is not yet in use (i.e. not in class_hash), then the
  52. * thread loading the class may access its method lists without locking.
  53. *
  54. * The following functions acquire methodListLock:
  55. * class_getInstanceMethod
  56. * class_getClassMethod
  57. * class_nextMethodList
  58. * class_addMethods
  59. * class_removeMethods
  60. * class_respondsToMethod
  61. * _class_lookupMethodAndLoadCache
  62. * lookupMethodInClassAndLoadCache
  63. * _objc_add_category_flush_caches
  64. *
  65. * The following functions don't acquire methodListLock because they
  66. * only access method lists during class load and unload:
  67. * _objc_register_category
  68. * _resolve_categories_for_class (calls _objc_add_category)
  69. * add_class_to_loadable_list
  70. * _objc_addClass
  71. * _objc_remove_classes_in_image
  72. *
  73. * The following functions use method lists without holding methodListLock.
  74. * The caller must either hold methodListLock, or be loading the class.
  75. * _getMethod (called by class_getInstanceMethod, class_getClassMethod,
  76. * and class_respondsToMethod)
  77. * _findMethodInClass (called by _class_lookupMethodAndLoadCache,
  78. * lookupMethodInClassAndLoadCache, _getMethod)
  79. * _findMethodInList (called by _findMethodInClass)
  80. * nextMethodList (called by _findMethodInClass and class_nextMethodList
  81. * fixupSelectorsInMethodList (called by nextMethodList)
  82. * _objc_add_category (called by _objc_add_category_flush_caches,
  83. * resolve_categories_for_class and _objc_register_category)
  84. * _objc_insertMethods (called by class_addMethods and _objc_add_category)
  85. * _objc_removeMethods (called by class_removeMethods)
  86. * _objcTweakMethodListPointerForClass (called by _objc_insertMethods)
  87. * get_base_method_list (called by add_class_to_loadable_list)
  88. * lookupNamedMethodInMethodList (called by add_class_to_loadable_list)
  89. ***********************************************************************/
  90. /***********************************************************************
  91. * Thread-safety of class info bits (2004-10-19)
  92. *
  93. * Some class info bits are used to store mutable runtime state.
  94. * Modifications of the info bits at particular times need to be
  95. * synchronized to prevent races.
  96. *
  97. * Three thread-safe modification functions are provided:
  98. * cls->setInfo() // atomically sets some bits
  99. * cls->clearInfo() // atomically clears some bits
  100. * cls->changeInfo() // atomically sets some bits and clears others
  101. * These replace CLS_SETINFO() for the multithreaded cases.
  102. *
  103. * Three modification windows are defined:
  104. * - compile time
  105. * - class construction or image load (before +load) in one thread
  106. * - multi-threaded messaging and method caches
  107. *
  108. * Info bit modification at compile time and class construction do not
  109. * need to be locked, because only one thread is manipulating the class.
  110. * Info bit modification during messaging needs to be locked, because
  111. * there may be other threads simultaneously messaging or otherwise
  112. * manipulating the class.
  113. *
  114. * Modification windows for each flag:
  115. *
  116. * CLS_CLASS: compile-time and class load
  117. * CLS_META: compile-time and class load
  118. * CLS_INITIALIZED: +initialize
  119. * CLS_POSING: messaging
  120. * CLS_MAPPED: compile-time
  121. * CLS_FLUSH_CACHE: class load and messaging
  122. * CLS_GROW_CACHE: messaging
  123. * CLS_NEED_BIND: unused
  124. * CLS_METHOD_ARRAY: unused
  125. * CLS_JAVA_HYBRID: JavaBridge only
  126. * CLS_JAVA_CLASS: JavaBridge only
  127. * CLS_INITIALIZING: messaging
  128. * CLS_FROM_BUNDLE: class load
  129. * CLS_HAS_CXX_STRUCTORS: compile-time and class load
  130. * CLS_NO_METHOD_ARRAY: class load and messaging
  131. * CLS_HAS_LOAD_METHOD: class load
  132. *
  133. * CLS_INITIALIZED and CLS_INITIALIZING have additional thread-safety
  134. * constraints to support thread-safe +initialize. See "Thread safety
  135. * during class initialization" for details.
  136. *
  137. * CLS_JAVA_HYBRID and CLS_JAVA_CLASS are set immediately after JavaBridge
  138. * calls objc_addClass(). The JavaBridge does not use an atomic update,
  139. * but the modification counts as "class construction" unless some other
  140. * thread quickly finds the class via the class list. This race is
  141. * small and unlikely in well-behaved code.
  142. *
  143. * Most info bits that may be modified during messaging are also never
  144. * read without a lock. There is no general read lock for the info bits.
  145. * CLS_INITIALIZED: classInitLock
  146. * CLS_FLUSH_CACHE: cacheUpdateLock
  147. * CLS_GROW_CACHE: cacheUpdateLock
  148. * CLS_NO_METHOD_ARRAY: methodListLock
  149. * CLS_INITIALIZING: classInitLock
  150. ***********************************************************************/
  151. /***********************************************************************
  152. * Imports.
  153. **********************************************************************/
  154. #include "objc-private.h"
  155. #include "objc-abi.h"
  156. #include <objc/message.h>
  157. /***********************************************************************
  158. * Information about multi-thread support:
  159. *
  160. * Since we do not lock many operations which walk the superclass, method
  161. * and ivar chains, these chains must remain intact once a class is published
  162. * by inserting it into the class hashtable. All modifications must be
  163. * atomic so that someone walking these chains will always geta valid
  164. * result.
  165. ***********************************************************************/
  166. /***********************************************************************
  167. * object_getClass.
  168. * Locking: None. If you add locking, tell gdb (rdar://7516456).
  169. **********************************************************************/
  170. Class object_getClass(id obj)
  171. {
  172. //如果obj是instance对象,返回class对象
  173. //如果obj是class,返回meta-class对象
  174. //如果obj是meta-class,返回NSObjct(基类)的meta-class对象
  175. if (obj) return obj->getIsa();//返回isa指向的对象
  176. else return Nil;
  177. }
  178. /***********************************************************************
  179. * object_setClass.
  180. **********************************************************************/
  181. Class object_setClass(id obj, Class cls)
  182. {
  183. if (!obj) return nil;
  184. // Prevent a deadlock between the weak reference machinery
  185. // and the +initialize machinery by ensuring that no
  186. // weakly-referenced object has an un-+initialized isa.
  187. // Unresolved future classes are not so protected.
  188. if (!cls->isFuture() && !cls->isInitialized()) {
  189. // use lookUpImpOrNil to indirectly provoke +initialize
  190. // to avoid duplicating the code to actually send +initialize
  191. lookUpImpOrNil(nil, @selector(initialize), cls, LOOKUP_INITIALIZE);
  192. }
  193. return obj->changeIsa(cls);
  194. }
  195. /***********************************************************************
  196. * object_isClass.
  197. **********************************************************************/
  198. BOOL object_isClass(id obj)
  199. {
  200. if (!obj) return NO;
  201. return obj->isClass();
  202. }
  203. /***********************************************************************
  204. * object_getClassName.
  205. **********************************************************************/
  206. const char *object_getClassName(id obj)
  207. {
  208. return class_getName(obj ? obj->getIsa() : nil);
  209. }
  210. /***********************************************************************
  211. * object_getMethodImplementation.
  212. **********************************************************************/
  213. IMP object_getMethodImplementation(id obj, SEL name)
  214. {
  215. Class cls = (obj ? obj->getIsa() : nil);
  216. return class_getMethodImplementation(cls, name);
  217. }
  218. /***********************************************************************
  219. * object_getMethodImplementation_stret.
  220. **********************************************************************/
  221. #if SUPPORT_STRET
  222. IMP object_getMethodImplementation_stret(id obj, SEL name)
  223. {
  224. Class cls = (obj ? obj->getIsa() : nil);
  225. return class_getMethodImplementation_stret(cls, name);
  226. }
  227. #endif
  228. static bool isScanned(ptrdiff_t ivar_offset, const uint8_t *layout)
  229. {
  230. if (!layout) return NO;
  231. ptrdiff_t index = 0, ivar_index = ivar_offset / sizeof(void*);
  232. uint8_t byte;
  233. while ((byte = *layout++)) {
  234. unsigned skips = (byte >> 4);
  235. unsigned scans = (byte & 0x0F);
  236. index += skips;
  237. if (index > ivar_index) return NO;
  238. index += scans;
  239. if (index > ivar_index) return YES;
  240. }
  241. return NO;
  242. }
  243. /***********************************************************************
  244. * _class_lookUpIvar
  245. * Given an object and an ivar in it, look up some data about that ivar:
  246. * - its offset
  247. * - its memory management behavior
  248. * The ivar is assumed to be word-aligned and of of object type.
  249. **********************************************************************/
  250. static void
  251. _class_lookUpIvar(Class cls, Ivar ivar, ptrdiff_t& ivarOffset,
  252. objc_ivar_memory_management_t& memoryManagement)
  253. {
  254. ivarOffset = ivar_getOffset(ivar);
  255. // Look for ARC variables and ARC-style weak.
  256. // Preflight the hasAutomaticIvars check
  257. // because _class_getClassForIvar() may need to take locks.
  258. bool hasAutomaticIvars = NO;
  259. for (Class c = cls; c; c = c->superclass) {
  260. if (c->hasAutomaticIvars()) {
  261. hasAutomaticIvars = YES;
  262. break;
  263. }
  264. }
  265. if (hasAutomaticIvars) {
  266. Class ivarCls = _class_getClassForIvar(cls, ivar);
  267. if (ivarCls->hasAutomaticIvars()) {
  268. // ARC layout bitmaps encode the class's own ivars only.
  269. // Use alignedInstanceStart() because unaligned bytes at the start
  270. // of this class's ivars are not represented in the layout bitmap.
  271. ptrdiff_t localOffset =
  272. ivarOffset - ivarCls->alignedInstanceStart();
  273. if (isScanned(localOffset, class_getIvarLayout(ivarCls))) {
  274. memoryManagement = objc_ivar_memoryStrong;
  275. return;
  276. }
  277. if (isScanned(localOffset, class_getWeakIvarLayout(ivarCls))) {
  278. memoryManagement = objc_ivar_memoryWeak;
  279. return;
  280. }
  281. // Unretained is only for true ARC classes.
  282. if (ivarCls->isARC()) {
  283. memoryManagement = objc_ivar_memoryUnretained;
  284. return;
  285. }
  286. }
  287. }
  288. memoryManagement = objc_ivar_memoryUnknown;
  289. }
  290. /***********************************************************************
  291. * _class_getIvarMemoryManagement
  292. * SPI for KVO and others to decide what memory management to use
  293. * when setting instance variables directly.
  294. **********************************************************************/
  295. objc_ivar_memory_management_t
  296. _class_getIvarMemoryManagement(Class cls, Ivar ivar)
  297. {
  298. ptrdiff_t offset;
  299. objc_ivar_memory_management_t memoryManagement;
  300. _class_lookUpIvar(cls, ivar, offset, memoryManagement);
  301. return memoryManagement;
  302. }
  303. static ALWAYS_INLINE
  304. void _object_setIvar(id obj, Ivar ivar, id value, bool assumeStrong)
  305. {
  306. if (!obj || !ivar || obj->isTaggedPointer()) return;
  307. ptrdiff_t offset;
  308. objc_ivar_memory_management_t memoryManagement;
  309. _class_lookUpIvar(obj->ISA(), ivar, offset, memoryManagement);
  310. if (memoryManagement == objc_ivar_memoryUnknown) {
  311. if (assumeStrong) memoryManagement = objc_ivar_memoryStrong;
  312. else memoryManagement = objc_ivar_memoryUnretained;
  313. }
  314. id *location = (id *)((char *)obj + offset);
  315. switch (memoryManagement) {
  316. case objc_ivar_memoryWeak: objc_storeWeak(location, value); break;
  317. case objc_ivar_memoryStrong: objc_storeStrong(location, value); break;
  318. case objc_ivar_memoryUnretained: *location = value; break;
  319. case objc_ivar_memoryUnknown: _objc_fatal("impossible");
  320. }
  321. }
  322. void object_setIvar(id obj, Ivar ivar, id value)
  323. {
  324. return _object_setIvar(obj, ivar, value, false /*not strong default*/);
  325. }
  326. void object_setIvarWithStrongDefault(id obj, Ivar ivar, id value)
  327. {
  328. return _object_setIvar(obj, ivar, value, true /*strong default*/);
  329. }
  330. id object_getIvar(id obj, Ivar ivar)
  331. {
  332. if (!obj || !ivar || obj->isTaggedPointer()) return nil;
  333. ptrdiff_t offset;
  334. objc_ivar_memory_management_t memoryManagement;
  335. _class_lookUpIvar(obj->ISA(), ivar, offset, memoryManagement);
  336. id *location = (id *)((char *)obj + offset);
  337. if (memoryManagement == objc_ivar_memoryWeak) {
  338. return objc_loadWeak(location);
  339. } else {
  340. return *location;
  341. }
  342. }
  343. static ALWAYS_INLINE
  344. Ivar _object_setInstanceVariable(id obj, const char *name, void *value,
  345. bool assumeStrong)
  346. {
  347. Ivar ivar = nil;
  348. if (obj && name && !obj->isTaggedPointer()) {
  349. if ((ivar = _class_getVariable(obj->ISA(), name))) {
  350. _object_setIvar(obj, ivar, (id)value, assumeStrong);
  351. }
  352. }
  353. return ivar;
  354. }
  355. Ivar object_setInstanceVariable(id obj, const char *name, void *value)
  356. {
  357. return _object_setInstanceVariable(obj, name, value, false);
  358. }
  359. Ivar object_setInstanceVariableWithStrongDefault(id obj, const char *name,
  360. void *value)
  361. {
  362. return _object_setInstanceVariable(obj, name, value, true);
  363. }
  364. Ivar object_getInstanceVariable(id obj, const char *name, void **value)
  365. {
  366. if (obj && name && !obj->isTaggedPointer()) {
  367. Ivar ivar;
  368. if ((ivar = class_getInstanceVariable(obj->ISA(), name))) {
  369. if (value) *value = (void *)object_getIvar(obj, ivar);
  370. return ivar;
  371. }
  372. }
  373. if (value) *value = nil;
  374. return nil;
  375. }
  376. /***********************************************************************
  377. * object_cxxDestructFromClass.
  378. * Call C++ destructors on obj, starting with cls's
  379. * dtor method (if any) followed by superclasses' dtors (if any),
  380. * stopping at cls's dtor (if any).
  381. * Uses methodListLock and cacheUpdateLock. The caller must hold neither.
  382. **********************************************************************/
  383. static void object_cxxDestructFromClass(id obj, Class cls)
  384. {
  385. void (*dtor)(id);
  386. // Call cls's dtor first, then superclasses's dtors.
  387. for ( ; cls; cls = cls->superclass) {
  388. if (!cls->hasCxxDtor()) return;
  389. dtor = (void(*)(id))
  390. lookupMethodInClassAndLoadCache(cls, SEL_cxx_destruct);
  391. if (dtor != (void(*)(id))_objc_msgForward_impcache) {
  392. if (PrintCxxCtors) {
  393. _objc_inform("CXX: calling C++ destructors for class %s",
  394. cls->nameForLogging());
  395. }
  396. (*dtor)(obj);
  397. }
  398. }
  399. }
  400. /***********************************************************************
  401. * object_cxxDestruct.
  402. * Call C++ destructors on obj, if any.
  403. * Uses methodListLock and cacheUpdateLock. The caller must hold neither.
  404. **********************************************************************/
  405. void object_cxxDestruct(id obj)
  406. {
  407. if (!obj) return;
  408. if (obj->isTaggedPointer()) return;
  409. object_cxxDestructFromClass(obj, obj->ISA());
  410. }
  411. /***********************************************************************
  412. * object_cxxConstructFromClass.
  413. * Recursively call C++ constructors on obj, starting with base class's
  414. * ctor method (if any) followed by subclasses' ctors (if any), stopping
  415. * at cls's ctor (if any).
  416. * Does not check cls->hasCxxCtor(). The caller should preflight that.
  417. * Returns self if construction succeeded.
  418. * Returns nil if some constructor threw an exception. The exception is
  419. * caught and discarded. Any partial construction is destructed.
  420. * Uses methodListLock and cacheUpdateLock. The caller must hold neither.
  421. *
  422. * .cxx_construct returns id. This really means:
  423. * return self: construction succeeded
  424. * return nil: construction failed because a C++ constructor threw an exception
  425. **********************************************************************/
  426. id
  427. object_cxxConstructFromClass(id obj, Class cls, int flags)
  428. {
  429. ASSERT(cls->hasCxxCtor()); // required for performance, not correctness
  430. id (*ctor)(id);
  431. Class supercls;
  432. supercls = cls->superclass;
  433. // Call superclasses' ctors first, if any.
  434. if (supercls && supercls->hasCxxCtor()) {
  435. bool ok = object_cxxConstructFromClass(obj, supercls, flags);
  436. if (slowpath(!ok)) return nil; // some superclass's ctor failed - give up
  437. }
  438. // Find this class's ctor, if any.
  439. ctor = (id(*)(id))lookupMethodInClassAndLoadCache(cls, SEL_cxx_construct);
  440. if (ctor == (id(*)(id))_objc_msgForward_impcache) return obj; // no ctor - ok
  441. // Call this class's ctor.
  442. if (PrintCxxCtors) {
  443. _objc_inform("CXX: calling C++ constructors for class %s",
  444. cls->nameForLogging());
  445. }
  446. if (fastpath((*ctor)(obj))) return obj; // ctor called and succeeded - ok
  447. supercls = cls->superclass; // this reload avoids a spill on the stack
  448. // This class's ctor was called and failed.
  449. // Call superclasses's dtors to clean up.
  450. if (supercls) object_cxxDestructFromClass(obj, supercls);
  451. if (flags & OBJECT_CONSTRUCT_FREE_ONFAILURE) free(obj);
  452. if (flags & OBJECT_CONSTRUCT_CALL_BADALLOC) {
  453. return _objc_callBadAllocHandler(cls);
  454. }
  455. return nil;
  456. }
  457. /***********************************************************************
  458. * fixupCopiedIvars
  459. * Fix up ARC strong and ARC-style weak variables
  460. * after oldObject was memcpy'd to newObject.
  461. **********************************************************************/
  462. void fixupCopiedIvars(id newObject, id oldObject)
  463. {
  464. for (Class cls = oldObject->ISA(); cls; cls = cls->superclass) {
  465. if (cls->hasAutomaticIvars()) {
  466. // Use alignedInstanceStart() because unaligned bytes at the start
  467. // of this class's ivars are not represented in the layout bitmap.
  468. size_t instanceStart = cls->alignedInstanceStart();
  469. const uint8_t *strongLayout = class_getIvarLayout(cls);
  470. if (strongLayout) {
  471. id *newPtr = (id *)((char*)newObject + instanceStart);
  472. unsigned char byte;
  473. while ((byte = *strongLayout++)) {
  474. unsigned skips = (byte >> 4);
  475. unsigned scans = (byte & 0x0F);
  476. newPtr += skips;
  477. while (scans--) {
  478. // ensure strong references are properly retained.
  479. id value = *newPtr++;
  480. if (value) objc_retain(value);
  481. }
  482. }
  483. }
  484. const uint8_t *weakLayout = class_getWeakIvarLayout(cls);
  485. // fix up weak references if any.
  486. if (weakLayout) {
  487. id *newPtr = (id *)((char*)newObject + instanceStart), *oldPtr = (id *)((char*)oldObject + instanceStart);
  488. unsigned char byte;
  489. while ((byte = *weakLayout++)) {
  490. unsigned skips = (byte >> 4);
  491. unsigned weaks = (byte & 0x0F);
  492. newPtr += skips, oldPtr += skips;
  493. while (weaks--) {
  494. objc_copyWeak(newPtr, oldPtr);
  495. ++newPtr, ++oldPtr;
  496. }
  497. }
  498. }
  499. }
  500. }
  501. }
  502. /***********************************************************************
  503. * class_getClassMethod. Return the class method for the specified
  504. * class and selector.
  505. **********************************************************************/
  506. Method class_getClassMethod(Class cls, SEL sel)
  507. {
  508. if (!cls || !sel) return nil;
  509. return class_getInstanceMethod(cls->getMeta(), sel);
  510. }
  511. /***********************************************************************
  512. * class_getInstanceVariable. Return the named instance variable.
  513. **********************************************************************/
  514. Ivar class_getInstanceVariable(Class cls, const char *name)
  515. {
  516. if (!cls || !name) return nil;
  517. return _class_getVariable(cls, name);
  518. }
  519. /***********************************************************************
  520. * class_getClassVariable. Return the named class variable.
  521. **********************************************************************/
  522. Ivar class_getClassVariable(Class cls, const char *name)
  523. {
  524. if (!cls) return nil;
  525. return class_getInstanceVariable(cls->ISA(), name);
  526. }
  527. /***********************************************************************
  528. * gdb_objc_class_changed
  529. * Tell gdb that a class changed. Currently used for OBJC2 ivar layouts only
  530. * Does nothing; gdb sets a breakpoint on it.
  531. **********************************************************************/
  532. BREAKPOINT_FUNCTION(
  533. void gdb_objc_class_changed(Class cls, unsigned long changes, const char *classname)
  534. );
  535. /***********************************************************************
  536. * class_respondsToSelector.
  537. **********************************************************************/
  538. BOOL class_respondsToMethod(Class cls, SEL sel)
  539. {
  540. OBJC_WARN_DEPRECATED;
  541. return class_respondsToSelector(cls, sel);
  542. }
  543. BOOL class_respondsToSelector(Class cls, SEL sel)
  544. {
  545. return class_respondsToSelector_inst(nil, sel, cls);
  546. }
  547. // inst is an instance of cls or a subclass thereof, or nil if none is known.
  548. // Non-nil inst is faster in some cases. See lookUpImpOrForward() for details.
  549. NEVER_INLINE BOOL
  550. class_respondsToSelector_inst(id inst, SEL sel, Class cls)
  551. {
  552. // Avoids +initialize because it historically did so.
  553. // We're not returning a callable IMP anyway.
  554. return sel && cls && lookUpImpOrNil(inst, sel, cls, LOOKUP_RESOLVER);
  555. }
  556. /***********************************************************************
  557. * class_getMethodImplementation.
  558. * Returns the IMP that would be invoked if [obj sel] were sent,
  559. * where obj is an instance of class cls.
  560. **********************************************************************/
  561. IMP class_lookupMethod(Class cls, SEL sel)
  562. {
  563. OBJC_WARN_DEPRECATED;
  564. // No one responds to zero!
  565. if (!sel) {
  566. __objc_error(cls, "invalid selector (null)");
  567. }
  568. return class_getMethodImplementation(cls, sel);
  569. }
  570. IMP class_getMethodImplementation(Class cls, SEL sel)
  571. {
  572. IMP imp;
  573. if (!cls || !sel) return nil;
  574. imp = lookUpImpOrNil(nil, sel, cls, LOOKUP_INITIALIZE | LOOKUP_RESOLVER);
  575. // Translate forwarding function to C-callable external version
  576. if (!imp) {
  577. return _objc_msgForward;
  578. }
  579. return imp;
  580. }
  581. #if SUPPORT_STRET
  582. IMP class_getMethodImplementation_stret(Class cls, SEL sel)
  583. {
  584. IMP imp = class_getMethodImplementation(cls, sel);
  585. // Translate forwarding function to struct-returning version
  586. if (imp == (IMP)&_objc_msgForward /* not _internal! */) {
  587. return (IMP)&_objc_msgForward_stret;
  588. }
  589. return imp;
  590. }
  591. #endif
  592. /***********************************************************************
  593. * instrumentObjcMessageSends
  594. **********************************************************************/
  595. // Define this everywhere even if it isn't used to simplify fork() safety code.
  596. spinlock_t objcMsgLogLock;
  597. #if !SUPPORT_MESSAGE_LOGGING
  598. void instrumentObjcMessageSends(BOOL flag)
  599. {
  600. }
  601. #else
  602. bool objcMsgLogEnabled = false;
  603. static int objcMsgLogFD = -1;
  604. bool logMessageSend(bool isClassMethod,
  605. const char *objectsClass,
  606. const char *implementingClass,
  607. SEL selector)
  608. {
  609. char buf[ 1024 ];
  610. // Create/open the log file
  611. if (objcMsgLogFD == (-1))
  612. {
  613. snprintf (buf, sizeof(buf), "/tmp/msgSends-%d", (int) getpid ());
  614. objcMsgLogFD = secure_open (buf, O_WRONLY | O_CREAT, geteuid());
  615. if (objcMsgLogFD < 0) {
  616. // no log file - disable logging
  617. objcMsgLogEnabled = false;
  618. objcMsgLogFD = -1;
  619. return true;
  620. }
  621. }
  622. // Make the log entry
  623. snprintf(buf, sizeof(buf), "%c %s %s %s\n",
  624. isClassMethod ? '+' : '-',
  625. objectsClass,
  626. implementingClass,
  627. sel_getName(selector));
  628. objcMsgLogLock.lock();
  629. write (objcMsgLogFD, buf, strlen(buf));
  630. objcMsgLogLock.unlock();
  631. // Tell caller to not cache the method
  632. return false;
  633. }
  634. void instrumentObjcMessageSends(BOOL flag)
  635. {
  636. bool enable = flag;
  637. // Shortcut NOP
  638. if (objcMsgLogEnabled == enable)
  639. return;
  640. // If enabling, flush all method caches so we get some traces
  641. if (enable)
  642. _objc_flush_caches(Nil);
  643. // Sync our log file
  644. if (objcMsgLogFD != -1)
  645. fsync (objcMsgLogFD);
  646. objcMsgLogEnabled = enable;
  647. }
  648. // SUPPORT_MESSAGE_LOGGING
  649. #endif
  650. Class _calloc_class(size_t size)
  651. {
  652. return (Class) calloc(1, size);
  653. }
  654. Class class_getSuperclass(Class cls)
  655. {
  656. if (!cls) return nil;
  657. return cls->superclass;
  658. }
  659. BOOL class_isMetaClass(Class cls)
  660. {
  661. if (!cls) return NO;
  662. return cls->isMetaClass();
  663. }
  664. size_t class_getInstanceSize(Class cls)
  665. {
  666. if (!cls) return 0;
  667. return cls->alignedInstanceSize();
  668. }
  669. /***********************************************************************
  670. * method_getNumberOfArguments.
  671. **********************************************************************/
  672. unsigned int method_getNumberOfArguments(Method m)
  673. {
  674. if (!m) return 0;
  675. return encoding_getNumberOfArguments(method_getTypeEncoding(m));
  676. }
  677. void method_getReturnType(Method m, char *dst, size_t dst_len)
  678. {
  679. encoding_getReturnType(method_getTypeEncoding(m), dst, dst_len);
  680. }
  681. char * method_copyReturnType(Method m)
  682. {
  683. return encoding_copyReturnType(method_getTypeEncoding(m));
  684. }
  685. void method_getArgumentType(Method m, unsigned int index,
  686. char *dst, size_t dst_len)
  687. {
  688. encoding_getArgumentType(method_getTypeEncoding(m),
  689. index, dst, dst_len);
  690. }
  691. char * method_copyArgumentType(Method m, unsigned int index)
  692. {
  693. return encoding_copyArgumentType(method_getTypeEncoding(m), index);
  694. }
  695. /***********************************************************************
  696. * _class_createInstancesFromZone
  697. * Batch-allocating version of _class_createInstanceFromZone.
  698. * Attempts to allocate num_requested objects, each with extraBytes.
  699. * Returns the number of allocated objects (possibly zero), with
  700. * the allocated pointers in *results.
  701. **********************************************************************/
  702. unsigned
  703. _class_createInstancesFromZone(Class cls, size_t extraBytes, void *zone,
  704. id *results, unsigned num_requested)
  705. {
  706. unsigned num_allocated;
  707. if (!cls) return 0;
  708. size_t size = cls->instanceSize(extraBytes);
  709. num_allocated =
  710. malloc_zone_batch_malloc((malloc_zone_t *)(zone ? zone : malloc_default_zone()),
  711. size, (void**)results, num_requested);
  712. for (unsigned i = 0; i < num_allocated; i++) {
  713. bzero(results[i], size);
  714. }
  715. // Construct each object, and delete any that fail construction.
  716. unsigned shift = 0;
  717. bool ctor = cls->hasCxxCtor();
  718. for (unsigned i = 0; i < num_allocated; i++) {
  719. id obj = results[i];
  720. obj->initIsa(cls); // fixme allow nonpointer
  721. if (ctor) {
  722. obj = object_cxxConstructFromClass(obj, cls,
  723. OBJECT_CONSTRUCT_FREE_ONFAILURE);
  724. }
  725. if (obj) {
  726. results[i-shift] = obj;
  727. } else {
  728. shift++;
  729. }
  730. }
  731. return num_allocated - shift;
  732. }
  733. /***********************************************************************
  734. * inform_duplicate. Complain about duplicate class implementations.
  735. **********************************************************************/
  736. void
  737. inform_duplicate(const char *name, Class oldCls, Class newCls)
  738. {
  739. #if TARGET_OS_WIN32
  740. (DebugDuplicateClasses ? _objc_fatal : _objc_inform)
  741. ("Class %s is implemented in two different images.", name);
  742. #else
  743. const header_info *oldHeader = _headerForClass(oldCls);
  744. const header_info *newHeader = _headerForClass(newCls);
  745. const char *oldName = oldHeader ? oldHeader->fname() : "??";
  746. const char *newName = newHeader ? newHeader->fname() : "??";
  747. (DebugDuplicateClasses ? _objc_fatal : _objc_inform)
  748. ("Class %s is implemented in both %s (%p) and %s (%p). "
  749. "One of the two will be used. Which one is undefined.",
  750. name, oldName, oldCls, newName, newCls);
  751. #endif
  752. }
  753. const char *
  754. copyPropertyAttributeString(const objc_property_attribute_t *attrs,
  755. unsigned int count)
  756. {
  757. char *result;
  758. unsigned int i;
  759. if (count == 0) return strdup("");
  760. #if DEBUG
  761. // debug build: sanitize input
  762. for (i = 0; i < count; i++) {
  763. ASSERT(attrs[i].name);
  764. ASSERT(strlen(attrs[i].name) > 0);
  765. ASSERT(! strchr(attrs[i].name, ','));
  766. ASSERT(! strchr(attrs[i].name, '"'));
  767. if (attrs[i].value) ASSERT(! strchr(attrs[i].value, ','));
  768. }
  769. #endif
  770. size_t len = 0;
  771. for (i = 0; i < count; i++) {
  772. if (attrs[i].value) {
  773. size_t namelen = strlen(attrs[i].name);
  774. if (namelen > 1) namelen += 2; // long names get quoted
  775. len += namelen + strlen(attrs[i].value) + 1;
  776. }
  777. }
  778. result = (char *)malloc(len + 1);
  779. char *s = result;
  780. for (i = 0; i < count; i++) {
  781. if (attrs[i].value) {
  782. size_t namelen = strlen(attrs[i].name);
  783. if (namelen > 1) {
  784. s += sprintf(s, "\"%s\"%s,", attrs[i].name, attrs[i].value);
  785. } else {
  786. s += sprintf(s, "%s%s,", attrs[i].name, attrs[i].value);
  787. }
  788. }
  789. }
  790. // remove trailing ',' if any
  791. if (s > result) s[-1] = '\0';
  792. return result;
  793. }
  794. /*
  795. Property attribute string format:
  796. - Comma-separated name-value pairs.
  797. - Name and value may not contain ,
  798. - Name may not contain "
  799. - Value may be empty
  800. - Name is single char, value follows
  801. - OR Name is double-quoted string of 2+ chars, value follows
  802. Grammar:
  803. attribute-string: \0
  804. attribute-string: name-value-pair (',' name-value-pair)*
  805. name-value-pair: unquoted-name optional-value
  806. name-value-pair: quoted-name optional-value
  807. unquoted-name: [^",]
  808. quoted-name: '"' [^",]{2,} '"'
  809. optional-value: [^,]*
  810. */
  811. static unsigned int
  812. iteratePropertyAttributes(const char *attrs,
  813. bool (*fn)(unsigned int index,
  814. void *ctx1, void *ctx2,
  815. const char *name, size_t nlen,
  816. const char *value, size_t vlen),
  817. void *ctx1, void *ctx2)
  818. {
  819. if (!attrs) return 0;
  820. #if DEBUG
  821. const char *attrsend = attrs + strlen(attrs);
  822. #endif
  823. unsigned int attrcount = 0;
  824. while (*attrs) {
  825. // Find the next comma-separated attribute
  826. const char *start = attrs;
  827. const char *end = start + strcspn(attrs, ",");
  828. // Move attrs past this attribute and the comma (if any)
  829. attrs = *end ? end+1 : end;
  830. assert(attrs <= attrsend);
  831. assert(start <= attrsend);
  832. assert(end <= attrsend);
  833. // Skip empty attribute
  834. if (start == end) continue;
  835. // Process one non-empty comma-free attribute [start,end)
  836. const char *nameStart;
  837. const char *nameEnd;
  838. ASSERT(start < end);
  839. ASSERT(*start);
  840. if (*start != '\"') {
  841. // single-char short name
  842. nameStart = start;
  843. nameEnd = start+1;
  844. start++;
  845. }
  846. else {
  847. // double-quoted long name
  848. nameStart = start+1;
  849. nameEnd = nameStart + strcspn(nameStart, "\",");
  850. start++; // leading quote
  851. start += nameEnd - nameStart; // name
  852. if (*start == '\"') start++; // trailing quote, if any
  853. }
  854. // Process one possibly-empty comma-free attribute value [start,end)
  855. const char *valueStart;
  856. const char *valueEnd;
  857. ASSERT(start <= end);
  858. valueStart = start;
  859. valueEnd = end;
  860. bool more = (*fn)(attrcount, ctx1, ctx2,
  861. nameStart, nameEnd-nameStart,
  862. valueStart, valueEnd-valueStart);
  863. attrcount++;
  864. if (!more) break;
  865. }
  866. return attrcount;
  867. }
  868. static bool
  869. copyOneAttribute(unsigned int index, void *ctxa, void *ctxs,
  870. const char *name, size_t nlen, const char *value, size_t vlen)
  871. {
  872. objc_property_attribute_t **ap = (objc_property_attribute_t**)ctxa;
  873. char **sp = (char **)ctxs;
  874. objc_property_attribute_t *a = *ap;
  875. char *s = *sp;
  876. a->name = s;
  877. memcpy(s, name, nlen);
  878. s += nlen;
  879. *s++ = '\0';
  880. a->value = s;
  881. memcpy(s, value, vlen);
  882. s += vlen;
  883. *s++ = '\0';
  884. a++;
  885. *ap = a;
  886. *sp = s;
  887. return YES;
  888. }
  889. objc_property_attribute_t *
  890. copyPropertyAttributeList(const char *attrs, unsigned int *outCount)
  891. {
  892. if (!attrs) {
  893. if (outCount) *outCount = 0;
  894. return nil;
  895. }
  896. // Result size:
  897. // number of commas plus 1 for the attributes (upper bound)
  898. // plus another attribute for the attribute array terminator
  899. // plus strlen(attrs) for name/value string data (upper bound)
  900. // plus count*2 for the name/value string terminators (upper bound)
  901. unsigned int attrcount = 1;
  902. const char *s;
  903. for (s = attrs; s && *s; s++) {
  904. if (*s == ',') attrcount++;
  905. }
  906. size_t size =
  907. attrcount * sizeof(objc_property_attribute_t) +
  908. sizeof(objc_property_attribute_t) +
  909. strlen(attrs) +
  910. attrcount * 2;
  911. objc_property_attribute_t *result = (objc_property_attribute_t *)
  912. calloc(size, 1);
  913. objc_property_attribute_t *ra = result;
  914. char *rs = (char *)(ra+attrcount+1);
  915. attrcount = iteratePropertyAttributes(attrs, copyOneAttribute, &ra, &rs);
  916. ASSERT((uint8_t *)(ra+1) <= (uint8_t *)result+size);
  917. ASSERT((uint8_t *)rs <= (uint8_t *)result+size);
  918. if (attrcount == 0) {
  919. free(result);
  920. result = nil;
  921. }
  922. if (outCount) *outCount = attrcount;
  923. return result;
  924. }
  925. static bool
  926. findOneAttribute(unsigned int index, void *ctxa, void *ctxs,
  927. const char *name, size_t nlen, const char *value, size_t vlen)
  928. {
  929. const char *query = (char *)ctxa;
  930. char **resultp = (char **)ctxs;
  931. if (strlen(query) == nlen && 0 == strncmp(name, query, nlen)) {
  932. char *result = (char *)calloc(vlen+1, 1);
  933. memcpy(result, value, vlen);
  934. result[vlen] = '\0';
  935. *resultp = result;
  936. return NO;
  937. }
  938. return YES;
  939. }
  940. char *copyPropertyAttributeValue(const char *attrs, const char *name)
  941. {
  942. char *result = nil;
  943. iteratePropertyAttributes(attrs, findOneAttribute, (void*)name, &result);
  944. return result;
  945. }