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 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
53 NEAR_DEATH // Callback has informed the handle is near death. | 53 NEAR_DEATH // Callback has informed the handle is near death. |
54 }; | 54 }; |
55 | 55 |
56 // Maps handle location (slot) to the containing node. | 56 // Maps handle location (slot) to the containing node. |
57 static Node* FromLocation(Object** location) { | 57 static Node* FromLocation(Object** location) { |
58 ASSERT(OFFSET_OF(Node, object_) == 0); | 58 ASSERT(OFFSET_OF(Node, object_) == 0); |
59 return reinterpret_cast<Node*>(location); | 59 return reinterpret_cast<Node*>(location); |
60 } | 60 } |
61 | 61 |
62 Node() { | 62 Node() { |
63 ASSERT(OFFSET_OF(Node, flags_) == Internals::kNodeFlagsOffset); | 63 STATIC_ASSERT(offsetof(Node, class_id_) == Internals::kNodeClassIdOffset); |
64 ASSERT(OFFSET_OF(Node, class_id_) == Internals::kNodeClassIdOffset); | 64 STATIC_ASSERT(offsetof(Node, flags_) == Internals::kNodeFlagsOffset); |
65 ASSERT(static_cast<int>(IsIndependent::kShift) == | 65 STATIC_ASSERT(static_cast<int>(NodeState::kMask) == |
66 Internals::kNodeIsIndependentShift); | 66 Internals::kNodeStateMask); |
67 ASSERT(static_cast<int>(IsPartiallyDependent::kShift) == | 67 STATIC_ASSERT(WEAK == Internals::kNodeStateIsWeakValue); |
68 Internals::kNodeIsPartiallyDependentShift); | 68 STATIC_ASSERT(NEAR_DEATH == Internals::kNodeStateIsNearDeathValue); |
69 STATIC_ASSERT(static_cast<int>(IsIndependent::kShift) == | |
70 Internals::kNodeIsIndependentShift); | |
71 STATIC_ASSERT(static_cast<int>(IsPartiallyDependent::kShift) == | |
72 Internals::kNodeIsPartiallyDependentShift); | |
69 } | 73 } |
70 | 74 |
71 #ifdef DEBUG | 75 #ifdef DEBUG |
72 ~Node() { | 76 ~Node() { |
73 // TODO(1428): if it's a weak handle we should have invoked its callback. | 77 // TODO(1428): if it's a weak handle we should have invoked its callback. |
74 // Zap the values for eager trapping. | 78 // Zap the values for eager trapping. |
75 object_ = NULL; | 79 object_ = NULL; |
76 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; | 80 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; |
77 index_ = 0; | 81 index_ = 0; |
78 set_independent(false); | 82 set_independent(false); |
79 set_partially_dependent(false); | 83 set_partially_dependent(false); |
80 set_in_new_space_list(false); | 84 set_in_new_space_list(false); |
81 parameter_or_next_free_.next_free = NULL; | 85 parameter_or_next_free_.next_free = NULL; |
82 callback_ = NULL; | 86 weak_reference_callback_ = NULL; |
87 near_death_callback_ = NULL; | |
83 } | 88 } |
84 #endif | 89 #endif |
85 | 90 |
86 void Initialize(int index, Node** first_free) { | 91 void Initialize(int index, Node** first_free) { |
87 index_ = static_cast<uint8_t>(index); | 92 index_ = static_cast<uint8_t>(index); |
88 ASSERT(static_cast<int>(index_) == index); | 93 ASSERT(static_cast<int>(index_) == index); |
89 set_state(FREE); | 94 set_state(FREE); |
90 set_in_new_space_list(false); | 95 set_in_new_space_list(false); |
91 parameter_or_next_free_.next_free = *first_free; | 96 parameter_or_next_free_.next_free = *first_free; |
92 *first_free = this; | 97 *first_free = this; |
93 } | 98 } |
94 | 99 |
95 void Acquire(Object* object, GlobalHandles* global_handles) { | 100 void Acquire(Object* object, GlobalHandles* global_handles) { |
96 ASSERT(state() == FREE); | 101 ASSERT(state() == FREE); |
97 object_ = object; | 102 object_ = object; |
98 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; | 103 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; |
99 set_independent(false); | 104 set_independent(false); |
100 set_partially_dependent(false); | 105 set_partially_dependent(false); |
101 set_state(NORMAL); | 106 set_state(NORMAL); |
102 parameter_or_next_free_.parameter = NULL; | 107 parameter_or_next_free_.parameter = NULL; |
103 callback_ = NULL; | 108 weak_reference_callback_ = NULL; |
109 near_death_callback_ = NULL; | |
104 IncreaseBlockUses(global_handles); | 110 IncreaseBlockUses(global_handles); |
105 } | 111 } |
106 | 112 |
107 void Release(GlobalHandles* global_handles) { | 113 void Release(GlobalHandles* global_handles) { |
108 ASSERT(state() != FREE); | 114 ASSERT(state() != FREE); |
109 set_state(FREE); | 115 set_state(FREE); |
110 parameter_or_next_free_.next_free = global_handles->first_free_; | 116 parameter_or_next_free_.next_free = global_handles->first_free_; |
111 global_handles->first_free_ = this; | 117 global_handles->first_free_ = this; |
112 DecreaseBlockUses(global_handles); | 118 DecreaseBlockUses(global_handles); |
113 } | 119 } |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
182 | 188 |
183 void MarkPartiallyDependent(GlobalHandles* global_handles) { | 189 void MarkPartiallyDependent(GlobalHandles* global_handles) { |
184 ASSERT(state() != FREE); | 190 ASSERT(state() != FREE); |
185 if (global_handles->isolate()->heap()->InNewSpace(object_)) { | 191 if (global_handles->isolate()->heap()->InNewSpace(object_)) { |
186 set_partially_dependent(true); | 192 set_partially_dependent(true); |
187 } | 193 } |
188 } | 194 } |
189 void clear_partially_dependent() { set_partially_dependent(false); } | 195 void clear_partially_dependent() { set_partially_dependent(false); } |
190 | 196 |
191 // Callback accessor. | 197 // Callback accessor. |
192 WeakReferenceCallback callback() { return callback_; } | 198 // TODO(svenpanne) Re-enable or nuke later. |
Michael Starzinger
2013/01/24 13:09:05
Definitely re-enable, but I am fine with this inte
| |
199 // WeakReferenceCallback callback() { return callback_; } | |
193 | 200 |
194 // Callback parameter accessors. | 201 // Callback parameter accessors. |
195 void set_parameter(void* parameter) { | 202 void set_parameter(void* parameter) { |
196 ASSERT(state() != FREE); | 203 ASSERT(state() != FREE); |
197 parameter_or_next_free_.parameter = parameter; | 204 parameter_or_next_free_.parameter = parameter; |
198 } | 205 } |
199 void* parameter() const { | 206 void* parameter() const { |
200 ASSERT(state() != FREE); | 207 ASSERT(state() != FREE); |
201 return parameter_or_next_free_.parameter; | 208 return parameter_or_next_free_.parameter; |
202 } | 209 } |
203 | 210 |
204 // Accessors for next free node in the free list. | 211 // Accessors for next free node in the free list. |
205 Node* next_free() { | 212 Node* next_free() { |
206 ASSERT(state() == FREE); | 213 ASSERT(state() == FREE); |
207 return parameter_or_next_free_.next_free; | 214 return parameter_or_next_free_.next_free; |
208 } | 215 } |
209 void set_next_free(Node* value) { | 216 void set_next_free(Node* value) { |
210 ASSERT(state() == FREE); | 217 ASSERT(state() == FREE); |
211 parameter_or_next_free_.next_free = value; | 218 parameter_or_next_free_.next_free = value; |
212 } | 219 } |
213 | 220 |
214 void MakeWeak(GlobalHandles* global_handles, | 221 void MakeWeak(GlobalHandles* global_handles, |
215 void* parameter, | 222 void* parameter, |
216 WeakReferenceCallback callback) { | 223 WeakReferenceCallback weak_reference_callback, |
224 NearDeathCallback near_death_callback) { | |
217 ASSERT(state() != FREE); | 225 ASSERT(state() != FREE); |
218 set_state(WEAK); | 226 set_state(WEAK); |
219 set_parameter(parameter); | 227 set_parameter(parameter); |
220 callback_ = callback; | 228 weak_reference_callback_ = weak_reference_callback; |
229 near_death_callback_ = near_death_callback; | |
221 } | 230 } |
222 | 231 |
223 void ClearWeakness(GlobalHandles* global_handles) { | 232 void ClearWeakness(GlobalHandles* global_handles) { |
224 ASSERT(state() != FREE); | 233 ASSERT(state() != FREE); |
225 set_state(NORMAL); | 234 set_state(NORMAL); |
226 set_parameter(NULL); | 235 set_parameter(NULL); |
227 } | 236 } |
228 | 237 |
229 bool PostGarbageCollectionProcessing(Isolate* isolate, | 238 bool PostGarbageCollectionProcessing(Isolate* isolate, |
230 GlobalHandles* global_handles) { | 239 GlobalHandles* global_handles) { |
231 if (state() != Node::PENDING) return false; | 240 if (state() != Node::PENDING) return false; |
232 WeakReferenceCallback func = callback(); | 241 if (weak_reference_callback_ == NULL && |
233 if (func == NULL) { | 242 near_death_callback_ == NULL) { |
234 Release(global_handles); | 243 Release(global_handles); |
235 return false; | 244 return false; |
236 } | 245 } |
237 void* par = parameter(); | 246 void* par = parameter(); |
238 set_state(NEAR_DEATH); | 247 set_state(NEAR_DEATH); |
239 set_parameter(NULL); | 248 set_parameter(NULL); |
240 | 249 |
241 v8::Persistent<v8::Object> object = ToApi<v8::Object>(handle()); | 250 v8::Persistent<v8::Object> object = ToApi<v8::Object>(handle()); |
242 { | 251 { |
243 // Check that we are not passing a finalized external string to | 252 // Check that we are not passing a finalized external string to |
244 // the callback. | 253 // the callback. |
245 ASSERT(!object_->IsExternalAsciiString() || | 254 ASSERT(!object_->IsExternalAsciiString() || |
246 ExternalAsciiString::cast(object_)->resource() != NULL); | 255 ExternalAsciiString::cast(object_)->resource() != NULL); |
247 ASSERT(!object_->IsExternalTwoByteString() || | 256 ASSERT(!object_->IsExternalTwoByteString() || |
248 ExternalTwoByteString::cast(object_)->resource() != NULL); | 257 ExternalTwoByteString::cast(object_)->resource() != NULL); |
249 // Leaving V8. | 258 // Leaving V8. |
250 VMState state(isolate, EXTERNAL); | 259 VMState state(isolate, EXTERNAL); |
251 func(object, par); | 260 if (weak_reference_callback_ != NULL) { |
261 weak_reference_callback_(object, par); | |
262 } | |
263 if (near_death_callback_ != NULL) { | |
264 near_death_callback_(reinterpret_cast<v8::Isolate*>(isolate), | |
265 object, | |
266 par); | |
267 } | |
252 } | 268 } |
253 // Absence of explicit cleanup or revival of weak handle | 269 // Absence of explicit cleanup or revival of weak handle |
254 // in most of the cases would lead to memory leak. | 270 // in most of the cases would lead to memory leak. |
255 ASSERT(state() != NEAR_DEATH); | 271 ASSERT(state() != NEAR_DEATH); |
256 return true; | 272 return true; |
257 } | 273 } |
258 | 274 |
259 private: | 275 private: |
260 inline NodeBlock* FindBlock(); | 276 inline NodeBlock* FindBlock(); |
261 inline void IncreaseBlockUses(GlobalHandles* global_handles); | 277 inline void IncreaseBlockUses(GlobalHandles* global_handles); |
(...skipping 15 matching lines...) Expand all Loading... | |
277 // This stores three flags (independent, partially_dependent and | 293 // This stores three flags (independent, partially_dependent and |
278 // in_new_space_list) and a State. | 294 // in_new_space_list) and a State. |
279 class NodeState: public BitField<State, 0, 4> {}; | 295 class NodeState: public BitField<State, 0, 4> {}; |
280 class IsIndependent: public BitField<bool, 4, 1> {}; | 296 class IsIndependent: public BitField<bool, 4, 1> {}; |
281 class IsPartiallyDependent: public BitField<bool, 5, 1> {}; | 297 class IsPartiallyDependent: public BitField<bool, 5, 1> {}; |
282 class IsInNewSpaceList: public BitField<bool, 6, 1> {}; | 298 class IsInNewSpaceList: public BitField<bool, 6, 1> {}; |
283 | 299 |
284 uint8_t flags_; | 300 uint8_t flags_; |
285 | 301 |
286 // Handle specific callback. | 302 // Handle specific callback. |
287 WeakReferenceCallback callback_; | 303 WeakReferenceCallback weak_reference_callback_; |
304 NearDeathCallback near_death_callback_; | |
288 | 305 |
289 // Provided data for callback. In FREE state, this is used for | 306 // Provided data for callback. In FREE state, this is used for |
290 // the free list link. | 307 // the free list link. |
291 union { | 308 union { |
292 void* parameter; | 309 void* parameter; |
293 Node* next_free; | 310 Node* next_free; |
294 } parameter_or_next_free_; | 311 } parameter_or_next_free_; |
295 | 312 |
296 DISALLOW_COPY_AND_ASSIGN(Node); | 313 DISALLOW_COPY_AND_ASSIGN(Node); |
297 }; | 314 }; |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
443 | 460 |
444 | 461 |
445 void GlobalHandles::Destroy(Object** location) { | 462 void GlobalHandles::Destroy(Object** location) { |
446 isolate_->counters()->global_handles()->Decrement(); | 463 isolate_->counters()->global_handles()->Decrement(); |
447 number_of_global_handles_--; | 464 number_of_global_handles_--; |
448 if (location == NULL) return; | 465 if (location == NULL) return; |
449 Node::FromLocation(location)->Release(this); | 466 Node::FromLocation(location)->Release(this); |
450 } | 467 } |
451 | 468 |
452 | 469 |
453 void GlobalHandles::MakeWeak(Object** location, void* parameter, | 470 void GlobalHandles::MakeWeak(Object** location, |
454 WeakReferenceCallback callback) { | 471 void* parameter, |
455 ASSERT(callback != NULL); | 472 WeakReferenceCallback weak_reference_callback, |
456 Node::FromLocation(location)->MakeWeak(this, parameter, callback); | 473 NearDeathCallback near_death_callback) { |
Michael Starzinger
2013/01/24 13:09:05
Add an assertion similar to the following:
ASSERT
Sven Panne
2013/01/25 08:28:40
Done.
| |
474 Node::FromLocation(location)->MakeWeak(this, | |
475 parameter, | |
476 weak_reference_callback, | |
477 near_death_callback); | |
457 } | 478 } |
458 | 479 |
459 | 480 |
460 void GlobalHandles::ClearWeakness(Object** location) { | 481 void GlobalHandles::ClearWeakness(Object** location) { |
461 Node::FromLocation(location)->ClearWeakness(this); | 482 Node::FromLocation(location)->ClearWeakness(this); |
462 } | 483 } |
463 | 484 |
464 | 485 |
465 void GlobalHandles::MarkIndependent(Object** location) { | 486 void GlobalHandles::MarkIndependent(Object** location) { |
466 Node::FromLocation(location)->MarkIndependent(); | 487 Node::FromLocation(location)->MarkIndependent(); |
(...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
810 implicit_ref_groups_.Clear(); | 831 implicit_ref_groups_.Clear(); |
811 } | 832 } |
812 | 833 |
813 | 834 |
814 void GlobalHandles::TearDown() { | 835 void GlobalHandles::TearDown() { |
815 // TODO(1428): invoke weak callbacks. | 836 // TODO(1428): invoke weak callbacks. |
816 } | 837 } |
817 | 838 |
818 | 839 |
819 } } // namespace v8::internal | 840 } } // namespace v8::internal |
OLD | NEW |