Skip to content
Merged
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
52 changes: 0 additions & 52 deletions substratevm/mx.substratevm/suite.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,27 +39,6 @@
},

"libraries" : {
"ASM_9.7.1" : {
"digest" : "sha512:4767b01603dad5c79cc1e2b5f3722f72b1059d928f184f446ba11badeb1b381b3a3a9a801cc43d25d396df950b09d19597c73173c411b1da890de808b94f1f50",
"sourceDigest" : "sha512:d7c0de5912d04949a3d06cad366ff35a877da2682d9c74579625d62686032ea9349aff6102b17f92e9ec7eb4e9b1cd906b649c6a3ac798bfb9e31e5425de009d",
"maven" : {
"groupId" : "org.ow2.asm",
"artifactId" : "asm",
"version" : "9.7.1",
},
"license" : "BSD-new",
},
"ASM_TREE_9.7.1" : {
"digest" : "sha512:e55008c392fdd35e95d3404766b12dd4b46e13d5c362fcd0ab42a65751a82737eaf0ebc857691d1916190d34407adfde4437615d69c278785416fd911e00978d",
"sourceDigest" : "sha512:3cea80bc7b55679dfa3d2065c6cb6951007cc7817082e9fcf4c5e3cdc073c22eddf7c7899cff60b1092049ec9038e8d3aa9a8828ef731739bda8b5afcec30e86",
"maven" : {
"groupId" : "org.ow2.asm",
"artifactId" : "asm-tree",
"version" : "9.7.1",
},
"dependencies" : ["ASM_9.7.1"],
"license" : "BSD-new",
},
"RENAISSANCE_HARNESS_v0.9" : {
"urls" : ["https://lafo.ssw.uni-linz.ac.at/pub/graal-external-deps/renaissance/renaissance-harness_v0.9.0.tar.gz"],
"digest" : "sha512:068207adf6bbd0a934429f7d6ddba8810e55992d06e131479658a7933bb352ea892d4304f745806dc342a6f7187a434ff2f106c6f8a6ee35ee696ea4fc998f7b",
Expand Down Expand Up @@ -306,36 +285,6 @@
"graalCompilerSourceEdition": "ignore",
},

# This shaded ASM project is just a quickfix.
# Eventually, we should migrate to the Classfile API [JDK-8294982] (GR-61102).
"com.oracle.svm.shaded.org.objectweb.asm": {
# Shadowed ASM libraries (org.ow2.asm:asm,asm-tree)
"subDir" : "src",
"sourceDirs" : ["src"],
"javaCompliance" : "17+",
"spotbugsIgnoresGenerated" : True,
"shadedDependencies" : [
"ASM_9.7.1",
"ASM_TREE_9.7.1",
],
"class" : "ShadedLibraryProject",
"shade" : {
"packages" : {
"org.objectweb.asm" : "com.oracle.svm.shaded.org.objectweb.asm",
},
"exclude" : [
"META-INF/MANIFEST.MF",
"**/package.html",
],
},
"description" : "ASM library shadowed for Native Iamge.",
# We need to force javac because the generated sources in this project produce warnings in JDT.
"forceJavac" : "true",
"javac.lint.overrides" : "none",
"jacoco" : "exclude",
"graalCompilerSourceEdition": "ignore",
},

"com.oracle.svm.processor" : {
"subDir" : "src",
"sourceDirs" : ["src"],
Expand All @@ -360,7 +309,6 @@
],
"dependencies": [
"com.oracle.svm.common",
"com.oracle.svm.shaded.org.objectweb.asm",
"com.oracle.objectfile",
"SVM_CONFIGURE",
"espresso-shared:ESPRESSO_SVM",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,21 @@
*/
package com.oracle.svm.core.hub;

import static java.lang.classfile.ClassFile.ConstantPoolSharingOption.NEW_POOL;

import java.io.Serializable;
import java.lang.classfile.ClassFile;
import java.lang.classfile.ClassModel;
import java.lang.classfile.ClassTransform;
import java.lang.classfile.MethodTransform;
import java.lang.classfile.constantpool.ClassEntry;
import java.lang.classfile.instruction.FieldInstruction;
import java.lang.classfile.instruction.InvokeInstruction;
import java.lang.classfile.instruction.NewMultiArrayInstruction;
import java.lang.classfile.instruction.NewObjectInstruction;
import java.lang.classfile.instruction.NewReferenceArrayInstruction;
import java.lang.classfile.instruction.TypeCheckInstruction;
import java.lang.constant.ClassDesc;
import java.lang.reflect.Method;
import java.security.ProtectionDomain;
import java.util.HashSet;
Expand All @@ -44,11 +58,6 @@
import com.oracle.svm.core.reflect.serialize.SerializationSupport;
import com.oracle.svm.core.util.ImageHeapMap;
import com.oracle.svm.core.util.VMError;
import com.oracle.svm.shaded.org.objectweb.asm.ClassReader;
import com.oracle.svm.shaded.org.objectweb.asm.ClassVisitor;
import com.oracle.svm.shaded.org.objectweb.asm.ClassWriter;
import com.oracle.svm.shaded.org.objectweb.asm.MethodVisitor;
import com.oracle.svm.shaded.org.objectweb.asm.Opcodes;
import com.oracle.svm.util.ClassUtil;

import jdk.graal.compiler.api.replacements.Fold;
Expand Down Expand Up @@ -332,41 +341,32 @@ public static Class<?> maybeAdjustLambdaNestHost(String className, Class<?> java

@Platforms(Platform.HOSTED_ONLY.class)
public static byte[] changeLambdaClassName(byte[] data, String oldName, String newName) {
ClassReader cr = new ClassReader(data);
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);

cr.accept(new ClassVisitor(Opcodes.ASM5, cw) {
// Change lambda class name in the bytecode
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
super.visit(version, access, newName, signature, superName, interfaces);
}

// Change all class references in the lambda class bytecode
@Override
public MethodVisitor visitMethod(int access, String originalName, String desc, String signature, String[] exceptions) {
return new MethodVisitor(Opcodes.ASM5, super.visitMethod(access, originalName, desc, signature, exceptions)) {
@Override
public void visitTypeInsn(int opcode, String type) {
String name = type.equals(oldName) ? newName : type;
super.visitTypeInsn(opcode, name);
}

@Override
public void visitMethodInsn(int opcode, String owner, String methodName, String descriptor, boolean isInterface) {
String name = owner.equals(oldName) ? newName : owner;
super.visitMethodInsn(opcode, name, methodName, descriptor, isInterface);
}

@Override
public void visitFieldInsn(int opcode, String owner, String fieldName, String descriptor) {
String name = owner.equals(oldName) ? newName : owner;
super.visitFieldInsn(opcode, name, fieldName, descriptor);
}
};
}
}, ClassReader.EXPAND_FRAMES);

return cw.toByteArray();
ClassDesc oldDesc = ClassDesc.ofInternalName(oldName);
ClassDesc newDesc = ClassDesc.ofInternalName(newName);

ClassFile classFile = ClassFile.of(NEW_POOL);
ClassModel original = classFile.parse(data);

return classFile.transformClass(original, newDesc,
ClassTransform.transformingMethods(
MethodTransform.transformingCode((builder, element) -> {
ClassEntry newClassEntry = builder.constantPool().classEntry(newDesc);
// Pass through any unhandled elements unchanged
if (element instanceof TypeCheckInstruction ti && ti.type().asSymbol().equals(oldDesc)) {
builder.with(TypeCheckInstruction.of(ti.opcode(), newClassEntry));
} else if (element instanceof NewObjectInstruction ti && ti.className().asSymbol().equals(oldDesc)) {
builder.with(NewObjectInstruction.of(newClassEntry));
} else if (element instanceof NewReferenceArrayInstruction ti && ti.componentType().asSymbol().equals(oldDesc)) {
builder.with(NewReferenceArrayInstruction.of(newClassEntry));
} else if (element instanceof NewMultiArrayInstruction ti && ti.arrayType().asSymbol().equals(oldDesc)) {
builder.with(NewMultiArrayInstruction.of(newClassEntry, ti.dimensions()));
} else if (element instanceof InvokeInstruction mi && mi.owner().asSymbol().equals(oldDesc)) {
builder.with(InvokeInstruction.of(mi.opcode(), newClassEntry, mi.name(), mi.type(), mi.isInterface()));
} else if (element instanceof FieldInstruction fi && fi.owner().asSymbol().equals(oldDesc)) {
builder.with(FieldInstruction.of(fi.opcode(), newClassEntry, fi.name(), fi.type()));
} else {
builder.with(element);
}
})));
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,16 @@
import static com.oracle.svm.jvmtiagentbase.Support.check;
import static com.oracle.svm.jvmtiagentbase.Support.jvmtiFunctions;
import static com.oracle.svm.jvmtiagentbase.jvmti.JvmtiEvent.JVMTI_EVENT_CLASS_FILE_LOAD_HOOK;

import static java.lang.classfile.ClassFile.ACC_PUBLIC;

import java.io.Serial;
import java.lang.classfile.ClassBuilder;
import java.lang.classfile.ClassElement;
import java.lang.classfile.ClassFile;
import java.lang.classfile.ClassModel;
import java.lang.classfile.ClassTransform;
import java.lang.classfile.MethodModel;
import java.lang.constant.ConstantDescs;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -65,8 +74,6 @@
import com.oracle.svm.jvmtiagentbase.jvmti.JvmtiEventCallbacks;
import com.oracle.svm.jvmtiagentbase.jvmti.JvmtiEventMode;
import com.oracle.svm.jvmtiagentbase.jvmti.JvmtiInterface;
import com.oracle.svm.shaded.org.objectweb.asm.ClassReader;
import com.oracle.svm.shaded.org.objectweb.asm.ClassWriter;

/**
* JVMTI agent that provides diagnostics information that helps resolve native-image build failures.
Expand Down Expand Up @@ -380,25 +387,13 @@ private static void onClassFileLoadHook(@SuppressWarnings("unused") JvmtiEnv jvm
newClassDataLen.write(newClassDataLength);
}

static final int ASM8 = 8 << 16;
static final int ASM_TARGET_VERSION = ASM8;

private byte[] maybeInstrumentClassWithClinit(String clazzName, byte[] clazzData) {
if (clazzName != null && !advisor.shouldTraceClassInitialization(clazzName.replace('/', '.'))) {
return null;
}

try {
ClassReader reader = new ClassReader(clazzData);
ClassWriter writer = new ClassWriter(reader, 0);
ClinitGenerationVisitor visitor = new ClinitGenerationVisitor(ASM_TARGET_VERSION, writer);
reader.accept(visitor, 0);

if (!visitor.didGeneration()) {
return null;
TracingAdvisor advisor = JvmtiAgentBase.<NativeImageDiagnosticsAgentJNIHandleSet, NativeImageDiagnosticsAgent> singleton().advisor;
if (advisor.shouldTraceClassInitialization(clazzName.replace("/", "."))) {
return instrumentClassWithClinit(clazzData);
}

return writer.toByteArray();
return null;
} catch (Throwable e) {
String targetClazzName = clazzName != null ? clazzName : "<unknown class>";
System.err.println("[native-image-diagnostics-agent] Failed to instrument class " + targetClazzName + ": ");
Expand All @@ -407,6 +402,48 @@ private byte[] maybeInstrumentClassWithClinit(String clazzName, byte[] clazzData
}
}

/**
* Instruments the given class data with a synthetic <clinit> method if missing. Returns null if
* no changes are made, otherwise the modified classfile bytes.
*/
public byte[] instrumentClassWithClinit(byte[] classData) {
class ClinitAlreadyExistsException extends RuntimeException {
@Serial private static final long serialVersionUID = 1L;
}
try {
ClassModel cm = ClassFile.of().parse(classData);
return ClassFile.of().transformClass(cm, new ClassTransform() {
/**
* Copies over all elements from the original class.
*/
@Override
public void accept(ClassBuilder clb, ClassElement ce) {
if (ce instanceof MethodModel mm && ConstantDescs.CLASS_INIT_NAME.equals((mm.methodName().stringValue()))) {
// already has a <clinit> method
throw new ClinitAlreadyExistsException();
}
clb.with(ce);
}

/**
* Add an empty <clinit> method to the class.
*/
@Override
public void atEnd(ClassBuilder clb) {
clb.withMethodBody(
ConstantDescs.CLASS_INIT_NAME,
ConstantDescs.MTD_void,
ACC_PUBLIC | ClassFile.ACC_STATIC,
cob -> {
cob.return_();
});
}
});
} catch (ClinitAlreadyExistsException e) {
return null;
}
}

@CEntryPoint
@CEntryPointOptions(prologue = AgentIsolate.Prologue.class)
@SuppressWarnings("unused")
Expand Down
Loading