objc-weak.h 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. /*
  2. * Copyright (c) 2010-2011 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. #ifndef _OBJC_WEAK_H_
  24. #define _OBJC_WEAK_H_
  25. #include <objc/objc.h>
  26. #include "objc-config.h"
  27. __BEGIN_DECLS
  28. /*
  29. The weak table is a hash table governed by a single spin lock.
  30. An allocated blob of memory, most often an object, but under GC any such
  31. allocation, may have its address stored in a __weak marked storage location
  32. through use of compiler generated write-barriers or hand coded uses of the
  33. register weak primitive. Associated with the registration can be a callback
  34. block for the case when one of the allocated chunks of memory is reclaimed.
  35. The table is hashed on the address of the allocated memory. When __weak
  36. marked memory changes its reference, we count on the fact that we can still
  37. see its previous reference.
  38. So, in the hash table, indexed by the weakly referenced item, is a list of
  39. all locations where this address is currently being stored.
  40. For ARC, we also keep track of whether an arbitrary object is being
  41. deallocated by briefly placing it in the table just prior to invoking
  42. dealloc, and removing it via objc_clear_deallocating just prior to memory
  43. reclamation.
  44. */
  45. // The address of a __weak variable.
  46. // These pointers are stored disguised so memory analysis tools
  47. // don't see lots of interior pointers from the weak table into objects.
  48. typedef DisguisedPtr<objc_object *> weak_referrer_t;
  49. #if __LP64__
  50. #define PTR_MINUS_2 62
  51. #else
  52. #define PTR_MINUS_2 30
  53. #endif
  54. /**
  55. * The internal structure stored in the weak references table.
  56. * It maintains and stores
  57. * a hash set of weak references pointing to an object.
  58. * If out_of_line_ness != REFERRERS_OUT_OF_LINE then the set
  59. * is instead a small inline array.
  60. */
  61. #define WEAK_INLINE_COUNT 4
  62. // out_of_line_ness field overlaps with the low two bits of inline_referrers[1].
  63. // inline_referrers[1] is a DisguisedPtr of a pointer-aligned address.
  64. // The low two bits of a pointer-aligned DisguisedPtr will always be 0b00
  65. // (disguised nil or 0x80..00) or 0b11 (any other address).
  66. // Therefore out_of_line_ness == 0b10 is used to mark the out-of-line state.
  67. #define REFERRERS_OUT_OF_LINE 2
  68. struct weak_entry_t {
  69. DisguisedPtr<objc_object> referent;
  70. union {
  71. struct {
  72. weak_referrer_t *referrers;
  73. uintptr_t out_of_line_ness : 2;
  74. uintptr_t num_refs : PTR_MINUS_2;
  75. uintptr_t mask;
  76. uintptr_t max_hash_displacement;
  77. };
  78. struct {
  79. // out_of_line_ness field is low bits of inline_referrers[1]
  80. weak_referrer_t inline_referrers[WEAK_INLINE_COUNT];
  81. };
  82. };
  83. bool out_of_line() {
  84. return (out_of_line_ness == REFERRERS_OUT_OF_LINE);
  85. }
  86. weak_entry_t& operator=(const weak_entry_t& other) {
  87. memcpy(this, &other, sizeof(other));
  88. return *this;
  89. }
  90. weak_entry_t(objc_object *newReferent, objc_object **newReferrer)
  91. : referent(newReferent)
  92. {
  93. inline_referrers[0] = newReferrer;
  94. for (int i = 1; i < WEAK_INLINE_COUNT; i++) {
  95. inline_referrers[i] = nil;
  96. }
  97. }
  98. };
  99. /**
  100. * The global weak references table. Stores object ids as keys,
  101. * and weak_entry_t structs as their values.
  102. */
  103. struct weak_table_t {
  104. weak_entry_t *weak_entries;
  105. size_t num_entries;
  106. uintptr_t mask;
  107. uintptr_t max_hash_displacement;
  108. };
  109. /// Adds an (object, weak pointer) pair to the weak table.
  110. id weak_register_no_lock(weak_table_t *weak_table, id referent,
  111. id *referrer, bool crashIfDeallocating);
  112. /// Removes an (object, weak pointer) pair from the weak table.
  113. void weak_unregister_no_lock(weak_table_t *weak_table, id referent, id *referrer);
  114. #if DEBUG
  115. /// Returns true if an object is weakly referenced somewhere.
  116. bool weak_is_registered_no_lock(weak_table_t *weak_table, id referent);
  117. #endif
  118. /// Called on object destruction. Sets all remaining weak pointers to nil.
  119. void weak_clear_no_lock(weak_table_t *weak_table, id referent);
  120. __END_DECLS
  121. #endif /* _OBJC_WEAK_H_ */