protected RefChainElement getLastRefChainElement()

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