Skip to content

Commit 82518e3

Browse files
dougxcansalond
authored andcommitted
[GR-70912] Replace AnnotatedElement usages with AnnotatedValueSupport in the compiler.
PullRequest: graal/22421
2 parents e13880e + 75d2a3b commit 82518e3

File tree

36 files changed

+627
-122
lines changed

36 files changed

+627
-122
lines changed

compiler/mx.compiler/suite.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,6 @@
140140
"requiresConcealed" : {
141141
"java.base" : [
142142
"jdk.internal.misc",
143-
"sun.reflect.generics.parser",
144143
],
145144
"jdk.internal.vm.ci" : [
146145
"jdk.vm.ci.meta",

compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalFeature.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@
4444
import java.util.function.Consumer;
4545
import java.util.stream.Collectors;
4646

47-
import jdk.graal.compiler.serviceprovider.GraalServices;
4847
import org.graalvm.collections.EconomicMap;
4948
import org.graalvm.jniutils.NativeBridgeSupport;
5049
import org.graalvm.nativeimage.ImageInfo;
@@ -72,6 +71,7 @@
7271
import jdk.graal.compiler.options.OptionDescriptor;
7372
import jdk.graal.compiler.options.OptionKey;
7473
import jdk.graal.compiler.options.OptionsParser;
74+
import jdk.graal.compiler.serviceprovider.GraalServices;
7575
import jdk.graal.compiler.truffle.host.TruffleHostEnvironment;
7676
import jdk.graal.compiler.util.CollectionsUtil;
7777
import jdk.graal.compiler.util.EconomicHashMap;

compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/annotation/test/TestAnnotationsBase.java

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import static org.junit.Assert.assertEquals;
3030
import static org.junit.Assert.assertNull;
3131
import static org.junit.Assert.assertTrue;
32+
import static org.junit.Assert.fail;
3233

3334
import java.lang.annotation.Annotation;
3435
import java.lang.reflect.AnnotatedElement;
@@ -209,6 +210,13 @@ private static Annotated toAnnotated(AnnotatedElement element) {
209210
}
210211
}
211212

213+
/**
214+
* Used to test error handling in {@link AnnotationValue#getEnum(Class, String)}.
215+
*/
216+
enum MyEnum {
217+
}
218+
219+
@SuppressWarnings({"unchecked", "rawtypes"})
212220
public static void assertAnnotationsEquals(Annotation a, AnnotationValue av) {
213221
Map<String, Object> values = AnnotationSupport.memberValues(a);
214222
for (Map.Entry<String, Object> e : values.entrySet()) {
@@ -224,6 +232,46 @@ public static void assertAnnotationsEquals(Annotation a, AnnotationValue av) {
224232
if (!(aElement instanceof ExceptionProxy)) {
225233
Class<?> elementType = toAnnotationValueElementType(aElement.getClass());
226234
av.get(name, elementType);
235+
236+
Object actual;
237+
if (elementType == Byte.class) {
238+
actual = av.getByte(name);
239+
} else if (elementType == Boolean.class) {
240+
actual = av.getBoolean(name);
241+
} else if (elementType == Short.class) {
242+
actual = av.getShort(name);
243+
} else if (elementType == Character.class) {
244+
actual = av.getChar(name);
245+
} else if (elementType == Integer.class) {
246+
actual = av.getInt(name);
247+
} else if (elementType == Float.class) {
248+
actual = av.getFloat(name);
249+
} else if (elementType == Long.class) {
250+
actual = av.getLong(name);
251+
} else if (elementType == Double.class) {
252+
actual = av.getDouble(name);
253+
} else if (elementType == String.class) {
254+
actual = av.getString(name);
255+
} else if (elementType == ResolvedJavaType.class) {
256+
actual = av.getType(name);
257+
} else if (elementType == EnumElement.class) {
258+
actual = av.getEnum(name);
259+
Class<? extends Enum> enumClass = (Class<? extends Enum>) aElement.getClass();
260+
var avEnumConstant = av.getEnum(enumClass, name);
261+
assertEquals(aElement, avEnumConstant);
262+
try {
263+
av.getEnum(MyEnum.class, name);
264+
fail("expected " + IllegalArgumentException.class.getName());
265+
} catch (IllegalArgumentException iae) {
266+
// expected
267+
}
268+
} else if (elementType == AnnotationValue.class) {
269+
actual = av.getAnnotation(name);
270+
} else {
271+
assert elementType == List.class : aElement + " // " + elementType;
272+
actual = avElement;
273+
}
274+
assertAnnotationElementsEqual(aElement, actual);
227275
}
228276
}
229277
}

compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/annotation/test/TestAnnotationsOnMethods.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ public void getAnnotationValuesTest() throws Exception {
198198
checkAnnotationValues(AnnotationTestInput.class.getDeclaredMethod("missingMember"));
199199
List<AnnotationValue> avList = checkAnnotationValues(AnnotationTestInput.class.getDeclaredMethod("addedMember"));
200200
try {
201-
avList.getFirst().get("addedElement", Integer.class);
201+
avList.getFirst().getInt("addedElement");
202202
throw new AssertionError("expected " + IllegalArgumentException.class.getName());
203203
} catch (IllegalArgumentException e) {
204204
Assert.assertEquals(MemberAdded.class.getName() + " missing element addedElement", e.getMessage());

compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/annotation/test/TestAnnotationsOnTypes.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ public void getAnnotationValuesTest() {
102102
// Test that inherited annotations are handled properly.
103103
ResolvedJavaType namedType = metaAccess.lookupJavaType(AnnotationTestInput.Named.class);
104104
AnnotationValue av = AnnotationValueSupport.getDeclaredAnnotationValue(namedType, metaAccess.lookupJavaType(AnnotationTestInput.OwnName.class));
105-
Assert.assertEquals("NonInheritedValue", av.get("value", String.class));
105+
Assert.assertEquals("NonInheritedValue", av.getString("value"));
106106
av = getDeclaredAnnotationValue(namedType, metaAccess.lookupJavaType(AnnotationTestInput.InheritedName1.class));
107107
Assert.assertNull(av);
108108
av = getDeclaredAnnotationValue(namedType, metaAccess.lookupJavaType(AnnotationTestInput.InheritedName2.class));

compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/api/directives/test/BlackholeDirectiveTest.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,16 @@
2929
import java.lang.annotation.RetentionPolicy;
3030
import java.lang.annotation.Target;
3131

32+
import org.junit.Assert;
33+
import org.junit.Test;
34+
35+
import jdk.graal.compiler.annotation.AnnotationValue;
36+
import jdk.graal.compiler.annotation.AnnotationValueSupport;
3237
import jdk.graal.compiler.api.directives.GraalDirectives;
3338
import jdk.graal.compiler.core.test.GraalCompilerTest;
3439
import jdk.graal.compiler.nodes.ParameterNode;
3540
import jdk.graal.compiler.nodes.StructuredGraph;
3641
import jdk.graal.compiler.phases.OptimisticOptimizations;
37-
import org.junit.Assert;
38-
import org.junit.Test;
3942

4043
/**
4144
* Tests for {@link GraalDirectives#blackhole}.
@@ -137,9 +140,9 @@ protected OptimisticOptimizations getOptimisticOptimizations() {
137140

138141
@Override
139142
protected void checkLowTierGraph(StructuredGraph graph) {
140-
BlackholeSnippet snippet = graph.method().getAnnotation(BlackholeSnippet.class);
143+
AnnotationValue snippet = AnnotationValueSupport.getAnnotationValue(graph.method(), BlackholeSnippet.class);
141144
ParameterNode arg = graph.getParameter(0);
142-
if (snippet.expectParameterUsage()) {
145+
if (snippet != null && snippet.getBoolean("expectParameterUsage")) {
143146
Assert.assertNotNull("couldn't find ParameterNode(0)", arg);
144147
Assert.assertFalse("expected usages of " + arg, arg.hasNoUsages());
145148
} else {

compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/CheckGraalInvariants.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,13 @@ public boolean shouldVerifyFoldableMethods() {
215215
return true;
216216
}
217217

218+
/**
219+
* Determines if {@link VerifyAnnotatedElementUsage} is to be checked.
220+
*/
221+
public boolean shouldVerifyAnnotatedElementUsages() {
222+
return true;
223+
}
224+
218225
public void verifyCurrentTimeMillis(MetaAccessProvider meta, MethodCallTargetNode t, ResolvedJavaType declaringClass) {
219226
final ResolvedJavaType services = meta.lookupJavaType(GraalServices.class);
220227
if (!declaringClass.equals(services)) {
@@ -393,6 +400,9 @@ public static void runTest(InvariantsTool tool) {
393400
if (tool.shouldVerifyFoldableMethods()) {
394401
verifiers.add(foldableMethodsVerifier);
395402
}
403+
if (tool.shouldVerifyAnnotatedElementUsages()) {
404+
verifiers.add(new VerifyAnnotatedElementUsage());
405+
}
396406

397407
verifiers.add(new VerifyCurrentTimeMillisUsage(tool));
398408

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*
2+
* Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package jdk.graal.compiler.core.test;
26+
27+
import java.lang.reflect.AnnotatedElement;
28+
import java.lang.reflect.Method;
29+
import java.util.Map;
30+
import java.util.Set;
31+
import java.util.stream.Collectors;
32+
import java.util.stream.Stream;
33+
34+
import jdk.graal.compiler.annotation.AnnotationValueSupport;
35+
import jdk.graal.compiler.core.common.type.Stamp;
36+
import jdk.graal.compiler.nodes.NodeView;
37+
import jdk.graal.compiler.nodes.StructuredGraph;
38+
import jdk.graal.compiler.nodes.ValueNode;
39+
import jdk.graal.compiler.nodes.java.MethodCallTargetNode;
40+
import jdk.graal.compiler.nodes.spi.CoreProviders;
41+
import jdk.graal.compiler.nodes.spi.UncheckedInterfaceProvider;
42+
import jdk.graal.compiler.util.EconomicHashMap;
43+
import jdk.vm.ci.meta.MetaAccessProvider;
44+
import jdk.vm.ci.meta.ResolvedJavaField;
45+
import jdk.vm.ci.meta.ResolvedJavaMethod;
46+
import jdk.vm.ci.meta.ResolvedJavaType;
47+
48+
/**
49+
* Verifies that calls to methods declared by {@link AnnotatedElement} never have a receiver of type
50+
* {@link ResolvedJavaType}, {@link ResolvedJavaMethod} or {@link ResolvedJavaField}. Once GR-69713,
51+
* is resolved ("Remove AnnotatedElement from JVMCI types"), this verification can be deleted.
52+
*/
53+
public class VerifyAnnotatedElementUsage extends VerifyStringFormatterUsage {
54+
55+
private volatile Map<String, String> annotatedElementMethods;
56+
57+
private static final String JVMCI_META_PACKAGE_PREFIX = "L" + ResolvedJavaType.class.getPackage().getName().replace('.', '/');
58+
private static final Set<String> ANNOTATED_ELEMENT_METHOD_NAMES = Stream.of(AnnotatedElement.class.getDeclaredMethods()).map(Method::getName).collect(Collectors.toSet());
59+
60+
@Override
61+
protected void verify(StructuredGraph graph, CoreProviders context) {
62+
MetaAccessProvider metaAccess = context.getMetaAccess();
63+
ResolvedJavaType annotatedElementType = metaAccess.lookupJavaType(AnnotatedElement.class);
64+
ResolvedJavaType resolvedJavaTypeType = metaAccess.lookupJavaType(ResolvedJavaType.class);
65+
ResolvedJavaType resolvedJavaMethodType = metaAccess.lookupJavaType(ResolvedJavaMethod.class);
66+
ResolvedJavaType resolvedJavaFieldType = metaAccess.lookupJavaType(ResolvedJavaField.class);
67+
68+
if (annotatedElementMethods == null) {
69+
Map<String, String> map = new EconomicHashMap<>();
70+
for (Method m : AnnotatedElement.class.getDeclaredMethods()) {
71+
map.put(m.getName(), metaAccess.lookupJavaMethod(m).getSignature().toMethodDescriptor());
72+
}
73+
annotatedElementMethods = map;
74+
}
75+
76+
for (MethodCallTargetNode t : graph.getNodes(MethodCallTargetNode.TYPE)) {
77+
ResolvedJavaMethod callee = t.targetMethod();
78+
String descriptor = annotatedElementMethods.get(callee.getName());
79+
if (descriptor != null && descriptor.equals(callee.getSignature().toMethodDescriptor())) {
80+
if (callee.hasReceiver()) {
81+
ValueNode receiver = t.arguments().getFirst();
82+
Stamp receiverStamp = receiver.stamp(NodeView.DEFAULT);
83+
if (receiver instanceof UncheckedInterfaceProvider unchecked) {
84+
Stamp uncheckedStamp = unchecked.uncheckedStamp();
85+
if (uncheckedStamp != null) {
86+
receiverStamp = uncheckedStamp;
87+
}
88+
}
89+
ResolvedJavaType receiverType = receiverStamp.javaType(metaAccess);
90+
if (resolvedJavaTypeType.isAssignableFrom(receiverType) ||
91+
resolvedJavaMethodType.isAssignableFrom(receiverType) ||
92+
resolvedJavaFieldType.isAssignableFrom(receiverType)) {
93+
94+
throw new VerificationError(
95+
t, "call to %s with receiver type %s should be replaced by use of %s.%n",
96+
callee.format("%H.%n(%p)"),
97+
receiverType.toClassName(),
98+
AnnotationValueSupport.class.getName());
99+
}
100+
}
101+
}
102+
}
103+
}
104+
}

0 commit comments

Comments
 (0)