Skip to content

Commit

Permalink
Always store bci in frame info
Browse files Browse the repository at this point in the history
  • Loading branch information
Christian Wimmer committed Jun 8, 2023
1 parent c8a0e76 commit d747c30
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import java.util.Arrays;

import org.graalvm.compiler.core.common.util.TypeConversion;
import org.graalvm.compiler.nodes.FrameState;

import com.oracle.svm.core.Uninterruptible;
import com.oracle.svm.core.c.NonmovableArray;
Expand All @@ -45,17 +46,38 @@
import com.oracle.svm.core.util.NonmovableByteArrayTypeReader;
import com.oracle.svm.core.util.VMError;

import jdk.vm.ci.code.BytecodeFrame;
import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.JavaKind;

public class FrameInfoDecoder {

protected static final int BCI_SHIFT = 2;
protected static final int DURING_CALL_MASK = 2;
protected static final int RETHROW_EXCEPTION_MASK = 1;
/**
* Shift of raw bci values to make room for the {@link #ENCODED_BCI_DURING_CALL_MASK} and
* {@link #ENCODED_BCI_RETHROW_EXCEPTION_MASK} flags.
*/
protected static final int ENCODED_BCI_SHIFT = 2;
/**
* Added to raw bci values to make them non-negative. Some of the negative marker values defined
* in {@link BytecodeFrame} can show up as bci values. The encoded bci is stored as an unsigned
* value to avoid wasting one bit on the sign.
*/
protected static final int ENCODED_BCI_ADDEND = 4;
/**
* Flag in the encoded bci to preserve {@link FrameState#duringCall()} information.
*/
protected static final int ENCODED_BCI_DURING_CALL_MASK = 2;
/**
* Flag in the encoded bci to preserve {@link FrameState#rethrowException()} information.
*/
protected static final int ENCODED_BCI_RETHROW_EXCEPTION_MASK = 1;

protected static final int NO_CALLER_BCI = -1;
protected static final int NO_LOCAL_INFO_BCI = -2;
/**
* There cannot be any frame state with both the {@link #ENCODED_BCI_DURING_CALL_MASK} and
* {@link #ENCODED_BCI_RETHROW_EXCEPTION_MASK} flag set, so we can use that combination as a
* marker value.
*/
protected static final int ENCODED_BCI_NO_CALLER = ENCODED_BCI_DURING_CALL_MASK | ENCODED_BCI_RETHROW_EXCEPTION_MASK;

/**
* Differentiates between compressed and uncompressed frame slices. See
Expand Down Expand Up @@ -85,8 +107,8 @@ protected static boolean isFrameInfoMatch(long frameInfoIndex, NonmovableArray<B
}

/* Read encoded bci from uncompressed frame slice. */
long actualEncodedBci = readBuffer.getSV();
assert actualEncodedBci != NO_CALLER_BCI;
long actualEncodedBci = readBuffer.getUV();
assert actualEncodedBci != ENCODED_BCI_NO_CALLER;

return actualEncodedBci == searchEncodedBci;
}
Expand Down Expand Up @@ -279,7 +301,6 @@ private static FrameInfoQueryResult decodeCompressedFrameInfo(boolean isDeoptEnt
return result;
}

cur.encodedBci = NO_LOCAL_INFO_BCI;
cur.isDeoptEntry = isDeoptEntry;

long bufferIndexToRestore = -1;
Expand Down Expand Up @@ -346,6 +367,7 @@ private static void decodeCompressedFrameData(ReusableTypeReader readBuffer, Cod
int sourceMethodNameIndex = CompressedFrameDecoderHelper.decodeMethodIndex(encodedSourceMethodNameIndex);
int encodedSourceLineNumber = readBuffer.getSVInt();
int sourceLineNumber = CompressedFrameDecoderHelper.decodeSourceLineNumber(encodedSourceLineNumber);
long encodedBci = readBuffer.getUV();
int methodId = readBuffer.getSVInt();

queryResult.sourceClassIndex = sourceClassIndex;
Expand All @@ -354,6 +376,7 @@ private static void decodeCompressedFrameData(ReusableTypeReader readBuffer, Cod
queryResult.sourceClass = NonmovableArrays.getObject(CodeInfoAccess.getFrameInfoSourceClasses(info), sourceClassIndex);
queryResult.sourceMethodName = NonmovableArrays.getObject(CodeInfoAccess.getFrameInfoSourceMethodNames(info), sourceMethodNameIndex);
queryResult.sourceLineNumber = sourceLineNumber;
queryResult.encodedBci = encodedBci;
queryResult.methodId = methodId;

if (CompressedFrameDecoderHelper.hasEncodedUniqueSharedFrameSuccessor(encodedSourceMethodNameIndex)) {
Expand All @@ -376,8 +399,8 @@ private static FrameInfoQueryResult decodeUncompressedFrameInfo(boolean isDeoptE

while (!state.isDone) {
long start = readBuffer.getByteIndex();
int encodedBci = readBuffer.getSVInt();
if (encodedBci == NO_CALLER_BCI) {
long encodedBci = readBuffer.getUV();
if (encodedBci == ENCODED_BCI_NO_CALLER) {
state.isDone = true;
return result;
}
Expand All @@ -393,8 +416,6 @@ private static FrameInfoQueryResult decodeUncompressedFrameInfo(boolean isDeoptE
cur.encodedBci = encodedBci;
cur.isDeoptEntry = isDeoptEntry;

assert encodedBci != NO_LOCAL_INFO_BCI : "Compressed frame info must be used when no local values are needed";

cur.numLocks = readBuffer.getUVInt();
cur.numLocals = readBuffer.getUVInt();
cur.numStack = readBuffer.getUVInt();
Expand Down Expand Up @@ -509,31 +530,34 @@ private static ValueInfo newValueInfo(ValueInfoAllocator valueInfoAllocator) {

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
protected static int decodeBci(long encodedBci) {
long value = encodedBci >> BCI_SHIFT;
assert value >= Integer.MIN_VALUE && value <= Integer.MAX_VALUE;
return (int) value;
assert encodedBci > 0 && encodedBci != FrameInfoDecoder.ENCODED_BCI_NO_CALLER;
long result = (encodedBci >> ENCODED_BCI_SHIFT) - ENCODED_BCI_ADDEND;
assert result >= Integer.MIN_VALUE && result <= Integer.MAX_VALUE;
return (int) result;
}

protected static boolean decodeDuringCall(long encodedBci) {
return (encodedBci & DURING_CALL_MASK) != 0;
assert encodedBci > 0 && encodedBci != FrameInfoDecoder.ENCODED_BCI_NO_CALLER;
return (encodedBci & ENCODED_BCI_DURING_CALL_MASK) != 0;
}

protected static boolean decodeRethrowException(long encodedBci) {
return (encodedBci & RETHROW_EXCEPTION_MASK) != 0;
assert encodedBci > 0 && encodedBci != FrameInfoDecoder.ENCODED_BCI_NO_CALLER;
return (encodedBci & ENCODED_BCI_RETHROW_EXCEPTION_MASK) != 0;
}

public static String readableBci(long encodedBci) {
return decodeBci(encodedBci) +
((encodedBci & DURING_CALL_MASK) != 0 ? " duringCall" : "") +
((encodedBci & RETHROW_EXCEPTION_MASK) != 0 ? " rethrowException" : "");
(decodeDuringCall(encodedBci) ? " duringCall" : "") +
(decodeRethrowException(encodedBci) ? " rethrowException" : "");
}

public static void logReadableBci(Log log, long encodedBci) {
log.signed(decodeBci(encodedBci));
if ((encodedBci & DURING_CALL_MASK) != 0) {
if (decodeDuringCall(encodedBci)) {
log.string(" duringCall");
}
if ((encodedBci & RETHROW_EXCEPTION_MASK) != 0) {
if (decodeRethrowException(encodedBci)) {
log.string(" rethrowException");
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,38 +186,13 @@ static class FrameData {
}
}

private static class CompressedFrameData {
final Class<?> sourceClass;
final String sourceMethodName;
final int sourceLineNumber;
final int methodId;
final boolean isSliceEnd;

CompressedFrameData(Class<?> sourceClass, String sourceMethodName, int sourceLineNumber, int methodId, boolean isSliceEnd) {
this.sourceClass = sourceClass;
this.sourceMethodName = sourceMethodName;
this.sourceLineNumber = sourceLineNumber;
this.methodId = methodId;
this.isSliceEnd = isSliceEnd;
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
CompressedFrameData that = (CompressedFrameData) o;
return sourceLineNumber == that.sourceLineNumber && methodId == that.methodId && isSliceEnd == that.isSliceEnd && sourceClass.equals(that.sourceClass) &&
sourceMethodName.equals(that.sourceMethodName);
}

@Override
public int hashCode() {
return Objects.hash(sourceClass, sourceMethodName, sourceLineNumber, methodId, isSliceEnd);
}
record CompressedFrameData(
Class<?> sourceClass,
String sourceMethodName,
int sourceLineNumber,
long encodedBci,
int methodId,
boolean isSliceEnd) {
}

/**
Expand Down Expand Up @@ -422,6 +397,7 @@ private static void encodeCompressedFrame(UnsafeArrayTypeWriter encodingBuffer,
boolean encodeUniqueSuccessor = uniqueSuccessorIndex != NO_SUCCESSOR_INDEX_MARKER;
encodingBuffer.putSV(encodeCompressedMethodIndex(methodIndex, encodeUniqueSuccessor));
encodingBuffer.putSV(encodeCompressedSourceLineNumber(frame.sourceLineNumber, frame.isSliceEnd));
encodingBuffer.putUV(frame.encodedBci);
encodingBuffer.putSV(frame.methodId);
if (encodeUniqueSuccessor) {
encodingBuffer.putSV(uniqueSuccessorIndex);
Expand All @@ -443,13 +419,12 @@ boolean writeFrameVerificationInfo(FrameData data, Encoders encoders) {
int curIdx = 0;
List<CompressedFrameData> slice = frameSlices.get(data.frameSliceIndex);
for (FrameInfoQueryResult cur = data.frame; cur != null; cur = cur.caller) {
cur.encodedBci = FrameInfoDecoder.NO_LOCAL_INFO_BCI;
assert cur == data.frame || !cur.isDeoptEntry : "Deoptimization entry information for caller frames is not persisted";

cur.sourceClassIndex = encoders.sourceClasses.getIndex(cur.sourceClass);
cur.sourceMethodNameIndex = encoders.sourceMethodNames.getIndex(cur.sourceMethodName);
boolean isSliceEnd = cur.caller == null;
CompressedFrameData frame = new CompressedFrameData(cur.sourceClass, cur.sourceMethodName, cur.sourceLineNumber, cur.methodId, isSliceEnd);
CompressedFrameData frame = new CompressedFrameData(cur.sourceClass, cur.sourceMethodName, cur.sourceLineNumber, cur.encodedBci, cur.methodId, isSliceEnd);
assert frame.equals(slice.get(curIdx));
curIdx++;
}
Expand Down Expand Up @@ -503,10 +478,8 @@ protected FrameData addDebugInfo(ResolvedJavaMethod method, CompilationResult co
// save encoding metadata
assert resultFrame.hasLocalValueInfo() == includeLocalValues;
if (!includeLocalValues) {
final boolean isSliceEnd = resultFrame.caller == null;
final int sourceLineNumber = resultFrame.sourceLineNumber;
final int methodId = resultFrame.methodId;
CompressedFrameData frame = new CompressedFrameData(sourceClass, sourceMethodName, sourceLineNumber, methodId, isSliceEnd);
CompressedFrameData frame = new CompressedFrameData(sourceClass, sourceMethodName, resultFrame.sourceLineNumber, resultFrame.encodedBci,
resultFrame.methodId, resultFrame.caller == null);
frameSlice.add(frame);
}

Expand Down Expand Up @@ -913,11 +886,11 @@ private void encodeUncompressedFrameData(FrameData data, UnsafeArrayTypeWriter e
encodingBuffer.putSV(FrameInfoDecoder.UNCOMPRESSED_FRAME_SLICE_MARKER);

for (FrameInfoQueryResult cur = data.frame; cur != null; cur = cur.caller) {
assert cur.encodedBci != FrameInfoDecoder.NO_CALLER_BCI : "used as the end marker during decoding";
assert cur.encodedBci != FrameInfoDecoder.ENCODED_BCI_NO_CALLER : "used as the end marker during decoding";
assert cur.hasLocalValueInfo() : "Compressed frame info must be used when no local values are needed";
assert cur == data.frame || !cur.isDeoptEntry : "Deoptimization entry information for caller frames is not persisted";

encodingBuffer.putSV(cur.encodedBci);
encodingBuffer.putUV(cur.encodedBci);
encodingBuffer.putUV(cur.numLocks);
encodingBuffer.putUV(cur.numLocals);
encodingBuffer.putUV(cur.numStack);
Expand Down Expand Up @@ -954,7 +927,7 @@ private void encodeUncompressedFrameData(FrameData data, UnsafeArrayTypeWriter e
encodingBuffer.putSV(cur.sourceLineNumber);
encodingBuffer.putUV(cur.methodId);
}
encodingBuffer.putSV(FrameInfoDecoder.NO_CALLER_BCI);
encodingBuffer.putUV(FrameInfoDecoder.ENCODED_BCI_NO_CALLER);
}

private void encodeValues(ValueInfo[] valueInfos, UnsafeArrayTypeWriter encodingBuffer) {
Expand Down Expand Up @@ -999,7 +972,12 @@ private static int encodeFlags(ValueType type, JavaKind kind, boolean isCompress
* Encodes the BCI and the duringCall- and rethrowException flags into a single value.
*/
public static long encodeBci(int bci, boolean duringCall, boolean rethrowException) {
return (((long) bci) << FrameInfoDecoder.BCI_SHIFT) | (duringCall ? FrameInfoDecoder.DURING_CALL_MASK : 0) | (rethrowException ? FrameInfoDecoder.RETHROW_EXCEPTION_MASK : 0);
long result = (((long) bci + FrameInfoDecoder.ENCODED_BCI_ADDEND) << FrameInfoDecoder.ENCODED_BCI_SHIFT) |
(duringCall ? FrameInfoDecoder.ENCODED_BCI_DURING_CALL_MASK : 0) |
(rethrowException ? FrameInfoDecoder.ENCODED_BCI_RETHROW_EXCEPTION_MASK : 0);
VMError.guarantee(result >= 0, "encoded bci is stored as an unsigned value");
VMError.guarantee(result != FrameInfoDecoder.ENCODED_BCI_NO_CALLER, "Encoding must not return marker value");
return result;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ public void init() {
caller = null;
deoptMethod = null;
deoptMethodOffset = 0;
encodedBci = 0;
encodedBci = -1;
isDeoptEntry = false;
numLocals = 0;
numStack = 0;
Expand Down

0 comments on commit d747c30

Please sign in to comment.