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/cancelable-task.h" | 8 #include "src/cancelable-task.h" |
9 #include "src/objects-inl.h" | 9 #include "src/objects-inl.h" |
10 #include "src/v8.h" | 10 #include "src/v8.h" |
| 11 #include "src/visitors.h" |
11 #include "src/vm-state-inl.h" | 12 #include "src/vm-state-inl.h" |
12 | 13 |
13 namespace v8 { | 14 namespace v8 { |
14 namespace internal { | 15 namespace internal { |
15 | 16 |
16 class GlobalHandles::Node { | 17 class GlobalHandles::Node { |
17 public: | 18 public: |
18 // State transition diagram: | 19 // State transition diagram: |
19 // FREE -> NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, FREE } | 20 // FREE -> NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, FREE } |
20 enum State { | 21 enum State { |
(...skipping 580 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
601 bool GlobalHandles::IsNearDeath(Object** location) { | 602 bool GlobalHandles::IsNearDeath(Object** location) { |
602 return Node::FromLocation(location)->IsNearDeath(); | 603 return Node::FromLocation(location)->IsNearDeath(); |
603 } | 604 } |
604 | 605 |
605 | 606 |
606 bool GlobalHandles::IsWeak(Object** location) { | 607 bool GlobalHandles::IsWeak(Object** location) { |
607 return Node::FromLocation(location)->IsWeak(); | 608 return Node::FromLocation(location)->IsWeak(); |
608 } | 609 } |
609 | 610 |
610 DISABLE_CFI_PERF | 611 DISABLE_CFI_PERF |
611 void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) { | 612 void GlobalHandles::IterateWeakRoots(RootVisitor* v) { |
612 for (NodeIterator it(this); !it.done(); it.Advance()) { | 613 for (NodeIterator it(this); !it.done(); it.Advance()) { |
613 Node* node = it.node(); | 614 Node* node = it.node(); |
614 if (node->IsWeakRetainer()) { | 615 if (node->IsWeakRetainer()) { |
615 // Pending weak phantom handles die immediately. Everything else survives. | 616 // Pending weak phantom handles die immediately. Everything else survives. |
616 if (node->IsPendingPhantomResetHandle()) { | 617 if (node->IsPendingPhantomResetHandle()) { |
617 node->ResetPhantomHandle(); | 618 node->ResetPhantomHandle(); |
618 ++number_of_phantom_handle_resets_; | 619 ++number_of_phantom_handle_resets_; |
619 } else if (node->IsPendingPhantomCallback()) { | 620 } else if (node->IsPendingPhantomCallback()) { |
620 node->CollectPhantomCallbackData(isolate(), | 621 node->CollectPhantomCallbackData(isolate(), |
621 &pending_phantom_callbacks_); | 622 &pending_phantom_callbacks_); |
622 } else { | 623 } else { |
623 v->VisitPointer(node->location()); | 624 v->VisitRootPointer(Root::kGlobalHandles, node->location()); |
624 } | 625 } |
625 } | 626 } |
626 } | 627 } |
627 } | 628 } |
628 | 629 |
629 | 630 |
630 void GlobalHandles::IdentifyWeakHandles(WeakSlotCallback f) { | 631 void GlobalHandles::IdentifyWeakHandles(WeakSlotCallback f) { |
631 for (NodeIterator it(this); !it.done(); it.Advance()) { | 632 for (NodeIterator it(this); !it.done(); it.Advance()) { |
632 if (it.node()->IsWeak() && f(it.node()->location())) { | 633 if (it.node()->IsWeak() && f(it.node()->location())) { |
633 it.node()->MarkPending(); | 634 it.node()->MarkPending(); |
634 } | 635 } |
635 } | 636 } |
636 } | 637 } |
637 | 638 |
638 | 639 void GlobalHandles::IterateNewSpaceStrongAndDependentRoots(RootVisitor* v) { |
639 void GlobalHandles::IterateNewSpaceStrongAndDependentRoots(ObjectVisitor* v) { | |
640 for (int i = 0; i < new_space_nodes_.length(); ++i) { | 640 for (int i = 0; i < new_space_nodes_.length(); ++i) { |
641 Node* node = new_space_nodes_[i]; | 641 Node* node = new_space_nodes_[i]; |
642 if (node->IsStrongRetainer() || | 642 if (node->IsStrongRetainer() || |
643 (node->IsWeakRetainer() && !node->is_independent() && | 643 (node->IsWeakRetainer() && !node->is_independent() && |
644 node->is_active())) { | 644 node->is_active())) { |
645 v->VisitPointer(node->location()); | 645 v->VisitRootPointer(Root::kGlobalHandles, node->location()); |
646 } | 646 } |
647 } | 647 } |
648 } | 648 } |
649 | 649 |
650 | 650 |
651 void GlobalHandles::IdentifyNewSpaceWeakIndependentHandles( | 651 void GlobalHandles::IdentifyNewSpaceWeakIndependentHandles( |
652 WeakSlotCallbackWithHeap f) { | 652 WeakSlotCallbackWithHeap f) { |
653 for (int i = 0; i < new_space_nodes_.length(); ++i) { | 653 for (int i = 0; i < new_space_nodes_.length(); ++i) { |
654 Node* node = new_space_nodes_[i]; | 654 Node* node = new_space_nodes_[i]; |
655 DCHECK(node->is_in_new_space_list()); | 655 DCHECK(node->is_in_new_space_list()); |
656 if (node->is_independent() && node->IsWeak() && | 656 if (node->is_independent() && node->IsWeak() && |
657 f(isolate_->heap(), node->location())) { | 657 f(isolate_->heap(), node->location())) { |
658 node->MarkPending(); | 658 node->MarkPending(); |
659 } | 659 } |
660 } | 660 } |
661 } | 661 } |
662 | 662 |
663 | 663 void GlobalHandles::IterateNewSpaceWeakIndependentRoots(RootVisitor* v) { |
664 void GlobalHandles::IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v) { | |
665 for (int i = 0; i < new_space_nodes_.length(); ++i) { | 664 for (int i = 0; i < new_space_nodes_.length(); ++i) { |
666 Node* node = new_space_nodes_[i]; | 665 Node* node = new_space_nodes_[i]; |
667 DCHECK(node->is_in_new_space_list()); | 666 DCHECK(node->is_in_new_space_list()); |
668 if (node->is_independent() && node->IsWeakRetainer()) { | 667 if (node->is_independent() && node->IsWeakRetainer()) { |
669 // Pending weak phantom handles die immediately. Everything else survives. | 668 // Pending weak phantom handles die immediately. Everything else survives. |
670 if (node->IsPendingPhantomResetHandle()) { | 669 if (node->IsPendingPhantomResetHandle()) { |
671 node->ResetPhantomHandle(); | 670 node->ResetPhantomHandle(); |
672 ++number_of_phantom_handle_resets_; | 671 ++number_of_phantom_handle_resets_; |
673 } else if (node->IsPendingPhantomCallback()) { | 672 } else if (node->IsPendingPhantomCallback()) { |
674 node->CollectPhantomCallbackData(isolate(), | 673 node->CollectPhantomCallbackData(isolate(), |
675 &pending_phantom_callbacks_); | 674 &pending_phantom_callbacks_); |
676 } else { | 675 } else { |
677 v->VisitPointer(node->location()); | 676 v->VisitRootPointer(Root::kGlobalHandles, node->location()); |
678 } | 677 } |
679 } | 678 } |
680 } | 679 } |
681 } | 680 } |
682 | 681 |
683 | 682 |
684 void GlobalHandles::IdentifyWeakUnmodifiedObjects( | 683 void GlobalHandles::IdentifyWeakUnmodifiedObjects( |
685 WeakSlotCallback is_unmodified) { | 684 WeakSlotCallback is_unmodified) { |
686 for (int i = 0; i < new_space_nodes_.length(); ++i) { | 685 for (int i = 0; i < new_space_nodes_.length(); ++i) { |
687 Node* node = new_space_nodes_[i]; | 686 Node* node = new_space_nodes_[i]; |
(...skipping 10 matching lines...) Expand all Loading... |
698 Node* node = new_space_nodes_[i]; | 697 Node* node = new_space_nodes_[i]; |
699 DCHECK(node->is_in_new_space_list()); | 698 DCHECK(node->is_in_new_space_list()); |
700 if ((node->is_independent() || !node->is_active()) && node->IsWeak() && | 699 if ((node->is_independent() || !node->is_active()) && node->IsWeak() && |
701 is_unscavenged(isolate_->heap(), node->location())) { | 700 is_unscavenged(isolate_->heap(), node->location())) { |
702 node->MarkPending(); | 701 node->MarkPending(); |
703 } | 702 } |
704 } | 703 } |
705 } | 704 } |
706 | 705 |
707 template <GlobalHandles::IterationMode mode> | 706 template <GlobalHandles::IterationMode mode> |
708 void GlobalHandles::IterateNewSpaceWeakUnmodifiedRoots(ObjectVisitor* v) { | 707 void GlobalHandles::IterateNewSpaceWeakUnmodifiedRoots(RootVisitor* v) { |
709 for (int i = 0; i < new_space_nodes_.length(); ++i) { | 708 for (int i = 0; i < new_space_nodes_.length(); ++i) { |
710 Node* node = new_space_nodes_[i]; | 709 Node* node = new_space_nodes_[i]; |
711 DCHECK(node->is_in_new_space_list()); | 710 DCHECK(node->is_in_new_space_list()); |
712 if ((node->is_independent() || !node->is_active()) && | 711 if ((node->is_independent() || !node->is_active()) && |
713 node->IsWeakRetainer()) { | 712 node->IsWeakRetainer()) { |
714 // Pending weak phantom handles die immediately. Everything else survives. | 713 // Pending weak phantom handles die immediately. Everything else survives. |
715 if (node->IsPendingPhantomResetHandle()) { | 714 if (node->IsPendingPhantomResetHandle()) { |
716 if (mode == IterationMode::HANDLE_PHANTOM_NODES || | 715 if (mode == IterationMode::HANDLE_PHANTOM_NODES || |
717 mode == IterationMode::HANDLE_PHANTOM_NODES_VISIT_OTHERS) { | 716 mode == IterationMode::HANDLE_PHANTOM_NODES_VISIT_OTHERS) { |
718 node->ResetPhantomHandle(); | 717 node->ResetPhantomHandle(); |
719 ++number_of_phantom_handle_resets_; | 718 ++number_of_phantom_handle_resets_; |
720 } | 719 } |
721 } else if (node->IsPendingPhantomCallback()) { | 720 } else if (node->IsPendingPhantomCallback()) { |
722 if (mode == IterationMode::HANDLE_PHANTOM_NODES || | 721 if (mode == IterationMode::HANDLE_PHANTOM_NODES || |
723 mode == IterationMode::HANDLE_PHANTOM_NODES_VISIT_OTHERS) { | 722 mode == IterationMode::HANDLE_PHANTOM_NODES_VISIT_OTHERS) { |
724 node->CollectPhantomCallbackData(isolate(), | 723 node->CollectPhantomCallbackData(isolate(), |
725 &pending_phantom_callbacks_); | 724 &pending_phantom_callbacks_); |
726 } | 725 } |
727 } else { | 726 } else { |
728 if (mode == IterationMode::VISIT_OTHERS || | 727 if (mode == IterationMode::VISIT_OTHERS || |
729 mode == IterationMode::HANDLE_PHANTOM_NODES_VISIT_OTHERS) { | 728 mode == IterationMode::HANDLE_PHANTOM_NODES_VISIT_OTHERS) { |
730 v->VisitPointer(node->location()); | 729 v->VisitRootPointer(Root::kGlobalHandles, node->location()); |
731 } | 730 } |
732 } | 731 } |
733 } | 732 } |
734 } | 733 } |
735 } | 734 } |
736 | 735 |
737 template void GlobalHandles::IterateNewSpaceWeakUnmodifiedRoots< | 736 template void GlobalHandles::IterateNewSpaceWeakUnmodifiedRoots< |
738 GlobalHandles::HANDLE_PHANTOM_NODES>(ObjectVisitor* v); | 737 GlobalHandles::HANDLE_PHANTOM_NODES>(RootVisitor* v); |
739 | 738 |
740 template void GlobalHandles::IterateNewSpaceWeakUnmodifiedRoots< | 739 template void GlobalHandles::IterateNewSpaceWeakUnmodifiedRoots< |
741 GlobalHandles::VISIT_OTHERS>(ObjectVisitor* v); | 740 GlobalHandles::VISIT_OTHERS>(RootVisitor* v); |
742 | 741 |
743 template void GlobalHandles::IterateNewSpaceWeakUnmodifiedRoots< | 742 template void GlobalHandles::IterateNewSpaceWeakUnmodifiedRoots< |
744 GlobalHandles::HANDLE_PHANTOM_NODES_VISIT_OTHERS>(ObjectVisitor* v); | 743 GlobalHandles::HANDLE_PHANTOM_NODES_VISIT_OTHERS>(RootVisitor* v); |
745 | 744 |
746 void GlobalHandles::InvokeSecondPassPhantomCallbacks( | 745 void GlobalHandles::InvokeSecondPassPhantomCallbacks( |
747 List<PendingPhantomCallback>* callbacks, Isolate* isolate) { | 746 List<PendingPhantomCallback>* callbacks, Isolate* isolate) { |
748 while (callbacks->length() != 0) { | 747 while (callbacks->length() != 0) { |
749 auto callback = callbacks->RemoveLast(); | 748 auto callback = callbacks->RemoveLast(); |
750 DCHECK(callback.node() == nullptr); | 749 DCHECK(callback.node() == nullptr); |
751 // Fire second pass callback | 750 // Fire second pass callback |
752 callback.Invoke(isolate); | 751 callback.Invoke(isolate); |
753 } | 752 } |
754 } | 753 } |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
921 // If the callbacks caused a nested GC, then return. See comment in | 920 // If the callbacks caused a nested GC, then return. See comment in |
922 // PostScavengeProcessing. | 921 // PostScavengeProcessing. |
923 return freed_nodes; | 922 return freed_nodes; |
924 } | 923 } |
925 if (initial_post_gc_processing_count == post_gc_processing_count_) { | 924 if (initial_post_gc_processing_count == post_gc_processing_count_) { |
926 UpdateListOfNewSpaceNodes(); | 925 UpdateListOfNewSpaceNodes(); |
927 } | 926 } |
928 return freed_nodes; | 927 return freed_nodes; |
929 } | 928 } |
930 | 929 |
931 | 930 void GlobalHandles::IterateStrongRoots(RootVisitor* v) { |
932 void GlobalHandles::IterateStrongRoots(ObjectVisitor* v) { | |
933 for (NodeIterator it(this); !it.done(); it.Advance()) { | 931 for (NodeIterator it(this); !it.done(); it.Advance()) { |
934 if (it.node()->IsStrongRetainer()) { | 932 if (it.node()->IsStrongRetainer()) { |
935 v->VisitPointer(it.node()->location()); | 933 v->VisitRootPointer(Root::kGlobalHandles, it.node()->location()); |
936 } | 934 } |
937 } | 935 } |
938 } | 936 } |
939 | 937 |
940 | 938 |
941 DISABLE_CFI_PERF | 939 DISABLE_CFI_PERF |
942 void GlobalHandles::IterateAllRoots(ObjectVisitor* v) { | 940 void GlobalHandles::IterateAllRoots(RootVisitor* v) { |
943 for (NodeIterator it(this); !it.done(); it.Advance()) { | 941 for (NodeIterator it(this); !it.done(); it.Advance()) { |
944 if (it.node()->IsRetainer()) { | 942 if (it.node()->IsRetainer()) { |
945 v->VisitPointer(it.node()->location()); | 943 v->VisitRootPointer(Root::kGlobalHandles, it.node()->location()); |
946 } | 944 } |
947 } | 945 } |
948 } | 946 } |
949 | 947 |
950 | 948 |
951 DISABLE_CFI_PERF | 949 DISABLE_CFI_PERF |
952 void GlobalHandles::ApplyPersistentHandleVisitor( | 950 void GlobalHandles::ApplyPersistentHandleVisitor( |
953 v8::PersistentHandleVisitor* visitor, GlobalHandles::Node* node) { | 951 v8::PersistentHandleVisitor* visitor, GlobalHandles::Node* node) { |
954 v8::Value* value = ToApi<v8::Value>(Handle<Object>(node->location())); | 952 v8::Value* value = ToApi<v8::Value>(Handle<Object>(node->location())); |
955 visitor->VisitPersistentHandle( | 953 visitor->VisitPersistentHandle( |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1082 for (unsigned i = 0; i < arraysize(singleton_handles_); i++) { | 1080 for (unsigned i = 0; i < arraysize(singleton_handles_); i++) { |
1083 singleton_handles_[i] = kInvalidIndex; | 1081 singleton_handles_[i] = kInvalidIndex; |
1084 } | 1082 } |
1085 } | 1083 } |
1086 | 1084 |
1087 | 1085 |
1088 EternalHandles::~EternalHandles() { | 1086 EternalHandles::~EternalHandles() { |
1089 for (int i = 0; i < blocks_.length(); i++) delete[] blocks_[i]; | 1087 for (int i = 0; i < blocks_.length(); i++) delete[] blocks_[i]; |
1090 } | 1088 } |
1091 | 1089 |
1092 | 1090 void EternalHandles::IterateAllRoots(RootVisitor* visitor) { |
1093 void EternalHandles::IterateAllRoots(ObjectVisitor* visitor) { | |
1094 int limit = size_; | 1091 int limit = size_; |
1095 for (int i = 0; i < blocks_.length(); i++) { | 1092 for (int i = 0; i < blocks_.length(); i++) { |
1096 DCHECK(limit > 0); | 1093 DCHECK(limit > 0); |
1097 Object** block = blocks_[i]; | 1094 Object** block = blocks_[i]; |
1098 visitor->VisitPointers(block, block + Min(limit, kSize)); | 1095 visitor->VisitRootPointers(Root::kEternalHandles, block, |
| 1096 block + Min(limit, kSize)); |
1099 limit -= kSize; | 1097 limit -= kSize; |
1100 } | 1098 } |
1101 } | 1099 } |
1102 | 1100 |
1103 | 1101 void EternalHandles::IterateNewSpaceRoots(RootVisitor* visitor) { |
1104 void EternalHandles::IterateNewSpaceRoots(ObjectVisitor* visitor) { | |
1105 for (int i = 0; i < new_space_indices_.length(); i++) { | 1102 for (int i = 0; i < new_space_indices_.length(); i++) { |
1106 visitor->VisitPointer(GetLocation(new_space_indices_[i])); | 1103 visitor->VisitRootPointer(Root::kEternalHandles, |
| 1104 GetLocation(new_space_indices_[i])); |
1107 } | 1105 } |
1108 } | 1106 } |
1109 | 1107 |
1110 | 1108 |
1111 void EternalHandles::PostGarbageCollectionProcessing(Heap* heap) { | 1109 void EternalHandles::PostGarbageCollectionProcessing(Heap* heap) { |
1112 int last = 0; | 1110 int last = 0; |
1113 for (int i = 0; i < new_space_indices_.length(); i++) { | 1111 for (int i = 0; i < new_space_indices_.length(); i++) { |
1114 int index = new_space_indices_[i]; | 1112 int index = new_space_indices_[i]; |
1115 if (heap->InNewSpace(*GetLocation(index))) { | 1113 if (heap->InNewSpace(*GetLocation(index))) { |
1116 new_space_indices_[last++] = index; | 1114 new_space_indices_[last++] = index; |
(...skipping 20 matching lines...) Expand all Loading... |
1137 blocks_[block][offset] = object; | 1135 blocks_[block][offset] = object; |
1138 if (isolate->heap()->InNewSpace(object)) { | 1136 if (isolate->heap()->InNewSpace(object)) { |
1139 new_space_indices_.Add(size_); | 1137 new_space_indices_.Add(size_); |
1140 } | 1138 } |
1141 *index = size_++; | 1139 *index = size_++; |
1142 } | 1140 } |
1143 | 1141 |
1144 | 1142 |
1145 } // namespace internal | 1143 } // namespace internal |
1146 } // namespace v8 | 1144 } // namespace v8 |
OLD | NEW |