Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
*/
package com.oracle.svm.core.code;

import static com.oracle.svm.core.Uninterruptible.CALLED_FROM_UNINTERRUPTIBLE_CODE;
import static com.oracle.svm.core.util.VMError.shouldNotReachHereUnexpectedInput;

import org.graalvm.nativeimage.ImageSingletons;
Expand Down Expand Up @@ -423,7 +424,7 @@ private static FrameInfoQueryResult loadFrameInfo(CodeInfo info, long entryOffse
* @see CodeInfoEncoder.Encoders#encodeMethodTable
*/
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
static void fillInSourceClassAndMethodName(FrameInfoQueryResult result) {
static void fillSourceFields(FrameInfoQueryResult result) {
int methodId = result.sourceMethodId;
CodeInfo info;
CodeInfo next = CodeInfoTable.getFirstImageCodeInfo();
Expand All @@ -436,19 +437,46 @@ static void fillInSourceClassAndMethodName(FrameInfoQueryResult result) {

boolean shortClass = NonmovableArrays.lengthOf(CodeInfoAccess.getClasses(info)) <= 0xffff;
boolean shortName = NonmovableArrays.lengthOf(CodeInfoAccess.getMemberNames(info)) <= 0xffff;
boolean shortSignature = NonmovableArrays.lengthOf(CodeInfoAccess.getOtherStrings(info)) <= 0xffff;
int classBytes = shortClass ? Short.BYTES : Integer.BYTES;
int entryBytes = classBytes + (shortName ? Short.BYTES : Integer.BYTES);
int nameBytes = shortName ? Short.BYTES : Integer.BYTES;
int signatureBytes = shortSignature ? Short.BYTES : Integer.BYTES;
int modifierBytes = Short.BYTES;

int classOffset = 0;
int nameOffset = classOffset + classBytes;
int signatureOffset = nameOffset + nameBytes;
int modifierOffset = signatureOffset + signatureBytes;

int entryBytes = classBytes + nameBytes;
if (CodeInfoEncoder.shouldEncodeAllMethodMetadata()) {
entryBytes += signatureBytes + modifierBytes;
}

int methodIndex = methodId - CodeInfoAccess.getMethodTableFirstId(info);
NonmovableArray<Byte> methodEncodings = CodeInfoAccess.getMethodTable(info);
VMError.guarantee(methodIndex >= 0 && methodIndex < NonmovableArrays.lengthOf(methodEncodings) / entryBytes);

Pointer p = NonmovableArrays.addressOf(methodEncodings, methodIndex * entryBytes);
int classIndex = shortClass ? (p.readShort(0) & 0xffff) : p.readInt(0);
int classIndex = readIndex(p, shortClass, classOffset);
Class<?> sourceClass = NonmovableArrays.getObject(CodeInfoAccess.getClasses(info), classIndex);
int methodNameIndex = shortName ? (p.readShort(classBytes) & 0xffff) : p.readInt(classBytes);
int methodNameIndex = readIndex(p, shortName, nameOffset);
String sourceMethodName = NonmovableArrays.getObject(CodeInfoAccess.getMemberNames(info), methodNameIndex);
result.setSourceClassAndMethodName(sourceClass, sourceMethodName);

String sourceMethodSignature = CodeInfoEncoder.Encoders.INVALID_METHOD_SIGNATURE;
int sourceSignatureModifiers = CodeInfoEncoder.Encoders.INVALID_METHOD_MODIFIERS;
if (CodeInfoEncoder.shouldEncodeAllMethodMetadata()) {
int sourceSignatureIndex = readIndex(p, shortSignature, signatureOffset);
sourceMethodSignature = NonmovableArrays.getObject(CodeInfoAccess.getOtherStrings(info), sourceSignatureIndex);

sourceSignatureModifiers = readIndex(p, true, modifierOffset);
}
result.setSourceFields(sourceClass, sourceMethodName, sourceMethodSignature, sourceSignatureModifiers);
}

@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
private static int readIndex(Pointer p, boolean isShort, int offset) {
return isShort ? (p.readShort(offset) & 0xffff) : p.readInt(offset);
}

@AlwaysInline("Make IP-lookup loop call free")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
import com.oracle.svm.core.heap.SubstrateReferenceMap;
import com.oracle.svm.core.hub.DynamicHub;
import com.oracle.svm.core.hub.LayoutEncoding;
import com.oracle.svm.core.jfr.HasJfrSupport;
import com.oracle.svm.core.meta.SharedField;
import com.oracle.svm.core.meta.SharedMethod;
import com.oracle.svm.core.meta.SharedType;
Expand All @@ -68,6 +69,7 @@
import com.oracle.svm.core.util.Counter;
import com.oracle.svm.core.util.VMError;

import jdk.graal.compiler.api.replacements.Fold;
import jdk.graal.compiler.code.CompilationResult;
import jdk.graal.compiler.core.common.NumUtil;
import jdk.graal.compiler.core.common.util.FrequencyEncoder;
Expand Down Expand Up @@ -118,8 +120,10 @@ public void addToReferenceMapSize(long size) {
public static final class Encoders {
static final Class<?> INVALID_CLASS = null;
static final String INVALID_METHOD_NAME = "";
static final int INVALID_METHOD_MODIFIERS = -1;
static final String INVALID_METHOD_SIGNATURE = null;

public record Member(ResolvedJavaMethod method, Class<?> clazz, String name) {
public record Member(ResolvedJavaMethod method, Class<?> clazz, String name, String signature, int modifiers) {
}

public final FrequencyEncoder<JavaConstant> objectConstants;
Expand Down Expand Up @@ -158,23 +162,29 @@ public Encoders(boolean imageCode) {
this.methods.addObject(null);
this.classes.addObject(INVALID_CLASS);
this.memberNames.addObject(INVALID_METHOD_NAME);
if (shouldEncodeAllMethodMetadata()) {
this.otherStrings.addObject(INVALID_METHOD_SIGNATURE);
}
}
}

public void addMethod(ResolvedJavaMethod method, Class<?> clazz, String name) {
public void addMethod(ResolvedJavaMethod method, Class<?> clazz, String name, String signature, int modifiers) {
VMError.guarantee(SubstrateUtil.HOSTED, "Runtime code info must reference image methods by id");

Member member = new Member(Objects.requireNonNull(method), clazz, name);
Member member = new Member(Objects.requireNonNull(method), clazz, name, signature, modifiers);
if (methods.addObject(member)) {
classes.addObject(clazz);
memberNames.addObject(name);
if (shouldEncodeAllMethodMetadata()) {
otherStrings.addObject(signature);
}
}
}

public int findMethodIndex(ResolvedJavaMethod method, Class<?> clazz, String name, boolean optional) {
public int findMethodIndex(ResolvedJavaMethod method, Class<?> clazz, String name, String signature, int modifiers, boolean optional) {
VMError.guarantee(SubstrateUtil.HOSTED, "Runtime code info must obtain method ids from image code info");

Member member = new Member(Objects.requireNonNull(method), clazz, name);
Member member = new Member(Objects.requireNonNull(method), clazz, name, signature, modifiers);
return optional ? methods.findIndex(member) : methods.getIndex(member);
}

Expand Down Expand Up @@ -214,7 +224,7 @@ private static <T> T[] encodeArray(FrequencyEncoder<T> encoder, IntFunction<T[]>
* fewer bytes}. Still, the fields of the entries are dimensioned to not be larger than
* necessary to index into another array such as {@link #classes}.
*
* @see CodeInfoDecoder#fillInSourceClassAndMethodName
* @see CodeInfoDecoder#fillSourceFields
*/
private NonmovableArray<Byte> encodeMethodTable() {
if (methods == null) {
Expand All @@ -225,18 +235,21 @@ private NonmovableArray<Byte> encodeMethodTable() {

final boolean shortClassIndexes = (classes.getLength() <= 0xffff);
final boolean shortNameIndexes = (memberNames.getLength() <= 0xffff);
final boolean shortSignatureIndexes = (otherStrings.getLength() <= 0xffff);
UnsafeArrayTypeWriter writer = UnsafeArrayTypeWriter.create(ByteArrayReader.supportsUnalignedMemoryAccess());
assert encodedMethods[0] == null : "id 0 must mean invalid";
encodeMethod(writer, INVALID_CLASS, INVALID_METHOD_NAME, shortClassIndexes, shortNameIndexes);
encodeMethod(writer, INVALID_CLASS, INVALID_METHOD_NAME, INVALID_METHOD_SIGNATURE, INVALID_METHOD_MODIFIERS, shortClassIndexes, shortNameIndexes, shortSignatureIndexes);
for (int id = 1; id < encodedMethods.length; id++) {
encodeMethod(writer, encodedMethods[id].clazz, encodedMethods[id].name, shortClassIndexes, shortNameIndexes);
encodeMethod(writer, encodedMethods[id].clazz, encodedMethods[id].name, encodedMethods[id].signature, encodedMethods[id].modifiers, shortClassIndexes, shortNameIndexes,
shortSignatureIndexes);
}
NonmovableArray<Byte> bytes = NonmovableArrays.createByteArray(NumUtil.safeToInt(writer.getBytesWritten()), NmtCategory.Code);
writer.toByteBuffer(NonmovableArrays.asByteBuffer(bytes));
return bytes;
}

private void encodeMethod(UnsafeArrayTypeWriter writer, Class<?> clazz, String name, boolean shortClassIndexes, boolean shortNameIndexes) {
private void encodeMethod(UnsafeArrayTypeWriter writer, Class<?> clazz, String name, String signature, int modifiers, boolean shortClassIndexes, boolean shortNameIndexes,
boolean shortSignatureIndexes) {
int classIndex = classes.getIndex(clazz);
if (shortClassIndexes) {
writer.putU2(classIndex);
Expand All @@ -249,6 +262,15 @@ private void encodeMethod(UnsafeArrayTypeWriter writer, Class<?> clazz, String n
} else {
writer.putU4(memberNamesIndex);
}
if (shouldEncodeAllMethodMetadata()) {
int signatureNamesIndex = otherStrings.getIndex(signature);
if (shortSignatureIndexes) {
writer.putU2(signatureNamesIndex);
} else {
writer.putU4(signatureNamesIndex);
}
writer.putS2(modifiers);
}
}

@Uninterruptible(reason = "Nonmovable object arrays are not visible to GC until installed in target.")
Expand Down Expand Up @@ -300,6 +322,11 @@ public Encoders getEncoders() {
return encoders;
}

@Fold
public static boolean shouldEncodeAllMethodMetadata() {
return HasJfrSupport.get();
}

public static int getEntryOffset(Infopoint infopoint) {
if (infopoint instanceof Call || infopoint instanceof DeoptEntryInfopoint) {
int offset = infopoint.pcOffset;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,11 @@ protected void fillSourceFields(ResolvedJavaMethod method, FrameInfoQueryResult
* StackTraceElement contains interned strings, so we un-intern these strings and
* perform our own de-duplication.
*/
int sourceMethodModifiers = method.getModifiers();
String methodSignature = method.getSignature().toMethodDescriptor();
String sourceMethodName = stringTable.deduplicate(source.getMethodName(), true);
resultFrameInfo.setSourceClassAndMethodName(sourceClass, sourceMethodName);
String sourceMethodSignature = CodeInfoEncoder.shouldEncodeAllMethodMetadata() ? stringTable.deduplicate(methodSignature, true) : methodSignature;
resultFrameInfo.setSourceFields(sourceClass, sourceMethodName, sourceMethodSignature, sourceMethodModifiers);
}

protected abstract Class<?> getDeclaringJavaClass(ResolvedJavaMethod method);
Expand Down Expand Up @@ -197,6 +200,8 @@ record CompressedFrameData(
ResolvedJavaMethod sourceMethod, // for when methodId is not yet known (== 0)
Class<?> sourceClass,
String sourceMethodName,
String sourceMethodSignature,
int sourceMethodModifier,
int sourceLineNumber,
long encodedBci,
boolean isSliceEnd) {
Expand Down Expand Up @@ -400,7 +405,7 @@ private static void encodeCompressedFrame(UnsafeArrayTypeWriter encodingBuffer,
int methodId = frame.methodId;
if (frame.sourceMethod != null) {
assert methodId == 0;
methodId = encoders.findMethodIndex(frame.sourceMethod, frame.sourceClass, frame.sourceMethodName, false);
methodId = encoders.findMethodIndex(frame.sourceMethod, frame.sourceClass, frame.sourceMethodName, frame.sourceMethodSignature, frame.sourceMethodModifier, false);
}

encodingBuffer.putSV(encodeCompressedFirstEntry(methodId, true));
Expand Down Expand Up @@ -428,13 +433,14 @@ boolean writeFrameVerificationInfo(FrameData data, Encoders encoders) {

int previousMethodId = cur.sourceMethodId;
if (cur.getSourceMethod() != null) {
cur.sourceMethodId = encoders.findMethodIndex(cur.getSourceMethod(), cur.getSourceClass(), cur.getSourceMethodName(), false);
cur.sourceMethodId = encoders.findMethodIndex(cur.getSourceMethod(), cur.getSourceClass(), cur.getSourceMethodName(), cur.getSourceMethodSignature(),
cur.getSourceMethodModifiers(), false);
assert previousMethodId == 0 || previousMethodId == cur.sourceMethodId;
}

boolean isSliceEnd = (cur.caller == null);
CompressedFrameData expected = new CompressedFrameData(previousMethodId, cur.getSourceMethod(), cur.getSourceClass(),
cur.getSourceMethodName(), cur.sourceLineNumber, cur.encodedBci, isSliceEnd);
CompressedFrameData expected = new CompressedFrameData(previousMethodId, cur.getSourceMethod(), cur.getSourceClass(), cur.getSourceMethodName(),
cur.getSourceMethodSignature(), cur.getSourceMethodModifiers(), cur.sourceLineNumber, cur.encodedBci, isSliceEnd);
assert expected.equals(slice.get(curIdx)) : expected;
curIdx++;
}
Expand Down Expand Up @@ -487,14 +493,15 @@ protected FrameData addDebugInfo(ResolvedJavaMethod method, CompilationResult co

if (resultFrame.getSourceMethod() != null) {
assert resultFrame.sourceMethodId == 0;
encoders.addMethod(resultFrame.getSourceMethod(), resultFrame.getSourceClass(), resultFrame.getSourceMethodName());
encoders.addMethod(resultFrame.getSourceMethod(), resultFrame.getSourceClass(), resultFrame.getSourceMethodName(), resultFrame.getSourceMethodSignature(),
resultFrame.getSourceMethodModifiers());
}

// save encoding metadata
assert resultFrame.hasLocalValueInfo() == includeLocalValues : resultFrame;
if (!includeLocalValues) {
CompressedFrameData frame = new CompressedFrameData(resultFrame.sourceMethodId, resultFrame.getSourceMethod(), resultFrame.getSourceClass(),
resultFrame.getSourceMethodName(), resultFrame.sourceLineNumber, resultFrame.encodedBci, (resultFrame.caller == null));
CompressedFrameData frame = new CompressedFrameData(resultFrame.sourceMethodId, resultFrame.getSourceMethod(), resultFrame.getSourceClass(), resultFrame.getSourceMethodName(),
resultFrame.getSourceMethodSignature(), resultFrame.getSourceMethodModifiers(), resultFrame.sourceLineNumber, resultFrame.encodedBci, (resultFrame.caller == null));
frameSlice.add(frame);
}

Expand All @@ -517,12 +524,13 @@ protected FrameData addDefaultDebugInfo(ResolvedJavaMethod method, int totalFram

if (data.frame.getSourceMethod() != null) {
assert data.frame.sourceMethodId == 0;
encoders.addMethod(data.frame.getSourceMethod(), data.frame.getSourceClass(), data.frame.getSourceMethodName());
encoders.addMethod(data.frame.getSourceMethod(), data.frame.getSourceClass(), data.frame.getSourceMethodName(), data.frame.getSourceMethodSignature(),
data.frame.getSourceMethodModifiers());
}

// save encoding metadata
CompressedFrameData frame = new CompressedFrameData(data.frame.sourceMethodId, data.frame.getSourceMethod(), data.frame.getSourceClass(),
data.frame.getSourceMethodName(), data.frame.sourceLineNumber, data.frame.encodedBci, true);
CompressedFrameData frame = new CompressedFrameData(data.frame.sourceMethodId, data.frame.getSourceMethod(), data.frame.getSourceClass(), data.frame.getSourceMethodName(),
data.frame.getSourceMethodSignature(), data.frame.getSourceMethodModifiers(), data.frame.sourceLineNumber, data.frame.encodedBci, true);
frameMetadata.addFrameSlice(data, List.of(frame));

allDebugInfos.add(data);
Expand Down Expand Up @@ -951,7 +959,8 @@ private void encodeUncompressedFrameData(FrameData data, UnsafeArrayTypeWriter e

if (cur.getSourceMethod() != null) {
assert cur.sourceMethodId == 0;
cur.sourceMethodId = encoders.findMethodIndex(cur.getSourceMethod(), cur.getSourceClass(), cur.getSourceMethodName(), false);
cur.sourceMethodId = encoders.findMethodIndex(cur.getSourceMethod(), cur.getSourceClass(), cur.getSourceMethodName(), cur.getSourceMethodSignature(), cur.getSourceMethodModifiers(),
false);
}

encodingBuffer.putSV(cur.sourceMethodId);
Expand Down
Loading