Skip to content

Commit

Permalink
Bug 491109 Some collections queries fail for some collections from PHD
Browse files Browse the repository at this point in the history
Improve linked list and hash and tree sets

Task-Url: https://bugs.eclipse.org/bugs/show_bug.cgi?id=491109
Change-Id: I6da44bcc43222cc968aa717d5e07681413795024
  • Loading branch information
ajohnson1 committed Oct 26, 2023
1 parent bc0c541 commit e4ad7e2
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@

import org.eclipse.mat.SnapshotException;
import org.eclipse.mat.collect.ArrayInt;
import org.eclipse.mat.collect.BitField;
import org.eclipse.mat.inspections.collectionextract.IMapExtractor;
import org.eclipse.mat.snapshot.ISnapshot;
import org.eclipse.mat.snapshot.model.IClass;
import org.eclipse.mat.snapshot.model.IInstance;
import org.eclipse.mat.snapshot.model.IObject;
import org.eclipse.mat.snapshot.model.IObjectArray;
Expand Down Expand Up @@ -62,6 +64,9 @@ public Integer getSize(IObject coll) throws SnapshotException
if (size_attribute != null)
{
Integer ret = ExtractionUtils.toInteger(coll.resolveValue(size_attribute));
if (ret != null)
return ret;
ret = createHashMapExtractor().getSize(coll);
if (ret != null)
return ret;
return getNumberOfNotNullElements(coll);
Expand Down Expand Up @@ -154,10 +159,96 @@ public int[] extractEntryIds(IObject coll) throws SnapshotException
ret.add(((IObject) f).getObjectId());
}
}
if (ret.size() == 0 && entries.length > 0)
{
// No fields?
// Dummy extractor for resolveSameNextField
HashMapCollectionExtractor hme2 = new HashMapCollectionExtractor(size_attribute, array_attribute, key_attribute, value_attribute);
getSetEntries(coll, hme2, entries, ret);
}
}
return ret.toArray();
}

int getSetEntries(IObject collection, HashMapCollectionExtractor hme, int[] objects, ArrayInt ret) throws SnapshotException
{
// Maps have chained buckets in case of clashes
// LinkedMaps have additional chains to maintain ordering
int count = 0;
ISnapshot snapshot = collection.getSnapshot();
// Find the possible dummy value reference used to convert map to set
ArrayInt collRefs1 = new ArrayInt();
for (IClass c = collection.getClazz(); c != null; c = c.getSuperClass())
{
for (int o : snapshot.getOutboundReferentIds(c.getObjectId()))
{
if (snapshot.getClassOf(o).getName().equals("java.lang.Object")) //$NON-NLS-1$
{
collRefs1.add(o);
}
}
}
int collRefs[] = collRefs1.toArray();
// Avoid visiting nodes twice
BitField seen = new BitField(snapshot.getSnapshotInfo().getNumberOfObjects());
// Used for alternative nodes if there is a choice
ArrayInt extra = new ArrayInt();
// Eliminate the LinkedHashMap header node
// seen.set(array.getObjectId());
// Walk over whole array, or all outbounds of header
for (int i : objects)
{
// Ignore classes, outbounds we have seen, and plain Objects (which
// can't be buckets e.g. ConcurrentSkipListMap)
if (!snapshot.isClass(i) && !seen.get(i) && !snapshot.getClassOf(i).getName().equals("java.lang.Object")) //$NON-NLS-1$
{
// Found a new outbound
// Look at the reachable nodes from this one, remember this
extra.clear();
extra.add(i);
seen.set(i);
for (int k = 0; k < extra.size(); ++k)
{
for (int j = extra.get(k); j >= 0;)
{
++count;
int val = -1;
IClass entryClazz = snapshot.getClassOf(j);
l1: for (int o : snapshot.getOutboundReferentIds(j))
{
if (entryClazz.getObjectId() == o)
continue;
IClass c = snapshot.getClassOf(o);
if (entryClazz.equals(c))
continue;
String cname = c.getName();
if (cname.endsWith("$Node") || cname.endsWith("$TreeNode") || cname.endsWith("$Entry")) //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
{
continue;
}
if (cname.equals("java.lang.Object")) //$NON-NLS-1$
{
for (int o2 : collRefs)
{
if (o2 == o)
continue l1;
}
}
if (val == -1)
val = o;
else
val = -2;
}
if (val >= 0)
ret.add(val);
j = hme.resolveNextSameField(snapshot, j, seen, extra);
}
}
}
}
return count;
}

public Integer getNumberOfNotNullElements(IObject coll) throws SnapshotException
{
return createHashMapExtractor().getNumberOfNotNullElements(coll);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,29 +63,45 @@ public int[] extractEntryIds(IObject list) throws SnapshotException
{
// Look for the only object field
header = ExtractionUtils.followOnlyOutgoingReferencesExceptLast(leadField, list);
if (header == null)
header = list;
}
IObject tail = null;
if (header == list)
{
// Try without using field names
IObject first = null;
IObject first = null, second = null;
final ISnapshot snapshot = header.getSnapshot();
for (int i : snapshot.getOutboundReferentIds(header.getObjectId()))
{
IObject o = snapshot.getObject(i);
// Exclude the class
if (i != header.getClazz().getObjectId())
{
String tn = o.getClazz().getName();
if (!(tn.endsWith("$Entry") || tn.endsWith("$Node"))) //$NON-NLS-1$//$NON-NLS-2$
continue;
if (first == null)
{
first = o;
else if (!first.getClass().equals(o.getClass()))
}
else if (first.getClass().equals(o.getClass()) && second == null)
{
second = o;
}
else
{
first = null;
second = null;
break;
}
}
}
if (first != null)
{
header = first;
tail = second;
}
}
if (header == null)
return new int[0];
Expand Down Expand Up @@ -181,6 +197,14 @@ else if (!first.getClass().equals(o.getClass()))
header = current;
previous = current;
current = next;
// ConcurrentLinkedQueue without fields ?
if (current == null && tail != null && tail.getObjectId() != header.getObjectId()
&& tail.getObjectId() != previous.getObjectId())
{
current = tail;
tail = null;
header = previous;
}
listener.worked(1);
// If the user cancels then just return what we have got so far
if (listener.isCanceled())
Expand Down

0 comments on commit e4ad7e2

Please sign in to comment.