Chromium Code Reviews| Index: src/global-handles.cc |
| diff --git a/src/global-handles.cc b/src/global-handles.cc |
| index cb3115abfca7db7ce9baec4a29c9da134437c223..1201f32aa851fa53bf06c8881c377866f2a9e545 100644 |
| --- a/src/global-handles.cc |
| +++ b/src/global-handles.cc |
| @@ -37,7 +37,11 @@ namespace internal { |
| ObjectGroup::~ObjectGroup() { |
| - if (info_ != NULL) info_->Dispose(); |
| + if (info != NULL) info->Dispose(); |
| +} |
| + |
| + |
| +GroupRetainedObjectInfo::~GroupRetainedObjectInfo() { |
| } |
| @@ -438,7 +442,8 @@ GlobalHandles::GlobalHandles(Isolate* isolate) |
| first_block_(NULL), |
| first_used_block_(NULL), |
| first_free_(NULL), |
| - post_gc_processing_count_(0) {} |
| + post_gc_processing_count_(0), |
| + object_groups_(new List<ObjectGroupConnection>()) {} |
| GlobalHandles::~GlobalHandles() { |
| @@ -449,6 +454,7 @@ GlobalHandles::~GlobalHandles() { |
| block = tmp; |
| } |
| first_block_ = NULL; |
| + delete object_groups_; |
| } |
| @@ -575,48 +581,58 @@ void GlobalHandles::IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v) { |
| } |
| } |
| - |
| bool GlobalHandles::IterateObjectGroups(ObjectVisitor* v, |
| WeakSlotCallbackWithHeap can_skip) { |
| - int last = 0; |
| + if (object_groups_->length() == 0) |
| + return false; |
| + |
| + object_groups_->Sort(); |
| + // Stores information about unvisited object groups for later use. |
| + List<ObjectGroupConnection>* new_object_groups = |
| + new List<ObjectGroupConnection>(); |
| + |
| + void* current_group_id = NULL; |
| + size_t current_group_start = 0; |
| bool any_group_was_visited = false; |
| - for (int i = 0; i < object_groups_.length(); i++) { |
| - ObjectGroup* entry = object_groups_.at(i); |
| - ASSERT(entry != NULL); |
| - |
| - Object*** objects = entry->objects_; |
| - bool group_should_be_visited = false; |
| - for (size_t j = 0; j < entry->length_; j++) { |
| - Object* object = *objects[j]; |
| - if (object->IsHeapObject()) { |
| - if (!can_skip(isolate_->heap(), &object)) { |
| - group_should_be_visited = true; |
| - break; |
| + |
| + for (int i = 0; i <= object_groups_->length(); ++i) { |
| + if (i == 0) |
| + current_group_id = object_groups_->at(i).id; |
| + if (i == object_groups_->length() || |
| + current_group_id != object_groups_->at(i).id) { |
| + // Group detected: objects in indices [current_group_start, i[. |
| + bool group_should_be_visited = false; |
| + for (int j = current_group_start; j < i; ++j) { |
| + Object* object = *(object_groups_->at(j).object); |
| + if (object->IsHeapObject()) { |
| + if (!can_skip(isolate_->heap(), &object)) { |
| + group_should_be_visited = true; |
| + break; |
| + } |
| } |
| } |
| - } |
| - |
| - if (!group_should_be_visited) { |
| - object_groups_[last++] = entry; |
| - continue; |
| - } |
| - |
| - // An object in the group requires visiting, so iterate over all |
| - // objects in the group. |
| - for (size_t j = 0; j < entry->length_; ++j) { |
| - Object* object = *objects[j]; |
| - if (object->IsHeapObject()) { |
| - v->VisitPointer(&object); |
| - any_group_was_visited = true; |
| + if (!group_should_be_visited) { |
| + for (int j = current_group_start; j < i; ++j) |
| + 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.
|
| + } else { |
| + // An object in the group requires visiting, so iterate over all |
| + // objects in the group. |
| + for (int j = current_group_start; j < i; ++j) { |
| + Object* object = *(object_groups_->at(j).object); |
| + if (object->IsHeapObject()) { |
| + v->VisitPointer(&object); |
| + any_group_was_visited = true; |
| + } |
| + } |
| + } |
| + if (i < object_groups_->length()) { |
| + current_group_id = object_groups_->at(i).id; |
| + current_group_start = i; |
| } |
| } |
| - |
| - // Once the entire group has been iterated over, set the object |
| - // group to NULL so it won't be processed again. |
| - entry->Dispose(); |
| - object_groups_.at(i) = NULL; |
| } |
| - object_groups_.Rewind(last); |
| + delete object_groups_; |
| + object_groups_ = new_object_groups; |
| return any_group_was_visited; |
| } |
| @@ -824,7 +840,21 @@ void GlobalHandles::AddObjectGroup(Object*** handles, |
| if (info != NULL) info->Dispose(); |
| return; |
| } |
| - object_groups_.Add(ObjectGroup::New(handles, length, info)); |
| + for (size_t i = 0; i < length; ++i) |
| + object_groups_->Add(ObjectGroupConnection(handles[0], handles[i])); |
| + retained_object_infos_.Add(GroupRetainedObjectInfo(handles[0], info)); |
| +} |
| + |
| + |
| +void GlobalHandles::SetObjectGroupId(Object** handle, |
| + void* id) { |
| + object_groups_->Add(ObjectGroupConnection(id, handle)); |
| +} |
| + |
| + |
| +void GlobalHandles::SetRetainedObjectInfo(void* id, |
| + RetainedObjectInfo* info) { |
| + retained_object_infos_.Add(GroupRetainedObjectInfo(id, info)); |
| } |
| @@ -841,12 +871,50 @@ void GlobalHandles::AddImplicitReferences(HeapObject** parent, |
| implicit_ref_groups_.Add(ImplicitRefGroup::New(parent, children, length)); |
| } |
| +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
|
| + List<ObjectGroup*>* to_return = new List<ObjectGroup*>(); |
| + |
| + object_groups_->Sort(); |
| + retained_object_infos_.Sort(); |
| + int retained_object_infos_ix = 0; |
| + |
| + void* current_group_id = NULL; |
| + size_t current_group_start = 0; |
| + |
| + for (int i = 0; i <= object_groups_->length(); ++i) { |
| + if (i == 0) |
| + current_group_id = object_groups_->at(i).id; |
| + if (i == object_groups_->length() || |
| + current_group_id != object_groups_->at(i).id) { |
| + // Group detected: objects in indices [current_group_start, i[. |
| + ObjectGroup* group = new ObjectGroup(); |
| + if (retained_object_infos_ix < retained_object_infos_.length() && |
| + retained_object_infos_[retained_object_infos_ix].id == |
| + object_groups_->at(current_group_start).id) { |
| + // Transfer the ownership of info. |
| + group->info = retained_object_infos_[retained_object_infos_ix].info; |
| + retained_object_infos_[retained_object_infos_ix].info = NULL; |
| + ++retained_object_infos_ix; |
| + } |
| + for (int j = current_group_start; j < i; ++j) |
| + group->objects.Add(object_groups_->at(j).object); |
| + to_return->Add(group); |
| + } |
| + if (i < object_groups_->length()) { |
| + current_group_id = object_groups_->at(i).id; |
| + current_group_start = i; |
| + } |
| + } |
| + return to_return; |
| +} |
| void GlobalHandles::RemoveObjectGroups() { |
| - for (int i = 0; i < object_groups_.length(); i++) { |
| - object_groups_.at(i)->Dispose(); |
| + object_groups_->Clear(); |
| + for (int i = 0; i < retained_object_infos_.length(); ++i) { |
| + if (retained_object_infos_[i].info != NULL) |
| + retained_object_infos_[i].info->Dispose(); |
| } |
| - object_groups_.Clear(); |
| + retained_object_infos_.Clear(); |
| } |