Skip to content

Commit 2e4d323

Browse files
committed
Implement JVM_GetClassFileVersion.
1 parent 2a04a03 commit 2e4d323

File tree

7 files changed

+54
-8
lines changed

7 files changed

+54
-8
lines changed

espresso-shared/src/com.oracle.truffle.espresso.classfile/src/com/oracle/truffle/espresso/classfile/ClassfileParser.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -636,7 +636,7 @@ private ParserKlass parseClassImpl() throws ValidationException {
636636
// Ensure there are no trailing bytes
637637
stream.checkEndOfFile();
638638

639-
return new ParserKlass(pool, classFlags, thisKlassName, thisKlassType, superKlass, superInterfaces, methods, fields, attributes, thisKlassIndex, -1);
639+
return new ParserKlass(pool, classFlags, thisKlassName, thisKlassType, superKlass, superInterfaces, methods, fields, attributes, thisKlassIndex, majorVersion, minorVersion, -1);
640640
}
641641

642642
public static Symbol<Name> getClassName(ParsingContext parsingContext, byte[] bytes) throws ValidationException {

espresso-shared/src/com.oracle.truffle.espresso.classfile/src/com/oracle/truffle/espresso/classfile/JavaVersion.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ public boolean contains(JavaVersion version) {
7777
public static final JavaVersion HOST_VERSION = forVersion(Runtime.version());
7878

7979
public static final int LATEST_SUPPORTED = 25;
80+
public static final int LATEST_SUPPORTED_CLASSFILE = ClassfileParser.JAVA_25_VERSION;
8081

8182
private final int version;
8283

espresso-shared/src/com.oracle.truffle.espresso.classfile/src/com/oracle/truffle/espresso/classfile/ParserKlass.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ public final class ParserKlass {
5959
*/
6060
private final ParserConstantPool pool;
6161

62+
private final char majorVersion;
63+
private final char minorVersion;
64+
6265
private final int thisKlassIndex;
6366
private final long hiddenKlassId;
6467

@@ -72,7 +75,11 @@ public ParserKlass(ParserConstantPool pool,
7275
ParserField[] fields,
7376
Attribute[] attributes,
7477
int thisKlassIndex,
78+
int majorVersion,
79+
int minorVersion,
7580
long hiddenKlassId) {
81+
assert majorVersion == (char) majorVersion;
82+
assert minorVersion == (char) minorVersion;
7683
this.pool = pool;
7784
this.flags = flags;
7885
this.name = name;
@@ -83,6 +90,8 @@ public ParserKlass(ParserConstantPool pool,
8390
this.fields = fields;
8491
this.attributes = attributes;
8592
this.thisKlassIndex = thisKlassIndex;
93+
this.majorVersion = (char) majorVersion;
94+
this.minorVersion = (char) minorVersion;
8695
this.hiddenKlassId = hiddenKlassId;
8796
}
8897

@@ -147,6 +156,14 @@ public long getHiddenKlassId() {
147156
return hiddenKlassId;
148157
}
149158

159+
public int getMajorVersion() {
160+
return majorVersion;
161+
}
162+
163+
public int getMinorVersion() {
164+
return minorVersion;
165+
}
166+
150167
@Override
151168
public String toString() {
152169
return "ParserKlass<" + getType() + ">";

espresso/src/com.oracle.truffle.espresso.mokapot/include/mokapot.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -361,10 +361,7 @@ typedef uint64_t julong;
361361
/* V(JVM_VirtualThreadUnmountEnd) */ \
362362
/* Java 20 VM methods */ \
363363
/* V(JVM_VirtualThreadHideFrames) */ \
364-
/* V(JVM_GetClassFileVersion) */ \
365-
V(JVM_ScopedValueCache) \
366-
V(JVM_SetScopedValueCache) \
367-
V(JVM_FindScopedValueBindings) \
364+
V(JVM_GetClassFileVersion) \
368365
/* Java 21 VM Methods */ \
369366
V(JVM_IsForeignLinkerSupported) \
370367
/* V(JVM_VirtualThreadStart) */ \
@@ -999,6 +996,8 @@ void (*JVM_ReportFinalizationComplete)(JNIEnv *env, jobject finalizee);
999996

1000997
jboolean (*JVM_IsFinalizationEnabled)(JNIEnv *env);
1001998

999+
jint (*JVM_GetClassFileVersion)(JNIEnv* env, jclass clazz);
1000+
10021001
jboolean (*JVM_IsForeignLinkerSupported)(void);
10031002

10041003
void (*JVM_SleepNanos)(JNIEnv *env, jclass threadClass, jlong nanos);

espresso/src/com.oracle.truffle.espresso.mokapot/src/mokapot.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1698,8 +1698,8 @@ JVM_TakeVirtualThreadListToUnblock(JNIEnv* env, jclass ignored) {
16981698
}
16991699

17001700
JNIEXPORT jint JNICALL JVM_GetClassFileVersion(JNIEnv *env, jclass current) {
1701-
UNIMPLEMENTED(JVM_GetClassFileVersion);
1702-
return 0;
1701+
IMPLEMENTED(JVM_GetClassFileVersion);
1702+
return (*getEnv())->JVM_GetClassFileVersion(env, current);
17031703
}
17041704

17051705
JNIEXPORT jboolean JNICALL JVM_IsForeignLinkerSupported(void) {

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/preinit/ParserKlassProvider.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,9 @@ static ParserKlass parseKlass(ClassRegistry.ClassDefinitionInfo info, ClassLoadi
7373
parserKlass.getSuperKlass(), parserKlass.getSuperInterfaces(),
7474
parserKlass.getMethods(), parserKlass.getFields(),
7575
parserKlass.getAttributes(),
76-
parserKlass.getThisKlassIndex(), parserKlass.getHiddenKlassId());
76+
parserKlass.getThisKlassIndex(),
77+
parserKlass.getMajorVersion(), parserKlass.getMinorVersion(),
78+
parserKlass.getHiddenKlassId());
7779
}
7880

7981
return parserKlass;

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/vm/VM.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@
8989
import com.oracle.truffle.espresso.classfile.ConstantPool;
9090
import com.oracle.truffle.espresso.classfile.Constants;
9191
import com.oracle.truffle.espresso.classfile.JavaKind;
92+
import com.oracle.truffle.espresso.classfile.JavaVersion;
93+
import com.oracle.truffle.espresso.classfile.ParserKlass;
9294
import com.oracle.truffle.espresso.classfile.attributes.Attribute;
9395
import com.oracle.truffle.espresso.classfile.attributes.EnclosingMethodAttribute;
9496
import com.oracle.truffle.espresso.classfile.attributes.InnerClassesAttribute;
@@ -1372,6 +1374,31 @@ public int JVM_GetClassAccessFlags(@JavaType(Class.class) StaticObject clazz) {
13721374
return klass.getModifiers() & Constants.JVM_ACC_WRITTEN_FLAGS;
13731375
}
13741376

1377+
@VmImpl(isJni = true)
1378+
public int JVM_GetClassFileVersion(@JavaType(Class.class) StaticObject clazz, @Inject SubstitutionProfiler profiler) {
1379+
if (StaticObject.isNull(clazz)) {
1380+
profiler.profile(0);
1381+
throw getMeta().throwNullPointerException();
1382+
}
1383+
/*
1384+
* From HotSpot:
1385+
*
1386+
* Return the current class's class file version. The low order 16 bits of the returned jint
1387+
* contain the class's major version. The high order 16 bits contain the class's minor
1388+
* version.
1389+
*/
1390+
Klass klass = clazz.getMirrorKlass(getMeta());
1391+
if (klass instanceof ObjectKlass objKlass) {
1392+
profiler.profile(1);
1393+
ParserKlass parser = objKlass.getLinkedKlass().getParserKlass();
1394+
return ((parser.getMinorVersion() << 16) | (parser.getMajorVersion()));
1395+
}
1396+
profiler.profile(2);
1397+
// For primitives, return latest (Same as HotSpot).
1398+
// We do the same for arrays. HotSpot just crashes in that case.
1399+
return JavaVersion.LATEST_SUPPORTED_CLASSFILE;
1400+
}
1401+
13751402
@VmImpl(isJni = true)
13761403
public boolean JVM_AreNestMates(@JavaType(Class.class) StaticObject current, @JavaType(Class.class) StaticObject member) {
13771404
return current.getMirrorKlass(getMeta()).nest() == member.getMirrorKlass(getMeta()).nest();

0 commit comments

Comments
 (0)