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