| OLD | NEW |
| 1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/global-handles.h" | 5 #include "src/global-handles.h" |
| 6 | 6 |
| 7 #include "src/api.h" | 7 #include "src/api.h" |
| 8 #include "src/v8.h" | 8 #include "src/v8.h" |
| 9 #include "src/vm-state-inl.h" | 9 #include "src/vm-state-inl.h" |
| 10 | 10 |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 75 parameter_or_next_free_.next_free = NULL; | 75 parameter_or_next_free_.next_free = NULL; |
| 76 weak_callback_ = NULL; | 76 weak_callback_ = NULL; |
| 77 } | 77 } |
| 78 #endif | 78 #endif |
| 79 | 79 |
| 80 void Initialize(int index, Node** first_free) { | 80 void Initialize(int index, Node** first_free) { |
| 81 object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue); | 81 object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue); |
| 82 index_ = static_cast<uint8_t>(index); | 82 index_ = static_cast<uint8_t>(index); |
| 83 DCHECK(static_cast<int>(index_) == index); | 83 DCHECK(static_cast<int>(index_) == index); |
| 84 set_state(FREE); | 84 set_state(FREE); |
| 85 set_weakness_type(NORMAL_WEAK); | |
| 86 set_in_new_space_list(false); | 85 set_in_new_space_list(false); |
| 87 parameter_or_next_free_.next_free = *first_free; | 86 parameter_or_next_free_.next_free = *first_free; |
| 88 *first_free = this; | 87 *first_free = this; |
| 89 } | 88 } |
| 90 | 89 |
| 91 void Acquire(Object* object) { | 90 void Acquire(Object* object) { |
| 92 DCHECK(state() == FREE); | 91 DCHECK(state() == FREE); |
| 93 object_ = object; | 92 object_ = object; |
| 94 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; | 93 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; |
| 95 set_independent(false); | 94 set_independent(false); |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 190 // Check for PENDING to ensure correct answer when processing callbacks. | 189 // Check for PENDING to ensure correct answer when processing callbacks. |
| 191 return state() == PENDING || state() == NEAR_DEATH; | 190 return state() == PENDING || state() == NEAR_DEATH; |
| 192 } | 191 } |
| 193 | 192 |
| 194 bool IsWeak() const { return state() == WEAK; } | 193 bool IsWeak() const { return state() == WEAK; } |
| 195 | 194 |
| 196 bool IsInUse() const { return state() != FREE; } | 195 bool IsInUse() const { return state() != FREE; } |
| 197 | 196 |
| 198 bool IsRetainer() const { | 197 bool IsRetainer() const { |
| 199 return state() != FREE && | 198 return state() != FREE && |
| 200 !(state() == NEAR_DEATH && weakness_type() != NORMAL_WEAK && | 199 !(state() == NEAR_DEATH && weakness_type() != FINALIZER_WEAK); |
| 201 weakness_type() != FINALIZER_WEAK); | |
| 202 } | 200 } |
| 203 | 201 |
| 204 bool IsStrongRetainer() const { return state() == NORMAL; } | 202 bool IsStrongRetainer() const { return state() == NORMAL; } |
| 205 | 203 |
| 206 bool IsWeakRetainer() const { | 204 bool IsWeakRetainer() const { |
| 207 return state() == WEAK || state() == PENDING || | 205 return state() == WEAK || state() == PENDING || |
| 208 (state() == NEAR_DEATH && (weakness_type() == NORMAL_WEAK || | 206 (state() == NEAR_DEATH && weakness_type() == FINALIZER_WEAK); |
| 209 weakness_type() == FINALIZER_WEAK)); | |
| 210 } | 207 } |
| 211 | 208 |
| 212 void MarkPending() { | 209 void MarkPending() { |
| 213 DCHECK(state() == WEAK); | 210 DCHECK(state() == WEAK); |
| 214 set_state(PENDING); | 211 set_state(PENDING); |
| 215 } | 212 } |
| 216 | 213 |
| 217 // Independent flag accessors. | 214 // Independent flag accessors. |
| 218 void MarkIndependent() { | 215 void MarkIndependent() { |
| 219 DCHECK(IsInUse()); | 216 DCHECK(IsInUse()); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 245 // Accessors for next free node in the free list. | 242 // Accessors for next free node in the free list. |
| 246 Node* next_free() { | 243 Node* next_free() { |
| 247 DCHECK(state() == FREE); | 244 DCHECK(state() == FREE); |
| 248 return parameter_or_next_free_.next_free; | 245 return parameter_or_next_free_.next_free; |
| 249 } | 246 } |
| 250 void set_next_free(Node* value) { | 247 void set_next_free(Node* value) { |
| 251 DCHECK(state() == FREE); | 248 DCHECK(state() == FREE); |
| 252 parameter_or_next_free_.next_free = value; | 249 parameter_or_next_free_.next_free = value; |
| 253 } | 250 } |
| 254 | 251 |
| 255 void MakeWeak(void* parameter, WeakCallback weak_callback) { | |
| 256 DCHECK(weak_callback != nullptr); | |
| 257 DCHECK(IsInUse()); | |
| 258 CHECK_NE(object_, reinterpret_cast<Object*>(kGlobalHandleZapValue)); | |
| 259 set_state(WEAK); | |
| 260 set_weakness_type(NORMAL_WEAK); | |
| 261 set_parameter(parameter); | |
| 262 weak_callback_ = weak_callback; | |
| 263 } | |
| 264 | |
| 265 void MakeWeak(void* parameter, | 252 void MakeWeak(void* parameter, |
| 266 WeakCallbackInfo<void>::Callback phantom_callback, | 253 WeakCallbackInfo<void>::Callback phantom_callback, |
| 267 v8::WeakCallbackType type) { | 254 v8::WeakCallbackType type) { |
| 268 DCHECK(phantom_callback != nullptr); | 255 DCHECK(phantom_callback != nullptr); |
| 269 DCHECK(IsInUse()); | 256 DCHECK(IsInUse()); |
| 270 CHECK_NE(object_, reinterpret_cast<Object*>(kGlobalHandleZapValue)); | 257 CHECK_NE(object_, reinterpret_cast<Object*>(kGlobalHandleZapValue)); |
| 271 set_state(WEAK); | 258 set_state(WEAK); |
| 272 switch (type) { | 259 switch (type) { |
| 273 case v8::WeakCallbackType::kParameter: | 260 case v8::WeakCallbackType::kParameter: |
| 274 set_weakness_type(PHANTOM_WEAK); | 261 set_weakness_type(PHANTOM_WEAK); |
| 275 break; | 262 break; |
| 276 case v8::WeakCallbackType::kInternalFields: | 263 case v8::WeakCallbackType::kInternalFields: |
| 277 set_weakness_type(PHANTOM_WEAK_2_INTERNAL_FIELDS); | 264 set_weakness_type(PHANTOM_WEAK_2_INTERNAL_FIELDS); |
| 278 break; | 265 break; |
| 279 case v8::WeakCallbackType::kFinalizer: | 266 case v8::WeakCallbackType::kFinalizer: |
| 280 set_weakness_type(FINALIZER_WEAK); | 267 set_weakness_type(FINALIZER_WEAK); |
| 281 break; | 268 break; |
| 282 } | 269 } |
| 283 set_parameter(parameter); | 270 set_parameter(parameter); |
| 284 weak_callback_ = reinterpret_cast<WeakCallback>(phantom_callback); | 271 weak_callback_ = phantom_callback; |
| 285 } | 272 } |
| 286 | 273 |
| 287 void* ClearWeakness() { | 274 void* ClearWeakness() { |
| 288 DCHECK(IsInUse()); | 275 DCHECK(IsInUse()); |
| 289 void* p = parameter(); | 276 void* p = parameter(); |
| 290 set_state(NORMAL); | 277 set_state(NORMAL); |
| 291 set_parameter(NULL); | 278 set_parameter(NULL); |
| 292 return p; | 279 return p; |
| 293 } | 280 } |
| 294 | 281 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 330 return false; | 317 return false; |
| 331 } | 318 } |
| 332 set_state(NEAR_DEATH); | 319 set_state(NEAR_DEATH); |
| 333 | 320 |
| 334 // Check that we are not passing a finalized external string to | 321 // Check that we are not passing a finalized external string to |
| 335 // the callback. | 322 // the callback. |
| 336 DCHECK(!object_->IsExternalOneByteString() || | 323 DCHECK(!object_->IsExternalOneByteString() || |
| 337 ExternalOneByteString::cast(object_)->resource() != NULL); | 324 ExternalOneByteString::cast(object_)->resource() != NULL); |
| 338 DCHECK(!object_->IsExternalTwoByteString() || | 325 DCHECK(!object_->IsExternalTwoByteString() || |
| 339 ExternalTwoByteString::cast(object_)->resource() != NULL); | 326 ExternalTwoByteString::cast(object_)->resource() != NULL); |
| 340 if (weakness_type() != NORMAL_WEAK && weakness_type() != FINALIZER_WEAK) { | 327 if (weakness_type() != FINALIZER_WEAK) { |
| 341 return false; | 328 return false; |
| 342 } | 329 } |
| 343 | 330 |
| 344 // Leaving V8. | 331 // Leaving V8. |
| 345 VMState<EXTERNAL> vmstate(isolate); | 332 VMState<EXTERNAL> vmstate(isolate); |
| 346 HandleScope handle_scope(isolate); | 333 HandleScope handle_scope(isolate); |
| 347 if (weakness_type() == NORMAL_WEAK) { | 334 void* internal_fields[v8::kInternalFieldsInWeakCallback] = {nullptr, |
| 348 Object** object = location(); | 335 nullptr}; |
| 349 Handle<Object> handle(*object, isolate); | 336 v8::WeakCallbackInfo<void> data(reinterpret_cast<v8::Isolate*>(isolate), |
| 350 v8::WeakCallbackData<v8::Value, void> data( | 337 parameter(), internal_fields, nullptr); |
| 351 reinterpret_cast<v8::Isolate*>(isolate), parameter(), | 338 weak_callback_(data); |
| 352 v8::Utils::ToLocal(handle)); | |
| 353 set_parameter(NULL); | |
| 354 weak_callback_(data); | |
| 355 } else { | |
| 356 void* internal_fields[v8::kInternalFieldsInWeakCallback] = {nullptr, | |
| 357 nullptr}; | |
| 358 v8::WeakCallbackInfo<void> data(reinterpret_cast<v8::Isolate*>(isolate), | |
| 359 parameter(), internal_fields, nullptr); | |
| 360 auto callback = reinterpret_cast<v8::WeakCallbackInfo<void>::Callback>( | |
| 361 weak_callback_); | |
| 362 callback(data); | |
| 363 } | |
| 364 | 339 |
| 365 // Absence of explicit cleanup or revival of weak handle | 340 // Absence of explicit cleanup or revival of weak handle |
| 366 // in most of the cases would lead to memory leak. | 341 // in most of the cases would lead to memory leak. |
| 367 CHECK(state() != NEAR_DEATH); | 342 CHECK(state() != NEAR_DEATH); |
| 368 return true; | 343 return true; |
| 369 } | 344 } |
| 370 | 345 |
| 371 inline GlobalHandles* GetGlobalHandles(); | 346 inline GlobalHandles* GetGlobalHandles(); |
| 372 | 347 |
| 373 private: | 348 private: |
| (...skipping 20 matching lines...) Expand all Loading... |
| 394 class IsIndependent : public BitField<bool, 3, 1> {}; | 369 class IsIndependent : public BitField<bool, 3, 1> {}; |
| 395 // The following two fields are mutually exclusive | 370 // The following two fields are mutually exclusive |
| 396 class IsActive : public BitField<bool, 4, 1> {}; | 371 class IsActive : public BitField<bool, 4, 1> {}; |
| 397 class IsPartiallyDependent : public BitField<bool, 4, 1> {}; | 372 class IsPartiallyDependent : public BitField<bool, 4, 1> {}; |
| 398 class IsInNewSpaceList : public BitField<bool, 5, 1> {}; | 373 class IsInNewSpaceList : public BitField<bool, 5, 1> {}; |
| 399 class NodeWeaknessType : public BitField<WeaknessType, 6, 2> {}; | 374 class NodeWeaknessType : public BitField<WeaknessType, 6, 2> {}; |
| 400 | 375 |
| 401 uint8_t flags_; | 376 uint8_t flags_; |
| 402 | 377 |
| 403 // Handle specific callback - might be a weak reference in disguise. | 378 // Handle specific callback - might be a weak reference in disguise. |
| 404 WeakCallback weak_callback_; | 379 WeakCallbackInfo<void>::Callback weak_callback_; |
| 405 | 380 |
| 406 // Provided data for callback. In FREE state, this is used for | 381 // Provided data for callback. In FREE state, this is used for |
| 407 // the free list link. | 382 // the free list link. |
| 408 union { | 383 union { |
| 409 void* parameter; | 384 void* parameter; |
| 410 Node* next_free; | 385 Node* next_free; |
| 411 } parameter_or_next_free_; | 386 } parameter_or_next_free_; |
| 412 | 387 |
| 413 DISALLOW_COPY_AND_ASSIGN(Node); | 388 DISALLOW_COPY_AND_ASSIGN(Node); |
| 414 }; | 389 }; |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 610 DCHECK(location != NULL); | 585 DCHECK(location != NULL); |
| 611 return Node::FromLocation(location)->GetGlobalHandles()->Create(*location); | 586 return Node::FromLocation(location)->GetGlobalHandles()->Create(*location); |
| 612 } | 587 } |
| 613 | 588 |
| 614 | 589 |
| 615 void GlobalHandles::Destroy(Object** location) { | 590 void GlobalHandles::Destroy(Object** location) { |
| 616 if (location != NULL) Node::FromLocation(location)->Release(); | 591 if (location != NULL) Node::FromLocation(location)->Release(); |
| 617 } | 592 } |
| 618 | 593 |
| 619 | 594 |
| 620 void GlobalHandles::MakeWeak(Object** location, void* parameter, | |
| 621 WeakCallback weak_callback) { | |
| 622 Node::FromLocation(location)->MakeWeak(parameter, weak_callback); | |
| 623 } | |
| 624 | |
| 625 | |
| 626 typedef v8::WeakCallbackInfo<void>::Callback GenericCallback; | 595 typedef v8::WeakCallbackInfo<void>::Callback GenericCallback; |
| 627 | 596 |
| 628 | 597 |
| 629 void GlobalHandles::MakeWeak(Object** location, void* parameter, | 598 void GlobalHandles::MakeWeak(Object** location, void* parameter, |
| 630 GenericCallback phantom_callback, | 599 GenericCallback phantom_callback, |
| 631 v8::WeakCallbackType type) { | 600 v8::WeakCallbackType type) { |
| 632 Node::FromLocation(location)->MakeWeak(parameter, phantom_callback, type); | 601 Node::FromLocation(location)->MakeWeak(parameter, phantom_callback, type); |
| 633 } | 602 } |
| 634 | 603 |
| 635 | 604 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 661 bool GlobalHandles::IsWeak(Object** location) { | 630 bool GlobalHandles::IsWeak(Object** location) { |
| 662 return Node::FromLocation(location)->IsWeak(); | 631 return Node::FromLocation(location)->IsWeak(); |
| 663 } | 632 } |
| 664 | 633 |
| 665 void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) { | 634 void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) { |
| 666 for (NodeIterator it(this); !it.done(); it.Advance()) { | 635 for (NodeIterator it(this); !it.done(); it.Advance()) { |
| 667 Node* node = it.node(); | 636 Node* node = it.node(); |
| 668 if (node->IsWeakRetainer()) { | 637 if (node->IsWeakRetainer()) { |
| 669 // Pending weak phantom handles die immediately. Everything else survives. | 638 // Pending weak phantom handles die immediately. Everything else survives. |
| 670 if (node->state() == Node::PENDING && | 639 if (node->state() == Node::PENDING && |
| 671 node->weakness_type() != NORMAL_WEAK && | |
| 672 node->weakness_type() != FINALIZER_WEAK) { | 640 node->weakness_type() != FINALIZER_WEAK) { |
| 673 node->CollectPhantomCallbackData(isolate(), | 641 node->CollectPhantomCallbackData(isolate(), |
| 674 &pending_phantom_callbacks_); | 642 &pending_phantom_callbacks_); |
| 675 } else { | 643 } else { |
| 676 v->VisitPointer(node->location()); | 644 v->VisitPointer(node->location()); |
| 677 } | 645 } |
| 678 } | 646 } |
| 679 } | 647 } |
| 680 } | 648 } |
| 681 | 649 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 723 | 691 |
| 724 | 692 |
| 725 void GlobalHandles::IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v) { | 693 void GlobalHandles::IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v) { |
| 726 for (int i = 0; i < new_space_nodes_.length(); ++i) { | 694 for (int i = 0; i < new_space_nodes_.length(); ++i) { |
| 727 Node* node = new_space_nodes_[i]; | 695 Node* node = new_space_nodes_[i]; |
| 728 DCHECK(node->is_in_new_space_list()); | 696 DCHECK(node->is_in_new_space_list()); |
| 729 if ((node->is_independent() || node->is_partially_dependent()) && | 697 if ((node->is_independent() || node->is_partially_dependent()) && |
| 730 node->IsWeakRetainer()) { | 698 node->IsWeakRetainer()) { |
| 731 // Pending weak phantom handles die immediately. Everything else survives. | 699 // Pending weak phantom handles die immediately. Everything else survives. |
| 732 if (node->state() == Node::PENDING && | 700 if (node->state() == Node::PENDING && |
| 733 node->weakness_type() != NORMAL_WEAK && | |
| 734 node->weakness_type() != FINALIZER_WEAK) { | 701 node->weakness_type() != FINALIZER_WEAK) { |
| 735 node->CollectPhantomCallbackData(isolate(), | 702 node->CollectPhantomCallbackData(isolate(), |
| 736 &pending_phantom_callbacks_); | 703 &pending_phantom_callbacks_); |
| 737 } else { | 704 } else { |
| 738 v->VisitPointer(node->location()); | 705 v->VisitPointer(node->location()); |
| 739 } | 706 } |
| 740 } | 707 } |
| 741 } | 708 } |
| 742 } | 709 } |
| 743 | 710 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 767 | 734 |
| 768 | 735 |
| 769 void GlobalHandles::IterateNewSpaceWeakUnmodifiedRoots(ObjectVisitor* v) { | 736 void GlobalHandles::IterateNewSpaceWeakUnmodifiedRoots(ObjectVisitor* v) { |
| 770 for (int i = 0; i < new_space_nodes_.length(); ++i) { | 737 for (int i = 0; i < new_space_nodes_.length(); ++i) { |
| 771 Node* node = new_space_nodes_[i]; | 738 Node* node = new_space_nodes_[i]; |
| 772 DCHECK(node->is_in_new_space_list()); | 739 DCHECK(node->is_in_new_space_list()); |
| 773 if ((node->is_independent() || !node->is_active()) && | 740 if ((node->is_independent() || !node->is_active()) && |
| 774 node->IsWeakRetainer()) { | 741 node->IsWeakRetainer()) { |
| 775 // Pending weak phantom handles die immediately. Everything else survives. | 742 // Pending weak phantom handles die immediately. Everything else survives. |
| 776 if (node->state() == Node::PENDING && | 743 if (node->state() == Node::PENDING && |
| 777 node->weakness_type() != NORMAL_WEAK && | |
| 778 node->weakness_type() != FINALIZER_WEAK) { | 744 node->weakness_type() != FINALIZER_WEAK) { |
| 779 node->CollectPhantomCallbackData(isolate(), | 745 node->CollectPhantomCallbackData(isolate(), |
| 780 &pending_phantom_callbacks_); | 746 &pending_phantom_callbacks_); |
| 781 } else { | 747 } else { |
| 782 v->VisitPointer(node->location()); | 748 v->VisitPointer(node->location()); |
| 783 } | 749 } |
| 784 } | 750 } |
| 785 } | 751 } |
| 786 } | 752 } |
| 787 | 753 |
| (...skipping 714 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1502 blocks_[block][offset] = object; | 1468 blocks_[block][offset] = object; |
| 1503 if (isolate->heap()->InNewSpace(object)) { | 1469 if (isolate->heap()->InNewSpace(object)) { |
| 1504 new_space_indices_.Add(size_); | 1470 new_space_indices_.Add(size_); |
| 1505 } | 1471 } |
| 1506 *index = size_++; | 1472 *index = size_++; |
| 1507 } | 1473 } |
| 1508 | 1474 |
| 1509 | 1475 |
| 1510 } // namespace internal | 1476 } // namespace internal |
| 1511 } // namespace v8 | 1477 } // namespace v8 |
| OLD | NEW |