| 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 |