 Chromium Code Reviews
 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 // 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 18 matching lines...) Expand all Loading... | |
| 29 | 29 | 
| 30 #include "api.h" | 30 #include "api.h" | 
| 31 #include "global-handles.h" | 31 #include "global-handles.h" | 
| 32 | 32 | 
| 33 #include "vm-state-inl.h" | 33 #include "vm-state-inl.h" | 
| 34 | 34 | 
| 35 namespace v8 { | 35 namespace v8 { | 
| 36 namespace internal { | 36 namespace internal { | 
| 37 | 37 | 
| 38 | 38 | 
| 39 ObjectGroup::~ObjectGroup() { | |
| 40 if (info_ != NULL) info_->Dispose(); | |
| 41 } | |
| 42 | |
| 43 | |
| 44 class GlobalHandles::Node { | 39 class GlobalHandles::Node { | 
| 45 public: | 40 public: | 
| 46 // State transition diagram: | 41 // State transition diagram: | 
| 47 // FREE -> NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, FREE } | 42 // FREE -> NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, FREE } | 
| 48 enum State { | 43 enum State { | 
| 49 FREE = 0, | 44 FREE = 0, | 
| 50 NORMAL, // Normal global handle. | 45 NORMAL, // Normal global handle. | 
| 51 WEAK, // Flagged as weak but not yet finalized. | 46 WEAK, // Flagged as weak but not yet finalized. | 
| 52 PENDING, // Has been recognized as only reachable by weak handles. | 47 PENDING, // Has been recognized as only reachable by weak handles. | 
| 53 NEAR_DEATH // Callback has informed the handle is near death. | 48 NEAR_DEATH // Callback has informed the handle is near death. | 
| (...skipping 517 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 571 if ((node->is_independent() || node->is_partially_dependent()) && | 566 if ((node->is_independent() || node->is_partially_dependent()) && | 
| 572 node->IsWeakRetainer()) { | 567 node->IsWeakRetainer()) { | 
| 573 v->VisitPointer(node->location()); | 568 v->VisitPointer(node->location()); | 
| 574 } | 569 } | 
| 575 } | 570 } | 
| 576 } | 571 } | 
| 577 | 572 | 
| 578 | 573 | 
| 579 bool GlobalHandles::IterateObjectGroups(ObjectVisitor* v, | 574 bool GlobalHandles::IterateObjectGroups(ObjectVisitor* v, | 
| 580 WeakSlotCallbackWithHeap can_skip) { | 575 WeakSlotCallbackWithHeap can_skip) { | 
| 581 int last = 0; | 576 if (object_groups_.length() == 0) | 
| 577 return false; | |
| 578 | |
| 579 object_groups_.Sort(); | |
| 
Michael Starzinger
2013/04/10 10:54:16
Isn't there a sort call to the retained_object_inf
 
marja
2013/04/10 13:14:51
Yes! Thanks for pointing that out.
 | |
| 580 | |
| 581 // During the iteration, some of the elements of object_groups are | |
| 582 // deleted. This is done by moving surviving elements at the front of the list | |
| 583 // and deleting from the end. This index tracks where the next surviving | |
| 584 // element should be moved. | |
| 585 int surviving_element_ix = 0; | |
| 
Michael Starzinger
2013/04/10 10:54:16
nit: Can we spell out the "index" in these variabl
 
marja
2013/04/10 13:14:51
Done.
 | |
| 586 int info_ix = 0; // For iterating retained_object_infos_. | |
| 587 int surviving_info_ix = 0; | |
| 588 | |
| 589 UniqueId current_group_id; | |
| 590 size_t current_group_start = 0; | |
| 582 bool any_group_was_visited = false; | 591 bool any_group_was_visited = false; | 
| 583 for (int i = 0; i < object_groups_.length(); i++) { | |
| 584 ObjectGroup* entry = object_groups_.at(i); | |
| 585 ASSERT(entry != NULL); | |
| 586 | 592 | 
| 587 Object*** objects = entry->objects_; | 593 for (int i = 0; i <= object_groups_.length(); ++i) { | 
| 588 bool group_should_be_visited = false; | 594 if (i == 0) | 
| 589 for (size_t j = 0; j < entry->length_; j++) { | 595 current_group_id = object_groups_[i].id; | 
| 590 Object* object = *objects[j]; | 596 if (i == object_groups_.length() || | 
| 591 if (object->IsHeapObject()) { | 597 current_group_id != object_groups_[i].id) { | 
| 592 if (!can_skip(isolate_->heap(), &object)) { | 598 // Group detected: objects in indices [current_group_start, i[. | 
| 593 group_should_be_visited = true; | 599 bool group_should_be_visited = false; | 
| 594 break; | 600 for (int j = current_group_start; j < i; ++j) { | 
| 601 Object* object = *(object_groups_[j].object); | |
| 602 if (object->IsHeapObject()) { | |
| 603 if (!can_skip(isolate_->heap(), &object)) { | |
| 604 group_should_be_visited = true; | |
| 605 break; | |
| 606 } | |
| 595 } | 607 } | 
| 596 } | 608 } | 
| 597 } | 609 if (!group_should_be_visited) { | 
| 
Michael Starzinger
2013/04/10 10:54:16
nit: Can we add an empty newline in front of this
 
marja
2013/04/10 13:14:51
Done.
 | |
| 598 | 610 for (int j = current_group_start; j < i; ++j) | 
| 599 if (!group_should_be_visited) { | 611 object_groups_[surviving_element_ix++] = object_groups_[j]; | 
| 600 object_groups_[last++] = entry; | 612 } else { | 
| 601 continue; | 613 // An object in the group requires visiting, so iterate over all | 
| 602 } | 614 // objects in the group. | 
| 603 | 615 for (int j = current_group_start; j < i; ++j) { | 
| 604 // An object in the group requires visiting, so iterate over all | 616 Object* object = *(object_groups_[j].object); | 
| 605 // objects in the group. | 617 if (object->IsHeapObject()) { | 
| 606 for (size_t j = 0; j < entry->length_; ++j) { | 618 v->VisitPointer(&object); | 
| 607 Object* object = *objects[j]; | 619 any_group_was_visited = true; | 
| 608 if (object->IsHeapObject()) { | 620 } | 
| 609 v->VisitPointer(&object); | 621 } | 
| 610 any_group_was_visited = true; | 622 } | 
| 623 if (info_ix < retained_object_infos_.length() && | |
| 
Michael Starzinger
2013/04/10 10:54:16
Likewise for this if.
 
marja
2013/04/10 13:14:51
Done.
 | |
| 624 retained_object_infos_[info_ix].id == | |
| 625 object_groups_[current_group_start].id) { | |
| 626 // This object group has an associated GroupRetainedObjectInfo. | |
| 627 if (!group_should_be_visited) { | |
| 628 retained_object_infos_[surviving_info_ix++] = | |
| 629 retained_object_infos_[info_ix]; | |
| 630 } else if (retained_object_infos_[info_ix].info != NULL) { | |
| 631 retained_object_infos_[info_ix].info->Dispose(); | |
| 632 retained_object_infos_[info_ix].info = NULL; | |
| 633 } | |
| 634 ++info_ix; | |
| 635 } | |
| 636 if (i < object_groups_.length()) { | |
| 637 current_group_id = object_groups_[i].id; | |
| 638 current_group_start = i; | |
| 611 } | 639 } | 
| 612 } | 640 } | 
| 613 | |
| 614 // Once the entire group has been iterated over, set the object | |
| 615 // group to NULL so it won't be processed again. | |
| 616 entry->Dispose(); | |
| 617 object_groups_.at(i) = NULL; | |
| 618 } | 641 } | 
| 619 object_groups_.Rewind(last); | 642 object_groups_.Rewind(surviving_element_ix); | 
| 643 retained_object_infos_.Rewind(surviving_info_ix); | |
| 620 return any_group_was_visited; | 644 return any_group_was_visited; | 
| 621 } | 645 } | 
| 622 | 646 | 
| 623 | 647 | 
| 624 bool GlobalHandles::PostGarbageCollectionProcessing( | 648 bool GlobalHandles::PostGarbageCollectionProcessing( | 
| 625 GarbageCollector collector, GCTracer* tracer) { | 649 GarbageCollector collector, GCTracer* tracer) { | 
| 626 // Process weak global handle callbacks. This must be done after the | 650 // Process weak global handle callbacks. This must be done after the | 
| 627 // GC is completely done, because the callbacks may invoke arbitrary | 651 // GC is completely done, because the callbacks may invoke arbitrary | 
| 628 // API functions. | 652 // API functions. | 
| 629 ASSERT(isolate_->heap()->gc_state() == Heap::NOT_IN_GC); | 653 ASSERT(isolate_->heap()->gc_state() == Heap::NOT_IN_GC); | 
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 817 v8::RetainedObjectInfo* info) { | 841 v8::RetainedObjectInfo* info) { | 
| 818 #ifdef DEBUG | 842 #ifdef DEBUG | 
| 819 for (size_t i = 0; i < length; ++i) { | 843 for (size_t i = 0; i < length; ++i) { | 
| 820 ASSERT(!Node::FromLocation(handles[i])->is_independent()); | 844 ASSERT(!Node::FromLocation(handles[i])->is_independent()); | 
| 821 } | 845 } | 
| 822 #endif | 846 #endif | 
| 823 if (length == 0) { | 847 if (length == 0) { | 
| 824 if (info != NULL) info->Dispose(); | 848 if (info != NULL) info->Dispose(); | 
| 825 return; | 849 return; | 
| 826 } | 850 } | 
| 827 object_groups_.Add(ObjectGroup::New(handles, length, info)); | 851 for (size_t i = 0; i < length; ++i) { | 
| 852 object_groups_.Add( | |
| 853 ObjectGroupConnection(UniqueId((intptr_t)handles[0]), handles[i])); | |
| 
Michael Starzinger
2013/04/10 10:54:16
nit: Use "static_cast<intptr_t>" instead of the C-
 
marja
2013/04/10 13:14:51
Done.
 | |
| 854 } | |
| 855 retained_object_infos_.Add( | |
| 856 GroupRetainedObjectInfo(UniqueId((intptr_t)handles[0]), info)); | |
| 
Michael Starzinger
2013/04/10 10:54:16
Likewise.
 
marja
2013/04/10 13:14:51
Done.
 | |
| 828 } | 857 } | 
| 829 | 858 | 
| 830 | 859 | 
| 860 void GlobalHandles::SetObjectGroupId(Object** handle, | |
| 861 UniqueId id) { | |
| 862 object_groups_.Add(ObjectGroupConnection(id, handle)); | |
| 863 } | |
| 864 | |
| 865 | |
| 866 void GlobalHandles::SetRetainedObjectInfo(UniqueId id, | |
| 867 RetainedObjectInfo* info) { | |
| 868 retained_object_infos_.Add(GroupRetainedObjectInfo(id, info)); | |
| 869 } | |
| 870 | |
| 871 | |
| 831 void GlobalHandles::AddImplicitReferences(HeapObject** parent, | 872 void GlobalHandles::AddImplicitReferences(HeapObject** parent, | 
| 832 Object*** children, | 873 Object*** children, | 
| 833 size_t length) { | 874 size_t length) { | 
| 834 #ifdef DEBUG | 875 #ifdef DEBUG | 
| 835 ASSERT(!Node::FromLocation(BitCast<Object**>(parent))->is_independent()); | 876 ASSERT(!Node::FromLocation(BitCast<Object**>(parent))->is_independent()); | 
| 836 for (size_t i = 0; i < length; ++i) { | 877 for (size_t i = 0; i < length; ++i) { | 
| 837 ASSERT(!Node::FromLocation(children[i])->is_independent()); | 878 ASSERT(!Node::FromLocation(children[i])->is_independent()); | 
| 838 } | 879 } | 
| 839 #endif | 880 #endif | 
| 840 if (length == 0) return; | 881 if (length == 0) return; | 
| 841 implicit_ref_groups_.Add(ImplicitRefGroup::New(parent, children, length)); | 882 implicit_ref_groups_.Add(ImplicitRefGroup::New(parent, children, length)); | 
| 842 } | 883 } | 
| 843 | 884 | 
| 844 | 885 | 
| 845 void GlobalHandles::RemoveObjectGroups() { | 886 void GlobalHandles::RemoveObjectGroups() { | 
| 846 for (int i = 0; i < object_groups_.length(); i++) { | 887 object_groups_.Clear(); | 
| 847 object_groups_.at(i)->Dispose(); | 888 for (int i = 0; i < retained_object_infos_.length(); ++i) { | 
| 889 if (retained_object_infos_[i].info != NULL) | |
| 890 retained_object_infos_[i].info->Dispose(); | |
| 848 } | 891 } | 
| 849 object_groups_.Clear(); | 892 retained_object_infos_.Clear(); | 
| 850 } | 893 } | 
| 851 | 894 | 
| 852 | 895 | 
| 853 void GlobalHandles::RemoveImplicitRefGroups() { | 896 void GlobalHandles::RemoveImplicitRefGroups() { | 
| 854 for (int i = 0; i < implicit_ref_groups_.length(); i++) { | 897 for (int i = 0; i < implicit_ref_groups_.length(); i++) { | 
| 855 implicit_ref_groups_.at(i)->Dispose(); | 898 implicit_ref_groups_.at(i)->Dispose(); | 
| 856 } | 899 } | 
| 857 implicit_ref_groups_.Clear(); | 900 implicit_ref_groups_.Clear(); | 
| 858 } | 901 } | 
| 859 | 902 | 
| 860 | 903 | 
| 861 void GlobalHandles::TearDown() { | 904 void GlobalHandles::TearDown() { | 
| 862 // TODO(1428): invoke weak callbacks. | 905 // TODO(1428): invoke weak callbacks. | 
| 863 } | 906 } | 
| 864 | 907 | 
| 865 | 908 | 
| 866 } } // namespace v8::internal | 909 } } // namespace v8::internal | 
| OLD | NEW |