| Index: src/global-handles.cc
|
| diff --git a/src/global-handles.cc b/src/global-handles.cc
|
| index cb3115abfca7db7ce9baec4a29c9da134437c223..d832d5d5a408dc193e1a805f8fca6f0335c821bd 100644
|
| --- a/src/global-handles.cc
|
| +++ b/src/global-handles.cc
|
| @@ -37,7 +37,13 @@ namespace internal {
|
|
|
|
|
| ObjectGroup::~ObjectGroup() {
|
| - if (info_ != NULL) info_->Dispose();
|
| + if (info != NULL) info->Dispose();
|
| +}
|
| +
|
| +
|
| +GroupRetainedObjectInfo::~GroupRetainedObjectInfo() {
|
| + if (info != NULL)
|
| + info->Dispose();
|
| }
|
|
|
|
|
| @@ -438,7 +444,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 +456,7 @@ GlobalHandles::~GlobalHandles() {
|
| block = tmp;
|
| }
|
| first_block_ = NULL;
|
| + delete object_groups_;
|
| }
|
|
|
|
|
| @@ -575,48 +583,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));
|
| + } 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 +842,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 +873,46 @@ void GlobalHandles::AddImplicitReferences(HeapObject** parent,
|
| implicit_ref_groups_.Add(ImplicitRefGroup::New(parent, children, length));
|
| }
|
|
|
| +List<ObjectGroup*>* GlobalHandles::object_groups() {
|
| + 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();
|
| + object_groups_->Clear();
|
| + retained_object_infos_.Clear();
|
| }
|
|
|
|
|
|
|