Chromium Code Reviews| 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 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 59 #ifdef ENABLE_HANDLE_ZAPPING | 59 #ifdef ENABLE_HANDLE_ZAPPING |
| 60 ~Node() { | 60 ~Node() { |
| 61 // TODO(1428): if it's a weak handle we should have invoked its callback. | 61 // TODO(1428): if it's a weak handle we should have invoked its callback. |
| 62 // Zap the values for eager trapping. | 62 // Zap the values for eager trapping. |
| 63 object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue); | 63 object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue); |
| 64 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; | 64 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; |
| 65 index_ = 0; | 65 index_ = 0; |
| 66 set_independent(false); | 66 set_independent(false); |
| 67 set_partially_dependent(false); | 67 set_partially_dependent(false); |
| 68 set_in_new_space_list(false); | 68 set_in_new_space_list(false); |
| 69 set_unmodified(false); | |
| 69 parameter_or_next_free_.next_free = NULL; | 70 parameter_or_next_free_.next_free = NULL; |
| 70 weak_callback_ = NULL; | 71 weak_callback_ = NULL; |
| 71 } | 72 } |
| 72 #endif | 73 #endif |
| 73 | 74 |
| 74 void Initialize(int index, Node** first_free) { | 75 void Initialize(int index, Node** first_free) { |
| 75 index_ = static_cast<uint8_t>(index); | 76 index_ = static_cast<uint8_t>(index); |
| 76 DCHECK(static_cast<int>(index_) == index); | 77 DCHECK(static_cast<int>(index_) == index); |
| 77 set_state(FREE); | 78 set_state(FREE); |
| 78 set_weakness_type(NORMAL_WEAK); | 79 set_weakness_type(NORMAL_WEAK); |
| 79 set_in_new_space_list(false); | 80 set_in_new_space_list(false); |
| 81 set_unmodified(false); | |
| 80 parameter_or_next_free_.next_free = *first_free; | 82 parameter_or_next_free_.next_free = *first_free; |
| 81 *first_free = this; | 83 *first_free = this; |
| 82 } | 84 } |
| 83 | 85 |
| 84 void Acquire(Object* object) { | 86 void Acquire(Object* object) { |
| 85 DCHECK(state() == FREE); | 87 DCHECK(state() == FREE); |
| 86 object_ = object; | 88 object_ = object; |
| 87 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; | 89 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; |
| 88 set_independent(false); | 90 set_independent(false); |
| 89 set_partially_dependent(false); | 91 set_partially_dependent(false); |
| 92 set_unmodified(false); | |
| 90 set_state(NORMAL); | 93 set_state(NORMAL); |
| 91 parameter_or_next_free_.parameter = NULL; | 94 parameter_or_next_free_.parameter = NULL; |
| 92 weak_callback_ = NULL; | 95 weak_callback_ = NULL; |
| 93 IncreaseBlockUses(); | 96 IncreaseBlockUses(); |
| 94 } | 97 } |
| 95 | 98 |
| 96 void Zap() { | 99 void Zap() { |
| 97 DCHECK(IsInUse()); | 100 DCHECK(IsInUse()); |
| 98 // Zap the values for eager trapping. | 101 // Zap the values for eager trapping. |
| 99 object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue); | 102 object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue); |
| 100 } | 103 } |
| 101 | 104 |
| 102 void Release() { | 105 void Release() { |
| 103 DCHECK(IsInUse()); | 106 DCHECK(IsInUse()); |
| 104 set_state(FREE); | 107 set_state(FREE); |
| 105 // Zap the values for eager trapping. | 108 // Zap the values for eager trapping. |
| 106 object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue); | 109 object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue); |
| 107 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; | 110 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; |
| 108 set_independent(false); | 111 set_independent(false); |
| 109 set_partially_dependent(false); | 112 set_partially_dependent(false); |
| 113 set_unmodified(false); | |
| 110 weak_callback_ = NULL; | 114 weak_callback_ = NULL; |
| 111 DecreaseBlockUses(); | 115 DecreaseBlockUses(); |
| 112 } | 116 } |
| 113 | 117 |
| 114 // Object slot accessors. | 118 // Object slot accessors. |
| 115 Object* object() const { return object_; } | 119 Object* object() const { return object_; } |
| 116 Object** location() { return &object_; } | 120 Object** location() { return &object_; } |
| 117 Handle<Object> handle() { return Handle<Object>(location()); } | 121 Handle<Object> handle() { return Handle<Object>(location()); } |
| 118 | 122 |
| 119 // Wrapper class ID accessors. | 123 // Wrapper class ID accessors. |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 146 flags_ = IsPartiallyDependent::update(flags_, v); | 150 flags_ = IsPartiallyDependent::update(flags_, v); |
| 147 } | 151 } |
| 148 | 152 |
| 149 bool is_in_new_space_list() { | 153 bool is_in_new_space_list() { |
| 150 return IsInNewSpaceList::decode(flags_); | 154 return IsInNewSpaceList::decode(flags_); |
| 151 } | 155 } |
| 152 void set_in_new_space_list(bool v) { | 156 void set_in_new_space_list(bool v) { |
| 153 flags_ = IsInNewSpaceList::update(flags_, v); | 157 flags_ = IsInNewSpaceList::update(flags_, v); |
| 154 } | 158 } |
| 155 | 159 |
| 160 bool is_unmodified() { return flag_unmodified_; } | |
| 161 | |
| 162 void set_unmodified(bool v) { flag_unmodified_ = v; } | |
| 163 | |
| 156 WeaknessType weakness_type() const { | 164 WeaknessType weakness_type() const { |
| 157 return NodeWeaknessType::decode(flags_); | 165 return NodeWeaknessType::decode(flags_); |
| 158 } | 166 } |
| 159 void set_weakness_type(WeaknessType weakness_type) { | 167 void set_weakness_type(WeaknessType weakness_type) { |
| 160 flags_ = NodeWeaknessType::update(flags_, weakness_type); | 168 flags_ = NodeWeaknessType::update(flags_, weakness_type); |
| 161 } | 169 } |
| 162 | 170 |
| 163 bool IsNearDeath() const { | 171 bool IsNearDeath() const { |
| 164 // Check for PENDING to ensure correct answer when processing callbacks. | 172 // Check for PENDING to ensure correct answer when processing callbacks. |
| 165 return state() == PENDING || state() == NEAR_DEATH; | 173 return state() == PENDING || state() == NEAR_DEATH; |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 347 | 355 |
| 348 // This stores three flags (independent, partially_dependent and | 356 // This stores three flags (independent, partially_dependent and |
| 349 // in_new_space_list) and a State. | 357 // in_new_space_list) and a State. |
| 350 class NodeState : public BitField<State, 0, 3> {}; | 358 class NodeState : public BitField<State, 0, 3> {}; |
| 351 class IsIndependent : public BitField<bool, 3, 1> {}; | 359 class IsIndependent : public BitField<bool, 3, 1> {}; |
| 352 class IsPartiallyDependent : public BitField<bool, 4, 1> {}; | 360 class IsPartiallyDependent : public BitField<bool, 4, 1> {}; |
| 353 class IsInNewSpaceList : public BitField<bool, 5, 1> {}; | 361 class IsInNewSpaceList : public BitField<bool, 5, 1> {}; |
| 354 class NodeWeaknessType : public BitField<WeaknessType, 6, 2> {}; | 362 class NodeWeaknessType : public BitField<WeaknessType, 6, 2> {}; |
| 355 | 363 |
| 356 uint8_t flags_; | 364 uint8_t flags_; |
| 365 // Merge this with flags_ later on. May be we need to extend flags_ | |
|
mythria
2015/09/28 15:20:08
I added a new field for the unmodified check.flags
jochen (gone - plz use gerrit)
2015/09/28 15:56:19
if the performance tests are looking good, we'll j
| |
| 366 bool flag_unmodified_; | |
| 357 | 367 |
| 358 // Handle specific callback - might be a weak reference in disguise. | 368 // Handle specific callback - might be a weak reference in disguise. |
| 359 WeakCallback weak_callback_; | 369 WeakCallback weak_callback_; |
| 360 | 370 |
| 361 // Provided data for callback. In FREE state, this is used for | 371 // Provided data for callback. In FREE state, this is used for |
| 362 // the free list link. | 372 // the free list link. |
| 363 union { | 373 union { |
| 364 void* parameter; | 374 void* parameter; |
| 365 Node* next_free; | 375 Node* next_free; |
| 366 } parameter_or_next_free_; | 376 } parameter_or_next_free_; |
| (...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 641 } | 651 } |
| 642 } | 652 } |
| 643 } | 653 } |
| 644 | 654 |
| 645 | 655 |
| 646 void GlobalHandles::IterateNewSpaceStrongAndDependentRoots(ObjectVisitor* v) { | 656 void GlobalHandles::IterateNewSpaceStrongAndDependentRoots(ObjectVisitor* v) { |
| 647 for (int i = 0; i < new_space_nodes_.length(); ++i) { | 657 for (int i = 0; i < new_space_nodes_.length(); ++i) { |
| 648 Node* node = new_space_nodes_[i]; | 658 Node* node = new_space_nodes_[i]; |
| 649 if (node->IsStrongRetainer() || | 659 if (node->IsStrongRetainer() || |
| 650 (node->IsWeakRetainer() && !node->is_independent() && | 660 (node->IsWeakRetainer() && !node->is_independent() && |
| 651 !node->is_partially_dependent())) { | 661 !node->is_partially_dependent() && !node->is_unmodified())) { |
| 652 v->VisitPointer(node->location()); | 662 v->VisitPointer(node->location()); |
| 653 } | 663 } |
| 654 } | 664 } |
| 655 } | 665 } |
| 656 | 666 |
| 657 | 667 |
| 658 void GlobalHandles::IdentifyNewSpaceWeakIndependentHandles( | 668 void GlobalHandles::IdentifyNewSpaceWeakIndependentHandles( |
| 659 WeakSlotCallbackWithHeap f) { | 669 WeakSlotCallbackWithHeap f) { |
| 660 for (int i = 0; i < new_space_nodes_.length(); ++i) { | 670 for (int i = 0; i < new_space_nodes_.length(); ++i) { |
| 661 Node* node = new_space_nodes_[i]; | 671 Node* node = new_space_nodes_[i]; |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 680 node->CollectPhantomCallbackData(isolate(), | 690 node->CollectPhantomCallbackData(isolate(), |
| 681 &pending_phantom_callbacks_); | 691 &pending_phantom_callbacks_); |
| 682 } else { | 692 } else { |
| 683 v->VisitPointer(node->location()); | 693 v->VisitPointer(node->location()); |
| 684 } | 694 } |
| 685 } | 695 } |
| 686 } | 696 } |
| 687 } | 697 } |
| 688 | 698 |
| 689 | 699 |
| 700 void GlobalHandles::IdentifyWeakUnmodifiedObjects(WeakSlotCallback f) { | |
|
jochen (gone - plz use gerrit)
2015/09/28 15:56:19
nit. f -> is_unmodified()
mythria
2015/10/02 15:29:16
Done.
| |
| 701 for (int i = 0; i < new_space_nodes_.length(); ++i) { | |
| 702 Node* node = new_space_nodes_[i]; | |
| 703 if (node->IsWeak() && f(node->location())) { | |
| 704 node->set_partially_dependent(true); | |
|
rmcilroy
2015/09/28 17:32:46
fix to set_unmodified(true);
mythria
2015/10/02 15:29:15
Done.
| |
| 705 } | |
| 706 } | |
| 707 } | |
| 708 | |
| 709 | |
| 710 void GlobalHandles::IdentifyNewSpaceWeakUnModifiedHandles( | |
| 711 WeakSlotCallbackWithHeap f) { | |
|
jochen (gone - plz use gerrit)
2015/09/28 15:56:19
f -> is_unscavenged
mythria
2015/10/02 15:29:15
Done.
| |
| 712 for (int i = 0; i < new_space_nodes_.length(); ++i) { | |
| 713 Node* node = new_space_nodes_[i]; | |
| 714 DCHECK(node->is_in_new_space_list()); | |
| 715 if ((node->is_independent() || node->is_unmodified()) && node->IsWeak() && | |
| 716 f(isolate_->heap(), node->location())) { | |
| 717 node->MarkPending(); | |
| 718 } | |
| 719 } | |
| 720 } | |
| 721 | |
| 722 | |
| 723 void GlobalHandles::IterateNewSpaceWeakUnModifiedRoots(ObjectVisitor* v) { | |
| 724 for (int i = 0; i < new_space_nodes_.length(); ++i) { | |
| 725 Node* node = new_space_nodes_[i]; | |
| 726 DCHECK(node->is_in_new_space_list()); | |
| 727 if ((node->is_independent() || node->is_unmodified()) && | |
| 728 node->IsWeakRetainer()) { | |
| 729 // Pending weak phantom handles die immediately. Everything else survives. | |
| 730 if (node->state() == Node::PENDING && | |
| 731 node->weakness_type() != NORMAL_WEAK) { | |
| 732 node->CollectPhantomCallbackData(isolate(), | |
| 733 &pending_phantom_callbacks_); | |
| 734 } else { | |
| 735 v->VisitPointer(node->location()); | |
| 736 } | |
| 737 } | |
| 738 } | |
| 739 } | |
| 740 | |
| 741 | |
| 690 bool GlobalHandles::IterateObjectGroups(ObjectVisitor* v, | 742 bool GlobalHandles::IterateObjectGroups(ObjectVisitor* v, |
| 691 WeakSlotCallbackWithHeap can_skip) { | 743 WeakSlotCallbackWithHeap can_skip) { |
| 692 ComputeObjectGroupsAndImplicitReferences(); | 744 ComputeObjectGroupsAndImplicitReferences(); |
| 693 int last = 0; | 745 int last = 0; |
| 694 bool any_group_was_visited = false; | 746 bool any_group_was_visited = false; |
| 695 for (int i = 0; i < object_groups_.length(); i++) { | 747 for (int i = 0; i < object_groups_.length(); i++) { |
| 696 ObjectGroup* entry = object_groups_.at(i); | 748 ObjectGroup* entry = object_groups_.at(i); |
| 697 DCHECK(entry != NULL); | 749 DCHECK(entry != NULL); |
| 698 | 750 |
| 699 Object*** objects = entry->objects; | 751 Object*** objects = entry->objects; |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 753 Node* node = new_space_nodes_[i]; | 805 Node* node = new_space_nodes_[i]; |
| 754 DCHECK(node->is_in_new_space_list()); | 806 DCHECK(node->is_in_new_space_list()); |
| 755 if (!node->IsRetainer()) { | 807 if (!node->IsRetainer()) { |
| 756 // Free nodes do not have weak callbacks. Do not use them to compute | 808 // Free nodes do not have weak callbacks. Do not use them to compute |
| 757 // the freed_nodes. | 809 // the freed_nodes. |
| 758 continue; | 810 continue; |
| 759 } | 811 } |
| 760 // Skip dependent handles. Their weak callbacks might expect to be | 812 // Skip dependent handles. Their weak callbacks might expect to be |
| 761 // called between two global garbage collection callbacks which | 813 // called between two global garbage collection callbacks which |
| 762 // are not called for minor collections. | 814 // are not called for minor collections. |
| 763 if (!node->is_independent() && !node->is_partially_dependent()) { | 815 if (!node->is_independent() && !node->is_partially_dependent() && |
| 816 !node->is_unmodified()) { | |
| 764 continue; | 817 continue; |
| 765 } | 818 } |
| 766 node->clear_partially_dependent(); | 819 node->clear_partially_dependent(); |
| 767 if (node->PostGarbageCollectionProcessing(isolate_)) { | 820 if (node->PostGarbageCollectionProcessing(isolate_)) { |
| 768 if (initial_post_gc_processing_count != post_gc_processing_count_) { | 821 if (initial_post_gc_processing_count != post_gc_processing_count_) { |
| 769 // Weak callback triggered another GC and another round of | 822 // Weak callback triggered another GC and another round of |
| 770 // PostGarbageCollection processing. The current node might | 823 // PostGarbageCollection processing. The current node might |
| 771 // have been deleted in that round, so we need to bail out (or | 824 // have been deleted in that round, so we need to bail out (or |
| 772 // restart the processing). | 825 // restart the processing). |
| 773 return freed_nodes; | 826 return freed_nodes; |
| (...skipping 500 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1274 blocks_[block][offset] = object; | 1327 blocks_[block][offset] = object; |
| 1275 if (isolate->heap()->InNewSpace(object)) { | 1328 if (isolate->heap()->InNewSpace(object)) { |
| 1276 new_space_indices_.Add(size_); | 1329 new_space_indices_.Add(size_); |
| 1277 } | 1330 } |
| 1278 *index = size_++; | 1331 *index = size_++; |
| 1279 } | 1332 } |
| 1280 | 1333 |
| 1281 | 1334 |
| 1282 } // namespace internal | 1335 } // namespace internal |
| 1283 } // namespace v8 | 1336 } // namespace v8 |
| OLD | NEW |