8168915: [JVMCI] use MethodParameters attribute instead of depending on -g option for sanity checks

Reviewed-by: kvn
This commit is contained in:
Doug Simon 2016-10-29 01:09:42 +02:00
parent dd45be3f41
commit 47096d7dd1
3 changed files with 187 additions and 1 deletions

View File

@ -33,8 +33,10 @@ import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
import java.lang.annotation.Annotation;
import java.lang.reflect.Executable;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@ -459,6 +461,22 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp
return constantPool;
}
@Override
public Parameter[] getParameters() {
Executable javaMethod = toJava();
if (javaMethod == null) {
return null;
}
java.lang.reflect.Parameter[] javaParameters = javaMethod.getParameters();
Parameter[] res = new Parameter[javaParameters.length];
for (int i = 0; i < res.length; i++) {
java.lang.reflect.Parameter src = javaParameters[i];
res[i] = new Parameter(src.getName(), src.getModifiers(), this, i);
}
return res;
}
@Override
public Annotation[][] getParameterAnnotations() {
Executable javaMethod = toJava();
@ -529,13 +547,31 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp
return result;
}
private static Method searchMethods(Method[] methods, String name, Class<?> returnType, Class<?>[] parameterTypes) {
for (Method m : methods) {
if (m.getName().equals(name) && returnType.equals(m.getReturnType()) && Arrays.equals(m.getParameterTypes(), parameterTypes)) {
return m;
}
}
return null;
}
private Executable toJava() {
if (toJavaCache != null) {
return toJavaCache;
}
try {
Class<?>[] parameterTypes = signatureToTypes();
Executable result = isConstructor() ? holder.mirror().getDeclaredConstructor(parameterTypes) : holder.mirror().getDeclaredMethod(name, parameterTypes);
Class<?> returnType = ((HotSpotResolvedJavaType) getSignature().getReturnType(holder).resolve(holder)).mirror();
Executable result;
if (isConstructor()) {
result = holder.mirror().getDeclaredConstructor(parameterTypes);
} else {
// Do not use Method.getDeclaredMethod() as it can return a bridge method
// when this.isBridge() is false and vice versa.
result = searchMethods(holder.mirror().getDeclaredMethods(), name, returnType, parameterTypes);
}
toJavaCache = result;
return result;
} catch (NoSuchMethodException | NoClassDefFoundError e) {

View File

@ -26,6 +26,7 @@ import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
/**
@ -173,6 +174,133 @@ public interface ResolvedJavaMethod extends JavaMethod, InvokeTarget, ModifiersP
*/
ConstantPool getConstantPool();
/**
* A {@code Parameter} provides information about method parameters.
*/
public static class Parameter implements AnnotatedElement {
private final String name;
private final ResolvedJavaMethod method;
private final int modifiers;
private final int index;
/**
* Constructor for {@code Parameter}.
*
* @param name the name of the parameter
* @param modifiers the modifier flags for the parameter
* @param method the method which defines this parameter
* @param index the index of the parameter
*/
public Parameter(String name,
int modifiers,
ResolvedJavaMethod method,
int index) {
this.name = name;
this.modifiers = modifiers;
this.method = method;
this.index = index;
}
/**
* Gets the name of the parameter.
*/
public String getName() {
return name;
}
/**
* Gets the method declaring the parameter.
*/
public ResolvedJavaMethod getDeclaringMethod() {
return method;
}
/**
* Get the modifier flags for the parameter
*/
public int getModifiers() {
return modifiers;
}
/**
* Gets the kind of the parameter.
*/
public JavaKind getKind() {
return method.getSignature().getParameterKind(index);
}
/**
* Gets the formal type of the parameter.
*/
public Type getParameterizedType() {
return method.getGenericParameterTypes()[index];
}
/**
* Gets the type of the parameter.
*/
public JavaType getType() {
return method.getSignature().getParameterType(index, method.getDeclaringClass());
}
/**
* Determines if the parameter represents a variable argument list.
*/
public boolean isVarArgs() {
return method.isVarArgs() && index == method.getSignature().getParameterCount(false) - 1;
}
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
return method.getParameterAnnotations(annotationClass)[index];
}
public Annotation[] getAnnotations() {
return method.getParameterAnnotations()[index];
}
public Annotation[] getDeclaredAnnotations() {
return getAnnotations();
}
@Override
public String toString() {
Type type = getParameterizedType();
String typename = type.getTypeName();
if (isVarArgs()) {
typename = typename.replaceFirst("\\[\\]$", "...");
}
final StringBuilder sb = new StringBuilder(Modifier.toString(getModifiers()));
if (sb.length() != 0) {
sb.append(' ');
}
return sb.append(typename).append(' ').append(getName()).toString();
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Parameter) {
Parameter other = (Parameter) obj;
return (other.method.equals(method) && other.index == index);
}
return false;
}
@Override
public int hashCode() {
return method.hashCode() ^ index;
}
}
/**
* Returns an array of {@code Parameter} objects that represent all the parameters to this
* method. Returns an array of length 0 if this method has no parameters. Returns {@code null}
* if the parameter information is unavailable.
*/
default Parameter[] getParameters() {
return null;
}
/**
* Returns an array of arrays that represent the annotations on the formal parameters, in
* declaration order, of this method.

View File

@ -33,6 +33,7 @@
package jdk.vm.ci.runtime.test;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@ -60,6 +61,7 @@ import org.junit.Test;
import jdk.vm.ci.meta.ConstantPool;
import jdk.vm.ci.meta.ExceptionHandler;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaMethod.Parameter;
import jdk.vm.ci.meta.ResolvedJavaType;
/**
@ -266,6 +268,26 @@ public class TestResolvedJavaMethod extends MethodUniverse {
}
}
@Test
public void getParametersTest() {
for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
java.lang.reflect.Parameter[] expected = e.getKey().getParameters();
Parameter[] actual = e.getValue().getParameters();
assertEquals(actual.length, expected.length);
for (int i = 0; i < actual.length; i++) {
java.lang.reflect.Parameter exp = expected[i];
Parameter act = actual[i];
assertEquals(exp.getName(), act.getName());
assertEquals(exp.getModifiers(), act.getModifiers());
assertEquals(exp.getModifiers(), act.getModifiers());
assertArrayEquals(exp.getAnnotations(), act.getAnnotations());
assertEquals(exp.getType().getName(), act.getType().toClassName());
assertEquals(exp.getParameterizedType(), act.getParameterizedType());
assertEquals(metaAccess.lookupJavaMethod(exp.getDeclaringExecutable()), act.getDeclaringMethod());
}
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface TestAnnotation {