RedefineTest.java revision 11707:ad7af1afda7a
1/*
2 * Copyright (c) 2016, 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 * @test
26 * @bug 8072008
27 * @modules java.base/jdk.internal.org.objectweb.asm
28 *          java.base/jdk.internal.misc
29 *          java.base/jdk.internal.vm.annotation
30 * @library /testlibrary /test/lib / ../patches
31 * @requires vm.flavor != "minimal"
32 *
33 * @build sun.hotspot.WhiteBox
34 *        java.base/java.lang.invoke.MethodHandleHelper
35 *        compiler.jsr292.NonInlinedCall.RedefineTest
36 * @run driver compiler.jsr292.NonInlinedCall.Agent
37 *             agent.jar
38 *             compiler.jsr292.NonInlinedCall.RedefineTest
39 * @run driver ClassFileInstaller sun.hotspot.WhiteBox
40 *                                sun.hotspot.WhiteBox$WhiteBoxPermission
41 *                                compiler.jsr292.NonInlinedCall.RedefineTest
42 * @run main/bootclasspath/othervm -javaagent:agent.jar
43 *                                 -XX:+IgnoreUnrecognizedVMOptions
44 *                                 -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
45 *                                 -Xbatch -XX:-TieredCompilation -XX:CICompilerCount=1
46 *                                 compiler.jsr292.NonInlinedCall.RedefineTest
47 */
48
49package compiler.jsr292.NonInlinedCall;
50
51import jdk.internal.misc.Unsafe;
52import jdk.internal.org.objectweb.asm.ClassWriter;
53import jdk.internal.org.objectweb.asm.MethodVisitor;
54import jdk.internal.vm.annotation.DontInline;
55import sun.hotspot.WhiteBox;
56
57import java.lang.instrument.ClassDefinition;
58import java.lang.instrument.Instrumentation;
59import java.lang.invoke.MethodHandle;
60import java.lang.invoke.MethodHandleHelper;
61import java.lang.invoke.MethodHandles;
62import java.lang.invoke.MethodType;
63
64import static jdk.internal.org.objectweb.asm.Opcodes.ACC_PUBLIC;
65import static jdk.internal.org.objectweb.asm.Opcodes.ACC_STATIC;
66import static jdk.internal.org.objectweb.asm.Opcodes.ACC_SUPER;
67import static jdk.internal.org.objectweb.asm.Opcodes.IRETURN;
68
69public class RedefineTest {
70    static final MethodHandles.Lookup LOOKUP = MethodHandleHelper.IMPL_LOOKUP;
71    static final Unsafe UNSAFE = Unsafe.getUnsafe();
72
73    static final String NAME = "compiler/jsr292/NonInlinedCall/RedefineTest$T";
74
75    static Class<?> getClass(int r) {
76        byte[] classFile = getClassFile(r);
77        return UNSAFE.defineClass(NAME, classFile, 0, classFile.length, null, null);
78    }
79
80    /**
81     * Generates a class of the following shape:
82     *     static class T {
83     *         @DontInline public static int f() { return $r; }
84     *     }
85     */
86    static byte[] getClassFile(int r) {
87        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
88        MethodVisitor mv;
89        cw.visit(52, ACC_PUBLIC | ACC_SUPER, NAME, null, "java/lang/Object", null);
90        {
91            mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "f", "()I", null, null);
92            mv.visitAnnotation("Ljdk/internal/vm/annotation/DontInline;", true);
93            mv.visitCode();
94            mv.visitLdcInsn(r);
95            mv.visitInsn(IRETURN);
96            mv.visitMaxs(0, 0);
97            mv.visitEnd();
98        }
99        cw.visitEnd();
100        return cw.toByteArray();
101    }
102
103    static final MethodHandle mh;
104    static final Class<?> CLS = getClass(0);
105    static {
106        try {
107            mh = LOOKUP.findStatic(CLS, "f", MethodType.methodType(int.class));
108        } catch (Exception e) {
109            throw new Error(e);
110        }
111    }
112
113    static final WhiteBox WB = WhiteBox.getWhiteBox();
114
115    @DontInline
116    static int invokeBasic() {
117        try {
118            return (int)mh.invokeExact();
119        } catch (Throwable e) {
120            throw new Error(e);
121        }
122    }
123
124    static Instrumentation instr;
125    public static void premain(String args, Instrumentation instr) {
126        RedefineTest.instr = instr;
127    }
128
129
130    public static void main(String[] args) throws Exception {
131        for (int i = 0; i < 20_000; i++) {
132            int r = invokeBasic();
133            if (r != 0) {
134                throw new Error(r + " != 0");
135            }
136        }
137        // WB.ensureCompiled();
138
139        redefine();
140
141        int exp = (instr != null) ? 1 : 0;
142
143        for (int i = 0; i < 20_000; i++) {
144            if (invokeBasic() != exp) {
145                throw new Error();
146            }
147        }
148
149        WB.clearInlineCaches();
150
151        for (int i = 0; i < 20_000; i++) {
152            if (invokeBasic() != exp) {
153                throw new Error();
154            }
155        }
156
157        // WB.ensureCompiled();
158    }
159
160    static void redefine() {
161        if (instr == null) {
162            System.out.println("NOT REDEFINED");
163            return;
164        }
165        ClassDefinition cd = new ClassDefinition(CLS, getClassFile(1));
166        try {
167            instr.redefineClasses(cd);
168        } catch (Exception e) {
169            throw new Error(e);
170        }
171        System.out.println("REDEFINED");
172    }
173}
174