OLD | NEW |
---|---|
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 23 matching lines...) Expand all Loading... | |
34 | 34 |
35 namespace v8 { | 35 namespace v8 { |
36 namespace internal { | 36 namespace internal { |
37 | 37 |
38 | 38 |
39 ObjectGroup::~ObjectGroup() { | 39 ObjectGroup::~ObjectGroup() { |
40 if (info_ != NULL) info_->Dispose(); | 40 if (info_ != NULL) info_->Dispose(); |
41 } | 41 } |
42 | 42 |
43 | 43 |
44 const uint8_t NodeIndependentFlag = 6; | |
45 const uint8_t NodePartiallyDependentFlag = 5; | |
46 const uint8_t NodeInNewSpaceListFlag = 4; | |
47 const uint8_t NodeIndependentFlagMask = 1 << NodeIndependentFlag; | |
48 const uint8_t NodePartiallyDependentFlagMask = 1 << NodePartiallyDependentFlag; | |
49 const uint8_t NodeInNewSpaceListFlagMask = 1 << NodeInNewSpaceListFlag; | |
50 const uint8_t NodeStateMask = 0xf; | |
51 | |
52 | |
44 class GlobalHandles::Node { | 53 class GlobalHandles::Node { |
45 public: | 54 public: |
46 // State transition diagram: | 55 // State transition diagram: |
47 // FREE -> NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, FREE } | 56 // FREE -> NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, FREE } |
48 enum State { | 57 enum State { |
49 FREE, | 58 FREE = 0, |
50 NORMAL, // Normal global handle. | 59 NORMAL, // Normal global handle. |
51 WEAK, // Flagged as weak but not yet finalized. | 60 WEAK, // Flagged as weak but not yet finalized. |
52 PENDING, // Has been recognized as only reachable by weak handles. | 61 PENDING, // Has been recognized as only reachable by weak handles. |
53 NEAR_DEATH // Callback has informed the handle is near death. | 62 NEAR_DEATH // Callback has informed the handle is near death. |
54 }; | 63 }; |
55 | 64 |
56 // Maps handle location (slot) to the containing node. | 65 // Maps handle location (slot) to the containing node. |
57 static Node* FromLocation(Object** location) { | 66 static Node* FromLocation(Object** location) { |
58 ASSERT(OFFSET_OF(Node, object_) == 0); | 67 ASSERT(OFFSET_OF(Node, object_) == 0); |
59 return reinterpret_cast<Node*>(location); | 68 return reinterpret_cast<Node*>(location); |
60 } | 69 } |
61 | 70 |
62 Node() {} | 71 Node() {} |
63 | 72 |
64 #ifdef DEBUG | 73 #ifdef DEBUG |
65 ~Node() { | 74 ~Node() { |
66 // TODO(1428): if it's a weak handle we should have invoked its callback. | 75 // TODO(1428): if it's a weak handle we should have invoked its callback. |
67 // Zap the values for eager trapping. | 76 // Zap the values for eager trapping. |
68 object_ = NULL; | 77 object_ = NULL; |
69 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; | 78 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; |
70 index_ = 0; | 79 index_ = 0; |
71 independent_ = false; | 80 set_independent(false); |
72 partially_dependent_ = false; | 81 set_partially_dependent_(false); |
73 in_new_space_list_ = false; | 82 set_in_new_space_list_(false); |
74 parameter_or_next_free_.next_free = NULL; | 83 parameter_or_next_free_.next_free = NULL; |
75 callback_ = NULL; | 84 callback_ = NULL; |
76 } | 85 } |
77 #endif | 86 #endif |
78 | 87 |
79 void Initialize(int index, Node** first_free) { | 88 void Initialize(int index, Node** first_free) { |
80 index_ = static_cast<uint8_t>(index); | 89 index_ = static_cast<uint8_t>(index); |
81 ASSERT(static_cast<int>(index_) == index); | 90 ASSERT(static_cast<int>(index_) == index); |
82 state_ = FREE; | 91 set_state(FREE); |
83 in_new_space_list_ = false; | 92 set_in_new_space_list(false); |
84 parameter_or_next_free_.next_free = *first_free; | 93 parameter_or_next_free_.next_free = *first_free; |
85 *first_free = this; | 94 *first_free = this; |
86 } | 95 } |
87 | 96 |
88 void Acquire(Object* object, GlobalHandles* global_handles) { | 97 void Acquire(Object* object, GlobalHandles* global_handles) { |
89 ASSERT(state_ == FREE); | 98 ASSERT(state() == FREE); |
90 object_ = object; | 99 object_ = object; |
91 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; | 100 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; |
92 independent_ = false; | 101 set_independent(false); |
93 partially_dependent_ = false; | 102 set_partially_dependent(false); |
94 state_ = NORMAL; | 103 set_state(NORMAL); |
95 parameter_or_next_free_.parameter = NULL; | 104 parameter_or_next_free_.parameter = NULL; |
96 callback_ = NULL; | 105 callback_ = NULL; |
97 IncreaseBlockUses(global_handles); | 106 IncreaseBlockUses(global_handles); |
98 } | 107 } |
99 | 108 |
100 void Release(GlobalHandles* global_handles) { | 109 void Release(GlobalHandles* global_handles) { |
101 ASSERT(state_ != FREE); | 110 ASSERT(state() != FREE); |
102 if (IsWeakRetainer()) { | 111 if (IsWeakRetainer()) { |
103 global_handles->number_of_weak_handles_--; | 112 global_handles->number_of_weak_handles_--; |
104 if (object_->IsJSGlobalObject()) { | 113 if (object_->IsJSGlobalObject()) { |
105 global_handles->number_of_global_object_weak_handles_--; | 114 global_handles->number_of_global_object_weak_handles_--; |
106 } | 115 } |
107 } | 116 } |
108 state_ = FREE; | 117 set_state(FREE); |
109 parameter_or_next_free_.next_free = global_handles->first_free_; | 118 parameter_or_next_free_.next_free = global_handles->first_free_; |
110 global_handles->first_free_ = this; | 119 global_handles->first_free_ = this; |
111 DecreaseBlockUses(global_handles); | 120 DecreaseBlockUses(global_handles); |
112 } | 121 } |
113 | 122 |
114 // Object slot accessors. | 123 // Object slot accessors. |
115 Object* object() const { return object_; } | 124 Object* object() const { return object_; } |
116 Object** location() { return &object_; } | 125 Object** location() { return &object_; } |
117 Handle<Object> handle() { return Handle<Object>(location()); } | 126 Handle<Object> handle() { return Handle<Object>(location()); } |
118 | 127 |
119 // Wrapper class ID accessors. | 128 // Wrapper class ID accessors. |
120 bool has_wrapper_class_id() const { | 129 bool has_wrapper_class_id() const { |
121 return class_id_ != v8::HeapProfiler::kPersistentHandleNoClassId; | 130 return class_id_ != v8::HeapProfiler::kPersistentHandleNoClassId; |
122 } | 131 } |
132 | |
123 uint16_t wrapper_class_id() const { return class_id_; } | 133 uint16_t wrapper_class_id() const { return class_id_; } |
124 void set_wrapper_class_id(uint16_t class_id) { | 134 void set_wrapper_class_id(uint16_t class_id) { |
125 class_id_ = class_id; | 135 class_id_ = static_cast<uint8_t>(class_id); |
Michael Starzinger
2013/01/15 09:06:41
The class_id is a full 16 bit, we can drop this ca
haraken
2013/01/15 09:40:39
Done.
| |
126 } | 136 } |
127 | 137 |
128 // State accessors. | 138 // State and flag accessors. |
129 | 139 |
130 State state() const { return state_; } | 140 State state() const { |
141 return static_cast<State>(flags_and_state_ & NodeStateMask); | |
Michael Starzinger
2013/01/15 09:06:41
Instead of using all of this hand-written magic, c
haraken
2013/01/15 09:40:39
Done.
| |
142 } | |
143 void set_state(State state) { | |
144 flags_and_state_ = | |
145 (flags_and_state_ & ~NodeStateMask) | state; | |
146 } | |
147 | |
148 bool is_independent() { | |
149 return flags_and_state_ & NodeIndependentFlagMask; | |
150 } | |
151 void set_independent(bool v) { | |
152 flags_and_state_ = | |
153 (flags_and_state_ & ~NodeIndependentFlagMask) | | |
154 (static_cast<uint8_t>(v) << NodeIndependentFlag); | |
155 } | |
156 | |
157 bool is_partially_dependent() { | |
158 return flags_and_state_ & NodePartiallyDependentFlagMask; | |
159 } | |
160 void set_partially_dependent(bool v) { | |
161 flags_and_state_ = | |
162 (flags_and_state_ & ~NodePartiallyDependentFlagMask) | | |
163 (static_cast<uint8_t>(v) << NodePartiallyDependentFlag); | |
164 } | |
165 | |
166 bool is_in_new_space_list() { | |
167 return flags_and_state_ & NodeInNewSpaceListFlagMask; | |
168 } | |
169 void set_in_new_space_list(bool v) { | |
170 flags_and_state_ = | |
171 (flags_and_state_ & ~NodeInNewSpaceListFlagMask) | | |
172 (static_cast<uint8_t>(v) << NodeInNewSpaceListFlag); | |
173 } | |
131 | 174 |
132 bool IsNearDeath() const { | 175 bool IsNearDeath() const { |
133 // Check for PENDING to ensure correct answer when processing callbacks. | 176 // Check for PENDING to ensure correct answer when processing callbacks. |
134 return state_ == PENDING || state_ == NEAR_DEATH; | 177 return state() == PENDING || state() == NEAR_DEATH; |
135 } | 178 } |
136 | 179 |
137 bool IsWeak() const { return state_ == WEAK; } | 180 bool IsWeak() const { return state() == WEAK; } |
138 | 181 |
139 bool IsRetainer() const { return state_ != FREE; } | 182 bool IsRetainer() const { return state() != FREE; } |
140 | 183 |
141 bool IsStrongRetainer() const { return state_ == NORMAL; } | 184 bool IsStrongRetainer() const { return state() == NORMAL; } |
142 | 185 |
143 bool IsWeakRetainer() const { | 186 bool IsWeakRetainer() const { |
144 return state_ == WEAK || state_ == PENDING || state_ == NEAR_DEATH; | 187 return state() == WEAK || state() == PENDING || state() == NEAR_DEATH; |
145 } | 188 } |
146 | 189 |
147 void MarkPending() { | 190 void MarkPending() { |
148 ASSERT(state_ == WEAK); | 191 ASSERT(state() == WEAK); |
149 state_ = PENDING; | 192 set_state(PENDING); |
150 } | 193 } |
151 | 194 |
152 // Independent flag accessors. | 195 // Independent flag accessors. |
153 void MarkIndependent() { | 196 void MarkIndependent() { |
154 ASSERT(state_ != FREE); | 197 ASSERT(state() != FREE); |
155 independent_ = true; | 198 set_independent(true); |
156 } | 199 } |
157 bool is_independent() const { return independent_; } | |
158 | 200 |
159 void MarkPartiallyDependent(GlobalHandles* global_handles) { | 201 void MarkPartiallyDependent(GlobalHandles* global_handles) { |
160 ASSERT(state_ != FREE); | 202 ASSERT(state() != FREE); |
161 if (global_handles->isolate()->heap()->InNewSpace(object_)) { | 203 if (global_handles->isolate()->heap()->InNewSpace(object_)) { |
162 partially_dependent_ = true; | 204 set_partially_dependent(true); |
163 } | 205 } |
164 } | 206 } |
165 bool is_partially_dependent() const { return partially_dependent_; } | 207 void clear_partially_dependent() { set_partially_dependent(false); } |
166 void clear_partially_dependent() { partially_dependent_ = false; } | |
167 | |
168 // In-new-space-list flag accessors. | |
169 void set_in_new_space_list(bool v) { in_new_space_list_ = v; } | |
170 bool is_in_new_space_list() const { return in_new_space_list_; } | |
171 | 208 |
172 // Callback accessor. | 209 // Callback accessor. |
173 WeakReferenceCallback callback() { return callback_; } | 210 WeakReferenceCallback callback() { return callback_; } |
174 | 211 |
175 // Callback parameter accessors. | 212 // Callback parameter accessors. |
176 void set_parameter(void* parameter) { | 213 void set_parameter(void* parameter) { |
177 ASSERT(state_ != FREE); | 214 ASSERT(state() != FREE); |
178 parameter_or_next_free_.parameter = parameter; | 215 parameter_or_next_free_.parameter = parameter; |
179 } | 216 } |
180 void* parameter() const { | 217 void* parameter() const { |
181 ASSERT(state_ != FREE); | 218 ASSERT(state() != FREE); |
182 return parameter_or_next_free_.parameter; | 219 return parameter_or_next_free_.parameter; |
183 } | 220 } |
184 | 221 |
185 // Accessors for next free node in the free list. | 222 // Accessors for next free node in the free list. |
186 Node* next_free() { | 223 Node* next_free() { |
187 ASSERT(state_ == FREE); | 224 ASSERT(state() == FREE); |
188 return parameter_or_next_free_.next_free; | 225 return parameter_or_next_free_.next_free; |
189 } | 226 } |
190 void set_next_free(Node* value) { | 227 void set_next_free(Node* value) { |
191 ASSERT(state_ == FREE); | 228 ASSERT(state() == FREE); |
192 parameter_or_next_free_.next_free = value; | 229 parameter_or_next_free_.next_free = value; |
193 } | 230 } |
194 | 231 |
195 void MakeWeak(GlobalHandles* global_handles, | 232 void MakeWeak(GlobalHandles* global_handles, |
196 void* parameter, | 233 void* parameter, |
197 WeakReferenceCallback callback) { | 234 WeakReferenceCallback callback) { |
198 ASSERT(state_ != FREE); | 235 ASSERT(state() != FREE); |
199 if (!IsWeakRetainer()) { | 236 if (!IsWeakRetainer()) { |
200 global_handles->number_of_weak_handles_++; | 237 global_handles->number_of_weak_handles_++; |
201 if (object_->IsJSGlobalObject()) { | 238 if (object_->IsJSGlobalObject()) { |
202 global_handles->number_of_global_object_weak_handles_++; | 239 global_handles->number_of_global_object_weak_handles_++; |
203 } | 240 } |
204 } | 241 } |
205 state_ = WEAK; | 242 set_state(WEAK); |
206 set_parameter(parameter); | 243 set_parameter(parameter); |
207 callback_ = callback; | 244 callback_ = callback; |
208 } | 245 } |
209 | 246 |
210 void ClearWeakness(GlobalHandles* global_handles) { | 247 void ClearWeakness(GlobalHandles* global_handles) { |
211 ASSERT(state_ != FREE); | 248 ASSERT(state() != FREE); |
212 if (IsWeakRetainer()) { | 249 if (IsWeakRetainer()) { |
213 global_handles->number_of_weak_handles_--; | 250 global_handles->number_of_weak_handles_--; |
214 if (object_->IsJSGlobalObject()) { | 251 if (object_->IsJSGlobalObject()) { |
215 global_handles->number_of_global_object_weak_handles_--; | 252 global_handles->number_of_global_object_weak_handles_--; |
216 } | 253 } |
217 } | 254 } |
218 state_ = NORMAL; | 255 set_state(NORMAL); |
219 set_parameter(NULL); | 256 set_parameter(NULL); |
220 } | 257 } |
221 | 258 |
222 bool PostGarbageCollectionProcessing(Isolate* isolate, | 259 bool PostGarbageCollectionProcessing(Isolate* isolate, |
223 GlobalHandles* global_handles) { | 260 GlobalHandles* global_handles) { |
224 if (state_ != Node::PENDING) return false; | 261 if (state() != Node::PENDING) return false; |
225 WeakReferenceCallback func = callback(); | 262 WeakReferenceCallback func = callback(); |
226 if (func == NULL) { | 263 if (func == NULL) { |
227 Release(global_handles); | 264 Release(global_handles); |
228 return false; | 265 return false; |
229 } | 266 } |
230 void* par = parameter(); | 267 void* par = parameter(); |
231 state_ = NEAR_DEATH; | 268 set_state(NEAR_DEATH); |
232 set_parameter(NULL); | 269 set_parameter(NULL); |
233 | 270 |
234 v8::Persistent<v8::Object> object = ToApi<v8::Object>(handle()); | 271 v8::Persistent<v8::Object> object = ToApi<v8::Object>(handle()); |
235 { | 272 { |
236 // Check that we are not passing a finalized external string to | 273 // Check that we are not passing a finalized external string to |
237 // the callback. | 274 // the callback. |
238 ASSERT(!object_->IsExternalAsciiString() || | 275 ASSERT(!object_->IsExternalAsciiString() || |
239 ExternalAsciiString::cast(object_)->resource() != NULL); | 276 ExternalAsciiString::cast(object_)->resource() != NULL); |
240 ASSERT(!object_->IsExternalTwoByteString() || | 277 ASSERT(!object_->IsExternalTwoByteString() || |
241 ExternalTwoByteString::cast(object_)->resource() != NULL); | 278 ExternalTwoByteString::cast(object_)->resource() != NULL); |
242 // Leaving V8. | 279 // Leaving V8. |
243 VMState state(isolate, EXTERNAL); | 280 VMState state(isolate, EXTERNAL); |
244 func(object, par); | 281 func(object, par); |
245 } | 282 } |
246 // Absence of explicit cleanup or revival of weak handle | 283 // Absence of explicit cleanup or revival of weak handle |
247 // in most of the cases would lead to memory leak. | 284 // in most of the cases would lead to memory leak. |
248 ASSERT(state_ != NEAR_DEATH); | 285 ASSERT(state() != NEAR_DEATH); |
249 return true; | 286 return true; |
250 } | 287 } |
251 | 288 |
252 private: | 289 private: |
253 inline NodeBlock* FindBlock(); | 290 inline NodeBlock* FindBlock(); |
254 inline void IncreaseBlockUses(GlobalHandles* global_handles); | 291 inline void IncreaseBlockUses(GlobalHandles* global_handles); |
255 inline void DecreaseBlockUses(GlobalHandles* global_handles); | 292 inline void DecreaseBlockUses(GlobalHandles* global_handles); |
256 | 293 |
257 // Storage for object pointer. | 294 // Storage for object pointer. |
258 // Placed first to avoid offset computation. | 295 // Placed first to avoid offset computation. |
259 Object* object_; | 296 Object* object_; |
260 | 297 |
261 // Next word stores class_id, index, state, and independent. | 298 // Next word stores class_id, index, state, and independent. |
262 // Note: the most aligned fields should go first. | 299 // Note: the most aligned fields should go first. |
263 | 300 |
264 // Wrapper class ID. | 301 // Wrapper class ID. |
265 uint16_t class_id_; | 302 uint16_t class_id_; |
266 | 303 |
267 // Index in the containing handle block. | 304 // Index in the containing handle block. |
268 uint8_t index_; | 305 uint8_t index_; |
269 | 306 |
270 // Need one more bit for MSVC as it treats enums as signed. | 307 // This stores three flags (independent, partially_dependent and |
271 State state_ : 4; | 308 // in_new_space_list) and a State. |
272 | 309 uint8_t flags_and_state_; |
Michael Starzinger
2013/01/15 09:06:41
Let's just call this field "flags_".
haraken
2013/01/15 09:40:39
Done.
| |
273 bool independent_ : 1; | |
274 bool partially_dependent_ : 1; | |
275 bool in_new_space_list_ : 1; | |
276 | 310 |
277 // Handle specific callback. | 311 // Handle specific callback. |
278 WeakReferenceCallback callback_; | 312 WeakReferenceCallback callback_; |
279 | 313 |
280 // Provided data for callback. In FREE state, this is used for | 314 // Provided data for callback. In FREE state, this is used for |
281 // the free list link. | 315 // the free list link. |
282 union { | 316 union { |
283 void* parameter; | 317 void* parameter; |
284 Node* next_free; | 318 Node* next_free; |
285 } parameter_or_next_free_; | 319 } parameter_or_next_free_; |
(...skipping 512 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
798 implicit_ref_groups_.Clear(); | 832 implicit_ref_groups_.Clear(); |
799 } | 833 } |
800 | 834 |
801 | 835 |
802 void GlobalHandles::TearDown() { | 836 void GlobalHandles::TearDown() { |
803 // TODO(1428): invoke weak callbacks. | 837 // TODO(1428): invoke weak callbacks. |
804 } | 838 } |
805 | 839 |
806 | 840 |
807 } } // namespace v8::internal | 841 } } // namespace v8::internal |
OLD | NEW |