Skip to content

Commit 2187a71

Browse files
committed
added JVMCI support for type annotations
1 parent c7cc21e commit 2187a71

File tree

22 files changed

+628
-152
lines changed

22 files changed

+628
-152
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, "([BLjava/lang/Class;Ljdk/internal/reflect/ConstantPool;[Ljava/lang/Class;)[B")\
709+
template(encodeAnnotations_signature, "([BZLjava/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: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3015,6 +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,
30183019
jint filter_length, jlong filter_klass_pointers,
30193020
JavaThread* THREAD, JVMCI_TRAPS) {
30203021
// Get a ConstantPool object for annotation parsing
@@ -3049,6 +3050,7 @@ static jbyteArray get_encoded_annotation_values(InstanceKlass* holder, Annotatio
30493050
JavaValue result(T_OBJECT);
30503051
JavaCallArguments args;
30513052
args.push_oop(annotations);
3053+
args.push_int(is_type_annotations);
30523054
args.push_oop(Handle(THREAD, holder->java_mirror()));
30533055
args.push_oop(jcp);
30543056
args.push_oop(filter_classes);
@@ -3079,26 +3081,29 @@ static jbyteArray get_encoded_annotation_values(InstanceKlass* holder, Annotatio
30793081
return JVMCIENV->get_jbyteArray(ba_dest);
30803082
}
30813083

3082-
C2V_VMENTRY_NULL(jbyteArray, getEncodedClassAnnotationValues, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass),
3084+
C2V_VMENTRY_NULL(jbyteArray, getEncodedClassAnnotationValues, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass), jboolean is_type_annotations,
30833085
jobject filter, jint filter_length, jlong filter_klass_pointers))
30843086
CompilerThreadCanCallJava canCallJava(thread, true); // Requires Java support
30853087
InstanceKlass* holder = InstanceKlass::cast(UNPACK_PAIR(Klass, klass));
3086-
return get_encoded_annotation_values(holder, holder->class_annotations(), filter_length, filter_klass_pointers, THREAD, JVMCIENV);
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);
30873090
C2V_END
30883091

3089-
C2V_VMENTRY_NULL(jbyteArray, getEncodedExecutableAnnotationValues, (JNIEnv* env, jobject, ARGUMENT_PAIR(method),
3092+
C2V_VMENTRY_NULL(jbyteArray, getEncodedExecutableAnnotationValues, (JNIEnv* env, jobject, ARGUMENT_PAIR(method), jboolean is_type_annotations,
30903093
jobject filter, jint filter_length, jlong filter_klass_pointers))
30913094
CompilerThreadCanCallJava canCallJava(thread, true); // Requires Java support
30923095
methodHandle method(THREAD, UNPACK_PAIR(Method, method));
3093-
return get_encoded_annotation_values(method->method_holder(), method->annotations(), filter_length, filter_klass_pointers, THREAD, JVMCIENV);
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);
30943098
C2V_END
30953099

3096-
C2V_VMENTRY_NULL(jbyteArray, getEncodedFieldAnnotationValues, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass), jint index,
3100+
C2V_VMENTRY_NULL(jbyteArray, getEncodedFieldAnnotationValues, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass), jint index, jboolean is_type_annotations,
30973101
jobject filter, jint filter_length, jlong filter_klass_pointers))
30983102
CompilerThreadCanCallJava canCallJava(thread, true); // Requires Java support
30993103
InstanceKlass* holder = check_field(InstanceKlass::cast(UNPACK_PAIR(Klass, klass)), index, JVMCI_CHECK_NULL);
31003104
fieldDescriptor fd(holder, index);
3101-
return get_encoded_annotation_values(holder, fd.annotations(), filter_length, filter_klass_pointers, THREAD, JVMCIENV);
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);
31023107
C2V_END
31033108

31043109
C2V_VMENTRY_NULL(jobjectArray, getFailedSpeculations, (JNIEnv* env, jobject, jlong failed_speculations_address, jobjectArray current))
@@ -3442,9 +3447,9 @@ JNINativeMethod CompilerToVM::methods[] = {
34423447
{CC "getCode", CC "(" HS_INSTALLED_CODE ")[B", FN_PTR(getCode)},
34433448
{CC "asReflectionExecutable", CC "(" HS_METHOD2 ")" REFLECTION_EXECUTABLE, FN_PTR(asReflectionExecutable)},
34443449
{CC "asReflectionField", CC "(" HS_KLASS2 "I)" REFLECTION_FIELD, FN_PTR(asReflectionField)},
3445-
{CC "getEncodedClassAnnotationValues", CC "(" HS_KLASS2 OBJECT "IJ)[B", FN_PTR(getEncodedClassAnnotationValues)},
3446-
{CC "getEncodedExecutableAnnotationValues", CC "(" HS_METHOD2 OBJECT "IJ)[B", FN_PTR(getEncodedExecutableAnnotationValues)},
3447-
{CC "getEncodedFieldAnnotationValues", CC "(" HS_KLASS2 "I" OBJECT "IJ)[B", FN_PTR(getEncodedFieldAnnotationValues)},
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)},
34483453
{CC "getFailedSpeculations", CC "(J[[B)[[B", FN_PTR(getFailedSpeculations)},
34493454
{CC "getFailedSpeculationsAddress", CC "(" HS_METHOD2 ")J", FN_PTR(getFailedSpeculationsAddress)},
34503455
{CC "releaseFailedSpeculations", CC "(J)V", FN_PTR(releaseFailedSpeculations)},

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

Lines changed: 102 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
import sun.reflect.annotation.AnnotationTypeMismatchExceptionProxy;
3232
import sun.reflect.annotation.EnumValue;
3333
import sun.reflect.annotation.EnumValueArray;
34+
import sun.reflect.annotation.TypeAnnotation;
35+
import sun.reflect.annotation.TypeAnnotationParser;
3436
import sun.reflect.annotation.TypeNotPresentExceptionProxy;
3537

3638
import java.io.ByteArrayInputStream;
@@ -184,14 +186,17 @@ public static int encodeThrowable(Throwable throwable, long buffer, int bufferSi
184186
}
185187

186188
/**
187-
* Parses {@code rawAnnotations} into a list of {@link Annotation}s and then
188-
* serializes them to a byte array with {@link #encodeAnnotations(Collection)}.
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[])}.
189193
*/
190194
public static byte[] encodeAnnotations(byte[] rawAnnotations,
195+
boolean isTypeAnnotations,
191196
Class<?> declaringClass,
192197
ConstantPool cp,
193198
Class<? extends Annotation>[] selectAnnotationClasses) {
194-
if (selectAnnotationClasses != null) {
199+
if (!isTypeAnnotations && selectAnnotationClasses != null) {
195200
if (selectAnnotationClasses.length == 0) {
196201
throw new IllegalArgumentException("annotation class selection must be null or non-empty");
197202
}
@@ -201,7 +206,11 @@ public static byte[] encodeAnnotations(byte[] rawAnnotations,
201206
}
202207
}
203208
}
204-
return encodeAnnotations(AnnotationParser.parseSelectAnnotations(rawAnnotations, cp, declaringClass, false, selectAnnotationClasses).values());
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+
}
205214
}
206215

207216
/**
@@ -399,18 +408,54 @@ private static void encodeAnnotation(DataOutputStream dos, Annotation a) throws
399408
}
400409
}
401410

411+
/**
412+
* Encodes typeAnnotations to a byte array. The byte array can be decoded with {@link #decodeAnnotations(byte[], AnnotationDecoder)}.
413+
*/
414+
public static byte[] encodeTypeAnnotations(TypeAnnotation[] typeAnnotations) {
415+
try {
416+
ByteArrayOutputStream baos = new ByteArrayOutputStream(128);
417+
try (DataOutputStream dos = new DataOutputStream(baos)) {
418+
writeLength(dos, typeAnnotations.length);
419+
for (TypeAnnotation ta : typeAnnotations) {
420+
encodeTypeAnnotation(dos, ta);
421+
}
422+
}
423+
return baos.toByteArray();
424+
} catch (Exception e) {
425+
throw new InternalError(e);
426+
}
427+
}
428+
429+
private static void encodeTypeAnnotation(DataOutputStream dos, TypeAnnotation ta) throws Exception {
430+
TypeAnnotation.TypeAnnotationTargetInfo ti = ta.getTargetInfo();
431+
TypeAnnotation.TypeAnnotationTarget target = ti.getTarget();
432+
dos.writeUTF(target.name());
433+
dos.writeInt(ti.getCount());
434+
dos.writeInt(ti.getSecondaryIndex());
435+
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);
440+
dos.write(loc.tag);
441+
dos.writeShort(loc.index);
442+
}
443+
encodeAnnotation(dos, ta.getAnnotation());
444+
}
445+
402446
/**
403447
* Helper for {@link #decodeAnnotations(byte[], AnnotationDecoder)} to convert a byte
404448
* array (ostensibly produced by {@link VMSupport#encodeAnnotations}) into objects.
405449
*
406450
* @param <T> type to which a type name is {@linkplain #resolveType(String) resolved}
407451
* @param <A> type of the object representing a decoded annotation
452+
* @param <TA> type of the object representing a decoded type annotation
408453
* @param <E> type of the object representing a decoded enum constant
409454
* @param <EA> type of the object representing a decoded array of enum constants
410455
* @param <MT> type of the object representing a missing type
411456
* @param <ETM> type of the object representing a decoded element type mismatch
412457
*/
413-
public interface AnnotationDecoder<T, A, E, EA, MT, ETM> {
458+
public interface AnnotationDecoder<T, A, TA, E, EA, MT, ETM> {
414459
/**
415460
* Resolves a name in {@link Class#getName()} format to an object of type {@code T}.
416461
*/
@@ -424,6 +469,11 @@ public interface AnnotationDecoder<T, A, E, EA, MT, ETM> {
424469
*/
425470
A newAnnotation(T type, Map.Entry<String, Object>[] elements);
426471

472+
/**
473+
* Creates an object representing a decoded type annotation.
474+
*/
475+
TA newTypeAnnotation(TypeAnnotation.TypeAnnotationTargetInfo targetInfo, TypeAnnotation.LocationInfo locationInfo, A annotation);
476+
427477
/**
428478
* Creates an object representing a decoded enum.
429479
*
@@ -468,7 +518,7 @@ public interface AnnotationDecoder<T, A, E, EA, MT, ETM> {
468518
* @return an immutable list of {@code A} objects
469519
*/
470520
@SuppressWarnings("unchecked")
471-
public static <T, A, E, EA, MT, ETM> List<A> decodeAnnotations(byte[] encoded, AnnotationDecoder<T, A, E, EA, MT, ETM> decoder) {
521+
public static <T, A, TA, E, EA, MT, ETM> List<A> decodeAnnotations(byte[] encoded, AnnotationDecoder<T, A, TA, E, EA, MT, ETM> decoder) {
472522
try {
473523
ByteArrayInputStream bais = new ByteArrayInputStream(encoded);
474524
DataInputStream dis = new DataInputStream(bais);
@@ -479,7 +529,7 @@ public static <T, A, E, EA, MT, ETM> List<A> decodeAnnotations(byte[] encoded, A
479529
}
480530

481531
@SuppressWarnings({"rawtypes", "unchecked"})
482-
private static <T, A, E, EA, MT, ETM> A decodeAnnotation(DataInputStream dis, AnnotationDecoder<T, A, E, EA, MT, ETM> decoder) throws IOException {
532+
private static <T, A, TA, E, EA, MT, ETM> A decodeAnnotation(DataInputStream dis, AnnotationDecoder<T, A, TA, E, EA, MT, ETM> decoder) throws IOException {
483533
String typeName = dis.readUTF();
484534
T type = decoder.resolveType(typeName);
485535
int n = readLength(dis);
@@ -508,12 +558,13 @@ private static <T, A, E, EA, MT, ETM> A decodeAnnotation(DataInputStream dis, An
508558
}
509559
return decoder.newAnnotation(type, (Map.Entry<String, Object>[]) elements);
510560
}
561+
511562
@FunctionalInterface
512563
interface IOReader {
513564
Object read() throws IOException;
514565
}
515566

516-
private static <T, A, E, EA, MT, ETM> Object decodeArray(DataInputStream dis, AnnotationDecoder<T, A, E, EA, MT, ETM> decoder) throws IOException {
567+
private static <T, A, TA, E, EA, MT, ETM> Object decodeArray(DataInputStream dis, AnnotationDecoder<T, A, TA, E, EA, MT, ETM> decoder) throws IOException {
517568
byte componentTag = dis.readByte();
518569
return switch (componentTag) {
519570
case 'B' -> readArray(dis, dis::readByte);
@@ -540,7 +591,7 @@ private static <T, A, E, EA, MT, ETM> Object decodeArray(DataInputStream dis, An
540591
* returns it as an object of type {@code E}.
541592
*/
542593
@SuppressWarnings("unchecked")
543-
private static <T, A, E, EA, MT, ETM> EA readEnumArray(DataInputStream dis, AnnotationDecoder<T, A, E, EA, MT, ETM> decoder, T enumType) throws IOException {
594+
private static <T, A, TA, E, EA, MT, ETM> EA readEnumArray(DataInputStream dis, AnnotationDecoder<T, A, TA, E, EA, MT, ETM> decoder, T enumType) throws IOException {
544595
List<String> names = (List<String>) readArray(dis, dis::readUTF);
545596
return decoder.newEnumArray(enumType, names);
546597
}
@@ -549,7 +600,7 @@ private static <T, A, E, EA, MT, ETM> EA readEnumArray(DataInputStream dis, Anno
549600
* Reads a class encoded at the current read position of {@code dis} and
550601
* returns it as an object of type {@code T}.
551602
*/
552-
private static <T, A, E, EA, MT, ETM> T readClass(DataInputStream dis, AnnotationDecoder<T, A, E, EA, MT, ETM> decoder) throws IOException {
603+
private static <T, A, TA, E, EA, MT, ETM> T readClass(DataInputStream dis, AnnotationDecoder<T, A, TA, E, EA, MT, ETM> decoder) throws IOException {
553604
return decoder.resolveType(dis.readUTF());
554605
}
555606

@@ -594,4 +645,45 @@ private static int readLength(DataInputStream dis) throws IOException {
594645
}
595646
return length;
596647
}
648+
649+
/**
650+
* Decodes type annotations serialized in {@code encoded} to objects.
651+
*
652+
* @param <T> type to which a type name is resolved
653+
* @param <A> type of the object representing a decoded annotation
654+
* @param <E> type of the object representing a decoded enum constant
655+
* @param <MT> type of the object representing a missing type
656+
* @param <ETM> type of the object representing a decoded element type mismatch
657+
* @return an immutable list of {@code A} objects
658+
*/
659+
@SuppressWarnings("unchecked")
660+
public static <T, A, TA, E, EA, MT, ETM> List<TA> decodeTypeAnnotations(byte[] encoded, AnnotationDecoder<T, A, TA, E, EA, MT, ETM> decoder) {
661+
try {
662+
ByteArrayInputStream bais = new ByteArrayInputStream(encoded);
663+
DataInputStream dis = new DataInputStream(bais);
664+
return (List<TA>) readArray(dis, () -> decodeTypeAnnotation(dis, decoder));
665+
} catch (Exception e) {
666+
throw new InternalError(e);
667+
}
668+
}
669+
670+
private static <T, A, TA, E, EA, MT, ETM> TA decodeTypeAnnotation(DataInputStream dis, AnnotationDecoder<T, A, TA, E, EA, MT, ETM> decoder) throws IOException {
671+
TypeAnnotation.TypeAnnotationTarget target = TypeAnnotation.TypeAnnotationTarget.valueOf(dis.readUTF());
672+
int count = dis.readInt();
673+
int secondaryIndex = dis.readInt();
674+
TypeAnnotation.TypeAnnotationTargetInfo ti = new TypeAnnotation.TypeAnnotationTargetInfo(target, count, secondaryIndex);
675+
int depth = dis.readInt();
676+
TypeAnnotation.LocationInfo li;
677+
if (depth == 0) {
678+
li = TypeAnnotation.LocationInfo.BASE_LOCATION;
679+
} else {
680+
TypeAnnotation.LocationInfo.Location[] locs = new TypeAnnotation.LocationInfo.Location[depth];
681+
for (int i = 0; i != depth; i++) {
682+
locs[i] = new TypeAnnotation.LocationInfo.Location(dis.readByte(), dis.readShort());
683+
}
684+
li = new TypeAnnotation.LocationInfo(depth, locs);
685+
}
686+
A annotation = decodeAnnotation(dis, decoder);
687+
return decoder.newTypeAnnotation(ti, li, annotation);
688+
}
597689
}

src/java.base/share/classes/module-info.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,8 @@
307307
exports sun.nio.fs to
308308
jdk.net;
309309
exports sun.reflect.annotation to
310-
jdk.compiler;
310+
jdk.compiler,
311+
jdk.internal.vm.ci;
311312
exports sun.reflect.generics.reflectiveObjects to
312313
java.desktop;
313314
exports sun.reflect.misc to

src/java.base/share/classes/sun/reflect/annotation/TypeAnnotation.java

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@
3636
* annotations on declarations in the class file to actual Annotations in
3737
* AnnotatedType instances.
3838
*
39-
* TypeAnnotaions contain a base Annotation, location info (which lets you
39+
* TypeAnnotations contain a base Annotation, location info (which lets you
4040
* distinguish between '@A Inner.@B Outer' in for example nested types),
41-
* target info and the declaration the TypeAnnotaiton was parsed from.
41+
* target info and the declaration the TypeAnnotation was parsed from.
4242
*/
4343
public final class TypeAnnotation {
4444
private final TypeAnnotationTargetInfo targetInfo;
@@ -143,11 +143,19 @@ public static final class LocationInfo {
143143
private LocationInfo() {
144144
this(0, new Location[0]);
145145
}
146-
private LocationInfo(int depth, Location[] locations) {
146+
public LocationInfo(int depth, Location[] locations) {
147147
this.depth = depth;
148148
this.locations = locations;
149149
}
150150

151+
public int getDepth() {
152+
return depth;
153+
}
154+
155+
public Location getLocationAt(int index) {
156+
return locations[index];
157+
}
158+
151159
public static final LocationInfo BASE_LOCATION = new LocationInfo();
152160

153161
public static LocationInfo parseLocationInfo(ByteBuffer buf) {
@@ -239,8 +247,8 @@ public Location(byte tag, short index) {
239247

240248
@Override
241249
public String toString() {
242-
return annotation.toString() + " with Targetnfo: " +
243-
targetInfo.toString() + " on base declaration: " +
244-
baseDeclaration.toString();
250+
return annotation + " with TargetInfo: " +
251+
targetInfo + " on base declaration: " +
252+
baseDeclaration;
245253
}
246254
}

0 commit comments

Comments
 (0)