1 /* 2 * Copyright (c) 2011, 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 org.graalvm.compiler.replacements.test; 24 25 import java.util.Random; 26 27 import org.graalvm.compiler.core.test.GraalCompilerTest; 28 import org.graalvm.compiler.phases.common.AbstractInliningPhase; 29 import org.graalvm.compiler.test.ExportingClassLoader; 30 import org.junit.Assert; 31 import org.junit.Test; 32 33 import org.objectweb.asm.ClassWriter; 34 import org.objectweb.asm.Label; 35 import org.objectweb.asm.MethodVisitor; 36 import org.objectweb.asm.Opcodes; 37 import jdk.vm.ci.meta.ResolvedJavaMethod; 38 39 /** 40 * Tests that deoptimization upon exception handling works. 41 */ 42 public class DeoptimizeOnExceptionTest extends GraalCompilerTest { 43 44 public DeoptimizeOnExceptionTest() { 45 getSuites().getHighTier().findPhase(AbstractInliningPhase.class).remove(); 46 } 47 48 private static void raiseException(String m1, String m2, String m3, String m4, String m5) { 49 throw new RuntimeException(m1 + m2 + m3 + m4 + m5); 50 } 51 52 @Test 53 public void test1() { 54 test("test1Snippet", "m1", "m2", "m3", "m4", "m5"); 55 } 56 57 // no local exception handler - will deopt 58 public static String test1Snippet(String m1, String m2, String m3, String m4, String m5) { 59 if (m1 != null) { 60 raiseException(m1, m2, m3, m4, m5); 61 } 62 return m1 + m2 + m3 + m4 + m5; 63 } 64 65 @Test 66 public void test2() { 67 test("test2Snippet"); 68 } 69 70 public String test2Snippet() throws Exception { 71 try { 72 ClassLoader testCl = new MyClassLoader(); 73 @SuppressWarnings("unchecked") 74 Class<Runnable> c = (Class<Runnable>) testCl.loadClass(name); 75 Runnable r = c.newInstance(); 76 ct = Long.MAX_VALUE; 77 // warmup 78 for (int i = 0; i < 100; i++) { 79 r.run(); 80 } 81 // compile 82 ResolvedJavaMethod method = getResolvedJavaMethod(c, "run"); 83 getCode(method); 84 ct = 0; 85 r.run(); 86 } catch (Throwable e) { 87 e.printStackTrace(System.out); 88 Assert.fail(); 89 } 90 return "SUCCESS"; 91 } 92 93 public static class MyClassLoader extends ExportingClassLoader { 94 @Override 95 protected Class<?> findClass(String className) throws ClassNotFoundException { 96 return defineClass(name.replace('/', '.'), clazz, 0, clazz.length); 97 } 98 } 99 100 public static void methodB() { 101 Random r = new Random(System.currentTimeMillis()); 102 while (r.nextFloat() > .03f) { 103 // Empty 104 } 105 106 return; 107 } 108 109 public static void methodA() { 110 Random r = new Random(System.currentTimeMillis()); 111 while (r.nextDouble() > .05) { 112 // Empty 113 } 114 return; 115 } 116 117 private static Object m = new Object(); 118 static long ct = Long.MAX_VALUE; 119 120 public static Object getM() { 121 if (ct-- > 0) { 122 return m; 123 } else { 124 return null; 125 } 126 } 127 128 private static String name = "t/TestJSR"; 129 130 private static final byte[] clazz = makeClazz(); 131 132 private static byte[] makeClazz() { 133 // Code generated the class below using asm. 134 String clazzName = DeoptimizeOnExceptionTest.class.getName().replace('.', '/'); 135 final ClassWriter w = new ClassWriter(0); 136 w.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC, 137 "t/TestJSR", null, "java/lang/Object", 138 new String[]{"java/lang/Runnable"}); 139 MethodVisitor mv = w.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, new String[]{}); 140 mv.visitCode(); 141 mv.visitVarInsn(Opcodes.ALOAD, 0); 142 mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false); 143 mv.visitInsn(Opcodes.RETURN); 144 mv.visitMaxs(10, 10); 145 mv.visitEnd(); 146 147 mv = w.visitMethod(Opcodes.ACC_PUBLIC, "run", "()V", null, null); 148 mv.visitCode(); 149 mv.visitMethodInsn(Opcodes.INVOKESTATIC, clazzName, "getM", "()Ljava/lang/Object;", false); 150 Label l1 = new Label(); 151 mv.visitJumpInsn(Opcodes.JSR, l1); 152 mv.visitInsn(Opcodes.RETURN); 153 154 mv.visitLabel(l1); 155 mv.visitVarInsn(Opcodes.ASTORE, 1); 156 157 Label lElse = new Label(); 158 Label lEnd = new Label(); 159 mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/System", "currentTimeMillis", "()J", false); 160 mv.visitInsn(Opcodes.POP2); 161 mv.visitMethodInsn(Opcodes.INVOKESTATIC, clazzName, "getM", "()Ljava/lang/Object;", false); 162 mv.visitInsn(Opcodes.DUP); 163 mv.visitJumpInsn(Opcodes.IFNULL, lElse); 164 mv.visitMethodInsn(Opcodes.INVOKESTATIC, clazzName, "methodA", "()V", false); 165 mv.visitJumpInsn(Opcodes.GOTO, lEnd); 166 mv.visitLabel(lElse); 167 mv.visitMethodInsn(Opcodes.INVOKESTATIC, clazzName, "methodB", "()V", false); 168 mv.visitLabel(lEnd); 169 170 mv.visitVarInsn(Opcodes.RET, 1); 171 mv.visitMaxs(10, 10); 172 mv.visitEnd(); 173 return w.toByteArray(); 174 } 175 }