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);
|
InstanceKlass* iklass = InstanceKlass::cast(klass);
|
||||||
// Ensure class is linked
|
|
||||||
iklass->link_class(CHECK_NULL);
|
|
||||||
|
|
||||||
GrowableArray<Method*> constructors_array;
|
GrowableArray<Method*> constructors_array;
|
||||||
for (int i = 0; i < iklass->methods()->length(); i++) {
|
for (int i = 0; i < iklass->methods()->length(); i++) {
|
||||||
Method* m = iklass->methods()->at(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);
|
InstanceKlass* iklass = InstanceKlass::cast(klass);
|
||||||
// Ensure class is linked
|
|
||||||
iklass->link_class(CHECK_NULL);
|
|
||||||
|
|
||||||
GrowableArray<Method*> methods_array;
|
GrowableArray<Method*> methods_array;
|
||||||
for (int i = 0; i < iklass->methods()->length(); i++) {
|
for (int i = 0; i < iklass->methods()->length(); i++) {
|
||||||
Method* m = iklass->methods()->at(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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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) {
|
HotSpotProfilingInfo(HotSpotMethodData methodData, HotSpotResolvedJavaMethod method, boolean includeNormal, boolean includeOSR) {
|
||||||
this.methodData = methodData;
|
this.methodData = methodData;
|
||||||
this.method = method;
|
this.method = method;
|
||||||
|
if (!method.getDeclaringClass().isLinked()) {
|
||||||
|
throw new IllegalArgumentException(method.format("%H.%n(%p) must be linked"));
|
||||||
|
}
|
||||||
this.includeNormal = includeNormal;
|
this.includeNormal = includeNormal;
|
||||||
this.includeOSR = includeOSR;
|
this.includeOSR = includeOSR;
|
||||||
this.isMature = methodData.isProfileMature();
|
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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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
|
@Override
|
||||||
public int getCodeSize() {
|
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
|
@Override
|
||||||
|
@ -996,11 +996,28 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResolvedJavaMethod[] getDeclaredConstructors() {
|
public ResolvedJavaMethod[] getDeclaredConstructors() {
|
||||||
|
link();
|
||||||
|
return runtime().compilerToVm.getDeclaredConstructors(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResolvedJavaMethod[] getDeclaredConstructors(boolean forceLink) {
|
||||||
|
if (forceLink) {
|
||||||
|
link();
|
||||||
|
}
|
||||||
return runtime().compilerToVm.getDeclaredConstructors(this);
|
return runtime().compilerToVm.getDeclaredConstructors(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResolvedJavaMethod[] getDeclaredMethods() {
|
public ResolvedJavaMethod[] getDeclaredMethods() {
|
||||||
|
return getDeclaredMethods(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResolvedJavaMethod[] getDeclaredMethods(boolean forceLink) {
|
||||||
|
if (forceLink) {
|
||||||
|
link();
|
||||||
|
}
|
||||||
return runtime().compilerToVm.getDeclaredMethods(this);
|
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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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 {
|
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
|
* Returns the method's bytecode. The returned bytecode does not contain breakpoints or non-Java
|
||||||
* contain breakpoints or non-Java bytecodes. This may return null if the
|
* bytecodes. This will return {@code null} if {@link #getCodeSize()} returns {@code <= 0} or if
|
||||||
* {@linkplain #getDeclaringClass() declaring class} is not
|
* {@link #hasBytecodes()} returns {@code false}.
|
||||||
* {@linkplain ResolvedJavaType#isLinked() linked}.
|
|
||||||
*
|
*
|
||||||
* 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}).
|
* 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
|
* @return {@code null} if {@code getLinkedCodeSize() <= 0} otherwise the bytecode of the method
|
||||||
* code is not ready.
|
* whose length is guaranteed to be {@code > 0}
|
||||||
*/
|
*/
|
||||||
byte[] getCode();
|
byte[] getCode();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the size of the bytecode of this method, if the method has code. This is equivalent
|
* Returns the size of the method's bytecode. If this method returns a value {@code > 0} then
|
||||||
* to {@link #getCode()}. {@code length} if the method has code.
|
* {@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();
|
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
|
* @see #getCodeSize()
|
||||||
* returns {@code true}, {@link #getCode} can return {@code null} if
|
* @return {@code getCodeSize() > 0}
|
||||||
* {@linkplain #getDeclaringClass() declaring class} is not
|
|
||||||
* {@linkplain ResolvedJavaType#isLinked() linked}.
|
|
||||||
*
|
|
||||||
* @return {@code this.getCodeSize() != 0}
|
|
||||||
*/
|
*/
|
||||||
default boolean hasBytecodes() {
|
default boolean hasBytecodes() {
|
||||||
return getCodeSize() != 0;
|
return getCodeSize() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -339,6 +339,16 @@ public interface ResolvedJavaType extends JavaType, ModifiersProvider, Annotated
|
|||||||
*/
|
*/
|
||||||
ResolvedJavaMethod[] getDeclaredConstructors();
|
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
|
* 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
|
* {@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();
|
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.
|
* 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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.Executable;
|
||||||
import java.lang.reflect.Member;
|
import java.lang.reflect.Member;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@ -77,17 +80,13 @@ public class TestResolvedJavaMethod extends MethodUniverse {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void getCodeTest() {
|
public void getCodeTest() {
|
||||||
for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
|
for (ResolvedJavaMethod m : joinValues(methods, constructors)) {
|
||||||
ResolvedJavaMethod m = e.getValue();
|
String ms = m.toString();
|
||||||
byte[] code = m.getCode();
|
byte[] code = m.getCode();
|
||||||
if (code == null) {
|
if (code == null) {
|
||||||
assertTrue(m.getCodeSize() == 0);
|
assertEquals(ms, m.getCodeSize(), 0);
|
||||||
} else {
|
} else {
|
||||||
if (m.isAbstract()) {
|
assertTrue(ms, code.length > 0);
|
||||||
assertTrue(code.length == 0);
|
|
||||||
} else if (!m.isNative()) {
|
|
||||||
assertTrue(code.length > 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -97,21 +96,27 @@ public class TestResolvedJavaMethod extends MethodUniverse {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void getCodeSizeTest() {
|
public void getCodeSizeTest() {
|
||||||
for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
|
ResolvedJavaType unlinkedType = metaAccess.lookupJavaType(UnlinkedType.class);
|
||||||
ResolvedJavaMethod m = e.getValue();
|
assertTrue(!unlinkedType.isLinked());
|
||||||
|
for (ResolvedJavaMethod m : addExecutables(joinValues(methods, constructors), unlinkedType, false)) {
|
||||||
int codeSize = m.getCodeSize();
|
int codeSize = m.getCodeSize();
|
||||||
if (m.isAbstract()) {
|
String ms = m.toString();
|
||||||
assertTrue(codeSize == 0);
|
if (m.isAbstract() || m.isNative()) {
|
||||||
} else if (!m.isNative()) {
|
assertEquals(ms, codeSize, 0);
|
||||||
assertTrue(codeSize > 0);
|
} else if (!m.getDeclaringClass().isLinked()) {
|
||||||
|
assertEquals(ms, -1, codeSize);
|
||||||
|
} else {
|
||||||
|
assertTrue(ms, codeSize > 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
assertTrue(!unlinkedType.isLinked());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void equalsTest() {
|
public void equalsTest() {
|
||||||
for (ResolvedJavaMethod m : methods.values()) {
|
List<ResolvedJavaMethod> executables = joinValues(methods, constructors);
|
||||||
for (ResolvedJavaMethod that : methods.values()) {
|
for (ResolvedJavaMethod m : executables) {
|
||||||
|
for (ResolvedJavaMethod that : executables) {
|
||||||
boolean expect = m == that;
|
boolean expect = m == that;
|
||||||
boolean actual = m.equals(that);
|
boolean actual = m.equals(that);
|
||||||
assertEquals(expect, actual);
|
assertEquals(expect, actual);
|
||||||
@ -121,13 +126,7 @@ public class TestResolvedJavaMethod extends MethodUniverse {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getModifiersTest() {
|
public void getModifiersTest() {
|
||||||
for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
|
for (Map.Entry<Executable, ResolvedJavaMethod> e : join(methods, constructors).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()) {
|
|
||||||
ResolvedJavaMethod m = e.getValue();
|
ResolvedJavaMethod m = e.getValue();
|
||||||
int expected = e.getKey().getModifiers();
|
int expected = e.getKey().getModifiers();
|
||||||
int actual = m.getModifiers();
|
int actual = m.getModifiers();
|
||||||
@ -140,15 +139,11 @@ public class TestResolvedJavaMethod extends MethodUniverse {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void isClassInitializerTest() {
|
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
|
// Class initializers are hidden from reflection
|
||||||
ResolvedJavaMethod m = e.getValue();
|
ResolvedJavaMethod m = e.getValue();
|
||||||
assertFalse(m.isClassInitializer());
|
assertFalse(m.isClassInitializer());
|
||||||
}
|
}
|
||||||
for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
|
|
||||||
ResolvedJavaMethod m = e.getValue();
|
|
||||||
assertFalse(m.isClassInitializer());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -165,11 +160,7 @@ public class TestResolvedJavaMethod extends MethodUniverse {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void isSyntheticTest() {
|
public void isSyntheticTest() {
|
||||||
for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
|
for (Map.Entry<Executable, ResolvedJavaMethod> e : join(methods, constructors).entrySet()) {
|
||||||
ResolvedJavaMethod m = e.getValue();
|
|
||||||
assertEquals(e.getKey().isSynthetic(), m.isSynthetic());
|
|
||||||
}
|
|
||||||
for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
|
|
||||||
ResolvedJavaMethod m = e.getValue();
|
ResolvedJavaMethod m = e.getValue();
|
||||||
assertEquals(e.getKey().isSynthetic(), m.isSynthetic());
|
assertEquals(e.getKey().isSynthetic(), m.isSynthetic());
|
||||||
}
|
}
|
||||||
@ -189,11 +180,7 @@ public class TestResolvedJavaMethod extends MethodUniverse {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void isVarArgsTest() {
|
public void isVarArgsTest() {
|
||||||
for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
|
for (Map.Entry<Executable, ResolvedJavaMethod> e : join(methods, constructors).entrySet()) {
|
||||||
ResolvedJavaMethod m = e.getValue();
|
|
||||||
assertEquals(e.getKey().isVarArgs(), m.isVarArgs());
|
|
||||||
}
|
|
||||||
for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
|
|
||||||
ResolvedJavaMethod m = e.getValue();
|
ResolvedJavaMethod m = e.getValue();
|
||||||
assertEquals(e.getKey().isVarArgs(), m.isVarArgs());
|
assertEquals(e.getKey().isVarArgs(), m.isVarArgs());
|
||||||
}
|
}
|
||||||
@ -201,11 +188,7 @@ public class TestResolvedJavaMethod extends MethodUniverse {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void isSynchronizedTest() {
|
public void isSynchronizedTest() {
|
||||||
for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
|
for (Map.Entry<Executable, ResolvedJavaMethod> e : join(methods, constructors).entrySet()) {
|
||||||
ResolvedJavaMethod m = e.getValue();
|
|
||||||
assertEquals(Modifier.isSynchronized(e.getKey().getModifiers()), m.isSynchronized());
|
|
||||||
}
|
|
||||||
for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
|
|
||||||
ResolvedJavaMethod m = e.getValue();
|
ResolvedJavaMethod m = e.getValue();
|
||||||
assertEquals(Modifier.isSynchronized(e.getKey().getModifiers()), m.isSynchronized());
|
assertEquals(Modifier.isSynchronized(e.getKey().getModifiers()), m.isSynchronized());
|
||||||
}
|
}
|
||||||
@ -228,11 +211,11 @@ public class TestResolvedJavaMethod extends MethodUniverse {
|
|||||||
private static boolean canBeStaticallyBound(Member method) {
|
private static boolean canBeStaticallyBound(Member method) {
|
||||||
int modifiers = method.getModifiers();
|
int modifiers = method.getModifiers();
|
||||||
return (Modifier.isFinal(modifiers) ||
|
return (Modifier.isFinal(modifiers) ||
|
||||||
Modifier.isPrivate(modifiers) ||
|
Modifier.isPrivate(modifiers) ||
|
||||||
Modifier.isStatic(modifiers) ||
|
Modifier.isStatic(modifiers) ||
|
||||||
method instanceof Constructor ||
|
method instanceof Constructor ||
|
||||||
Modifier.isFinal(method.getDeclaringClass().getModifiers())) &&
|
Modifier.isFinal(method.getDeclaringClass().getModifiers())) &&
|
||||||
!Modifier.isAbstract(modifiers);
|
!Modifier.isAbstract(modifiers);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String methodWithExceptionHandlers(String p1, Object o2) {
|
private static String methodWithExceptionHandlers(String p1, Object o2) {
|
||||||
@ -279,7 +262,7 @@ public class TestResolvedJavaMethod extends MethodUniverse {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getConstantPoolTest() {
|
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();
|
ResolvedJavaMethod m = e.getValue();
|
||||||
ConstantPool cp = m.getConstantPool();
|
ConstantPool cp = m.getConstantPool();
|
||||||
assertTrue(cp.length() > 0);
|
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
|
@Test
|
||||||
public void hasBytecodesTest() {
|
public void hasBytecodesTest() {
|
||||||
for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
|
ResolvedJavaType unlinkedType = metaAccess.lookupJavaType(UnlinkedType.class);
|
||||||
ResolvedJavaMethod m = e.getValue();
|
assertTrue(!unlinkedType.isLinked());
|
||||||
assertTrue(m.hasBytecodes() == (m.isConcrete() && !m.isNative()));
|
for (ResolvedJavaMethod m : addExecutables(joinValues(methods, constructors), unlinkedType, false)) {
|
||||||
}
|
boolean expect = m.getDeclaringClass().isLinked() && m.isConcrete() && !m.isNative();
|
||||||
for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
|
boolean actual = m.hasBytecodes();
|
||||||
ResolvedJavaMethod m = e.getValue();
|
assertEquals(m.toString(), expect, actual);
|
||||||
assertTrue(m.hasBytecodes());
|
|
||||||
}
|
}
|
||||||
|
assertTrue(!unlinkedType.isLinked());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@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