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(); |
} |