DeoptimizeOnExceptionTest.java revision 12748:fbb9c8026495
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 */
23package org.graalvm.compiler.replacements.test;
24
25import java.util.Random;
26
27import org.graalvm.compiler.core.test.GraalCompilerTest;
28import org.graalvm.compiler.phases.common.AbstractInliningPhase;
29import org.graalvm.compiler.test.ExportingClassLoader;
30import org.junit.Assert;
31import org.junit.Test;
32
33import org.objectweb.asm.ClassWriter;
34import org.objectweb.asm.Label;
35import org.objectweb.asm.MethodVisitor;
36import org.objectweb.asm.Opcodes;
37import jdk.vm.ci.meta.ResolvedJavaMethod;
38
39/**
40 * Tests that deoptimization upon exception handling works.
41 */
42public 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}
176