Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/jdk17u
Path: blob/master/test/hotspot/jtreg/compiler/cha/Utils.java
64474 views
1
/*
2
* Copyright (c) 2021, 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 compiler.cha;
24
25
import jdk.internal.misc.Unsafe;
26
import jdk.internal.org.objectweb.asm.ClassWriter;
27
import jdk.internal.org.objectweb.asm.MethodVisitor;
28
import jdk.internal.vm.annotation.DontInline;
29
import sun.hotspot.WhiteBox;
30
import sun.hotspot.code.NMethod;
31
32
import java.io.IOException;
33
import java.lang.annotation.Retention;
34
import java.lang.annotation.RetentionPolicy;
35
import java.lang.invoke.MethodHandle;
36
import java.lang.invoke.MethodHandles;
37
import java.lang.invoke.MethodType;
38
import java.lang.reflect.Method;
39
import java.util.HashMap;
40
import java.util.concurrent.Callable;
41
42
import static jdk.internal.org.objectweb.asm.ClassWriter.COMPUTE_FRAMES;
43
import static jdk.internal.org.objectweb.asm.ClassWriter.COMPUTE_MAXS;
44
import static jdk.internal.org.objectweb.asm.Opcodes.*;
45
import static jdk.test.lib.Asserts.assertTrue;
46
47
public class Utils {
48
public static final Unsafe U = Unsafe.getUnsafe();
49
public static final WhiteBox WB = WhiteBox.getWhiteBox();
50
51
interface Test<T> {
52
void call(T o);
53
T receiver(int id);
54
55
default Runnable monomophic() {
56
return () -> {
57
call(receiver(0)); // 100%
58
};
59
}
60
61
default Runnable bimorphic() {
62
return () -> {
63
call(receiver(0)); // 50%
64
call(receiver(1)); // 50%
65
};
66
}
67
68
default Runnable polymorphic() {
69
return () -> {
70
for (int i = 0; i < 23; i++) {
71
call(receiver(0)); // 92%
72
}
73
call(receiver(1)); // 4%
74
call(receiver(2)); // 4%
75
};
76
}
77
78
default Runnable megamorphic() {
79
return () -> {
80
call(receiver(0)); // 33%
81
call(receiver(1)); // 33%
82
call(receiver(2)); // 33%
83
};
84
}
85
86
default void load(Class<?>... cs) {
87
// nothing to do
88
}
89
90
default void initialize(Class<?>... cs) {
91
for (Class<?> c : cs) {
92
U.ensureClassInitialized(c);
93
}
94
}
95
96
default void repeat(int cnt, Runnable r) {
97
for (int i = 0; i < cnt; i++) {
98
r.run();
99
}
100
}
101
}
102
103
public static abstract class ATest<T> implements Test<T> {
104
public static final Object CORRECT = new Object();
105
public static final Object WRONG = new Object();
106
107
final Method TEST;
108
private final Class<T> declared;
109
private final Class<?> receiver;
110
111
private final HashMap<Integer, T> receivers = new HashMap<>();
112
113
public ATest(Class<T> declared, Class<?> receiver) {
114
this.declared = declared;
115
this.receiver = receiver;
116
TEST = compute(() -> this.getClass().getDeclaredMethod("test", declared));
117
}
118
119
@DontInline
120
public abstract Object test(T i) throws Throwable;
121
122
public abstract void checkInvalidReceiver();
123
124
public T receiver(int id) {
125
return receivers.computeIfAbsent(id, (i -> {
126
try {
127
MyClassLoader cl = (MyClassLoader) receiver.getClassLoader();
128
Class<?> sub = cl.subclass(receiver, i);
129
return (T)sub.getDeclaredConstructor().newInstance();
130
} catch (Exception e) {
131
throw new Error(e);
132
}
133
}));
134
}
135
136
public void compile(Runnable r) {
137
while (!WB.isMethodCompiled(TEST)) {
138
for (int i = 0; i < 100; i++) {
139
r.run();
140
}
141
}
142
assertCompiled(); // record nmethod info
143
}
144
145
private NMethod prevNM = null;
146
147
public void assertNotCompiled() {
148
NMethod curNM = NMethod.get(TEST, false);
149
assertTrue(prevNM != null); // was previously compiled
150
assertTrue(curNM == null || prevNM.compile_id != curNM.compile_id); // either no nmethod present or recompiled
151
prevNM = curNM; // update nmethod info
152
}
153
154
public void assertCompiled() {
155
NMethod curNM = NMethod.get(TEST, false);
156
assertTrue(curNM != null); // nmethod is present
157
assertTrue(prevNM == null || prevNM.compile_id == curNM.compile_id); // no recompilations if nmethod present
158
prevNM = curNM; // update nmethod info
159
}
160
161
@Override
162
public void call(T i) {
163
try {
164
assertTrue(test(i) != WRONG);
165
} catch (Throwable e) {
166
throw new InternalError(e);
167
}
168
}
169
170
public static <T> T compute(Callable<T> c) {
171
try {
172
return c.call();
173
} catch (Exception e) {
174
throw new Error(e);
175
}
176
}
177
178
public static MethodHandle findVirtualHelper(Class<?> refc, String name, Class<?> returnType, MethodHandles.Lookup lookup) {
179
return compute(() -> lookup.findVirtual(refc, name, MethodType.methodType(returnType)));
180
}
181
}
182
183
@Retention(value = RetentionPolicy.RUNTIME)
184
public @interface TestCase {}
185
186
static void run(Class<?> test, Class<?> enclosed) {
187
try {
188
for (Method m : test.getMethods()) {
189
if (m.isAnnotationPresent(TestCase.class)) {
190
System.out.println(m.toString());
191
ClassLoader cl = new MyClassLoader(enclosed);
192
Class<?> c = cl.loadClass(test.getName());
193
c.getMethod(m.getName()).invoke(c.getDeclaredConstructor().newInstance());
194
}
195
}
196
} catch (Exception e) {
197
throw new Error(e);
198
}
199
}
200
201
static void run(Class<?> test) {
202
run(test, test);
203
}
204
205
static class ObjectToStringHelper {
206
static Object testHelper(Object o) {
207
throw new Error("not used");
208
}
209
}
210
static class ObjectHashCodeHelper {
211
static int testHelper(Object o) {
212
throw new Error("not used");
213
}
214
}
215
216
static final class MyClassLoader extends ClassLoader {
217
private final Class<?> test;
218
219
MyClassLoader(Class<?> test) {
220
this.test = test;
221
}
222
223
static String intl(String s) {
224
return s.replace('.', '/');
225
}
226
227
Class<?> subclass(Class<?> c, int id) {
228
String name = c.getName() + id;
229
Class<?> sub = findLoadedClass(name);
230
if (sub == null) {
231
ClassWriter cw = new ClassWriter(COMPUTE_MAXS | COMPUTE_FRAMES);
232
cw.visit(52, ACC_PUBLIC | ACC_SUPER, intl(name), null, intl(c.getName()), null);
233
234
{ // Default constructor: <init>()V
235
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
236
mv.visitCode();
237
mv.visitVarInsn(ALOAD, 0);
238
mv.visitMethodInsn(INVOKESPECIAL, intl(c.getName()), "<init>", "()V", false);
239
mv.visitInsn(RETURN);
240
mv.visitMaxs(0, 0);
241
mv.visitEnd();
242
}
243
244
byte[] classFile = cw.toByteArray();
245
return defineClass(name, classFile, 0, classFile.length);
246
}
247
return sub;
248
}
249
250
protected Class<?> loadClass(String name, boolean resolve)
251
throws ClassNotFoundException
252
{
253
// First, check if the class has already been loaded
254
Class<?> c = findLoadedClass(name);
255
if (c == null) {
256
try {
257
c = getParent().loadClass(name);
258
if (name.endsWith("ObjectToStringHelper")) {
259
ClassWriter cw = new ClassWriter(COMPUTE_MAXS | COMPUTE_FRAMES);
260
cw.visit(52, ACC_PUBLIC | ACC_SUPER, intl(name), null, "java/lang/Object", null);
261
262
{
263
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "testHelper", "(Ljava/lang/Object;)Ljava/lang/Object;", null, null);
264
mv.visitCode();
265
mv.visitVarInsn(ALOAD, 0);
266
mv.visitMethodInsn(INVOKEINTERFACE, intl(test.getName()) + "$I", "toString", "()Ljava/lang/String;", true);
267
mv.visitInsn(ARETURN);
268
mv.visitMaxs(0, 0);
269
mv.visitEnd();
270
}
271
272
byte[] classFile = cw.toByteArray();
273
return defineClass(name, classFile, 0, classFile.length);
274
} else if (name.endsWith("ObjectHashCodeHelper")) {
275
ClassWriter cw = new ClassWriter(COMPUTE_MAXS | COMPUTE_FRAMES);
276
cw.visit(52, ACC_PUBLIC | ACC_SUPER, intl(name), null, "java/lang/Object", null);
277
278
{
279
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "testHelper", "(Ljava/lang/Object;)I", null, null);
280
mv.visitCode();
281
mv.visitVarInsn(ALOAD, 0);
282
mv.visitMethodInsn(INVOKEINTERFACE, intl(test.getName()) + "$I", "hashCode", "()I", true);
283
mv.visitInsn(IRETURN);
284
mv.visitMaxs(0, 0);
285
mv.visitEnd();
286
}
287
288
byte[] classFile = cw.toByteArray();
289
return defineClass(name, classFile, 0, classFile.length);
290
} else if (c == test || name.startsWith(test.getName())) {
291
try {
292
String path = name.replace('.', '/') + ".class";
293
byte[] classFile = getParent().getResourceAsStream(path).readAllBytes();
294
return defineClass(name, classFile, 0, classFile.length);
295
} catch (IOException e) {
296
throw new Error(e);
297
}
298
}
299
} catch (ClassNotFoundException e) {
300
// ClassNotFoundException thrown if class not found
301
// from the non-null parent class loader
302
}
303
304
if (c == null) {
305
// If still not found, then invoke findClass in order
306
// to find the class.
307
c = findClass(name);
308
}
309
}
310
if (resolve) {
311
resolveClass(c);
312
}
313
return c;
314
}
315
}
316
317
public interface RunnableWithException {
318
void run() throws Throwable;
319
}
320
321
public static void shouldThrow(Class<? extends Throwable> expectedException, RunnableWithException r) {
322
try {
323
r.run();
324
throw new AssertionError("Exception not thrown: " + expectedException.getName());
325
} catch (Throwable e) {
326
if (expectedException == e.getClass()) {
327
// success: proper exception is thrown
328
} else {
329
throw new Error(expectedException.getName() + " is expected", e);
330
}
331
}
332
}
333
334
public static MethodHandle unsafeCastMH(Class<?> cls) {
335
try {
336
MethodHandle mh = MethodHandles.identity(Object.class);
337
return MethodHandles.explicitCastArguments(mh, mh.type().changeReturnType(cls));
338
} catch (Throwable e) {
339
throw new Error(e);
340
}
341
}
342
}
343
344