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 delete[] objects; | |
| 41 } | 42 } |
| 42 | 43 |
| 43 | 44 |
| 45 ImplicitRefGroup::~ImplicitRefGroup() { | |
| 46 delete[] children; | |
| 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 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 425 } | 431 } |
| 426 | 432 |
| 427 private: | 433 private: |
| 428 NodeBlock* block_; | 434 NodeBlock* block_; |
| 429 int index_; | 435 int index_; |
| 430 | 436 |
| 431 DISALLOW_COPY_AND_ASSIGN(NodeIterator); | 437 DISALLOW_COPY_AND_ASSIGN(NodeIterator); |
| 432 }; | 438 }; |
| 433 | 439 |
| 434 | 440 |
| 441 | |
| 442 const int GlobalHandles::kObjectGroupConnectionsCapacity = 20; | |
|
Michael Starzinger
2013/04/24 13:58:56
Can we move the value into the header? I don't thi
marja
2013/04/24 14:05:43
Done.
| |
| 443 | |
| 444 | |
| 435 GlobalHandles::GlobalHandles(Isolate* isolate) | 445 GlobalHandles::GlobalHandles(Isolate* isolate) |
| 436 : isolate_(isolate), | 446 : isolate_(isolate), |
| 437 number_of_global_handles_(0), | 447 number_of_global_handles_(0), |
| 438 first_block_(NULL), | 448 first_block_(NULL), |
| 439 first_used_block_(NULL), | 449 first_used_block_(NULL), |
| 440 first_free_(NULL), | 450 first_free_(NULL), |
| 441 post_gc_processing_count_(0) {} | 451 post_gc_processing_count_(0), |
| 452 object_group_connections_(kObjectGroupConnectionsCapacity) {} | |
|
Michael Starzinger
2013/04/24 13:58:56
The retainer_infos_ and the implicit_ref_connectio
marja
2013/04/24 14:05:43
Discussed offline -> no.
| |
| 442 | 453 |
| 443 | 454 |
| 444 GlobalHandles::~GlobalHandles() { | 455 GlobalHandles::~GlobalHandles() { |
| 445 NodeBlock* block = first_block_; | 456 NodeBlock* block = first_block_; |
| 446 while (block != NULL) { | 457 while (block != NULL) { |
| 447 NodeBlock* tmp = block->next(); | 458 NodeBlock* tmp = block->next(); |
| 448 delete block; | 459 delete block; |
| 449 block = tmp; | 460 block = tmp; |
| 450 } | 461 } |
| 451 first_block_ = NULL; | 462 first_block_ = NULL; |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 571 if ((node->is_independent() || node->is_partially_dependent()) && | 582 if ((node->is_independent() || node->is_partially_dependent()) && |
| 572 node->IsWeakRetainer()) { | 583 node->IsWeakRetainer()) { |
| 573 v->VisitPointer(node->location()); | 584 v->VisitPointer(node->location()); |
| 574 } | 585 } |
| 575 } | 586 } |
| 576 } | 587 } |
| 577 | 588 |
| 578 | 589 |
| 579 bool GlobalHandles::IterateObjectGroups(ObjectVisitor* v, | 590 bool GlobalHandles::IterateObjectGroups(ObjectVisitor* v, |
| 580 WeakSlotCallbackWithHeap can_skip) { | 591 WeakSlotCallbackWithHeap can_skip) { |
| 592 ComputeObjectGroupsAndImplicitReferences(); | |
| 581 int last = 0; | 593 int last = 0; |
| 582 bool any_group_was_visited = false; | 594 bool any_group_was_visited = false; |
| 583 for (int i = 0; i < object_groups_.length(); i++) { | 595 for (int i = 0; i < object_groups_.length(); i++) { |
| 584 ObjectGroup* entry = object_groups_.at(i); | 596 ObjectGroup* entry = object_groups_.at(i); |
| 585 ASSERT(entry != NULL); | 597 ASSERT(entry != NULL); |
| 586 | 598 |
| 587 Object*** objects = entry->objects_; | 599 Object*** objects = entry->objects; |
| 588 bool group_should_be_visited = false; | 600 bool group_should_be_visited = false; |
| 589 for (size_t j = 0; j < entry->length_; j++) { | 601 for (size_t j = 0; j < entry->length; j++) { |
| 590 Object* object = *objects[j]; | 602 Object* object = *objects[j]; |
| 591 if (object->IsHeapObject()) { | 603 if (object->IsHeapObject()) { |
| 592 if (!can_skip(isolate_->heap(), &object)) { | 604 if (!can_skip(isolate_->heap(), &object)) { |
| 593 group_should_be_visited = true; | 605 group_should_be_visited = true; |
| 594 break; | 606 break; |
| 595 } | 607 } |
| 596 } | 608 } |
| 597 } | 609 } |
| 598 | 610 |
| 599 if (!group_should_be_visited) { | 611 if (!group_should_be_visited) { |
| 600 object_groups_[last++] = entry; | 612 object_groups_[last++] = entry; |
| 601 continue; | 613 continue; |
| 602 } | 614 } |
| 603 | 615 |
| 604 // An object in the group requires visiting, so iterate over all | 616 // An object in the group requires visiting, so iterate over all |
| 605 // objects in the group. | 617 // objects in the group. |
| 606 for (size_t j = 0; j < entry->length_; ++j) { | 618 for (size_t j = 0; j < entry->length; ++j) { |
| 607 Object* object = *objects[j]; | 619 Object* object = *objects[j]; |
| 608 if (object->IsHeapObject()) { | 620 if (object->IsHeapObject()) { |
| 609 v->VisitPointer(&object); | 621 v->VisitPointer(&object); |
| 610 any_group_was_visited = true; | 622 any_group_was_visited = true; |
| 611 } | 623 } |
| 612 } | 624 } |
| 613 | 625 |
| 614 // Once the entire group has been iterated over, set the object | 626 // Once the entire group has been iterated over, set the object |
| 615 // group to NULL so it won't be processed again. | 627 // group to NULL so it won't be processed again. |
| 616 entry->Dispose(); | 628 delete entry; |
| 617 object_groups_.at(i) = NULL; | 629 object_groups_.at(i) = NULL; |
| 618 } | 630 } |
| 619 object_groups_.Rewind(last); | 631 object_groups_.Rewind(last); |
| 620 return any_group_was_visited; | 632 return any_group_was_visited; |
| 621 } | 633 } |
| 622 | 634 |
| 623 | 635 |
| 624 bool GlobalHandles::PostGarbageCollectionProcessing( | 636 bool GlobalHandles::PostGarbageCollectionProcessing( |
| 625 GarbageCollector collector, GCTracer* tracer) { | 637 GarbageCollector collector, GCTracer* tracer) { |
| 626 // Process weak global handle callbacks. This must be done after the | 638 // Process weak global handle callbacks. This must be done after the |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 817 v8::RetainedObjectInfo* info) { | 829 v8::RetainedObjectInfo* info) { |
| 818 #ifdef DEBUG | 830 #ifdef DEBUG |
| 819 for (size_t i = 0; i < length; ++i) { | 831 for (size_t i = 0; i < length; ++i) { |
| 820 ASSERT(!Node::FromLocation(handles[i])->is_independent()); | 832 ASSERT(!Node::FromLocation(handles[i])->is_independent()); |
| 821 } | 833 } |
| 822 #endif | 834 #endif |
| 823 if (length == 0) { | 835 if (length == 0) { |
| 824 if (info != NULL) info->Dispose(); | 836 if (info != NULL) info->Dispose(); |
| 825 return; | 837 return; |
| 826 } | 838 } |
| 827 object_groups_.Add(ObjectGroup::New(handles, length, info)); | 839 ObjectGroup* group = new ObjectGroup(length); |
| 840 for (size_t i = 0; i < length; ++i) | |
| 841 group->objects[i] = handles[i]; | |
| 842 group->info = info; | |
| 843 object_groups_.Add(group); | |
| 828 } | 844 } |
| 829 | 845 |
| 830 | 846 |
| 847 void GlobalHandles::SetObjectGroupId(Object** handle, | |
| 848 UniqueId id) { | |
| 849 object_group_connections_.Add(ObjectGroupConnection(id, handle)); | |
| 850 } | |
| 851 | |
| 852 | |
| 853 void GlobalHandles::SetRetainedObjectInfo(UniqueId id, | |
| 854 RetainedObjectInfo* info) { | |
| 855 retainer_infos_.Add(ObjectGroupRetainerInfo(id, info)); | |
| 856 } | |
| 857 | |
| 858 | |
| 831 void GlobalHandles::AddImplicitReferences(HeapObject** parent, | 859 void GlobalHandles::AddImplicitReferences(HeapObject** parent, |
| 832 Object*** children, | 860 Object*** children, |
| 833 size_t length) { | 861 size_t length) { |
| 834 #ifdef DEBUG | 862 #ifdef DEBUG |
| 835 ASSERT(!Node::FromLocation(BitCast<Object**>(parent))->is_independent()); | 863 ASSERT(!Node::FromLocation(BitCast<Object**>(parent))->is_independent()); |
| 836 for (size_t i = 0; i < length; ++i) { | 864 for (size_t i = 0; i < length; ++i) { |
| 837 ASSERT(!Node::FromLocation(children[i])->is_independent()); | 865 ASSERT(!Node::FromLocation(children[i])->is_independent()); |
| 838 } | 866 } |
| 839 #endif | 867 #endif |
| 840 if (length == 0) return; | 868 if (length == 0) return; |
| 841 implicit_ref_groups_.Add(ImplicitRefGroup::New(parent, children, length)); | 869 ImplicitRefGroup* group = new ImplicitRefGroup(parent, length); |
| 870 for (size_t i = 0; i < length; ++i) | |
| 871 group->children[i] = children[i]; | |
| 872 implicit_ref_groups_.Add(group); | |
| 873 } | |
| 874 | |
| 875 | |
| 876 void GlobalHandles::SetReferenceFromGroup(UniqueId id, Object** child) { | |
| 877 ASSERT(!Node::FromLocation(child)->is_independent()); | |
| 878 implicit_ref_connections_.Add(ObjectGroupConnection(id, child)); | |
| 879 } | |
| 880 | |
| 881 | |
| 882 void GlobalHandles::SetReference(HeapObject** parent, Object** child) { | |
| 883 ASSERT(!Node::FromLocation(child)->is_independent()); | |
| 884 ImplicitRefGroup* group = new ImplicitRefGroup(parent, 1); | |
| 885 group->children[0] = child; | |
| 886 implicit_ref_groups_.Add(group); | |
| 842 } | 887 } |
| 843 | 888 |
| 844 | 889 |
| 845 void GlobalHandles::RemoveObjectGroups() { | 890 void GlobalHandles::RemoveObjectGroups() { |
| 846 for (int i = 0; i < object_groups_.length(); i++) { | 891 for (int i = 0; i < object_groups_.length(); i++) |
| 847 object_groups_.at(i)->Dispose(); | 892 delete object_groups_.at(i); |
| 848 } | |
| 849 object_groups_.Clear(); | 893 object_groups_.Clear(); |
| 894 for (int i = 0; i < retainer_infos_.length(); ++i) | |
| 895 retainer_infos_[i].info->Dispose(); | |
| 896 retainer_infos_.Clear(); | |
| 897 object_group_connections_.Clear(); | |
| 898 object_group_connections_.Initialize(kObjectGroupConnectionsCapacity); | |
| 850 } | 899 } |
| 851 | 900 |
| 852 | 901 |
| 853 void GlobalHandles::RemoveImplicitRefGroups() { | 902 void GlobalHandles::RemoveImplicitRefGroups() { |
| 854 for (int i = 0; i < implicit_ref_groups_.length(); i++) { | 903 for (int i = 0; i < implicit_ref_groups_.length(); i++) { |
| 855 implicit_ref_groups_.at(i)->Dispose(); | 904 delete implicit_ref_groups_.at(i); |
| 856 } | 905 } |
| 857 implicit_ref_groups_.Clear(); | 906 implicit_ref_groups_.Clear(); |
| 907 implicit_ref_connections_.Clear(); | |
| 858 } | 908 } |
| 859 | 909 |
| 860 | 910 |
| 861 void GlobalHandles::TearDown() { | 911 void GlobalHandles::TearDown() { |
| 862 // TODO(1428): invoke weak callbacks. | 912 // TODO(1428): invoke weak callbacks. |
| 863 } | 913 } |
| 864 | 914 |
|
Michael Starzinger
2013/04/24 13:58:56
nit: Two empty new-lines between functions.
marja
2013/04/24 14:05:43
Done.
| |
| 915 void GlobalHandles::ComputeObjectGroupsAndImplicitReferences() { | |
| 916 if (object_group_connections_.length() == 0) { | |
| 917 for (int i = 0; i < retainer_infos_.length(); ++i) | |
| 918 retainer_infos_[i].info->Dispose(); | |
| 919 retainer_infos_.Clear(); | |
| 920 implicit_ref_connections_.Clear(); | |
| 921 return; | |
| 922 } | |
| 923 | |
| 924 object_group_connections_.Sort(); | |
| 925 retainer_infos_.Sort(); | |
| 926 implicit_ref_connections_.Sort(); | |
| 927 | |
| 928 int info_index = 0; // For iterating retainer_infos_. | |
| 929 UniqueId current_group_id(0); | |
| 930 int current_group_start = 0; | |
| 931 | |
| 932 int current_implicit_refs_start = 0; | |
| 933 int current_implicit_refs_end = 0; | |
| 934 for (int i = 0; i <= object_group_connections_.length(); ++i) { | |
| 935 if (i == 0) | |
| 936 current_group_id = object_group_connections_[i].id; | |
| 937 if (i == object_group_connections_.length() || | |
| 938 current_group_id != object_group_connections_[i].id) { | |
| 939 // Group detected: objects in indices [current_group_start, i[. | |
| 940 | |
| 941 // Find out which implicit references are related to this group. (We want | |
| 942 // to ignore object groups which only have 1 object, but that object is | |
| 943 // needed as a representative object for the implicit refrerence group.) | |
| 944 while (current_implicit_refs_start < implicit_ref_connections_.length() && | |
| 945 implicit_ref_connections_[current_implicit_refs_start].id < | |
| 946 current_group_id) | |
| 947 ++current_implicit_refs_start; | |
| 948 current_implicit_refs_end = current_implicit_refs_start; | |
| 949 while (current_implicit_refs_end < implicit_ref_connections_.length() && | |
| 950 implicit_ref_connections_[current_implicit_refs_end].id == | |
| 951 current_group_id) | |
| 952 ++current_implicit_refs_end; | |
| 953 | |
| 954 if (current_implicit_refs_end > current_implicit_refs_start) { | |
| 955 // Find a representative object for the implicit references. | |
| 956 HeapObject** representative = NULL; | |
| 957 for (int j = current_group_start; j < i; ++j) { | |
| 958 Object** object = object_group_connections_[j].object; | |
| 959 if ((*object)->IsHeapObject()) { | |
| 960 representative = reinterpret_cast<HeapObject**>(object); | |
| 961 break; | |
| 962 } | |
| 963 } | |
| 964 if (representative) { | |
| 965 ImplicitRefGroup* group = new ImplicitRefGroup( | |
| 966 representative, | |
| 967 current_implicit_refs_end - current_implicit_refs_start); | |
| 968 for (int j = current_implicit_refs_start; | |
| 969 j < current_implicit_refs_end; | |
| 970 ++j) { | |
| 971 group->children[j - current_implicit_refs_start] = | |
| 972 implicit_ref_connections_[j].object; | |
| 973 } | |
| 974 implicit_ref_groups_.Add(group); | |
| 975 } | |
| 976 current_implicit_refs_start = current_implicit_refs_end; | |
| 977 } | |
| 978 | |
| 979 // Find a RetainedObjectInfo for the group. | |
| 980 RetainedObjectInfo* info = NULL; | |
| 981 while (info_index < retainer_infos_.length() && | |
| 982 retainer_infos_[info_index].id < current_group_id) { | |
| 983 retainer_infos_[info_index].info->Dispose(); | |
| 984 ++info_index; | |
| 985 } | |
| 986 if (info_index < retainer_infos_.length() && | |
| 987 retainer_infos_[info_index].id == current_group_id) { | |
| 988 // This object group has an associated ObjectGroupRetainerInfo. | |
| 989 info = retainer_infos_[info_index].info; | |
| 990 ++info_index; | |
| 991 } | |
| 992 | |
| 993 // Ignore groups which only contain one object. | |
| 994 if (i > current_group_start + 1) { | |
| 995 ObjectGroup* group = new ObjectGroup(i - current_group_start); | |
| 996 for (int j = current_group_start; j < i; ++j) { | |
| 997 group->objects[j - current_group_start] = | |
| 998 object_group_connections_[j].object; | |
| 999 } | |
| 1000 group->info = info; | |
| 1001 object_groups_.Add(group); | |
| 1002 } else if (info) { | |
| 1003 info->Dispose(); | |
| 1004 } | |
| 1005 | |
| 1006 if (i < object_group_connections_.length()) { | |
| 1007 current_group_id = object_group_connections_[i].id; | |
| 1008 current_group_start = i; | |
| 1009 } | |
| 1010 } | |
| 1011 } | |
| 1012 object_group_connections_.Clear(); | |
| 1013 object_group_connections_.Initialize(kObjectGroupConnectionsCapacity); | |
| 1014 retainer_infos_.Clear(); | |
| 1015 implicit_ref_connections_.Clear(); | |
| 1016 } | |
| 1017 | |
| 865 | 1018 |
| 866 } } // namespace v8::internal | 1019 } } // namespace v8::internal |
| OLD | NEW |