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