in application/org.openjdk.jmc.joverflow/src/main/java/org/openjdk/jmc/joverflow/stats/InterimRefChainStack.java [155:261]
protected RefChainElement getLastRefChainElement() {
if (refChainToRefTreeIdx.length < refChain.size()) {
int[] old = refChainToRefTreeIdx;
refChainToRefTreeIdx = new int[refChain.size() * 5 / 4];
System.arraycopy(old, 0, refChainToRefTreeIdx, 0, old.length);
}
int chainSizeMinusOne = refChain.size() - 1;
RefChainElement curRefChainElement = curCondensedRefChainElement;
if (newGCRoot || numCommonRefChainEls == 0) { // Build non-incremental condensed ref chain
newGCRoot = false;
int refTreeElementIdx = -1; // Proper initial value given loop code below
for (int i = 0; i < chainSizeMinusOne; i++) {
refTreeElementIdx++;
CollapsedObj clpsObj = collapseLinkedListImpl(i, curRefChainElement);
if (clpsObj == null) {
clpsObj = collapseCollectionImpl(i, curRefChainElement);
}
if (clpsObj != null) { // We went through a collection or linked list implementation
curRefChainElement = clpsObj.desc;
for (int j = i; j <= clpsObj.endIdx; j++) {
refChainToRefTreeIdx[j] = refTreeElementIdx;
}
i = clpsObj.endIdx;
} else { // index i points at a regular object in the reference chain
refChainToRefTreeIdx[i] = refChainToRefTreeIdx[i + 1] = refTreeElementIdx;
JavaHeapObject javaHeapObj = (JavaHeapObject) refChain.get(i++);
int fieldOrArrIdx = ((IndexContainer) refChain.get(i)).get();
curRefChainElement = getLinkDesc(javaHeapObj, fieldOrArrIdx, curRefChainElement);
}
condensedRefChain.add(curRefChainElement);
}
lastRecordedRefTreeIdx = refTreeElementIdx;
numCommonRefChainEls = chainSizeMinusOne;
curCondensedRefChainElement = curRefChainElement;
return curRefChainElement;
}
// Otherwise, need to build an incremental condensedRefChain.
int lastCommonRefChainIdx = numCommonRefChainEls - 1;
if ((lastCommonRefChainIdx & 1) == 1) {
// Need lastCommonRefChainIdx to point at an object, not at field after it.
// For that, the number should be even.
lastCommonRefChainIdx--;
}
// Incremental compressed ref chain cannot be constructed properly if
// lastCommonRefChainIdx points into the middle of compressible data structure
lastCommonRefChainIdx = skipBackPotentialCollectionImplOrLinkedList(lastCommonRefChainIdx);
// This gets lastCommonRefChainIdx above a compressible data structure
// or another object that will be the start of the incremental chain
lastCommonRefChainIdx -= 2;
// This points at the object that starts the incremental chain
// +2 is essentially a performance optimization; don't use it when in doubt.
int startIdx = lastCommonRefChainIdx == 0 ? 0 : lastCommonRefChainIdx + 2;
// If startIdx == 0, we have to attach the new chain directly to the GC root.
// That does not allow us to use normal indexing machinery below.
int nStepsBack = startIdx > 0 ? lastRecordedRefTreeIdx - refChainToRefTreeIdx[lastCommonRefChainIdx]
: lastRecordedRefTreeIdx + 1;
int refTreeElementIdx = startIdx > 0 ? refChainToRefTreeIdx[lastCommonRefChainIdx] : -1;
int lastIndex = condensedRefChain.size() - 1;
for (int i = 0; i < nStepsBack; i++, lastIndex--) {
condensedRefChain.remove(lastIndex);
}
curRefChainElement = condensedRefChain.get(lastIndex);
for (int i = startIdx; i < chainSizeMinusOne; i++) {
refTreeElementIdx++;
CollapsedObj clpsObj = collapseLinkedListImpl(i, curRefChainElement);
if (clpsObj == null) {
clpsObj = collapseCollectionImpl(i, curRefChainElement);
}
boolean stitchingLinkedListParts = false;
if (clpsObj != null) { // We went through a collection or linked list implementation
if (curRefChainElement == clpsObj.desc) {
// May happen for a linked list - we have two entities representing compressed
// parts of the same list. We need to, in effect, merge them together.
refTreeElementIdx--;
stitchingLinkedListParts = true;
} else {
curRefChainElement = clpsObj.desc;
}
for (int j = i; j <= clpsObj.endIdx; j++) {
refChainToRefTreeIdx[j] = refTreeElementIdx;
}
i = clpsObj.endIdx;
} else { // index i points at a regular object in the reference chain
refChainToRefTreeIdx[i] = refChainToRefTreeIdx[i + 1] = refTreeElementIdx;
JavaHeapObject javaHeapObj = (JavaHeapObject) refChain.get(i++);
int idx = ((IndexContainer) refChain.get(i)).get();
curRefChainElement = getLinkDesc(javaHeapObj, idx, curRefChainElement);
}
if (!stitchingLinkedListParts) {
condensedRefChain.add(curRefChainElement);
}
}
lastRecordedRefTreeIdx = refTreeElementIdx;
numCommonRefChainEls = chainSizeMinusOne;
curCondensedRefChainElement = curRefChainElement;
return curRefChainElement;
}