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