Skip to content

Commit dcaa4a8

Browse files
author
Andrew Haley
committed
Foo
1 parent 1292ead commit dcaa4a8

1 file changed

Lines changed: 136 additions & 2 deletions

File tree

test/micro/org/openjdk/bench/vm/lang/SecondarySupersLookup.java

Lines changed: 136 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,25 @@
2222
*/
2323
package org.openjdk.bench.vm.lang;
2424

25-
import org.openjdk.jmh.annotations.*;
26-
import java.util.concurrent.TimeUnit;
25+
import java.io.FileOutputStream;
26+
import java.io.IOException;
27+
import java.lang.classfile.*;
28+
import java.lang.classfile.constantpool.ClassEntry;
29+
import java.lang.constant.ClassDesc;
30+
import java.lang.constant.ConstantDescs;
31+
import java.lang.constant.MethodTypeDesc;
32+
import java.lang.invoke.MethodHandles;
33+
import java.security.SecureClassLoader;
34+
import java.util.Arrays;
35+
import java.util.List;
2736
import java.util.Random;
37+
import java.util.concurrent.TimeUnit;
38+
import java.util.function.Function;
39+
import java.util.stream.Stream;
40+
import org.openjdk.jmh.annotations.*;
41+
42+
import static java.lang.classfile.ClassFile.*;
43+
import static java.lang.invoke.MethodType.methodType;
2844

2945

3046
@BenchmarkMode(Mode.AverageTime)
@@ -34,6 +50,9 @@
3450
@Measurement(iterations = 3, time = 1)
3551
@Fork(value = 5)
3652
public class SecondarySupersLookup {
53+
@Param("100")
54+
private int interfaceCount;
55+
3756
interface J {}
3857
interface I01 {}
3958
interface I02 extends I01 {}
@@ -145,6 +164,117 @@ static Class<?> getSuper(int idx) {
145164
throw new InternalError("" + i);
146165
}
147166

167+
private static final ClassDesc CD_Hello = ClassDesc.of("Hello");
168+
private static final MethodTypeDesc MTD_void_StringArray = MethodTypeDesc.of(ConstantDescs.CD_void, ConstantDescs.CD_String.arrayType());
169+
private static final MethodTypeDesc MTD_void_String = MethodTypeDesc.of(ConstantDescs.CD_void, ConstantDescs.CD_String);
170+
private static final MethodTypeDesc MTD_Class_boolean = MethodTypeDesc.of(ConstantDescs.CD_boolean, ConstantDescs.CD_Class);
171+
private static final MethodTypeDesc MTD_Object_boolean = MethodTypeDesc.of(ConstantDescs.CD_boolean, ConstantDescs.CD_Object);
172+
private static final ClassDesc CD_System = ClassDesc.of("java.lang.System");
173+
private static final ClassDesc CD_PrintStream = ClassDesc.of("java.io.PrintStream");
174+
175+
static class MyLoader extends SecureClassLoader {
176+
public Class defineClass(String name, byte[] bytes) {
177+
try {
178+
try (FileOutputStream fos = new FileOutputStream("/tmp/" + name + ".class")) {
179+
fos.write(bytes);
180+
} catch (IOException e) {
181+
throw new RuntimeException(e);
182+
}
183+
} catch (Exception e) {
184+
throw new RuntimeException(e);
185+
}
186+
return defineClass(name, bytes, 0, bytes.length);
187+
}
188+
}
189+
190+
static MyLoader LOADER = new MyLoader();
191+
192+
static String interfaceName(Integer suffix) {
193+
return String.format("I%04d", suffix);
194+
}
195+
196+
private static Class<?>[] genInterfaces(Function<Integer, String> name, int first, int last) {
197+
Class<?>[] interfaces = new Class[last + 1];
198+
for (int n = first; n <= last; n++) {
199+
byte[] bytes = ClassFile.of().build(ClassDesc.of(name.apply(n)),
200+
(ClassBuilder clb) -> clb.withFlags(ACC_INTERFACE | ACC_PUBLIC | ACC_ABSTRACT));
201+
interfaces[n] = LOADER.defineClass(interfaceName(n), bytes);
202+
}
203+
System.out.println("LENGTH = " + interfaces.length);
204+
return interfaces;
205+
}
206+
207+
Class<?>[] interfaces;
208+
209+
public Class<?>[] genClasses(Class<?>[] interfaces, int length) {
210+
Class<?>[] impls = new Class[length];
211+
for (int n = 0; n < length; n++) {
212+
var klass = genClass(List.of(interfaces).stream()
213+
.map(iface -> ClassDesc.of(iface.getName())).toList(), "Impl" + n);
214+
impls[n] = klass;
215+
}
216+
return impls;
217+
}
218+
219+
private Class genClass(Class<?>[] interfaces, String name) {
220+
return genClass(List.of(interfaces).stream()
221+
.map(iface -> ClassDesc.of(iface.getName())).toList(),
222+
name);
223+
}
224+
225+
private Class<?> genClass(List<ClassDesc> interfaceDesc, String name) {
226+
byte[] bytes = ClassFile.of().build(ClassDesc.of(name),
227+
clb -> {
228+
clb = clb.withFlags(ACC_PUBLIC);
229+
var cpool = clb.constantPool();
230+
Stream<ClassEntry> interfaceEntryStream = interfaceDesc.stream()
231+
.map(cpool::classEntry);
232+
var interfaceEntries = interfaceEntryStream.toList();
233+
clb
234+
.withInterfaces(interfaceEntries)
235+
.withMethod(ConstantDescs.INIT_NAME, ConstantDescs.MTD_void,
236+
ClassFile.ACC_PUBLIC,
237+
mb -> mb.withCode(
238+
cob -> cob.aload(0)
239+
.invokespecial(ConstantDescs.CD_Object,
240+
ConstantDescs.INIT_NAME, ConstantDescs.MTD_void)
241+
.return_()))
242+
.withMethod("isInstance", MTD_Class_boolean,
243+
ACC_PUBLIC,
244+
mb -> mb.withCode(
245+
cob -> cob
246+
.aload(1)
247+
.aload(0)
248+
.invokevirtual(ConstantDescs.CD_Class, "isInstance",
249+
MethodTypeDesc.of(ConstantDescs.CD_boolean,
250+
ConstantDescs.CD_Object))
251+
.ireturn()))
252+
.withMethod("is" + interfaceEntries.get(Math.min(27,
253+
interfaceEntries.size() / 2)).name(),
254+
MethodTypeDesc.of(ConstantDescs.CD_boolean),
255+
ACC_PUBLIC,
256+
mb -> mb.withCode(
257+
cob -> cob
258+
.aload(0)
259+
.instanceOf(interfaceEntries.get
260+
(Math.min(27,
261+
interfaceEntries.size() / 2)))
262+
.ireturn()
263+
));
264+
});
265+
return LOADER.defineClass(name, bytes);
266+
}
267+
268+
Object testInstance;
269+
270+
@Setup
271+
public void init() throws Exception {
272+
interfaces = genInterfaces(SecondarySupersLookup::interfaceName, 0, interfaceCount);
273+
Class<?> barf = genClass(interfaces, "Humongous");
274+
testInstance = barf.getConstructor().newInstance();
275+
System.out.println("COUNT = " + interfaceCount);
276+
}
277+
148278
@Setup
149279
public void warmup() {
150280
for (int i = 0; i < 20_000; i++) {
@@ -307,4 +437,8 @@ public void testPositive01() {
307437
@Benchmark public void testNegative64() {
308438
test(obj64, J.class, false);
309439
}
440+
441+
@Benchmark public void testPositiveN() {
442+
test(testInstance, interfaces[interfaceCount >>> 1], true);
443+
}
310444
}

0 commit comments

Comments
 (0)