1 /* 2 * Copyright (c) 2019, 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 24 25 package org.graalvm.compiler.replacements.test; 26 27 import static org.graalvm.compiler.test.SubprocessUtil.getVMCommandLine; 28 import static org.graalvm.compiler.test.SubprocessUtil.withoutDebuggerArguments; 29 30 import java.nio.file.Files; 31 import java.nio.file.Path; 32 import java.nio.file.Paths; 33 import java.util.List; 34 35 import org.graalvm.compiler.core.test.CustomizedBytecodePatternTest; 36 import org.graalvm.compiler.serviceprovider.JavaVersionUtil; 37 import org.graalvm.compiler.test.SubprocessUtil; 38 import org.graalvm.compiler.test.SubprocessUtil.Subprocess; 39 import org.junit.Test; 40 import org.objectweb.asm.ClassWriter; 41 import org.objectweb.asm.MethodVisitor; 42 import org.objectweb.asm.Type; 43 44 public class InvokerSignatureMismatchTest extends CustomizedBytecodePatternTest { 45 46 @SuppressWarnings("try") 47 @Test test()48 public void test() throws Throwable { 49 List<String> args = withoutDebuggerArguments(getVMCommandLine()); 50 try (TemporaryDirectory temp = new TemporaryDirectory(null, getClass().getSimpleName())) { 51 if (JavaVersionUtil.JAVA_SPEC > 8) { 52 args.add("--class-path=" + temp); 53 args.add("--patch-module=java.base=" + temp); 54 } else { 55 args.add("-Xbootclasspath/a:" + temp); 56 } 57 args.add("-XX:-TieredCompilation"); 58 args.add("-XX:+UnlockExperimentalVMOptions"); 59 args.add("-XX:+EnableJVMCI"); 60 args.add("-XX:+UseJVMCICompiler"); 61 62 Path invokeDir = Files.createDirectories(temp.path.resolve(Paths.get("java", "lang", "invoke"))); 63 Files.write(temp.path.resolve("ISMTest.class"), generateClass("ISMTest")); 64 Files.write(invokeDir.resolve("MethodHandleHelper.class"), generateClass("java/lang/invoke/MethodHandleHelper")); 65 66 args.add("ISMTest"); 67 Subprocess proc = SubprocessUtil.java(args); 68 if (proc.exitCode != 0) { 69 throw new AssertionError(proc.toString()); 70 } 71 } 72 } 73 74 @Override generateClass(String className)75 protected byte[] generateClass(String className) { 76 String[] exceptions = new String[]{"java/lang/Throwable"}; 77 ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); 78 cw.visit(52, ACC_SUPER | ACC_PUBLIC, className, null, "java/lang/Object", null); 79 80 if (className.equals("java/lang/invoke/MethodHandleHelper")) { 81 MethodVisitor internalMemberName = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "internalMemberName", "(Ljava/lang/invoke/MethodHandle;)Ljava/lang/Object;", null, exceptions); 82 internalMemberName.visitCode(); 83 internalMemberName.visitVarInsn(ALOAD, 0); 84 internalMemberName.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandle", "internalMemberName", "()Ljava/lang/invoke/MemberName;", false); 85 internalMemberName.visitInsn(ARETURN); 86 internalMemberName.visitMaxs(1, 1); 87 internalMemberName.visitEnd(); 88 89 MethodVisitor linkToStatic = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "linkToStatic", "(FLjava/lang/Object;)I", null, exceptions); 90 linkToStatic.visitCode(); 91 linkToStatic.visitVarInsn(FLOAD, 0); 92 linkToStatic.visitVarInsn(ALOAD, 1); 93 linkToStatic.visitMethodInsn(INVOKESTATIC, "java/lang/invoke/MethodHandle", "linkToStatic", "(FLjava/lang/Object;)I", false); 94 linkToStatic.visitInsn(IRETURN); 95 linkToStatic.visitMaxs(1, 1); 96 linkToStatic.visitEnd(); 97 98 MethodVisitor invokeBasicI = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "invokeBasicI", "(Ljava/lang/invoke/MethodHandle;F)I", null, exceptions); 99 invokeBasicI.visitCode(); 100 invokeBasicI.visitVarInsn(ALOAD, 0); 101 invokeBasicI.visitVarInsn(FLOAD, 1); 102 invokeBasicI.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandle", "invokeBasic", "(F)I", false); 103 invokeBasicI.visitInsn(IRETURN); 104 invokeBasicI.visitMaxs(1, 1); 105 invokeBasicI.visitEnd(); 106 107 } else { 108 assert className.equals("ISMTest") : className; 109 cw.visitField(ACC_FINAL | ACC_STATIC, "INT_MH", "Ljava/lang/invoke/MethodHandle;", null, null).visitAnnotation("Ljava/lang/invoke/Stable.class;", true).visitEnd(); 110 MethodVisitor clinit = cw.visitMethod(ACC_STATIC, "<clinit>", "()V", null, exceptions); 111 clinit.visitCode(); 112 clinit.visitInsn(ACONST_NULL); 113 clinit.visitVarInsn(ASTORE, 0); 114 clinit.visitMethodInsn(INVOKESTATIC, "java/lang/invoke/MethodHandles", "lookup", "()Ljava/lang/invoke/MethodHandles$Lookup;", false); 115 clinit.visitLdcInsn(Type.getObjectType(className)); 116 clinit.visitLdcInsn("bodyI"); 117 clinit.visitFieldInsn(GETSTATIC, "java/lang/Integer", "TYPE", "Ljava/lang/Class;"); 118 clinit.visitFieldInsn(GETSTATIC, "java/lang/Integer", "TYPE", "Ljava/lang/Class;"); 119 clinit.visitMethodInsn(INVOKESTATIC, "java/lang/invoke/MethodType", "methodType", "(Ljava/lang/Class;Ljava/lang/Class;)Ljava/lang/invoke/MethodType;", false); 120 clinit.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandles$Lookup", "findStatic", 121 "(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle;", false); 122 clinit.visitFieldInsn(PUTSTATIC, className, "INT_MH", "Ljava/lang/invoke/MethodHandle;"); 123 clinit.visitInsn(RETURN); 124 clinit.visitMaxs(1, 1); 125 clinit.visitEnd(); 126 127 MethodVisitor mainLink = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "mainLink", "(I)I", null, exceptions); 128 mainLink.visitCode(); 129 mainLink.visitFieldInsn(GETSTATIC, className, "INT_MH", "Ljava/lang/invoke/MethodHandle;"); 130 mainLink.visitMethodInsn(INVOKESTATIC, "java/lang/invoke/MethodHandleHelper", "internalMemberName", "(Ljava/lang/invoke/MethodHandle;)Ljava/lang/Object;", false); 131 mainLink.visitVarInsn(ASTORE, 1); 132 mainLink.visitVarInsn(ILOAD, 0); 133 mainLink.visitInsn(I2F); 134 mainLink.visitVarInsn(ALOAD, 1); 135 mainLink.visitMethodInsn(INVOKESTATIC, "java/lang/invoke/MethodHandleHelper", "linkToStatic", "(FLjava/lang/Object;)I", false); 136 mainLink.visitInsn(IRETURN); 137 mainLink.visitMaxs(1, 1); 138 mainLink.visitEnd(); 139 140 MethodVisitor mainInvoke = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "mainInvoke", "(I)I", null, exceptions); 141 mainInvoke.visitCode(); 142 mainInvoke.visitFieldInsn(GETSTATIC, className, "INT_MH", "Ljava/lang/invoke/MethodHandle;"); 143 mainInvoke.visitVarInsn(ILOAD, 0); 144 mainInvoke.visitInsn(I2F); 145 mainInvoke.visitMethodInsn(INVOKESTATIC, "java/lang/invoke/MethodHandleHelper", "invokeBasicI", "(Ljava/lang/invoke/MethodHandle;F)I", false); 146 mainInvoke.visitInsn(IRETURN); 147 mainInvoke.visitMaxs(1, 1); 148 mainInvoke.visitEnd(); 149 150 MethodVisitor bodyI = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "bodyI", "(I)I", null, null); 151 bodyI.visitCode(); 152 bodyI.visitVarInsn(ILOAD, 0); 153 bodyI.visitIntInsn(SIPUSH, 1023); 154 bodyI.visitInsn(IAND); 155 bodyI.visitInsn(IRETURN); 156 bodyI.visitMaxs(1, 1); 157 bodyI.visitEnd(); 158 159 MethodVisitor main = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "main", "([Ljava/lang/String;)V", null, exceptions); 160 main.visitCode(); 161 main.visitIntInsn(SIPUSH, 100); 162 main.visitMethodInsn(INVOKESTATIC, "ISMTest", "mainLink", "(I)I", false); 163 main.visitInsn(POP); 164 main.visitIntInsn(SIPUSH, 100); 165 main.visitMethodInsn(INVOKESTATIC, "ISMTest", "mainInvoke", "(I)I", false); 166 main.visitInsn(POP); 167 main.visitInsn(RETURN); 168 main.visitMaxs(1, 1); 169 main.visitEnd(); 170 171 } 172 cw.visitEnd(); 173 return cw.toByteArray(); 174 } 175 } 176