Skip to content

Commit 0416f59

Browse files
committed
added JVMCI support for parameter annotations
1 parent d5fc1ae commit 0416f59

File tree

17 files changed

+308
-96
lines changed

17 files changed

+308
-96
lines changed

src/hotspot/share/classfile/vmSymbols.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -706,7 +706,7 @@ class SerializeClosure;
706706
template(encodeThrowable_signature, "(Ljava/lang/Throwable;JI)I") \
707707
template(decodeAndThrowThrowable_name, "decodeAndThrowThrowable") \
708708
template(encodeAnnotations_name, "encodeAnnotations") \
709-
template(encodeAnnotations_signature, "([BZLjava/lang/Class;Ljdk/internal/reflect/ConstantPool;[Ljava/lang/Class;)[B")\
709+
template(encodeAnnotations_signature, "([BILjava/lang/Class;Ljdk/internal/reflect/ConstantPool;[Ljava/lang/Class;)[B")\
710710
template(decodeAndThrowThrowable_signature, "(IJZZ)V") \
711711
template(classRedefinedCount_name, "classRedefinedCount") \
712712
template(classLoader_name, "classLoader") \

src/hotspot/share/jvmci/jvmciCompilerToVM.cpp

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3015,7 +3015,7 @@ C2V_VMENTRY_NULL(jobject, asReflectionField, (JNIEnv* env, jobject, ARGUMENT_PAI
30153015
C2V_END
30163016

30173017
static jbyteArray get_encoded_annotation_values(InstanceKlass* holder, AnnotationArray* annotations_array,
3018-
jboolean is_type_annotations,
3018+
jint category,
30193019
jint filter_length, jlong filter_klass_pointers,
30203020
JavaThread* THREAD, JVMCI_TRAPS) {
30213021
// Get a ConstantPool object for annotation parsing
@@ -3050,7 +3050,7 @@ static jbyteArray get_encoded_annotation_values(InstanceKlass* holder, Annotatio
30503050
JavaValue result(T_OBJECT);
30513051
JavaCallArguments args;
30523052
args.push_oop(annotations);
3053-
args.push_int(is_type_annotations);
3053+
args.push_int(category);
30543054
args.push_oop(Handle(THREAD, holder->java_mirror()));
30553055
args.push_oop(jcp);
30563056
args.push_oop(filter_classes);
@@ -3081,29 +3081,54 @@ static jbyteArray get_encoded_annotation_values(InstanceKlass* holder, Annotatio
30813081
return JVMCIENV->get_jbyteArray(ba_dest);
30823082
}
30833083

3084-
C2V_VMENTRY_NULL(jbyteArray, getEncodedClassAnnotationValues, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass), jboolean is_type_annotations,
3084+
C2V_VMENTRY_NULL(jbyteArray, getEncodedClassAnnotationValues, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass), jint category,
30853085
jobject filter, jint filter_length, jlong filter_klass_pointers))
30863086
CompilerThreadCanCallJava canCallJava(thread, true); // Requires Java support
30873087
InstanceKlass* holder = InstanceKlass::cast(UNPACK_PAIR(Klass, klass));
3088-
AnnotationArray* raw_annotations = is_type_annotations ? holder->class_type_annotations() : holder->class_annotations();
3089-
return get_encoded_annotation_values(holder, raw_annotations, is_type_annotations, filter_length, filter_klass_pointers, THREAD, JVMCIENV);
3088+
AnnotationArray* raw_annotations;
3089+
if (category == CompilerToVM::DECLARED_ANNOTATIONS) {
3090+
raw_annotations = holder->class_annotations();
3091+
} else if (category == CompilerToVM::TYPE_ANNOTATIONS) {
3092+
raw_annotations = holder->class_type_annotations();
3093+
} else {
3094+
THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(),
3095+
err_msg("%d", category));
3096+
}
3097+
return get_encoded_annotation_values(holder, raw_annotations, category, filter_length, filter_klass_pointers, THREAD, JVMCIENV);
30903098
C2V_END
30913099

3092-
C2V_VMENTRY_NULL(jbyteArray, getEncodedExecutableAnnotationValues, (JNIEnv* env, jobject, ARGUMENT_PAIR(method), jboolean is_type_annotations,
3100+
C2V_VMENTRY_NULL(jbyteArray, getEncodedExecutableAnnotationValues, (JNIEnv* env, jobject, ARGUMENT_PAIR(method), jint category,
30933101
jobject filter, jint filter_length, jlong filter_klass_pointers))
30943102
CompilerThreadCanCallJava canCallJava(thread, true); // Requires Java support
30953103
methodHandle method(THREAD, UNPACK_PAIR(Method, method));
3096-
AnnotationArray* raw_annotations = is_type_annotations ? method->type_annotations() : method->annotations();
3097-
return get_encoded_annotation_values(method->method_holder(), raw_annotations, is_type_annotations, filter_length, filter_klass_pointers, THREAD, JVMCIENV);
3104+
AnnotationArray* raw_annotations;
3105+
if (category == CompilerToVM::DECLARED_ANNOTATIONS) {
3106+
raw_annotations = method->annotations();
3107+
} else if (category == CompilerToVM::PARAMETER_ANNOTATIONS) {
3108+
raw_annotations = method->parameter_annotations();
3109+
} else if (category == CompilerToVM::TYPE_ANNOTATIONS) {
3110+
raw_annotations = method->type_annotations();
3111+
} else {
3112+
THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), err_msg("%d", category));
3113+
}
3114+
return get_encoded_annotation_values(method->method_holder(), raw_annotations, category, filter_length, filter_klass_pointers, THREAD, JVMCIENV);
30983115
C2V_END
30993116

3100-
C2V_VMENTRY_NULL(jbyteArray, getEncodedFieldAnnotationValues, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass), jint index, jboolean is_type_annotations,
3117+
C2V_VMENTRY_NULL(jbyteArray, getEncodedFieldAnnotationValues, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass), jint index, jint category,
31013118
jobject filter, jint filter_length, jlong filter_klass_pointers))
31023119
CompilerThreadCanCallJava canCallJava(thread, true); // Requires Java support
31033120
InstanceKlass* holder = check_field(InstanceKlass::cast(UNPACK_PAIR(Klass, klass)), index, JVMCI_CHECK_NULL);
31043121
fieldDescriptor fd(holder, index);
3105-
AnnotationArray* raw_annotations = is_type_annotations ? fd.type_annotations() : fd.annotations();
3106-
return get_encoded_annotation_values(holder, raw_annotations, is_type_annotations, filter_length, filter_klass_pointers, THREAD, JVMCIENV);
3122+
AnnotationArray* raw_annotations;
3123+
if (category == CompilerToVM::DECLARED_ANNOTATIONS) {
3124+
raw_annotations = fd.annotations();
3125+
} else if (category == CompilerToVM::TYPE_ANNOTATIONS) {
3126+
raw_annotations = fd.type_annotations();
3127+
} else {
3128+
THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(),
3129+
err_msg("%d", category));
3130+
}
3131+
return get_encoded_annotation_values(holder, raw_annotations, category, filter_length, filter_klass_pointers, THREAD, JVMCIENV);
31073132
C2V_END
31083133

31093134
C2V_VMENTRY_NULL(jobjectArray, getFailedSpeculations, (JNIEnv* env, jobject, jlong failed_speculations_address, jobjectArray current))
@@ -3447,9 +3472,9 @@ JNINativeMethod CompilerToVM::methods[] = {
34473472
{CC "getCode", CC "(" HS_INSTALLED_CODE ")[B", FN_PTR(getCode)},
34483473
{CC "asReflectionExecutable", CC "(" HS_METHOD2 ")" REFLECTION_EXECUTABLE, FN_PTR(asReflectionExecutable)},
34493474
{CC "asReflectionField", CC "(" HS_KLASS2 "I)" REFLECTION_FIELD, FN_PTR(asReflectionField)},
3450-
{CC "getEncodedClassAnnotationValues", CC "(" HS_KLASS2 "Z" OBJECT "IJ)[B", FN_PTR(getEncodedClassAnnotationValues)},
3451-
{CC "getEncodedExecutableAnnotationValues", CC "(" HS_METHOD2 "Z" OBJECT "IJ)[B", FN_PTR(getEncodedExecutableAnnotationValues)},
3452-
{CC "getEncodedFieldAnnotationValues", CC "(" HS_KLASS2 "IZ" OBJECT "IJ)[B", FN_PTR(getEncodedFieldAnnotationValues)},
3475+
{CC "getEncodedClassAnnotationValues", CC "(" HS_KLASS2 "I" OBJECT "IJ)[B", FN_PTR(getEncodedClassAnnotationValues)},
3476+
{CC "getEncodedExecutableAnnotationValues", CC "(" HS_METHOD2 "I" OBJECT "IJ)[B", FN_PTR(getEncodedExecutableAnnotationValues)},
3477+
{CC "getEncodedFieldAnnotationValues", CC "(" HS_KLASS2 "II" OBJECT "IJ)[B", FN_PTR(getEncodedFieldAnnotationValues)},
34533478
{CC "getFailedSpeculations", CC "(J[[B)[[B", FN_PTR(getFailedSpeculations)},
34543479
{CC "getFailedSpeculationsAddress", CC "(" HS_METHOD2 ")J", FN_PTR(getFailedSpeculationsAddress)},
34553480
{CC "releaseFailedSpeculations", CC "(J)V", FN_PTR(releaseFailedSpeculations)},

src/hotspot/share/jvmci/jvmciCompilerToVM.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ class JVMCIObjectArray;
3535

3636
class CompilerToVM {
3737
public:
38+
// Keep in sync with constants in VMSupport.java
39+
static const int DECLARED_ANNOTATIONS = 0;
40+
static const int PARAMETER_ANNOTATIONS = 1;
41+
static const int TYPE_ANNOTATIONS = 2;
42+
3843
class Data {
3944
friend class JVMCIVMStructs;
4045

src/hotspot/share/jvmci/jvmciJavaClasses.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@ void JNIJVMCI::initialize_field_id(JNIEnv* env, jfieldID &fieldid, jclass clazz,
403403
GET_JNI_CONSTRUCTOR(className, signature)
404404

405405
extern "C" {
406-
void JNICALL JVM_RegisterJVMCINatives(JNIEnv *env, jclass compilerToVMClass);
406+
void JNICALL JVM_RegisterJVMCINatives(JNIEnv *env, jclass compilerToVMClass, jint declaredAnnotations, jint parameterAnnotations, jint typeAnnotations);
407407
jobject JNICALL JVM_GetJVMCIRuntime(JNIEnv *env, jclass c);
408408
jlong JNICALL JVM_ReadSystemPropertiesInfo(JNIEnv *env, jclass c, jintArray offsets_handle);
409409
}

src/hotspot/share/jvmci/jvmciRuntime.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1512,9 +1512,14 @@ JVMCIObject JVMCIRuntime::get_HotSpotJVMCIRuntime(JVMCI_TRAPS) {
15121512

15131513
// Implementation of CompilerToVM.registerNatives()
15141514
// When called from libjvmci, `libjvmciOrHotspotEnv` is a libjvmci env so use JVM_ENTRY_NO_ENV.
1515-
JVM_ENTRY_NO_ENV(void, JVM_RegisterJVMCINatives(JNIEnv *libjvmciOrHotspotEnv, jclass c2vmClass))
1515+
JVM_ENTRY_NO_ENV(void, JVM_RegisterJVMCINatives(JNIEnv *libjvmciOrHotspotEnv, jclass c2vmClass,
1516+
jint declaredAnnotations, jint parameterAnnotations, jint typeAnnotations))
15161517
JVMCIENV_FROM_JNI(thread, libjvmciOrHotspotEnv);
15171518

1519+
assert(CompilerToVM::DECLARED_ANNOTATIONS == declaredAnnotations, "%d != %d", CompilerToVM::DECLARED_ANNOTATIONS, declaredAnnotations);
1520+
assert(CompilerToVM::PARAMETER_ANNOTATIONS == parameterAnnotations, "%d != %d", CompilerToVM::PARAMETER_ANNOTATIONS, parameterAnnotations);
1521+
assert(CompilerToVM::TYPE_ANNOTATIONS == typeAnnotations, "%d != %d", CompilerToVM::TYPE_ANNOTATIONS, typeAnnotations);
1522+
15181523
if (!EnableJVMCI) {
15191524
JVMCI_THROW_MSG(InternalError, JVMCI_NOT_ENABLED_ERROR_MESSAGE);
15201525
}

src/hotspot/share/prims/nativeLookup.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ extern "C" {
210210
#if INCLUDE_JVMCI
211211
jobject JNICALL JVM_GetJVMCIRuntime(JNIEnv *env, jclass c);
212212
jlong JNICALL JVM_ReadSystemPropertiesInfo(JNIEnv *env, jclass c, jintArray offsets);
213-
void JNICALL JVM_RegisterJVMCINatives(JNIEnv *env, jclass compilerToVMClass);
213+
void JNICALL JVM_RegisterJVMCINatives(JNIEnv *env, jclass compilerToVMClass, jint declaredAnnotations, jint parameterAnnotations, jint typeAnnotations);
214214
#endif
215215
}
216216

src/java.base/share/classes/jdk/internal/vm/VMSupport.java

Lines changed: 99 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -186,31 +186,58 @@ public static int encodeThrowable(Throwable throwable, long buffer, int bufferSi
186186
}
187187

188188
/**
189-
* Parses {@code rawAnnotations} into a list of {@link Annotation}s (isTypeAnnotations == false)
190-
* or {@link TypeAnnotation}s (isTypeAnnotations == true) and then
191-
* serializes them to a byte array with {@link #encodeAnnotations(Collection)} or
192-
* {@link #encodeTypeAnnotations(TypeAnnotation[])}.
189+
* Denotes a byte array that is parsed into a {@code Annotations[]}.
190+
*/
191+
public static final int DECLARED_ANNOTATIONS = 0;
192+
193+
/**
194+
* Denotes a byte array that is parsed into a {@code Annotations[][]}.
195+
*/
196+
public static final int PARAMETER_ANNOTATIONS = 1;
197+
198+
/**
199+
* Denotes a byte array that is parsed into a {@code TypeAnnotations[]}.
200+
*/
201+
public static final int TYPE_ANNOTATIONS = 2;
202+
203+
/**
204+
* Parses {@code rawAnnotations} according to {@code category} and returns the parse
205+
* result encoded as a byte array.
206+
* <pre>
207+
* category | parse result type | decoding method
208+
* ----------------------|--------------------|------------------------------------------
209+
* DECLARED_ANNOTATIONS | Annotation[] | {@link #decodeAnnotations(byte[], AnnotationDecoder)}
210+
* PARAMETER_ANNOTATIONS | Annotation[][] | {@link #decodeAnnotations(byte[], AnnotationDecoder)}
211+
* TYPE_ANNOTATIONS | TypeAnnotation[] | {@link #decodeTypeAnnotations(byte[], AnnotationDecoder)}
212+
* </pre>
213+
*
214+
* @param category {@link #DECLARED_ANNOTATIONS}, {@link #PARAMETER_ANNOTATIONS} or {@link #TYPE_ANNOTATIONS}
193215
*/
194216
public static byte[] encodeAnnotations(byte[] rawAnnotations,
195-
boolean isTypeAnnotations,
217+
int category,
196218
Class<?> declaringClass,
197219
ConstantPool cp,
198220
Class<? extends Annotation>[] selectAnnotationClasses) {
199-
if (!isTypeAnnotations && selectAnnotationClasses != null) {
200-
if (selectAnnotationClasses.length == 0) {
201-
throw new IllegalArgumentException("annotation class selection must be null or non-empty");
202-
}
203-
for (Class<?> c : selectAnnotationClasses) {
204-
if (!c.isAnnotation()) {
205-
throw new IllegalArgumentException(c + " is not an annotation interface");
221+
return switch (category) {
222+
case DECLARED_ANNOTATIONS -> {
223+
if (selectAnnotationClasses != null) {
224+
if (selectAnnotationClasses.length == 0) {
225+
throw new IllegalArgumentException("annotation class selection must be null or non-empty");
226+
}
227+
for (Class<?> c : selectAnnotationClasses) {
228+
if (!c.isAnnotation()) {
229+
throw new IllegalArgumentException(c + " is not an annotation interface");
230+
}
231+
}
206232
}
233+
yield encodeAnnotations(AnnotationParser.parseSelectAnnotations(rawAnnotations, cp, declaringClass, false, selectAnnotationClasses).values());
207234
}
208-
}
209-
if (isTypeAnnotations) {
210-
return encodeTypeAnnotations(TypeAnnotationParser.parseTypeAnnotations(rawAnnotations, cp, null, false, declaringClass));
211-
} else {
212-
return encodeAnnotations(AnnotationParser.parseSelectAnnotations(rawAnnotations, cp, declaringClass, false, selectAnnotationClasses).values());
213-
}
235+
case PARAMETER_ANNOTATIONS ->
236+
encodeParameterAnnotations(AnnotationParser.parseParameterAnnotations(rawAnnotations, cp, declaringClass));
237+
case TYPE_ANNOTATIONS ->
238+
encodeTypeAnnotations(TypeAnnotationParser.parseTypeAnnotations(rawAnnotations, cp, null, false, declaringClass));
239+
default -> throw new IllegalArgumentException("illegal category: " + category);
240+
};
214241
}
215242

216243
/**
@@ -231,6 +258,27 @@ public static byte[] encodeAnnotations(Collection<Annotation> annotations) {
231258
}
232259
}
233260

261+
/**
262+
* Encodes parameter annotations to a byte array. The byte array can be decoded with {@link #decodeParameterAnnotations(byte[], AnnotationDecoder)}.
263+
*/
264+
public static byte[] encodeParameterAnnotations(Annotation[][] parameterAnnotations) {
265+
try {
266+
ByteArrayOutputStream baos = new ByteArrayOutputStream(128);
267+
try (DataOutputStream dos = new DataOutputStream(baos)) {
268+
writeLength(dos, parameterAnnotations.length);
269+
for (Annotation[] annotations : parameterAnnotations) {
270+
writeLength(dos, annotations.length);
271+
for (Annotation a : annotations) {
272+
encodeAnnotation(dos, a);
273+
}
274+
}
275+
}
276+
return baos.toByteArray();
277+
} catch (Exception e) {
278+
throw new InternalError(e);
279+
}
280+
}
281+
234282
private static void encodeAnnotation(DataOutputStream dos, Annotation a) throws Exception {
235283
Class<? extends Annotation> type = a.annotationType();
236284
Map<String, Object> values = AnnotationSupport.memberValues(a);
@@ -433,10 +481,9 @@ private static void encodeTypeAnnotation(DataOutputStream dos, TypeAnnotation ta
433481
dos.writeInt(ti.getCount());
434482
dos.writeInt(ti.getSecondaryIndex());
435483
TypeAnnotation.LocationInfo li = ta.getLocationInfo();
436-
int depth = li.getDepth();
437-
dos.writeInt(depth);
438-
for (int i = 0; i < depth; i++) {
439-
TypeAnnotation.LocationInfo.Location loc = li.getLocationAt(i);
484+
List<TypeAnnotation.LocationInfo.Location> locs = li.getLocations();
485+
dos.writeInt(locs.size());
486+
for (TypeAnnotation.LocationInfo.Location loc : locs) {
440487
dos.write(loc.tag);
441488
dos.writeShort(loc.index);
442489
}
@@ -528,12 +575,40 @@ public static <T, A, TA, E, EA, MT, ETM> List<A> decodeAnnotations(byte[] encode
528575
}
529576
}
530577

578+
/**
579+
* Decodes parameter annotations serialized in {@code encoded} to objects.
580+
*
581+
* @param <T> type to which a type name is resolved
582+
* @param <A> type of the object representing a decoded annotation
583+
* @param <E> type of the object representing a decoded enum constant
584+
* @param <MT> type of the object representing a missing type
585+
* @param <ETM> type of the object representing a decoded element type mismatch
586+
* @return an immutable list of immutable lists of {@code A} objects
587+
*/
588+
@SuppressWarnings("unchecked")
589+
public static <T, A, TA, E, EA, MT, ETM> List<List<A>> decodeParameterAnnotations(byte[] encoded, AnnotationDecoder<T, A, TA, E, EA, MT, ETM> decoder) {
590+
try {
591+
ByteArrayInputStream bais = new ByteArrayInputStream(encoded);
592+
DataInputStream dis = new DataInputStream(bais);
593+
return (List<List<A>>) readArray(dis, () -> decodeAnnotations(dis, decoder));
594+
} catch (Exception e) {
595+
throw new InternalError(e);
596+
}
597+
}
598+
@SuppressWarnings({"unchecked"})
599+
private static <T, A, TA, E, EA, MT, ETM> List<A> decodeAnnotations(DataInputStream dis, AnnotationDecoder<T, A, TA, E, EA, MT, ETM> decoder) throws IOException {
600+
return (List<A>) readArray(dis, () -> decodeAnnotation(dis, decoder));
601+
}
602+
603+
@SuppressWarnings("rawtypes")
604+
private static final Map.Entry[] NO_ELEMENTS = {};
605+
531606
@SuppressWarnings({"rawtypes", "unchecked"})
532607
private static <T, A, TA, E, EA, MT, ETM> A decodeAnnotation(DataInputStream dis, AnnotationDecoder<T, A, TA, E, EA, MT, ETM> decoder) throws IOException {
533608
String typeName = dis.readUTF();
534609
T type = decoder.resolveType(typeName);
535610
int n = readLength(dis);
536-
Map.Entry[] elements = new Map.Entry[n];
611+
Map.Entry[] elements = n == 0 ? NO_ELEMENTS : new Map.Entry[n];
537612
for (int i = 0; i < n; i++) {
538613
String name = dis.readUTF();
539614
byte tag = dis.readByte();
@@ -681,7 +756,7 @@ private static <T, A, TA, E, EA, MT, ETM> TA decodeTypeAnnotation(DataInputStrea
681756
for (int i = 0; i != depth; i++) {
682757
locs[i] = new TypeAnnotation.LocationInfo.Location(dis.readByte(), dis.readShort());
683758
}
684-
li = new TypeAnnotation.LocationInfo(depth, locs);
759+
li = new TypeAnnotation.LocationInfo(locs);
685760
}
686761
A annotation = decodeAnnotation(dis, decoder);
687762
return decoder.newTypeAnnotation(ti, li, annotation);

0 commit comments

Comments
 (0)