1 /* 2 * Copyright (c) 2014, 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 import java.lang.reflect.Constructor; 25 import java.lang.reflect.Method; 26 27 import jdk.internal.org.objectweb.asm.ClassWriter; 28 import jdk.internal.org.objectweb.asm.Label; 29 import jdk.internal.org.objectweb.asm.MethodVisitor; 30 import static jdk.internal.org.objectweb.asm.Opcodes.*; 31 32 /** 33 * @test 34 * @bug 8051344 35 * @summary Force OSR compilation with non-empty stack at the OSR entry point. 36 * @modules java.base/jdk.internal.org.objectweb.asm 37 * @compile -XDignore.symbol.file TestOSRWithNonEmptyStack.java 38 * @run main/othervm -XX:CompileOnly=TestCase.test TestOSRWithNonEmptyStack 39 */ 40 public class TestOSRWithNonEmptyStack extends ClassLoader { 41 private static final int CLASS_FILE_VERSION = 52; 42 private static final String CLASS_NAME = "TestCase"; 43 private static final String METHOD_NAME = "test"; 44 private static final int ITERATIONS = 1_000_000; 45 46 private static byte[] generateTestClass() { 47 ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); 48 49 cw.visit(TestOSRWithNonEmptyStack.CLASS_FILE_VERSION, ACC_PUBLIC, 50 TestOSRWithNonEmptyStack.CLASS_NAME, null, "java/lang/Object", 51 null); 52 53 TestOSRWithNonEmptyStack.generateConstructor(cw); 54 TestOSRWithNonEmptyStack.generateTestMethod(cw); 55 56 cw.visitEnd(); 57 return cw.toByteArray(); 58 } 59 60 private static void generateConstructor(ClassWriter classWriter) { 61 MethodVisitor mv = classWriter.visitMethod(ACC_PUBLIC, "<init>", "()V", 62 null, null); 63 64 mv.visitCode(); 65 66 mv.visitVarInsn(ALOAD, 0); 67 mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", 68 false); 69 mv.visitInsn(RETURN); 70 71 mv.visitMaxs(0, 0); 72 mv.visitEnd(); 73 } 74 75 private static void generateTestMethod(ClassWriter classWriter) { 76 MethodVisitor mv = classWriter.visitMethod(ACC_PUBLIC, 77 TestOSRWithNonEmptyStack.METHOD_NAME, "()V", null, null); 78 Label osrEntryPoint = new Label(); 79 80 mv.visitCode(); 81 // Push 'this' into stack before OSR entry point to bail out compilation 82 mv.visitVarInsn(ALOAD, 0); 83 // Setup loop counter 84 mv.visitInsn(ICONST_0); 85 mv.visitVarInsn(ISTORE, 1); 86 // Begin loop 87 mv.visitLabel(osrEntryPoint); 88 // Increment loop counter 89 mv.visitVarInsn(ILOAD, 1); 90 mv.visitInsn(ICONST_1); 91 mv.visitInsn(IADD); 92 // Duplicate it for loop condition check 93 mv.visitInsn(DUP); 94 mv.visitVarInsn(ISTORE, 1); 95 // Check loop condition 96 mv.visitLdcInsn(TestOSRWithNonEmptyStack.ITERATIONS); 97 mv.visitJumpInsn(IF_ICMPLT, osrEntryPoint); 98 // Pop 'this'. 99 mv.visitInsn(POP); 100 mv.visitInsn(RETURN); 101 102 mv.visitMaxs(0, 0); 103 mv.visitEnd(); 104 } 105 106 private void run() { 107 byte[] bytecode = TestOSRWithNonEmptyStack.generateTestClass(); 108 109 try { 110 Class klass = defineClass(TestOSRWithNonEmptyStack.CLASS_NAME, 111 bytecode, 0, bytecode.length); 112 113 Constructor ctor = klass.getConstructor(); 114 Method method = klass.getDeclaredMethod( 115 TestOSRWithNonEmptyStack.METHOD_NAME); 116 117 Object testCase = ctor.newInstance(); 118 method.invoke(testCase); 119 } catch (Exception e) { 120 throw new RuntimeException( 121 "Test bug: generated class should be valid.", e); 122 } 123 } 124 125 public static void main(String args[]) { 126 new TestOSRWithNonEmptyStack().run(); 127 } 128 }