Skip to content

Commit 37848a9

Browse files
author
Doug Simon
committed
8296967: [JVMCI] rationalize relationship between getCodeSize and getCode in ResolvedJavaMethod
Reviewed-by: never
1 parent b3ef337 commit 37848a9

File tree

8 files changed

+279
-85
lines changed

8 files changed

+279
-85
lines changed

src/hotspot/share/jvmci/jvmciCompilerToVM.cpp

-6
Original file line numberDiff line numberDiff line change
@@ -1901,9 +1901,6 @@ C2V_VMENTRY_NULL(jobjectArray, getDeclaredConstructors, (JNIEnv* env, jobject, A
19011901
}
19021902

19031903
InstanceKlass* iklass = InstanceKlass::cast(klass);
1904-
// Ensure class is linked
1905-
iklass->link_class(CHECK_NULL);
1906-
19071904
GrowableArray<Method*> constructors_array;
19081905
for (int i = 0; i < iklass->methods()->length(); i++) {
19091906
Method* m = iklass->methods()->at(i);
@@ -1931,9 +1928,6 @@ C2V_VMENTRY_NULL(jobjectArray, getDeclaredMethods, (JNIEnv* env, jobject, ARGUME
19311928
}
19321929

19331930
InstanceKlass* iklass = InstanceKlass::cast(klass);
1934-
// Ensure class is linked
1935-
iklass->link_class(CHECK_NULL);
1936-
19371931
GrowableArray<Method*> methods_array;
19381932
for (int i = 0; i < iklass->methods()->length(); i++) {
19391933
Method* m = iklass->methods()->at(i);

src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotProfilingInfo.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -45,6 +45,9 @@ final class HotSpotProfilingInfo implements ProfilingInfo {
4545
HotSpotProfilingInfo(HotSpotMethodData methodData, HotSpotResolvedJavaMethod method, boolean includeNormal, boolean includeOSR) {
4646
this.methodData = methodData;
4747
this.method = method;
48+
if (!method.getDeclaringClass().isLinked()) {
49+
throw new IllegalArgumentException(method.format("%H.%n(%p) must be linked"));
50+
}
4851
this.includeNormal = includeNormal;
4952
this.includeOSR = includeOSR;
5053
this.isMature = methodData.isProfileMature();

src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -256,7 +256,11 @@ public byte[] getCode() {
256256

257257
@Override
258258
public int getCodeSize() {
259-
return UNSAFE.getChar(getConstMethod() + config().constMethodCodeSizeOffset);
259+
int codeSize = UNSAFE.getChar(getConstMethod() + config().constMethodCodeSizeOffset);
260+
if (codeSize > 0 && !getDeclaringClass().isLinked()) {
261+
return -1;
262+
}
263+
return codeSize;
260264
}
261265

262266
@Override

src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java

+17
Original file line numberDiff line numberDiff line change
@@ -996,11 +996,28 @@ public HotSpotResolvedObjectType getEnclosingType() {
996996

997997
@Override
998998
public ResolvedJavaMethod[] getDeclaredConstructors() {
999+
link();
1000+
return runtime().compilerToVm.getDeclaredConstructors(this);
1001+
}
1002+
1003+
@Override
1004+
public ResolvedJavaMethod[] getDeclaredConstructors(boolean forceLink) {
1005+
if (forceLink) {
1006+
link();
1007+
}
9991008
return runtime().compilerToVm.getDeclaredConstructors(this);
10001009
}
10011010

10021011
@Override
10031012
public ResolvedJavaMethod[] getDeclaredMethods() {
1013+
return getDeclaredMethods(true);
1014+
}
1015+
1016+
@Override
1017+
public ResolvedJavaMethod[] getDeclaredMethods(boolean forceLink) {
1018+
if (forceLink) {
1019+
link();
1020+
}
10041021
return runtime().compilerToVm.getDeclaredMethods(this);
10051022
}
10061023

src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaMethod.java

+16-18
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2009, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -36,24 +36,26 @@
3636
public interface ResolvedJavaMethod extends JavaMethod, InvokeTarget, ModifiersProvider, AnnotatedElement {
3737

3838
/**
39-
* Returns the bytecode of this method, if the method has code. The returned byte array does not
40-
* contain breakpoints or non-Java bytecodes. This may return null if the
41-
* {@linkplain #getDeclaringClass() declaring class} is not
42-
* {@linkplain ResolvedJavaType#isLinked() linked}.
39+
* Returns the method's bytecode. The returned bytecode does not contain breakpoints or non-Java
40+
* bytecodes. This will return {@code null} if {@link #getCodeSize()} returns {@code <= 0} or if
41+
* {@link #hasBytecodes()} returns {@code false}.
4342
*
44-
* The contained constant pool indices may not be the ones found in the original class file but
43+
* The contained constant pool indexes may not be the ones found in the original class file but
4544
* they can be used with the JVMCI API (e.g. methods in {@link ConstantPool}).
4645
*
47-
* @return the bytecode of the method, or {@code null} if {@code getCodeSize() == 0} or if the
48-
* code is not ready.
46+
* @return {@code null} if {@code getLinkedCodeSize() <= 0} otherwise the bytecode of the method
47+
* whose length is guaranteed to be {@code > 0}
4948
*/
5049
byte[] getCode();
5150

5251
/**
53-
* Returns the size of the bytecode of this method, if the method has code. This is equivalent
54-
* to {@link #getCode()}. {@code length} if the method has code.
52+
* Returns the size of the method's bytecode. If this method returns a value {@code > 0} then
53+
* {@link #getCode()} will not return {@code null}.
5554
*
56-
* @return the size of the bytecode in bytes, or 0 if no bytecode is available
55+
* @return 0 if the method has no bytecode, {@code -1} if the method does have bytecode but its
56+
* {@linkplain #getDeclaringClass() declaring class} is not
57+
* {@linkplain ResolvedJavaType#isLinked() linked} otherwise the size of the bytecode in
58+
* bytes (guaranteed to be {@code > 0})
5759
*/
5860
int getCodeSize();
5961

@@ -437,15 +439,11 @@ default <T extends Annotation> T[] getParameterAnnotations(Class<T> annotationCl
437439
}
438440

439441
/**
440-
* Checks whether the method has bytecodes associated with it. Note that even if this method
441-
* returns {@code true}, {@link #getCode} can return {@code null} if
442-
* {@linkplain #getDeclaringClass() declaring class} is not
443-
* {@linkplain ResolvedJavaType#isLinked() linked}.
444-
*
445-
* @return {@code this.getCodeSize() != 0}
442+
* @see #getCodeSize()
443+
* @return {@code getCodeSize() > 0}
446444
*/
447445
default boolean hasBytecodes() {
448-
return getCodeSize() != 0;
446+
return getCodeSize() > 0;
449447
}
450448

451449
/**

src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaType.java

+20
Original file line numberDiff line numberDiff line change
@@ -339,13 +339,33 @@ default ResolvedJavaMethod resolveConcreteMethod(ResolvedJavaMethod method, Reso
339339
*/
340340
ResolvedJavaMethod[] getDeclaredConstructors();
341341

342+
/**
343+
* Returns an array reflecting all the constructors declared by this type. This method is
344+
* similar to {@link Class#getDeclaredConstructors()} in terms of returned constructors.
345+
*
346+
* @param forceLink if {@code true}, forces this type to be {@link #link linked}
347+
*/
348+
default ResolvedJavaMethod[] getDeclaredConstructors(boolean forceLink) {
349+
throw new UnsupportedOperationException();
350+
}
351+
342352
/**
343353
* Returns an array reflecting all the methods declared by this type. This method is similar to
344354
* {@link Class#getDeclaredMethods()} in terms of returned methods. Calling this method forces
345355
* this type to be {@link #link linked}.
346356
*/
347357
ResolvedJavaMethod[] getDeclaredMethods();
348358

359+
/**
360+
* Returns an array reflecting all the methods declared by this type. This method is similar to
361+
* {@link Class#getDeclaredMethods()} in terms of returned methods.
362+
*
363+
* @param forceLink if {@code true}, forces this type to be {@link #link linked}
364+
*/
365+
default ResolvedJavaMethod[] getDeclaredMethods(boolean forceLink) {
366+
throw new UnsupportedOperationException();
367+
}
368+
349369
/**
350370
* Returns the {@code <clinit>} method for this class if there is one.
351371
*/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
/*
2+
* Copyright (c) 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.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
package jdk.vm.ci.hotspot.test;
24+
25+
import static java.lang.reflect.Modifier.FINAL;
26+
import static java.lang.reflect.Modifier.PRIVATE;
27+
import static java.lang.reflect.Modifier.PROTECTED;
28+
import static java.lang.reflect.Modifier.PUBLIC;
29+
import static java.lang.reflect.Modifier.STATIC;
30+
import static java.lang.reflect.Modifier.TRANSIENT;
31+
import static java.lang.reflect.Modifier.VOLATILE;
32+
33+
import java.lang.reflect.Field;
34+
import java.lang.reflect.InvocationTargetException;
35+
import java.lang.reflect.Method;
36+
37+
import org.junit.Assert;
38+
import org.junit.Test;
39+
40+
import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
41+
import jdk.vm.ci.hotspot.HotSpotResolvedJavaField;
42+
import jdk.vm.ci.hotspot.HotSpotVMConfigAccess;
43+
import jdk.vm.ci.meta.JavaType;
44+
import jdk.vm.ci.meta.MetaAccessProvider;
45+
import jdk.vm.ci.meta.ResolvedJavaField;
46+
import jdk.vm.ci.meta.ResolvedJavaType;
47+
import jdk.vm.ci.runtime.JVMCI;
48+
49+
/**
50+
* Tests {@link HotSpotResolvedJavaField} functionality.
51+
*/
52+
public class HotSpotResolvedJavaFieldTest {
53+
54+
private static final Class<?>[] classesWithInternalFields = {Class.class, ClassLoader.class};
55+
56+
private static final Method createFieldMethod;
57+
private static final Field indexField;
58+
59+
static {
60+
Method m = null;
61+
Field f = null;
62+
try {
63+
Class<?> typeImpl = Class.forName("jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl");
64+
m = typeImpl.getDeclaredMethod("createField", JavaType.class, long.class, int.class, int.class);
65+
m.setAccessible(true);
66+
Class<?> fieldImpl = Class.forName("jdk.vm.ci.hotspot.HotSpotResolvedJavaFieldImpl");
67+
f = fieldImpl.getDeclaredField("index");
68+
f.setAccessible(true);
69+
} catch (Exception e) {
70+
throw new AssertionError(e);
71+
}
72+
73+
createFieldMethod = m;
74+
indexField = f;
75+
}
76+
77+
/**
78+
* Same as {@code HotSpotModifiers.jvmFieldModifiers()} but works when using a JVMCI version
79+
* prior to the introduction of that method.
80+
*/
81+
private int jvmFieldModifiers() {
82+
HotSpotJVMCIRuntime runtime = runtime();
83+
HotSpotVMConfigAccess access = new HotSpotVMConfigAccess(runtime.getConfigStore());
84+
int accEnum = access.getConstant("JVM_ACC_ENUM", Integer.class, 0x4000);
85+
int accSynthetic = access.getConstant("JVM_ACC_SYNTHETIC", Integer.class, 0x1000);
86+
return PUBLIC | PRIVATE | PROTECTED | STATIC | FINAL | VOLATILE | TRANSIENT | accEnum | accSynthetic;
87+
}
88+
89+
HotSpotJVMCIRuntime runtime() {
90+
return (HotSpotJVMCIRuntime) JVMCI.getRuntime();
91+
}
92+
93+
MetaAccessProvider getMetaAccess() {
94+
return runtime().getHostJVMCIBackend().getMetaAccess();
95+
}
96+
97+
/**
98+
* Tests that {@link HotSpotResolvedJavaField#getModifiers()} only includes the modifiers
99+
* returned by {@link Field#getModifiers()}. Namely, it must not include
100+
* {@code HotSpotResolvedJavaField#FIELD_INTERNAL_FLAG}.
101+
*/
102+
@Test
103+
public void testModifiersForInternal() {
104+
for (Class<?> c : classesWithInternalFields) {
105+
ResolvedJavaType type = getMetaAccess().lookupJavaType(c);
106+
for (ResolvedJavaField field : type.getInstanceFields(false)) {
107+
if (field.isInternal()) {
108+
Assert.assertEquals(0, ~jvmFieldModifiers() & field.getModifiers());
109+
}
110+
}
111+
}
112+
}
113+
114+
/**
115+
* Tests that {@code HotSpotResolvedObjectTypeImpl#createField(String, JavaType, long, int)}
116+
* always returns an {@linkplain ResolvedJavaField#equals(Object) equivalent} object for an
117+
* internal field.
118+
*
119+
* @throws InvocationTargetException
120+
* @throws IllegalArgumentException
121+
* @throws IllegalAccessException
122+
*/
123+
@Test
124+
public void testEquivalenceForInternalFields() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
125+
for (Class<?> c : classesWithInternalFields) {
126+
ResolvedJavaType type = getMetaAccess().lookupJavaType(c);
127+
for (ResolvedJavaField field : type.getInstanceFields(false)) {
128+
if (field.isInternal()) {
129+
HotSpotResolvedJavaField expected = (HotSpotResolvedJavaField) field;
130+
int index = indexField.getInt(expected);
131+
ResolvedJavaField actual = (ResolvedJavaField) createFieldMethod.invoke(type, expected.getType(), expected.getOffset(), expected.getModifiers(), index);
132+
Assert.assertEquals(expected, actual);
133+
}
134+
}
135+
}
136+
}
137+
138+
@Test
139+
public void testIsInObject() {
140+
for (Field f : String.class.getDeclaredFields()) {
141+
HotSpotResolvedJavaField rf = (HotSpotResolvedJavaField) getMetaAccess().lookupJavaField(f);
142+
Assert.assertEquals(rf.toString(), rf.isInObject(runtime().getHostJVMCIBackend().getConstantReflection().forString("a string")), !rf.isStatic());
143+
}
144+
}
145+
}

0 commit comments

Comments
 (0)