1 /* 2 * Copyright (c) 2011, 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 /* 26 * @test 27 * 28 * @summary converted from VM Testbase vm/mlvm/meth/stress/compiler/i2c_c2i. 29 * VM Testbase keywords: [feature_mlvm, nonconcurrent, quarantine] 30 * VM Testbase comments: 8079714 31 * VM Testbase readme: 32 * DESCRIPTION 33 * The test attempts to check MethodHandle i2c and c2i adapters by using sequences. 34 * Then it forces compilation of some of intermediate method handles. The test enables 35 * diagnostic printing of compilation and analyse it's own standard output 36 * to see if method is really has been compiled. When some subsequence is compiled, 37 * the test calls the whole sequence and forces decompilation (by using uncommon trap logic) 38 * of some smaller subsequence. This way both i2c and c2i adapters are created. 39 * The test compares result of calling the sequence of MHs with the results computed 40 * by the test and fails if the result is different. 41 * The test is a random one, it makes random sequences of MH and calls random subsequences. 42 * To facilitate reproducing test failures, it prints it's random seed, which can be fed 43 * to test when reproducing a problem. 44 * See vm.mlvm.meth.stress.java.sequences.Test for details on MH sequences. 45 * 46 * @library /vmTestbase 47 * /test/lib 48 * @run driver jdk.test.lib.FileInstaller . . 49 * 50 * @comment build test class and indify classes 51 * @build vm.mlvm.meth.stress.compiler.i2c_c2i.Test 52 * @run driver vm.mlvm.share.IndifiedClassesBuilder 53 * 54 * @run main/othervm vm.mlvm.meth.stress.compiler.i2c_c2i.Test 55 */ 56 57 package vm.mlvm.meth.stress.compiler.i2c_c2i; 58 59 import java.lang.invoke.MethodHandle; 60 import java.lang.invoke.MethodHandles; 61 import java.lang.invoke.MethodType; 62 import java.util.concurrent.CyclicBarrier; 63 64 import vm.mlvm.meth.share.Argument; 65 import vm.mlvm.meth.share.MHTransformationGen; 66 import vm.mlvm.meth.share.RandomArgumentsGen; 67 import vm.mlvm.meth.share.transform.v2.MHMacroTF; 68 import vm.mlvm.share.Env; 69 import vm.mlvm.share.MlvmTest; 70 71 // TODO: check that i2c/c2i adapters are really created 72 // TODO: check deopt using vm.mlvm.share.comp framework 73 // TODO: use multi-threaded test framework 74 public class Test extends MlvmTest { 75 76 private static final int THREADS 77 = Runtime.getRuntime().availableProcessors(); 78 79 Object finalTarget() { 80 return new Integer(0); 81 } 82 83 static class A { 84 MHMacroTF trList; 85 86 A(MHMacroTF trList) { 87 this.trList = trList; 88 } 89 90 Object m() throws Throwable { 91 Env.traceNormal("Original m() in thread " 92 + Thread.currentThread().getName()); 93 return MHTransformationGen.callSequence(this.trList, false); 94 } 95 } 96 97 static class B extends A { 98 B() { 99 super(null); 100 } 101 102 @Override 103 Object m() throws Throwable { 104 Env.traceNormal("Deoptimized m() in thread " 105 + Thread.currentThread().getName()); 106 return new Integer(1); 107 } 108 } 109 110 volatile A intermediateTarget; 111 112 Object callIntemediateTarget() throws Throwable { 113 return this.intermediateTarget.m(); 114 } 115 116 CyclicBarrier startBarrier = new CyclicBarrier(THREADS + 1); 117 118 volatile boolean testDone = false; 119 120 @Override 121 public boolean run() throws Throwable { 122 123 final MethodHandle mhB = MethodHandles.lookup().findVirtual(Test.class, 124 "finalTarget", MethodType.methodType(Object.class)); 125 126 final Argument finalRetVal = Argument.fromValue(new Integer(0)); 127 finalRetVal.setPreserved(true); 128 129 this.intermediateTarget = new A( 130 MHTransformationGen.createSequence(finalRetVal, Test.this, mhB, 131 RandomArgumentsGen.createRandomArgs(true, mhB.type()))); 132 133 final MethodHandle mhM = MethodHandles.lookup().findVirtual(Test.class, 134 "callIntemediateTarget", MethodType.methodType(Object.class)); 135 136 final Argument[] finalArgs = RandomArgumentsGen.createRandomArgs(true, 137 mhM.type()); 138 139 Thread[] threads = new Thread[THREADS]; 140 for (int t = 0; t < THREADS; t++) { 141 (threads[t] = new Thread("Stresser " + t) { 142 143 public void run() { 144 try { 145 MHMacroTF tList = MHTransformationGen.createSequence( 146 finalRetVal, Test.this, mhM, finalArgs); 147 Test.this.startBarrier.await(); 148 while ( ! Test.this.testDone) { 149 int e = (Integer) Test.this.intermediateTarget.m(); 150 int r = (Integer) MHTransformationGen.callSequence( 151 tList, false); 152 if (r != e) 153 Env.traceNormal("Wrong result in thread " 154 + getName() + ", but this is OK"); 155 } 156 Env.traceVerbose("Thread " + getName()+ ": work done"); 157 } catch (Throwable t) { 158 markTestFailed("Exception in thread " + getName(), t); 159 } 160 } 161 }).start(); 162 } 163 164 this.startBarrier.await(); 165 Env.traceImportant("Threads started"); 166 167 Thread.sleep(3000); 168 169 Env.traceImportant("Deoptimizing"); 170 // Force deoptimization in uncommon trap logic 171 this.intermediateTarget = (A) Test.class.getClassLoader().loadClass( 172 Test.class.getName() + "$B").newInstance(); 173 174 Thread.sleep(3000); 175 176 this.testDone = true; 177 for (int t = 0; t < THREADS; t++) { 178 threads[t].join(); 179 } 180 return true; 181 } 182 183 public static void main(String[] args) { 184 MlvmTest.launch(args); 185 } 186 }