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 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
85 ~Node() { | 85 ~Node() { |
86 // TODO(1428): if it's a weak handle we should have invoked its callback. | 86 // TODO(1428): if it's a weak handle we should have invoked its callback. |
87 // Zap the values for eager trapping. | 87 // Zap the values for eager trapping. |
88 object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue); | 88 object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue); |
89 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; | 89 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; |
90 index_ = 0; | 90 index_ = 0; |
91 set_independent(false); | 91 set_independent(false); |
92 set_partially_dependent(false); | 92 set_partially_dependent(false); |
93 set_in_new_space_list(false); | 93 set_in_new_space_list(false); |
94 parameter_or_next_free_.next_free = NULL; | 94 parameter_or_next_free_.next_free = NULL; |
95 near_death_callback_ = NULL; | 95 weak_reference_callback_ = NULL; |
96 } | 96 } |
97 #endif | 97 #endif |
98 | 98 |
99 void Initialize(int index, Node** first_free) { | 99 void Initialize(int index, Node** first_free) { |
100 index_ = static_cast<uint8_t>(index); | 100 index_ = static_cast<uint8_t>(index); |
101 ASSERT(static_cast<int>(index_) == index); | 101 ASSERT(static_cast<int>(index_) == index); |
102 set_state(FREE); | 102 set_state(FREE); |
103 set_in_new_space_list(false); | 103 set_in_new_space_list(false); |
104 parameter_or_next_free_.next_free = *first_free; | 104 parameter_or_next_free_.next_free = *first_free; |
105 *first_free = this; | 105 *first_free = this; |
106 } | 106 } |
107 | 107 |
108 void Acquire(Object* object) { | 108 void Acquire(Object* object) { |
109 ASSERT(state() == FREE); | 109 ASSERT(state() == FREE); |
110 object_ = object; | 110 object_ = object; |
111 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; | 111 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; |
112 set_independent(false); | 112 set_independent(false); |
113 set_partially_dependent(false); | 113 set_partially_dependent(false); |
114 set_state(NORMAL); | 114 set_state(NORMAL); |
115 parameter_or_next_free_.parameter = NULL; | 115 parameter_or_next_free_.parameter = NULL; |
116 near_death_callback_ = NULL; | 116 weak_reference_callback_ = NULL; |
117 IncreaseBlockUses(); | 117 IncreaseBlockUses(); |
118 } | 118 } |
119 | 119 |
120 void Release() { | 120 void Release() { |
121 ASSERT(state() != FREE); | 121 ASSERT(state() != FREE); |
122 set_state(FREE); | 122 set_state(FREE); |
123 #ifdef ENABLE_EXTRA_CHECKS | 123 #ifdef ENABLE_EXTRA_CHECKS |
124 // Zap the values for eager trapping. | 124 // Zap the values for eager trapping. |
125 object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue); | 125 object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue); |
126 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; | 126 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; |
127 set_independent(false); | 127 set_independent(false); |
128 set_partially_dependent(false); | 128 set_partially_dependent(false); |
129 near_death_callback_ = NULL; | 129 weak_reference_callback_ = NULL; |
130 #endif | 130 #endif |
131 DecreaseBlockUses(); | 131 DecreaseBlockUses(); |
132 } | 132 } |
133 | 133 |
134 // Object slot accessors. | 134 // Object slot accessors. |
135 Object* object() const { return object_; } | 135 Object* object() const { return object_; } |
136 Object** location() { return &object_; } | 136 Object** location() { return &object_; } |
137 Handle<Object> handle() { return Handle<Object>(location()); } | 137 Handle<Object> handle() { return Handle<Object>(location()); } |
138 | 138 |
139 // Wrapper class ID accessors. | 139 // Wrapper class ID accessors. |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
225 Node* next_free() { | 225 Node* next_free() { |
226 ASSERT(state() == FREE); | 226 ASSERT(state() == FREE); |
227 return parameter_or_next_free_.next_free; | 227 return parameter_or_next_free_.next_free; |
228 } | 228 } |
229 void set_next_free(Node* value) { | 229 void set_next_free(Node* value) { |
230 ASSERT(state() == FREE); | 230 ASSERT(state() == FREE); |
231 parameter_or_next_free_.next_free = value; | 231 parameter_or_next_free_.next_free = value; |
232 } | 232 } |
233 | 233 |
234 void MakeWeak(void* parameter, | 234 void MakeWeak(void* parameter, |
235 RevivableCallback weak_reference_callback, | 235 RevivableCallback weak_reference_callback) { |
236 NearDeathCallback near_death_callback) { | |
237 ASSERT(state() != FREE); | 236 ASSERT(state() != FREE); |
238 set_state(WEAK); | 237 set_state(WEAK); |
239 set_parameter(parameter); | 238 set_parameter(parameter); |
240 if (weak_reference_callback != NULL) { | 239 weak_reference_callback_ = weak_reference_callback; |
241 flags_ = IsWeakCallback::update(flags_, true); | |
242 near_death_callback_ = | |
243 reinterpret_cast<NearDeathCallback>(weak_reference_callback); | |
244 } else { | |
245 flags_ = IsWeakCallback::update(flags_, false); | |
246 near_death_callback_ = near_death_callback; | |
247 } | |
248 } | 240 } |
249 | 241 |
250 void ClearWeakness() { | 242 void ClearWeakness() { |
251 ASSERT(state() != FREE); | 243 ASSERT(state() != FREE); |
252 set_state(NORMAL); | 244 set_state(NORMAL); |
253 set_parameter(NULL); | 245 set_parameter(NULL); |
254 } | 246 } |
255 | 247 |
256 bool PostGarbageCollectionProcessing(Isolate* isolate) { | 248 bool PostGarbageCollectionProcessing(Isolate* isolate) { |
257 if (state() != Node::PENDING) return false; | 249 if (state() != Node::PENDING) return false; |
258 if (near_death_callback_ == NULL) { | 250 if (weak_reference_callback_ == NULL) { |
259 Release(); | 251 Release(); |
260 return false; | 252 return false; |
261 } | 253 } |
262 void* par = parameter(); | 254 void* par = parameter(); |
263 set_state(NEAR_DEATH); | 255 set_state(NEAR_DEATH); |
264 set_parameter(NULL); | 256 set_parameter(NULL); |
265 | 257 |
266 v8::Persistent<v8::Value> object = ToApi<v8::Value>(handle()); | 258 Object** object = location(); |
267 { | 259 { |
268 // Check that we are not passing a finalized external string to | 260 // Check that we are not passing a finalized external string to |
269 // the callback. | 261 // the callback. |
270 ASSERT(!object_->IsExternalAsciiString() || | 262 ASSERT(!object_->IsExternalAsciiString() || |
271 ExternalAsciiString::cast(object_)->resource() != NULL); | 263 ExternalAsciiString::cast(object_)->resource() != NULL); |
272 ASSERT(!object_->IsExternalTwoByteString() || | 264 ASSERT(!object_->IsExternalTwoByteString() || |
273 ExternalTwoByteString::cast(object_)->resource() != NULL); | 265 ExternalTwoByteString::cast(object_)->resource() != NULL); |
274 // Leaving V8. | 266 // Leaving V8. |
275 VMState<EXTERNAL> state(isolate); | 267 VMState<EXTERNAL> state(isolate); |
276 if (near_death_callback_ != NULL) { | 268 weak_reference_callback_(reinterpret_cast<v8::Isolate*>(isolate), |
277 if (IsWeakCallback::decode(flags_)) { | 269 reinterpret_cast<Persistent<Value>*>(&object), |
278 RevivableCallback callback = | |
279 reinterpret_cast<RevivableCallback>(near_death_callback_); | |
280 callback(reinterpret_cast<v8::Isolate*>(isolate), | |
281 &object, | |
282 par); | |
283 } else { | |
284 near_death_callback_(reinterpret_cast<v8::Isolate*>(isolate), | |
285 object, | |
286 par); | 270 par); |
287 } | |
288 } | |
289 } | 271 } |
290 // Absence of explicit cleanup or revival of weak handle | 272 // Absence of explicit cleanup or revival of weak handle |
291 // in most of the cases would lead to memory leak. | 273 // in most of the cases would lead to memory leak. |
292 ASSERT(state() != NEAR_DEATH); | 274 ASSERT(state() != NEAR_DEATH); |
293 return true; | 275 return true; |
294 } | 276 } |
295 | 277 |
296 private: | 278 private: |
297 inline NodeBlock* FindBlock(); | 279 inline NodeBlock* FindBlock(); |
298 inline GlobalHandles* GetGlobalHandles(); | 280 inline GlobalHandles* GetGlobalHandles(); |
(...skipping 12 matching lines...) Expand all Loading... |
311 | 293 |
312 // Index in the containing handle block. | 294 // Index in the containing handle block. |
313 uint8_t index_; | 295 uint8_t index_; |
314 | 296 |
315 // This stores three flags (independent, partially_dependent and | 297 // This stores three flags (independent, partially_dependent and |
316 // in_new_space_list) and a State. | 298 // in_new_space_list) and a State. |
317 class NodeState: public BitField<State, 0, 4> {}; | 299 class NodeState: public BitField<State, 0, 4> {}; |
318 class IsIndependent: public BitField<bool, 4, 1> {}; | 300 class IsIndependent: public BitField<bool, 4, 1> {}; |
319 class IsPartiallyDependent: public BitField<bool, 5, 1> {}; | 301 class IsPartiallyDependent: public BitField<bool, 5, 1> {}; |
320 class IsInNewSpaceList: public BitField<bool, 6, 1> {}; | 302 class IsInNewSpaceList: public BitField<bool, 6, 1> {}; |
321 class IsWeakCallback: public BitField<bool, 7, 1> {}; | |
322 | 303 |
323 uint8_t flags_; | 304 uint8_t flags_; |
324 | 305 |
325 // Handle specific callback - might be a weak reference in disguise. | 306 // Handle specific callback - might be a weak reference in disguise. |
326 NearDeathCallback near_death_callback_; | 307 RevivableCallback weak_reference_callback_; |
327 | 308 |
328 // Provided data for callback. In FREE state, this is used for | 309 // Provided data for callback. In FREE state, this is used for |
329 // the free list link. | 310 // the free list link. |
330 union { | 311 union { |
331 void* parameter; | 312 void* parameter; |
332 Node* next_free; | 313 Node* next_free; |
333 } parameter_or_next_free_; | 314 } parameter_or_next_free_; |
334 | 315 |
335 DISALLOW_COPY_AND_ASSIGN(Node); | 316 DISALLOW_COPY_AND_ASSIGN(Node); |
336 }; | 317 }; |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
502 } | 483 } |
503 | 484 |
504 | 485 |
505 void GlobalHandles::Destroy(Object** location) { | 486 void GlobalHandles::Destroy(Object** location) { |
506 if (location != NULL) Node::FromLocation(location)->Release(); | 487 if (location != NULL) Node::FromLocation(location)->Release(); |
507 } | 488 } |
508 | 489 |
509 | 490 |
510 void GlobalHandles::MakeWeak(Object** location, | 491 void GlobalHandles::MakeWeak(Object** location, |
511 void* parameter, | 492 void* parameter, |
512 RevivableCallback weak_reference_callback, | 493 RevivableCallback weak_reference_callback) { |
513 NearDeathCallback near_death_callback) { | 494 ASSERT(weak_reference_callback != NULL); |
514 ASSERT((weak_reference_callback == NULL) != (near_death_callback == NULL)); | 495 Node::FromLocation(location)->MakeWeak(parameter, weak_reference_callback); |
515 Node::FromLocation(location)->MakeWeak(parameter, | |
516 weak_reference_callback, | |
517 near_death_callback); | |
518 } | 496 } |
519 | 497 |
520 | 498 |
521 void GlobalHandles::ClearWeakness(Object** location) { | 499 void GlobalHandles::ClearWeakness(Object** location) { |
522 Node::FromLocation(location)->ClearWeakness(); | 500 Node::FromLocation(location)->ClearWeakness(); |
523 } | 501 } |
524 | 502 |
525 | 503 |
526 void GlobalHandles::MarkIndependent(Object** location) { | 504 void GlobalHandles::MarkIndependent(Object** location) { |
527 Node::FromLocation(location)->MarkIndependent(); | 505 Node::FromLocation(location)->MarkIndependent(); |
(...skipping 497 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1025 } | 1003 } |
1026 } | 1004 } |
1027 object_group_connections_.Clear(); | 1005 object_group_connections_.Clear(); |
1028 object_group_connections_.Initialize(kObjectGroupConnectionsCapacity); | 1006 object_group_connections_.Initialize(kObjectGroupConnectionsCapacity); |
1029 retainer_infos_.Clear(); | 1007 retainer_infos_.Clear(); |
1030 implicit_ref_connections_.Clear(); | 1008 implicit_ref_connections_.Clear(); |
1031 } | 1009 } |
1032 | 1010 |
1033 | 1011 |
1034 } } // namespace v8::internal | 1012 } } // namespace v8::internal |
OLD | NEW |