Test6932496.java revision 11707:ad7af1afda7a
1/*
2 * Copyright (c) 2010, 2015, 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/**
26 * @test
27 * @bug 6932496
28 * @summary incorrect deopt of jsr subroutine on 64 bit c1
29 * @modules java.base/jdk.internal.org.objectweb.asm
30 *
31 * @run main/othervm -Xcomp
32 *      -XX:CompileCommand=compileonly,compiler.c1.Test6932496::test
33 *      compiler.c1.Test6932496
34 */
35
36package compiler.c1;
37
38import jdk.internal.org.objectweb.asm.ClassWriter;
39import jdk.internal.org.objectweb.asm.FieldVisitor;
40import jdk.internal.org.objectweb.asm.Label;
41import jdk.internal.org.objectweb.asm.MethodVisitor;
42import jdk.internal.org.objectweb.asm.Opcodes;
43import jdk.internal.org.objectweb.asm.Type;
44
45import java.io.IOException;
46import java.lang.reflect.Method;
47import java.nio.file.Files;
48import java.nio.file.Paths;
49
50public class Test6932496 extends ClassLoader {
51    private static final int CLASS_FILE_VERSION = 49;
52    private static final String CLASS_TEST = "Test";
53    private static final String CLASS_OBJECT = "java/lang/Object";
54    private static final String METHOD_INIT = "<init>";
55    private static final String METHOD_TEST = "test";
56    private static final String DESC_VOID_METHOD = "()V";
57    private static final String FIELD_FLAG = "flag";
58
59    public static void main(String[] args) {
60        Test6932496 test = new Test6932496();
61        test.execute();
62    }
63
64    private void execute() {
65        byte[] bytecode = Test6932496.generateTestClass();
66
67        try {
68            Files.write(Paths.get("Test.class.dump"), bytecode);
69        } catch (IOException e) {
70            System.err.println("classfile dump failed : " + e.getMessage());
71            e.printStackTrace();
72        }
73        try {
74            Class aClass = defineClass(CLASS_TEST, bytecode, 0, bytecode.length);
75            Method test = aClass.getDeclaredMethod(METHOD_TEST);
76            test.invoke(null);
77        } catch (ClassFormatError | IllegalArgumentException
78                    | ReflectiveOperationException e) {
79            throw new RuntimeException("TESTBUG : generated class is invalid", e);
80        }
81    }
82
83    /*
84        public class Test {
85            volatile boolean flag = false;
86            public static void m() {
87                try {
88                } finally {
89                    Test test = new Test();
90                    test.flag = true;
91                }
92            }
93        }
94    */
95    private static byte[] generateTestClass() {
96        ClassWriter cw = new ClassWriter(0);
97        cw.visit(CLASS_FILE_VERSION, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER,
98                CLASS_TEST, null, CLASS_OBJECT, null);
99        // volatile boolean flag;
100        {
101            FieldVisitor fv = cw.visitField(Opcodes.ACC_VOLATILE, FIELD_FLAG,
102                    Type.BOOLEAN_TYPE.getDescriptor(),
103                    /* signature = */ null, /* value = */ null);
104        }
105
106        /*
107            public Test() {
108                flag = false;
109            }
110        */
111        {
112            MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC,
113                    METHOD_INIT, DESC_VOID_METHOD,
114                    /* signature = */ null, /* exceptions = */ null);
115
116            mv.visitCode();
117            mv.visitVarInsn(Opcodes.ALOAD, 0);
118            mv.visitMethodInsn(Opcodes.INVOKESPECIAL, CLASS_OBJECT, METHOD_INIT,
119                    DESC_VOID_METHOD, false);
120
121            mv.visitVarInsn(Opcodes.ALOAD, 0);
122            mv.visitInsn(Opcodes.ICONST_0);
123            mv.visitFieldInsn(Opcodes.PUTFIELD, CLASS_TEST, FIELD_FLAG,
124                    Type.BOOLEAN_TYPE.getDescriptor());
125
126            mv.visitInsn(Opcodes.RETURN);
127            mv.visitMaxs(/* stack = */ 2, /* locals = */ 1);
128            mv.visitEnd();
129        }
130
131        /*
132            public static void m() {
133                try {
134                } finally {
135                    Test test = new Test();
136                    test.flag = true;
137                }
138            }
139        */
140        {
141            MethodVisitor mv = cw.visitMethod(
142                    Opcodes.ACC_STATIC + Opcodes.ACC_PUBLIC,
143                    METHOD_TEST, DESC_VOID_METHOD,
144                    /* signature = */ null, /* exceptions = */ null);
145            Label beginLabel = new Label();
146            Label block1EndLabel = new Label();
147            Label handlerLabel = new Label();
148            Label block2EndLabel = new Label();
149            Label label = new Label();
150            Label endLabel = new Label();
151
152            mv.visitCode();
153            mv.visitTryCatchBlock(beginLabel, block1EndLabel, handlerLabel,
154                    /* type = <any> */ null);
155            mv.visitTryCatchBlock(handlerLabel, block2EndLabel, handlerLabel,
156                    /* type = <any> */ null);
157
158            mv.visitLabel(beginLabel);
159            mv.visitJumpInsn(Opcodes.JSR, label);
160            mv.visitLabel(block1EndLabel);
161            mv.visitJumpInsn(Opcodes.GOTO, endLabel);
162
163            mv.visitLabel(handlerLabel);
164            mv.visitVarInsn(Opcodes.ASTORE, 0);
165            mv.visitJumpInsn(Opcodes.JSR, label);
166            mv.visitLabel(block2EndLabel);
167            mv.visitVarInsn(Opcodes.ALOAD, 0);
168            mv.visitInsn(Opcodes.ATHROW);
169
170            mv.visitLabel(label);
171            mv.visitVarInsn(Opcodes.ASTORE, 1);
172            mv.visitTypeInsn(Opcodes.NEW, CLASS_TEST);
173            mv.visitInsn(Opcodes.DUP);
174            mv.visitMethodInsn(Opcodes.INVOKESPECIAL, CLASS_TEST, METHOD_INIT,
175                    DESC_VOID_METHOD);
176            mv.visitVarInsn(Opcodes.ASTORE, 2);
177
178            mv.visitVarInsn(Opcodes.ALOAD, 2);
179            mv.visitInsn(Opcodes.ICONST_1);
180            mv.visitFieldInsn(Opcodes.PUTFIELD, CLASS_TEST, FIELD_FLAG,
181                    Type.BOOLEAN_TYPE.getDescriptor());
182
183            mv.visitVarInsn(Opcodes.RET, 1);
184
185            mv.visitLabel(endLabel);
186            mv.visitInsn(Opcodes.RETURN);
187            mv.visitMaxs(/* stack = */ 2, /* locals = */ 3);
188            mv.visitEnd();
189        }
190
191        cw.visitEnd();
192        return cw.toByteArray();
193    }
194}
195