blob: 375dc3413c5669919ca8d62c2c4c21e17469dfa7 [file] [log] [blame]
Mikaël Peltier7b7b53a2017-10-09 13:33:21 +02001// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4package invokecustom;
5
6import java.io.FileInputStream;
7import java.io.FileOutputStream;
8import java.io.IOException;
9import java.lang.invoke.CallSite;
10import java.lang.invoke.MethodHandle;
11import java.lang.invoke.MethodHandles;
12import java.lang.invoke.MethodType;
13import java.nio.file.Path;
14import java.nio.file.Paths;
15import org.objectweb.asm.ClassReader;
16import org.objectweb.asm.ClassVisitor;
17import org.objectweb.asm.ClassWriter;
18import org.objectweb.asm.Handle;
19import org.objectweb.asm.MethodVisitor;
20import org.objectweb.asm.Opcodes;
21import org.objectweb.asm.Type;
22
23public class TestGenerator {
24
25 private final Path classNamePath;
26
27 public static void main(String[] args) throws IOException {
28 assert args.length == 1;
29 TestGenerator testGenerator = new TestGenerator(Paths.get(args[0],
30 TestGenerator.class.getPackage().getName(), InvokeCustom.class.getSimpleName() + ".class"));
31 testGenerator.generateTests();
32 }
33
34 public TestGenerator(Path classNamePath) {
35 this.classNamePath = classNamePath;
36 }
37
38 private void generateTests() throws IOException {
39 ClassReader cr = new ClassReader(new FileInputStream(classNamePath.toFile()));
40 ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
41 cr.accept(
42 new ClassVisitor(Opcodes.ASM6, cw) {
43 @Override
44 public void visitEnd() {
45 generateMethodTest1(cw);
Mikaël Peltiercfd6dac2017-10-10 13:45:55 +020046 generateMethodTest2(cw);
Mikaël Peltier7b7b53a2017-10-09 13:33:21 +020047 generateMethodMain(cw);
48 super.visitEnd();
49 }
50 }, 0);
51 new FileOutputStream(classNamePath.toFile()).write(cw.toByteArray());
52 }
53
54 /* Generate main method that only call all test methods. */
55 private void generateMethodMain(ClassVisitor cv) {
56 MethodVisitor mv = cv.visitMethod(
57 Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null);
58 mv.visitMethodInsn(
59 Opcodes.INVOKESTATIC, Type.getInternalName(InvokeCustom.class), "test1", "()V", false);
Mikaël Peltiercfd6dac2017-10-10 13:45:55 +020060 mv.visitMethodInsn(
61 Opcodes.INVOKESTATIC, Type.getInternalName(InvokeCustom.class), "test2", "()V", false);
Mikaël Peltier7b7b53a2017-10-09 13:33:21 +020062 mv.visitInsn(Opcodes.RETURN);
63 mv.visitMaxs(-1, -1);
64 }
65
66 /**
67 * Generate test with an invokedynamic, a static bootstrap method without extra args and
68 * args to the target method.
69 */
70 private void generateMethodTest1(ClassVisitor cv) {
71 MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, "test1", "()V",
72 null, null);
73 MethodType mt = MethodType.methodType(
74 CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class);
75 Handle bootstrap = new Handle( Opcodes.H_INVOKESTATIC, Type.getInternalName(InvokeCustom.class),
76 "bsmLookupStatic", mt.toMethodDescriptorString(), false);
77 mv.visitLdcInsn(new Handle(Opcodes.H_INVOKESTATIC, Type.getInternalName(InvokeCustom.class),
78 "targetMethodTest1", "()V", false));
79 mv.visitLdcInsn(new Handle(Opcodes.H_GETSTATIC, Type.getInternalName(InvokeCustom.class),
80 "staticField1", "Ljava/lang/String;", false));
81 mv.visitInvokeDynamicInsn("targetMethodTest2",
82 "(Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;)V",
83 bootstrap);
84 mv.visitInsn(Opcodes.RETURN);
85 mv.visitMaxs(-1, -1);
86 }
Mikaël Peltiercfd6dac2017-10-10 13:45:55 +020087
88 /**
89 * Generate test with an invokedynamic, a static bootstrap method without extra args and
90 * args to the target method.
91 */
92 private void generateMethodTest2(ClassVisitor cv) {
93 MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, "test2", "()V",
94 null, null);
95 MethodType mt = MethodType.methodType(
96 CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class);
97 Handle bootstrap = new Handle( Opcodes.H_INVOKESTATIC, Type.getInternalName(InvokeCustom.class),
98 "bsmLookupStatic", mt.toMethodDescriptorString(), false);
99 mv.visitLdcInsn(Type.getMethodType("(ZBSCIFJDLjava/lang/String;)Ljava/lang/Object;"));
100 mv.visitInvokeDynamicInsn("targetMethodTest3", "(Ljava/lang/invoke/MethodType;)V",
101 bootstrap);
102 mv.visitInsn(Opcodes.RETURN);
103 mv.visitMaxs(-1, -1);
104 }
Mikaël Peltier7b7b53a2017-10-09 13:33:21 +0200105}