| 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 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 76 ~Node() { | 76 ~Node() { |
| 77 // 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. |
| 78 // Zap the values for eager trapping. | 78 // Zap the values for eager trapping. |
| 79 object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue); | 79 object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue); |
| 80 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; | 80 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; |
| 81 index_ = 0; | 81 index_ = 0; |
| 82 set_independent(false); | 82 set_independent(false); |
| 83 set_partially_dependent(false); | 83 set_partially_dependent(false); |
| 84 set_in_new_space_list(false); | 84 set_in_new_space_list(false); |
| 85 parameter_or_next_free_.next_free = NULL; | 85 parameter_or_next_free_.next_free = NULL; |
| 86 weak_reference_callback_ = NULL; | |
| 87 near_death_callback_ = NULL; | 86 near_death_callback_ = NULL; |
| 88 } | 87 } |
| 89 #endif | 88 #endif |
| 90 | 89 |
| 91 void Initialize(int index, Node** first_free) { | 90 void Initialize(int index, Node** first_free) { |
| 92 index_ = static_cast<uint8_t>(index); | 91 index_ = static_cast<uint8_t>(index); |
| 93 ASSERT(static_cast<int>(index_) == index); | 92 ASSERT(static_cast<int>(index_) == index); |
| 94 set_state(FREE); | 93 set_state(FREE); |
| 95 set_in_new_space_list(false); | 94 set_in_new_space_list(false); |
| 96 parameter_or_next_free_.next_free = *first_free; | 95 parameter_or_next_free_.next_free = *first_free; |
| 97 *first_free = this; | 96 *first_free = this; |
| 98 } | 97 } |
| 99 | 98 |
| 100 void Acquire(Object* object, GlobalHandles* global_handles) { | 99 void Acquire(Object* object, GlobalHandles* global_handles) { |
| 101 ASSERT(state() == FREE); | 100 ASSERT(state() == FREE); |
| 102 object_ = object; | 101 object_ = object; |
| 103 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; | 102 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; |
| 104 set_independent(false); | 103 set_independent(false); |
| 105 set_partially_dependent(false); | 104 set_partially_dependent(false); |
| 106 set_state(NORMAL); | 105 set_state(NORMAL); |
| 107 parameter_or_next_free_.parameter = NULL; | 106 parameter_or_next_free_.parameter = NULL; |
| 108 weak_reference_callback_ = NULL; | |
| 109 near_death_callback_ = NULL; | 107 near_death_callback_ = NULL; |
| 110 IncreaseBlockUses(global_handles); | 108 IncreaseBlockUses(global_handles); |
| 111 } | 109 } |
| 112 | 110 |
| 113 void Release(GlobalHandles* global_handles) { | 111 void Release(GlobalHandles* global_handles) { |
| 114 ASSERT(state() != FREE); | 112 ASSERT(state() != FREE); |
| 115 set_state(FREE); | 113 set_state(FREE); |
| 116 // TODO(mstarzinger): Put behind debug flag once embedders are stabilized. | 114 // TODO(mstarzinger): Put behind debug flag once embedders are stabilized. |
| 117 object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue); | 115 object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue); |
| 118 #ifdef DEBUG | 116 #ifdef DEBUG |
| 119 // Zap the values for eager trapping. | 117 // Zap the values for eager trapping. |
| 120 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; | 118 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; |
| 121 set_independent(false); | 119 set_independent(false); |
| 122 set_partially_dependent(false); | 120 set_partially_dependent(false); |
| 123 weak_reference_callback_ = NULL; | |
| 124 near_death_callback_ = NULL; | 121 near_death_callback_ = NULL; |
| 125 #endif | 122 #endif |
| 126 parameter_or_next_free_.next_free = global_handles->first_free_; | 123 parameter_or_next_free_.next_free = global_handles->first_free_; |
| 127 global_handles->first_free_ = this; | 124 global_handles->first_free_ = this; |
| 128 DecreaseBlockUses(global_handles); | 125 DecreaseBlockUses(global_handles); |
| 129 } | 126 } |
| 130 | 127 |
| 131 // Object slot accessors. | 128 // Object slot accessors. |
| 132 Object* object() const { return object_; } | 129 Object* object() const { return object_; } |
| 133 Object** location() { return &object_; } | 130 Object** location() { return &object_; } |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 228 parameter_or_next_free_.next_free = value; | 225 parameter_or_next_free_.next_free = value; |
| 229 } | 226 } |
| 230 | 227 |
| 231 void MakeWeak(GlobalHandles* global_handles, | 228 void MakeWeak(GlobalHandles* global_handles, |
| 232 void* parameter, | 229 void* parameter, |
| 233 WeakReferenceCallback weak_reference_callback, | 230 WeakReferenceCallback weak_reference_callback, |
| 234 NearDeathCallback near_death_callback) { | 231 NearDeathCallback near_death_callback) { |
| 235 ASSERT(state() != FREE); | 232 ASSERT(state() != FREE); |
| 236 set_state(WEAK); | 233 set_state(WEAK); |
| 237 set_parameter(parameter); | 234 set_parameter(parameter); |
| 238 weak_reference_callback_ = weak_reference_callback; | 235 if (weak_reference_callback != NULL) { |
| 239 near_death_callback_ = near_death_callback; | 236 flags_ = IsWeakCallback::update(flags_, true); |
| 237 near_death_callback_ = |
| 238 reinterpret_cast<NearDeathCallback>(weak_reference_callback); |
| 239 } else { |
| 240 flags_ = IsWeakCallback::update(flags_, false); |
| 241 near_death_callback_ = near_death_callback; |
| 242 } |
| 240 } | 243 } |
| 241 | 244 |
| 242 void ClearWeakness(GlobalHandles* global_handles) { | 245 void ClearWeakness(GlobalHandles* global_handles) { |
| 243 ASSERT(state() != FREE); | 246 ASSERT(state() != FREE); |
| 244 set_state(NORMAL); | 247 set_state(NORMAL); |
| 245 set_parameter(NULL); | 248 set_parameter(NULL); |
| 246 } | 249 } |
| 247 | 250 |
| 248 bool PostGarbageCollectionProcessing(Isolate* isolate, | 251 bool PostGarbageCollectionProcessing(Isolate* isolate, |
| 249 GlobalHandles* global_handles) { | 252 GlobalHandles* global_handles) { |
| 250 if (state() != Node::PENDING) return false; | 253 if (state() != Node::PENDING) return false; |
| 251 if (weak_reference_callback_ == NULL && | 254 if (near_death_callback_ == NULL) { |
| 252 near_death_callback_ == NULL) { | |
| 253 Release(global_handles); | 255 Release(global_handles); |
| 254 return false; | 256 return false; |
| 255 } | 257 } |
| 256 void* par = parameter(); | 258 void* par = parameter(); |
| 257 set_state(NEAR_DEATH); | 259 set_state(NEAR_DEATH); |
| 258 set_parameter(NULL); | 260 set_parameter(NULL); |
| 259 | 261 |
| 260 v8::Persistent<v8::Object> object = ToApi<v8::Object>(handle()); | 262 v8::Persistent<v8::Object> object = ToApi<v8::Object>(handle()); |
| 261 { | 263 { |
| 262 // Check that we are not passing a finalized external string to | 264 // Check that we are not passing a finalized external string to |
| 263 // the callback. | 265 // the callback. |
| 264 ASSERT(!object_->IsExternalAsciiString() || | 266 ASSERT(!object_->IsExternalAsciiString() || |
| 265 ExternalAsciiString::cast(object_)->resource() != NULL); | 267 ExternalAsciiString::cast(object_)->resource() != NULL); |
| 266 ASSERT(!object_->IsExternalTwoByteString() || | 268 ASSERT(!object_->IsExternalTwoByteString() || |
| 267 ExternalTwoByteString::cast(object_)->resource() != NULL); | 269 ExternalTwoByteString::cast(object_)->resource() != NULL); |
| 268 // Leaving V8. | 270 // Leaving V8. |
| 269 VMState state(isolate, EXTERNAL); | 271 VMState state(isolate, EXTERNAL); |
| 270 if (weak_reference_callback_ != NULL) { | |
| 271 weak_reference_callback_(object, par); | |
| 272 } | |
| 273 if (near_death_callback_ != NULL) { | 272 if (near_death_callback_ != NULL) { |
| 274 near_death_callback_(reinterpret_cast<v8::Isolate*>(isolate), | 273 if (IsWeakCallback::decode(flags_)) { |
| 275 object, | 274 WeakReferenceCallback callback = |
| 276 par); | 275 reinterpret_cast<WeakReferenceCallback>(near_death_callback_); |
| 276 callback(object, par); |
| 277 } else { |
| 278 near_death_callback_(reinterpret_cast<v8::Isolate*>(isolate), |
| 279 object, |
| 280 par); |
| 281 } |
| 277 } | 282 } |
| 278 } | 283 } |
| 279 // Absence of explicit cleanup or revival of weak handle | 284 // Absence of explicit cleanup or revival of weak handle |
| 280 // in most of the cases would lead to memory leak. | 285 // in most of the cases would lead to memory leak. |
| 281 ASSERT(state() != NEAR_DEATH); | 286 ASSERT(state() != NEAR_DEATH); |
| 282 return true; | 287 return true; |
| 283 } | 288 } |
| 284 | 289 |
| 285 private: | 290 private: |
| 286 inline NodeBlock* FindBlock(); | 291 inline NodeBlock* FindBlock(); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 299 | 304 |
| 300 // Index in the containing handle block. | 305 // Index in the containing handle block. |
| 301 uint8_t index_; | 306 uint8_t index_; |
| 302 | 307 |
| 303 // This stores three flags (independent, partially_dependent and | 308 // This stores three flags (independent, partially_dependent and |
| 304 // in_new_space_list) and a State. | 309 // in_new_space_list) and a State. |
| 305 class NodeState: public BitField<State, 0, 4> {}; | 310 class NodeState: public BitField<State, 0, 4> {}; |
| 306 class IsIndependent: public BitField<bool, 4, 1> {}; | 311 class IsIndependent: public BitField<bool, 4, 1> {}; |
| 307 class IsPartiallyDependent: public BitField<bool, 5, 1> {}; | 312 class IsPartiallyDependent: public BitField<bool, 5, 1> {}; |
| 308 class IsInNewSpaceList: public BitField<bool, 6, 1> {}; | 313 class IsInNewSpaceList: public BitField<bool, 6, 1> {}; |
| 314 class IsWeakCallback: public BitField<bool, 7, 1> {}; |
| 309 | 315 |
| 310 uint8_t flags_; | 316 uint8_t flags_; |
| 311 | 317 |
| 312 // Handle specific callback. | 318 // Handle specific callback - might be a weak reference in disguise. |
| 313 WeakReferenceCallback weak_reference_callback_; | |
| 314 NearDeathCallback near_death_callback_; | 319 NearDeathCallback near_death_callback_; |
| 315 | 320 |
| 316 // Provided data for callback. In FREE state, this is used for | 321 // Provided data for callback. In FREE state, this is used for |
| 317 // the free list link. | 322 // the free list link. |
| 318 union { | 323 union { |
| 319 void* parameter; | 324 void* parameter; |
| 320 Node* next_free; | 325 Node* next_free; |
| 321 } parameter_or_next_free_; | 326 } parameter_or_next_free_; |
| 322 | 327 |
| 323 DISALLOW_COPY_AND_ASSIGN(Node); | 328 DISALLOW_COPY_AND_ASSIGN(Node); |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 474 number_of_global_handles_--; | 479 number_of_global_handles_--; |
| 475 if (location == NULL) return; | 480 if (location == NULL) return; |
| 476 Node::FromLocation(location)->Release(this); | 481 Node::FromLocation(location)->Release(this); |
| 477 } | 482 } |
| 478 | 483 |
| 479 | 484 |
| 480 void GlobalHandles::MakeWeak(Object** location, | 485 void GlobalHandles::MakeWeak(Object** location, |
| 481 void* parameter, | 486 void* parameter, |
| 482 WeakReferenceCallback weak_reference_callback, | 487 WeakReferenceCallback weak_reference_callback, |
| 483 NearDeathCallback near_death_callback) { | 488 NearDeathCallback near_death_callback) { |
| 484 ASSERT((weak_reference_callback != NULL) != | 489 ASSERT(near_death_callback != NULL); |
| 485 (near_death_callback != NULL)); | |
| 486 Node::FromLocation(location)->MakeWeak(this, | 490 Node::FromLocation(location)->MakeWeak(this, |
| 487 parameter, | 491 parameter, |
| 488 weak_reference_callback, | 492 weak_reference_callback, |
| 489 near_death_callback); | 493 near_death_callback); |
| 490 } | 494 } |
| 491 | 495 |
| 492 | 496 |
| 493 void GlobalHandles::ClearWeakness(Object** location) { | 497 void GlobalHandles::ClearWeakness(Object** location) { |
| 494 Node::FromLocation(location)->ClearWeakness(this); | 498 Node::FromLocation(location)->ClearWeakness(this); |
| 495 } | 499 } |
| (...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 854 implicit_ref_groups_.Clear(); | 858 implicit_ref_groups_.Clear(); |
| 855 } | 859 } |
| 856 | 860 |
| 857 | 861 |
| 858 void GlobalHandles::TearDown() { | 862 void GlobalHandles::TearDown() { |
| 859 // TODO(1428): invoke weak callbacks. | 863 // TODO(1428): invoke weak callbacks. |
| 860 } | 864 } |
| 861 | 865 |
| 862 | 866 |
| 863 } } // namespace v8::internal | 867 } } // namespace v8::internal |
| OLD | NEW |