 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 19 matching lines...) Expand all Loading... | |
| 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() { | 39 ObjectGroup::~ObjectGroup() { | 
| 40 if (info_ != NULL) info_->Dispose(); | 40 if (info != NULL) info->Dispose(); | 
| 41 } | 41 } | 
| 42 | 42 | 
| 43 | 43 | 
| 44 GroupRetainedObjectInfo::~GroupRetainedObjectInfo() { | |
| 45 } | |
| 46 | |
| 47 | |
| 44 class GlobalHandles::Node { | 48 class GlobalHandles::Node { | 
| 45 public: | 49 public: | 
| 46 // State transition diagram: | 50 // State transition diagram: | 
| 47 // FREE -> NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, FREE } | 51 // FREE -> NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, FREE } | 
| 48 enum State { | 52 enum State { | 
| 49 FREE = 0, | 53 FREE = 0, | 
| 50 NORMAL, // Normal global handle. | 54 NORMAL, // Normal global handle. | 
| 51 WEAK, // Flagged as weak but not yet finalized. | 55 WEAK, // Flagged as weak but not yet finalized. | 
| 52 PENDING, // Has been recognized as only reachable by weak handles. | 56 PENDING, // Has been recognized as only reachable by weak handles. | 
| 53 NEAR_DEATH // Callback has informed the handle is near death. | 57 NEAR_DEATH // Callback has informed the handle is near death. | 
| (...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 431 DISALLOW_COPY_AND_ASSIGN(NodeIterator); | 435 DISALLOW_COPY_AND_ASSIGN(NodeIterator); | 
| 432 }; | 436 }; | 
| 433 | 437 | 
| 434 | 438 | 
| 435 GlobalHandles::GlobalHandles(Isolate* isolate) | 439 GlobalHandles::GlobalHandles(Isolate* isolate) | 
| 436 : isolate_(isolate), | 440 : isolate_(isolate), | 
| 437 number_of_global_handles_(0), | 441 number_of_global_handles_(0), | 
| 438 first_block_(NULL), | 442 first_block_(NULL), | 
| 439 first_used_block_(NULL), | 443 first_used_block_(NULL), | 
| 440 first_free_(NULL), | 444 first_free_(NULL), | 
| 441 post_gc_processing_count_(0) {} | 445 post_gc_processing_count_(0), | 
| 446 object_groups_(new List<ObjectGroupConnection>()) {} | |
| 442 | 447 | 
| 443 | 448 | 
| 444 GlobalHandles::~GlobalHandles() { | 449 GlobalHandles::~GlobalHandles() { | 
| 445 NodeBlock* block = first_block_; | 450 NodeBlock* block = first_block_; | 
| 446 while (block != NULL) { | 451 while (block != NULL) { | 
| 447 NodeBlock* tmp = block->next(); | 452 NodeBlock* tmp = block->next(); | 
| 448 delete block; | 453 delete block; | 
| 449 block = tmp; | 454 block = tmp; | 
| 450 } | 455 } | 
| 451 first_block_ = NULL; | 456 first_block_ = NULL; | 
| 457 delete object_groups_; | |
| 452 } | 458 } | 
| 453 | 459 | 
| 454 | 460 | 
| 455 Handle<Object> GlobalHandles::Create(Object* value) { | 461 Handle<Object> GlobalHandles::Create(Object* value) { | 
| 456 isolate_->counters()->global_handles()->Increment(); | 462 isolate_->counters()->global_handles()->Increment(); | 
| 457 number_of_global_handles_++; | 463 number_of_global_handles_++; | 
| 458 if (first_free_ == NULL) { | 464 if (first_free_ == NULL) { | 
| 459 first_block_ = new NodeBlock(first_block_); | 465 first_block_ = new NodeBlock(first_block_); | 
| 460 first_block_->PutNodesOnFreeList(&first_free_); | 466 first_block_->PutNodesOnFreeList(&first_free_); | 
| 461 } | 467 } | 
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 568 for (int i = 0; i < new_space_nodes_.length(); ++i) { | 574 for (int i = 0; i < new_space_nodes_.length(); ++i) { | 
| 569 Node* node = new_space_nodes_[i]; | 575 Node* node = new_space_nodes_[i]; | 
| 570 ASSERT(node->is_in_new_space_list()); | 576 ASSERT(node->is_in_new_space_list()); | 
| 571 if ((node->is_independent() || node->is_partially_dependent()) && | 577 if ((node->is_independent() || node->is_partially_dependent()) && | 
| 572 node->IsWeakRetainer()) { | 578 node->IsWeakRetainer()) { | 
| 573 v->VisitPointer(node->location()); | 579 v->VisitPointer(node->location()); | 
| 574 } | 580 } | 
| 575 } | 581 } | 
| 576 } | 582 } | 
| 577 | 583 | 
| 578 | |
| 579 bool GlobalHandles::IterateObjectGroups(ObjectVisitor* v, | 584 bool GlobalHandles::IterateObjectGroups(ObjectVisitor* v, | 
| 580 WeakSlotCallbackWithHeap can_skip) { | 585 WeakSlotCallbackWithHeap can_skip) { | 
| 581 int last = 0; | 586 if (object_groups_->length() == 0) | 
| 587 return false; | |
| 588 | |
| 589 object_groups_->Sort(); | |
| 590 // Stores information about unvisited object groups for later use. | |
| 591 List<ObjectGroupConnection>* new_object_groups = | |
| 592 new List<ObjectGroupConnection>(); | |
| 593 | |
| 594 void* current_group_id = NULL; | |
| 595 size_t current_group_start = 0; | |
| 582 bool any_group_was_visited = false; | 596 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 | 597 | 
| 587 Object*** objects = entry->objects_; | 598 for (int i = 0; i <= object_groups_->length(); ++i) { | 
| 588 bool group_should_be_visited = false; | 599 if (i == 0) | 
| 589 for (size_t j = 0; j < entry->length_; j++) { | 600 current_group_id = object_groups_->at(i).id; | 
| 590 Object* object = *objects[j]; | 601 if (i == object_groups_->length() || | 
| 591 if (object->IsHeapObject()) { | 602 current_group_id != object_groups_->at(i).id) { | 
| 592 if (!can_skip(isolate_->heap(), &object)) { | 603 // Group detected: objects in indices [current_group_start, i[. | 
| 593 group_should_be_visited = true; | 604 bool group_should_be_visited = false; | 
| 594 break; | 605 for (int j = current_group_start; j < i; ++j) { | 
| 606 Object* object = *(object_groups_->at(j).object); | |
| 607 if (object->IsHeapObject()) { | |
| 608 if (!can_skip(isolate_->heap(), &object)) { | |
| 609 group_should_be_visited = true; | |
| 610 break; | |
| 611 } | |
| 595 } | 612 } | 
| 596 } | 613 } | 
| 597 } | 614 if (!group_should_be_visited) { | 
| 598 | 615 for (int j = current_group_start; j < i; ++j) | 
| 599 if (!group_should_be_visited) { | 616 new_object_groups->Add(object_groups_->at(j)); | 
| 
Michael Starzinger
2013/04/09 14:18:40
It would be good if we could get by with an in-pla
 
marja
2013/04/09 16:46:51
Done.
 | |
| 600 object_groups_[last++] = entry; | 617 } else { | 
| 601 continue; | 618 // An object in the group requires visiting, so iterate over all | 
| 602 } | 619 // objects in the group. | 
| 603 | 620 for (int j = current_group_start; j < i; ++j) { | 
| 604 // An object in the group requires visiting, so iterate over all | 621 Object* object = *(object_groups_->at(j).object); | 
| 605 // objects in the group. | 622 if (object->IsHeapObject()) { | 
| 606 for (size_t j = 0; j < entry->length_; ++j) { | 623 v->VisitPointer(&object); | 
| 607 Object* object = *objects[j]; | 624 any_group_was_visited = true; | 
| 608 if (object->IsHeapObject()) { | 625 } | 
| 609 v->VisitPointer(&object); | 626 } | 
| 610 any_group_was_visited = true; | 627 } | 
| 628 if (i < object_groups_->length()) { | |
| 629 current_group_id = object_groups_->at(i).id; | |
| 630 current_group_start = i; | |
| 611 } | 631 } | 
| 612 } | 632 } | 
| 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 } | 633 } | 
| 619 object_groups_.Rewind(last); | 634 delete object_groups_; | 
| 635 object_groups_ = new_object_groups; | |
| 620 return any_group_was_visited; | 636 return any_group_was_visited; | 
| 621 } | 637 } | 
| 622 | 638 | 
| 623 | 639 | 
| 624 bool GlobalHandles::PostGarbageCollectionProcessing( | 640 bool GlobalHandles::PostGarbageCollectionProcessing( | 
| 625 GarbageCollector collector, GCTracer* tracer) { | 641 GarbageCollector collector, GCTracer* tracer) { | 
| 626 // Process weak global handle callbacks. This must be done after the | 642 // Process weak global handle callbacks. This must be done after the | 
| 627 // GC is completely done, because the callbacks may invoke arbitrary | 643 // GC is completely done, because the callbacks may invoke arbitrary | 
| 628 // API functions. | 644 // API functions. | 
| 629 ASSERT(isolate_->heap()->gc_state() == Heap::NOT_IN_GC); | 645 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) { | 833 v8::RetainedObjectInfo* info) { | 
| 818 #ifdef DEBUG | 834 #ifdef DEBUG | 
| 819 for (size_t i = 0; i < length; ++i) { | 835 for (size_t i = 0; i < length; ++i) { | 
| 820 ASSERT(!Node::FromLocation(handles[i])->is_independent()); | 836 ASSERT(!Node::FromLocation(handles[i])->is_independent()); | 
| 821 } | 837 } | 
| 822 #endif | 838 #endif | 
| 823 if (length == 0) { | 839 if (length == 0) { | 
| 824 if (info != NULL) info->Dispose(); | 840 if (info != NULL) info->Dispose(); | 
| 825 return; | 841 return; | 
| 826 } | 842 } | 
| 827 object_groups_.Add(ObjectGroup::New(handles, length, info)); | 843 for (size_t i = 0; i < length; ++i) | 
| 844 object_groups_->Add(ObjectGroupConnection(handles[0], handles[i])); | |
| 845 retained_object_infos_.Add(GroupRetainedObjectInfo(handles[0], info)); | |
| 828 } | 846 } | 
| 829 | 847 | 
| 830 | 848 | 
| 849 void GlobalHandles::SetObjectGroupId(Object** handle, | |
| 850 void* id) { | |
| 851 object_groups_->Add(ObjectGroupConnection(id, handle)); | |
| 852 } | |
| 853 | |
| 854 | |
| 855 void GlobalHandles::SetRetainedObjectInfo(void* id, | |
| 856 RetainedObjectInfo* info) { | |
| 857 retained_object_infos_.Add(GroupRetainedObjectInfo(id, info)); | |
| 858 } | |
| 859 | |
| 860 | |
| 831 void GlobalHandles::AddImplicitReferences(HeapObject** parent, | 861 void GlobalHandles::AddImplicitReferences(HeapObject** parent, | 
| 832 Object*** children, | 862 Object*** children, | 
| 833 size_t length) { | 863 size_t length) { | 
| 834 #ifdef DEBUG | 864 #ifdef DEBUG | 
| 835 ASSERT(!Node::FromLocation(BitCast<Object**>(parent))->is_independent()); | 865 ASSERT(!Node::FromLocation(BitCast<Object**>(parent))->is_independent()); | 
| 836 for (size_t i = 0; i < length; ++i) { | 866 for (size_t i = 0; i < length; ++i) { | 
| 837 ASSERT(!Node::FromLocation(children[i])->is_independent()); | 867 ASSERT(!Node::FromLocation(children[i])->is_independent()); | 
| 838 } | 868 } | 
| 839 #endif | 869 #endif | 
| 840 if (length == 0) return; | 870 if (length == 0) return; | 
| 841 implicit_ref_groups_.Add(ImplicitRefGroup::New(parent, children, length)); | 871 implicit_ref_groups_.Add(ImplicitRefGroup::New(parent, children, length)); | 
| 842 } | 872 } | 
| 843 | 873 | 
| 874 List<ObjectGroup*>* GlobalHandles::object_groups() { | |
| 
Michael Starzinger
2013/04/09 14:18:40
This transferal of ownership of the structure look
 
marja
2013/04/09 16:46:51
I couldn't wrap my head around how to transfer the
 | |
| 875 List<ObjectGroup*>* to_return = new List<ObjectGroup*>(); | |
| 876 | |
| 877 object_groups_->Sort(); | |
| 878 retained_object_infos_.Sort(); | |
| 879 int retained_object_infos_ix = 0; | |
| 880 | |
| 881 void* current_group_id = NULL; | |
| 882 size_t current_group_start = 0; | |
| 883 | |
| 884 for (int i = 0; i <= object_groups_->length(); ++i) { | |
| 885 if (i == 0) | |
| 886 current_group_id = object_groups_->at(i).id; | |
| 887 if (i == object_groups_->length() || | |
| 888 current_group_id != object_groups_->at(i).id) { | |
| 889 // Group detected: objects in indices [current_group_start, i[. | |
| 890 ObjectGroup* group = new ObjectGroup(); | |
| 891 if (retained_object_infos_ix < retained_object_infos_.length() && | |
| 892 retained_object_infos_[retained_object_infos_ix].id == | |
| 893 object_groups_->at(current_group_start).id) { | |
| 894 // Transfer the ownership of info. | |
| 895 group->info = retained_object_infos_[retained_object_infos_ix].info; | |
| 896 retained_object_infos_[retained_object_infos_ix].info = NULL; | |
| 897 ++retained_object_infos_ix; | |
| 898 } | |
| 899 for (int j = current_group_start; j < i; ++j) | |
| 900 group->objects.Add(object_groups_->at(j).object); | |
| 901 to_return->Add(group); | |
| 902 } | |
| 903 if (i < object_groups_->length()) { | |
| 904 current_group_id = object_groups_->at(i).id; | |
| 905 current_group_start = i; | |
| 906 } | |
| 907 } | |
| 908 return to_return; | |
| 909 } | |
| 844 | 910 | 
| 845 void GlobalHandles::RemoveObjectGroups() { | 911 void GlobalHandles::RemoveObjectGroups() { | 
| 846 for (int i = 0; i < object_groups_.length(); i++) { | 912 object_groups_->Clear(); | 
| 847 object_groups_.at(i)->Dispose(); | 913 for (int i = 0; i < retained_object_infos_.length(); ++i) { | 
| 914 if (retained_object_infos_[i].info != NULL) | |
| 915 retained_object_infos_[i].info->Dispose(); | |
| 848 } | 916 } | 
| 849 object_groups_.Clear(); | 917 retained_object_infos_.Clear(); | 
| 850 } | 918 } | 
| 851 | 919 | 
| 852 | 920 | 
| 853 void GlobalHandles::RemoveImplicitRefGroups() { | 921 void GlobalHandles::RemoveImplicitRefGroups() { | 
| 854 for (int i = 0; i < implicit_ref_groups_.length(); i++) { | 922 for (int i = 0; i < implicit_ref_groups_.length(); i++) { | 
| 855 implicit_ref_groups_.at(i)->Dispose(); | 923 implicit_ref_groups_.at(i)->Dispose(); | 
| 856 } | 924 } | 
| 857 implicit_ref_groups_.Clear(); | 925 implicit_ref_groups_.Clear(); | 
| 858 } | 926 } | 
| 859 | 927 | 
| 860 | 928 | 
| 861 void GlobalHandles::TearDown() { | 929 void GlobalHandles::TearDown() { | 
| 862 // TODO(1428): invoke weak callbacks. | 930 // TODO(1428): invoke weak callbacks. | 
| 863 } | 931 } | 
| 864 | 932 | 
| 865 | 933 | 
| 866 } } // namespace v8::internal | 934 } } // namespace v8::internal | 
| OLD | NEW |