8296967: [JVMCI] rationalize relationship between getCodeSize and getCode in ResolvedJavaMethod
Reviewed-by: never
This commit is contained in:
parent
b3ef337566
commit
37848a9ca2
@ -1901,9 +1901,6 @@ C2V_VMENTRY_NULL(jobjectArray, getDeclaredConstructors, (JNIEnv* env, jobject, A
|
||||
}
|
||||
|
||||
InstanceKlass* iklass = InstanceKlass::cast(klass);
|
||||
// Ensure class is linked
|
||||
iklass->link_class(CHECK_NULL);
|
||||
|
||||
GrowableArray<Method*> constructors_array;
|
||||
for (int i = 0; i < iklass->methods()->length(); i++) {
|
||||
Method* m = iklass->methods()->at(i);
|
||||
@ -1931,9 +1928,6 @@ C2V_VMENTRY_NULL(jobjectArray, getDeclaredMethods, (JNIEnv* env, jobject, ARGUME
|
||||
}
|
||||
|
||||
InstanceKlass* iklass = InstanceKlass::cast(klass);
|
||||
// Ensure class is linked
|
||||
iklass->link_class(CHECK_NULL);
|
||||
|
||||
GrowableArray<Method*> methods_array;
|
||||
for (int i = 0; i < iklass->methods()->length(); i++) {
|
||||
Method* m = iklass->methods()->at(i);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -45,6 +45,9 @@ final class HotSpotProfilingInfo implements ProfilingInfo {
|
||||
HotSpotProfilingInfo(HotSpotMethodData methodData, HotSpotResolvedJavaMethod method, boolean includeNormal, boolean includeOSR) {
|
||||
this.methodData = methodData;
|
||||
this.method = method;
|
||||
if (!method.getDeclaringClass().isLinked()) {
|
||||
throw new IllegalArgumentException(method.format("%H.%n(%p) must be linked"));
|
||||
}
|
||||
this.includeNormal = includeNormal;
|
||||
this.includeOSR = includeOSR;
|
||||
this.isMature = methodData.isProfileMature();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -256,7 +256,11 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp
|
||||
|
||||
@Override
|
||||
public int getCodeSize() {
|
||||
return UNSAFE.getChar(getConstMethod() + config().constMethodCodeSizeOffset);
|
||||
int codeSize = UNSAFE.getChar(getConstMethod() + config().constMethodCodeSizeOffset);
|
||||
if (codeSize > 0 && !getDeclaringClass().isLinked()) {
|
||||
return -1;
|
||||
}
|
||||
return codeSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -996,11 +996,28 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem
|
||||
|
||||
@Override
|
||||
public ResolvedJavaMethod[] getDeclaredConstructors() {
|
||||
link();
|
||||
return runtime().compilerToVm.getDeclaredConstructors(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResolvedJavaMethod[] getDeclaredConstructors(boolean forceLink) {
|
||||
if (forceLink) {
|
||||
link();
|
||||
}
|
||||
return runtime().compilerToVm.getDeclaredConstructors(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResolvedJavaMethod[] getDeclaredMethods() {
|
||||
return getDeclaredMethods(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResolvedJavaMethod[] getDeclaredMethods(boolean forceLink) {
|
||||
if (forceLink) {
|
||||
link();
|
||||
}
|
||||
return runtime().compilerToVm.getDeclaredMethods(this);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2009, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -36,24 +36,26 @@ import java.lang.reflect.Type;
|
||||
public interface ResolvedJavaMethod extends JavaMethod, InvokeTarget, ModifiersProvider, AnnotatedElement {
|
||||
|
||||
/**
|
||||
* Returns the bytecode of this method, if the method has code. The returned byte array does not
|
||||
* contain breakpoints or non-Java bytecodes. This may return null if the
|
||||
* {@linkplain #getDeclaringClass() declaring class} is not
|
||||
* {@linkplain ResolvedJavaType#isLinked() linked}.
|
||||
* Returns the method's bytecode. The returned bytecode does not contain breakpoints or non-Java
|
||||
* bytecodes. This will return {@code null} if {@link #getCodeSize()} returns {@code <= 0} or if
|
||||
* {@link #hasBytecodes()} returns {@code false}.
|
||||
*
|
||||
* The contained constant pool indices may not be the ones found in the original class file but
|
||||
* The contained constant pool indexes may not be the ones found in the original class file but
|
||||
* they can be used with the JVMCI API (e.g. methods in {@link ConstantPool}).
|
||||
*
|
||||
* @return the bytecode of the method, or {@code null} if {@code getCodeSize() == 0} or if the
|
||||
* code is not ready.
|
||||
* @return {@code null} if {@code getLinkedCodeSize() <= 0} otherwise the bytecode of the method
|
||||
* whose length is guaranteed to be {@code > 0}
|
||||
*/
|
||||
byte[] getCode();
|
||||
|
||||
/**
|
||||
* Returns the size of the bytecode of this method, if the method has code. This is equivalent
|
||||
* to {@link #getCode()}. {@code length} if the method has code.
|
||||
* Returns the size of the method's bytecode. If this method returns a value {@code > 0} then
|
||||
* {@link #getCode()} will not return {@code null}.
|
||||
*
|
||||
* @return the size of the bytecode in bytes, or 0 if no bytecode is available
|
||||
* @return 0 if the method has no bytecode, {@code -1} if the method does have bytecode but its
|
||||
* {@linkplain #getDeclaringClass() declaring class} is not
|
||||
* {@linkplain ResolvedJavaType#isLinked() linked} otherwise the size of the bytecode in
|
||||
* bytes (guaranteed to be {@code > 0})
|
||||
*/
|
||||
int getCodeSize();
|
||||
|
||||
@ -437,15 +439,11 @@ public interface ResolvedJavaMethod extends JavaMethod, InvokeTarget, ModifiersP
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the method has bytecodes associated with it. Note that even if this method
|
||||
* returns {@code true}, {@link #getCode} can return {@code null} if
|
||||
* {@linkplain #getDeclaringClass() declaring class} is not
|
||||
* {@linkplain ResolvedJavaType#isLinked() linked}.
|
||||
*
|
||||
* @return {@code this.getCodeSize() != 0}
|
||||
* @see #getCodeSize()
|
||||
* @return {@code getCodeSize() > 0}
|
||||
*/
|
||||
default boolean hasBytecodes() {
|
||||
return getCodeSize() != 0;
|
||||
return getCodeSize() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -339,6 +339,16 @@ public interface ResolvedJavaType extends JavaType, ModifiersProvider, Annotated
|
||||
*/
|
||||
ResolvedJavaMethod[] getDeclaredConstructors();
|
||||
|
||||
/**
|
||||
* Returns an array reflecting all the constructors declared by this type. This method is
|
||||
* similar to {@link Class#getDeclaredConstructors()} in terms of returned constructors.
|
||||
*
|
||||
* @param forceLink if {@code true}, forces this type to be {@link #link linked}
|
||||
*/
|
||||
default ResolvedJavaMethod[] getDeclaredConstructors(boolean forceLink) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array reflecting all the methods declared by this type. This method is similar to
|
||||
* {@link Class#getDeclaredMethods()} in terms of returned methods. Calling this method forces
|
||||
@ -346,6 +356,16 @@ public interface ResolvedJavaType extends JavaType, ModifiersProvider, Annotated
|
||||
*/
|
||||
ResolvedJavaMethod[] getDeclaredMethods();
|
||||
|
||||
/**
|
||||
* Returns an array reflecting all the methods declared by this type. This method is similar to
|
||||
* {@link Class#getDeclaredMethods()} in terms of returned methods.
|
||||
*
|
||||
* @param forceLink if {@code true}, forces this type to be {@link #link linked}
|
||||
*/
|
||||
default ResolvedJavaMethod[] getDeclaredMethods(boolean forceLink) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@code <clinit>} method for this class if there is one.
|
||||
*/
|
||||
|
@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.vm.ci.hotspot.test;
|
||||
|
||||
import static java.lang.reflect.Modifier.FINAL;
|
||||
import static java.lang.reflect.Modifier.PRIVATE;
|
||||
import static java.lang.reflect.Modifier.PROTECTED;
|
||||
import static java.lang.reflect.Modifier.PUBLIC;
|
||||
import static java.lang.reflect.Modifier.STATIC;
|
||||
import static java.lang.reflect.Modifier.TRANSIENT;
|
||||
import static java.lang.reflect.Modifier.VOLATILE;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
|
||||
import jdk.vm.ci.hotspot.HotSpotResolvedJavaField;
|
||||
import jdk.vm.ci.hotspot.HotSpotVMConfigAccess;
|
||||
import jdk.vm.ci.meta.JavaType;
|
||||
import jdk.vm.ci.meta.MetaAccessProvider;
|
||||
import jdk.vm.ci.meta.ResolvedJavaField;
|
||||
import jdk.vm.ci.meta.ResolvedJavaType;
|
||||
import jdk.vm.ci.runtime.JVMCI;
|
||||
|
||||
/**
|
||||
* Tests {@link HotSpotResolvedJavaField} functionality.
|
||||
*/
|
||||
public class HotSpotResolvedJavaFieldTest {
|
||||
|
||||
private static final Class<?>[] classesWithInternalFields = {Class.class, ClassLoader.class};
|
||||
|
||||
private static final Method createFieldMethod;
|
||||
private static final Field indexField;
|
||||
|
||||
static {
|
||||
Method m = null;
|
||||
Field f = null;
|
||||
try {
|
||||
Class<?> typeImpl = Class.forName("jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl");
|
||||
m = typeImpl.getDeclaredMethod("createField", JavaType.class, long.class, int.class, int.class);
|
||||
m.setAccessible(true);
|
||||
Class<?> fieldImpl = Class.forName("jdk.vm.ci.hotspot.HotSpotResolvedJavaFieldImpl");
|
||||
f = fieldImpl.getDeclaredField("index");
|
||||
f.setAccessible(true);
|
||||
} catch (Exception e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
||||
createFieldMethod = m;
|
||||
indexField = f;
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as {@code HotSpotModifiers.jvmFieldModifiers()} but works when using a JVMCI version
|
||||
* prior to the introduction of that method.
|
||||
*/
|
||||
private int jvmFieldModifiers() {
|
||||
HotSpotJVMCIRuntime runtime = runtime();
|
||||
HotSpotVMConfigAccess access = new HotSpotVMConfigAccess(runtime.getConfigStore());
|
||||
int accEnum = access.getConstant("JVM_ACC_ENUM", Integer.class, 0x4000);
|
||||
int accSynthetic = access.getConstant("JVM_ACC_SYNTHETIC", Integer.class, 0x1000);
|
||||
return PUBLIC | PRIVATE | PROTECTED | STATIC | FINAL | VOLATILE | TRANSIENT | accEnum | accSynthetic;
|
||||
}
|
||||
|
||||
HotSpotJVMCIRuntime runtime() {
|
||||
return (HotSpotJVMCIRuntime) JVMCI.getRuntime();
|
||||
}
|
||||
|
||||
MetaAccessProvider getMetaAccess() {
|
||||
return runtime().getHostJVMCIBackend().getMetaAccess();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that {@link HotSpotResolvedJavaField#getModifiers()} only includes the modifiers
|
||||
* returned by {@link Field#getModifiers()}. Namely, it must not include
|
||||
* {@code HotSpotResolvedJavaField#FIELD_INTERNAL_FLAG}.
|
||||
*/
|
||||
@Test
|
||||
public void testModifiersForInternal() {
|
||||
for (Class<?> c : classesWithInternalFields) {
|
||||
ResolvedJavaType type = getMetaAccess().lookupJavaType(c);
|
||||
for (ResolvedJavaField field : type.getInstanceFields(false)) {
|
||||
if (field.isInternal()) {
|
||||
Assert.assertEquals(0, ~jvmFieldModifiers() & field.getModifiers());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that {@code HotSpotResolvedObjectTypeImpl#createField(String, JavaType, long, int)}
|
||||
* always returns an {@linkplain ResolvedJavaField#equals(Object) equivalent} object for an
|
||||
* internal field.
|
||||
*
|
||||
* @throws InvocationTargetException
|
||||
* @throws IllegalArgumentException
|
||||
* @throws IllegalAccessException
|
||||
*/
|
||||
@Test
|
||||
public void testEquivalenceForInternalFields() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
|
||||
for (Class<?> c : classesWithInternalFields) {
|
||||
ResolvedJavaType type = getMetaAccess().lookupJavaType(c);
|
||||
for (ResolvedJavaField field : type.getInstanceFields(false)) {
|
||||
if (field.isInternal()) {
|
||||
HotSpotResolvedJavaField expected = (HotSpotResolvedJavaField) field;
|
||||
int index = indexField.getInt(expected);
|
||||
ResolvedJavaField actual = (ResolvedJavaField) createFieldMethod.invoke(type, expected.getType(), expected.getOffset(), expected.getModifiers(), index);
|
||||
Assert.assertEquals(expected, actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsInObject() {
|
||||
for (Field f : String.class.getDeclaredFields()) {
|
||||
HotSpotResolvedJavaField rf = (HotSpotResolvedJavaField) getMetaAccess().lookupJavaField(f);
|
||||
Assert.assertEquals(rf.toString(), rf.isInObject(runtime().getHostJVMCIBackend().getConstantReflection().forString("a string")), !rf.isStatic());
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -45,13 +45,16 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Executable;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@ -77,17 +80,13 @@ public class TestResolvedJavaMethod extends MethodUniverse {
|
||||
*/
|
||||
@Test
|
||||
public void getCodeTest() {
|
||||
for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
|
||||
ResolvedJavaMethod m = e.getValue();
|
||||
for (ResolvedJavaMethod m : joinValues(methods, constructors)) {
|
||||
String ms = m.toString();
|
||||
byte[] code = m.getCode();
|
||||
if (code == null) {
|
||||
assertTrue(m.getCodeSize() == 0);
|
||||
assertEquals(ms, m.getCodeSize(), 0);
|
||||
} else {
|
||||
if (m.isAbstract()) {
|
||||
assertTrue(code.length == 0);
|
||||
} else if (!m.isNative()) {
|
||||
assertTrue(code.length > 0);
|
||||
}
|
||||
assertTrue(ms, code.length > 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -97,21 +96,27 @@ public class TestResolvedJavaMethod extends MethodUniverse {
|
||||
*/
|
||||
@Test
|
||||
public void getCodeSizeTest() {
|
||||
for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
|
||||
ResolvedJavaMethod m = e.getValue();
|
||||
ResolvedJavaType unlinkedType = metaAccess.lookupJavaType(UnlinkedType.class);
|
||||
assertTrue(!unlinkedType.isLinked());
|
||||
for (ResolvedJavaMethod m : addExecutables(joinValues(methods, constructors), unlinkedType, false)) {
|
||||
int codeSize = m.getCodeSize();
|
||||
if (m.isAbstract()) {
|
||||
assertTrue(codeSize == 0);
|
||||
} else if (!m.isNative()) {
|
||||
assertTrue(codeSize > 0);
|
||||
String ms = m.toString();
|
||||
if (m.isAbstract() || m.isNative()) {
|
||||
assertEquals(ms, codeSize, 0);
|
||||
} else if (!m.getDeclaringClass().isLinked()) {
|
||||
assertEquals(ms, -1, codeSize);
|
||||
} else {
|
||||
assertTrue(ms, codeSize > 0);
|
||||
}
|
||||
}
|
||||
assertTrue(!unlinkedType.isLinked());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equalsTest() {
|
||||
for (ResolvedJavaMethod m : methods.values()) {
|
||||
for (ResolvedJavaMethod that : methods.values()) {
|
||||
List<ResolvedJavaMethod> executables = joinValues(methods, constructors);
|
||||
for (ResolvedJavaMethod m : executables) {
|
||||
for (ResolvedJavaMethod that : executables) {
|
||||
boolean expect = m == that;
|
||||
boolean actual = m.equals(that);
|
||||
assertEquals(expect, actual);
|
||||
@ -121,13 +126,7 @@ public class TestResolvedJavaMethod extends MethodUniverse {
|
||||
|
||||
@Test
|
||||
public void getModifiersTest() {
|
||||
for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
|
||||
ResolvedJavaMethod m = e.getValue();
|
||||
int expected = e.getKey().getModifiers();
|
||||
int actual = m.getModifiers();
|
||||
assertEquals(String.format("%s: 0x%x != 0x%x", m, expected, actual), expected, actual);
|
||||
}
|
||||
for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
|
||||
for (Map.Entry<Executable, ResolvedJavaMethod> e : join(methods, constructors).entrySet()) {
|
||||
ResolvedJavaMethod m = e.getValue();
|
||||
int expected = e.getKey().getModifiers();
|
||||
int actual = m.getModifiers();
|
||||
@ -140,15 +139,11 @@ public class TestResolvedJavaMethod extends MethodUniverse {
|
||||
*/
|
||||
@Test
|
||||
public void isClassInitializerTest() {
|
||||
for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
|
||||
for (Map.Entry<Executable, ResolvedJavaMethod> e : join(methods, constructors).entrySet()) {
|
||||
// Class initializers are hidden from reflection
|
||||
ResolvedJavaMethod m = e.getValue();
|
||||
assertFalse(m.isClassInitializer());
|
||||
}
|
||||
for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
|
||||
ResolvedJavaMethod m = e.getValue();
|
||||
assertFalse(m.isClassInitializer());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -165,11 +160,7 @@ public class TestResolvedJavaMethod extends MethodUniverse {
|
||||
|
||||
@Test
|
||||
public void isSyntheticTest() {
|
||||
for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
|
||||
ResolvedJavaMethod m = e.getValue();
|
||||
assertEquals(e.getKey().isSynthetic(), m.isSynthetic());
|
||||
}
|
||||
for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
|
||||
for (Map.Entry<Executable, ResolvedJavaMethod> e : join(methods, constructors).entrySet()) {
|
||||
ResolvedJavaMethod m = e.getValue();
|
||||
assertEquals(e.getKey().isSynthetic(), m.isSynthetic());
|
||||
}
|
||||
@ -189,11 +180,7 @@ public class TestResolvedJavaMethod extends MethodUniverse {
|
||||
|
||||
@Test
|
||||
public void isVarArgsTest() {
|
||||
for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
|
||||
ResolvedJavaMethod m = e.getValue();
|
||||
assertEquals(e.getKey().isVarArgs(), m.isVarArgs());
|
||||
}
|
||||
for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
|
||||
for (Map.Entry<Executable, ResolvedJavaMethod> e : join(methods, constructors).entrySet()) {
|
||||
ResolvedJavaMethod m = e.getValue();
|
||||
assertEquals(e.getKey().isVarArgs(), m.isVarArgs());
|
||||
}
|
||||
@ -201,11 +188,7 @@ public class TestResolvedJavaMethod extends MethodUniverse {
|
||||
|
||||
@Test
|
||||
public void isSynchronizedTest() {
|
||||
for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
|
||||
ResolvedJavaMethod m = e.getValue();
|
||||
assertEquals(Modifier.isSynchronized(e.getKey().getModifiers()), m.isSynchronized());
|
||||
}
|
||||
for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
|
||||
for (Map.Entry<Executable, ResolvedJavaMethod> e : join(methods, constructors).entrySet()) {
|
||||
ResolvedJavaMethod m = e.getValue();
|
||||
assertEquals(Modifier.isSynchronized(e.getKey().getModifiers()), m.isSynchronized());
|
||||
}
|
||||
@ -228,11 +211,11 @@ public class TestResolvedJavaMethod extends MethodUniverse {
|
||||
private static boolean canBeStaticallyBound(Member method) {
|
||||
int modifiers = method.getModifiers();
|
||||
return (Modifier.isFinal(modifiers) ||
|
||||
Modifier.isPrivate(modifiers) ||
|
||||
Modifier.isStatic(modifiers) ||
|
||||
method instanceof Constructor ||
|
||||
Modifier.isFinal(method.getDeclaringClass().getModifiers())) &&
|
||||
!Modifier.isAbstract(modifiers);
|
||||
Modifier.isPrivate(modifiers) ||
|
||||
Modifier.isStatic(modifiers) ||
|
||||
method instanceof Constructor ||
|
||||
Modifier.isFinal(method.getDeclaringClass().getModifiers())) &&
|
||||
!Modifier.isAbstract(modifiers);
|
||||
}
|
||||
|
||||
private static String methodWithExceptionHandlers(String p1, Object o2) {
|
||||
@ -279,7 +262,7 @@ public class TestResolvedJavaMethod extends MethodUniverse {
|
||||
|
||||
@Test
|
||||
public void getConstantPoolTest() {
|
||||
for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
|
||||
for (Map.Entry<Executable, ResolvedJavaMethod> e : join(methods, constructors).entrySet()) {
|
||||
ResolvedJavaMethod m = e.getValue();
|
||||
ConstantPool cp = m.getConstantPool();
|
||||
assertTrue(cp.length() > 0);
|
||||
@ -416,16 +399,22 @@ public class TestResolvedJavaMethod extends MethodUniverse {
|
||||
}
|
||||
}
|
||||
|
||||
public static List<ResolvedJavaMethod> addExecutables(List<ResolvedJavaMethod> to, ResolvedJavaType declaringType, boolean forceLink) {
|
||||
to.addAll(List.of(declaringType.getDeclaredMethods(forceLink)));
|
||||
to.addAll(List.of(declaringType.getDeclaredConstructors(forceLink)));
|
||||
return to;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasBytecodesTest() {
|
||||
for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
|
||||
ResolvedJavaMethod m = e.getValue();
|
||||
assertTrue(m.hasBytecodes() == (m.isConcrete() && !m.isNative()));
|
||||
}
|
||||
for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
|
||||
ResolvedJavaMethod m = e.getValue();
|
||||
assertTrue(m.hasBytecodes());
|
||||
ResolvedJavaType unlinkedType = metaAccess.lookupJavaType(UnlinkedType.class);
|
||||
assertTrue(!unlinkedType.isLinked());
|
||||
for (ResolvedJavaMethod m : addExecutables(joinValues(methods, constructors), unlinkedType, false)) {
|
||||
boolean expect = m.getDeclaringClass().isLinked() && m.isConcrete() && !m.isNative();
|
||||
boolean actual = m.hasBytecodes();
|
||||
assertEquals(m.toString(), expect, actual);
|
||||
}
|
||||
assertTrue(!unlinkedType.isLinked());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -447,7 +436,13 @@ public class TestResolvedJavaMethod extends MethodUniverse {
|
||||
}
|
||||
}
|
||||
|
||||
static class UnlinkedType {
|
||||
abstract static class UnlinkedType {
|
||||
abstract void abstractMethod();
|
||||
|
||||
void concreteMethod() {
|
||||
}
|
||||
|
||||
native void nativeMethod();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -530,4 +525,22 @@ public class TestResolvedJavaMethod extends MethodUniverse {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
public static <K, V> Map<K, V> join(Map<? extends K, V>... maps) {
|
||||
Map<K, V> res = new HashMap<>();
|
||||
for (Map<? extends K, V> e : maps) {
|
||||
res.putAll(e);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
public static <V> List<V> joinValues(Map<?, V>... maps) {
|
||||
List<V> res = new ArrayList<>();
|
||||
for (Map<?, V> e : maps) {
|
||||
res.addAll(e.values());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user