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 25 package compiler.codecache.stress; 26 27 import jdk.test.lib.Asserts; 28 import jdk.test.lib.ByteCodeLoader; 29 import jdk.test.lib.InfiniteLoop; 30 import jdk.test.lib.Utils; 31 import sun.hotspot.WhiteBox; 32 33 import java.io.BufferedInputStream; 34 import java.io.ByteArrayOutputStream; 35 import java.io.IOException; 36 import java.util.Random; 37 import java.util.concurrent.Callable; 38 39 public final class Helper { 40 public static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); 41 public static final Random RNG = Utils.getRandomInstance(); 42 43 private static final long THRESHOLD = WHITE_BOX.getIntxVMFlag("CompileThreshold"); 44 private static final String TEST_CASE_IMPL_CLASS_NAME = "compiler.codecache.stress.Helper$TestCaseImpl"; 45 private static byte[] CLASS_DATA; 46 static { 47 try { 48 CLASS_DATA = loadClassData(TEST_CASE_IMPL_CLASS_NAME); 49 } catch (IOException e) { 50 throw new Error("TESTBUG: cannot load class byte code " + TEST_CASE_IMPL_CLASS_NAME, e); 51 } 52 } 53 54 private Helper() { 55 } 56 57 public static void startInfiniteLoopThread(Runnable action) { 58 startInfiniteLoopThread(action, 0L); 59 } 60 61 public static void startInfiniteLoopThread(Runnable action, long millis) { 62 Thread t = new Thread(new InfiniteLoop(action, millis)); 63 t.setDaemon(true); 64 t.start(); 65 } 66 67 public static int callMethod(Callable<Integer> callable, int expected) { 68 int result = 0; 69 for (int i = 0; i < THRESHOLD; ++i) { 70 try { 71 result = callable.call(); 72 } catch (Exception e) { 73 throw new AssertionError( 74 "Exception occurred during test method execution", e); 75 } 76 Asserts.assertEQ(result, expected, "Method returns unexpected value"); 77 } 78 return result; 79 } 80 81 private static byte[] loadClassData(String name) throws IOException { 82 try (BufferedInputStream in = new BufferedInputStream( 83 ClassLoader.getSystemResourceAsStream(name.replace(".", "/") 84 + ".class"))) { 85 ByteArrayOutputStream result = new ByteArrayOutputStream(); 86 byte[] buffer = new byte[1024]; 87 int read; 88 while ((read = in.read(buffer)) != -1) { 89 result.write(buffer, 0, read); 90 } 91 return result.toByteArray(); 92 } 93 } 94 95 public interface TestCase { 96 97 public static TestCase get() { 98 try { 99 Class clazz = ByteCodeLoader.load( 100 TEST_CASE_IMPL_CLASS_NAME, CLASS_DATA); 101 return (TestCase) clazz.newInstance(); 102 } catch (ReflectiveOperationException e) { 103 throw new Error(String.format( 104 "TESTBUG: error while creating %s instance from reloaded class", 105 TEST_CASE_IMPL_CLASS_NAME), e); 106 } 107 } 108 109 Callable<Integer> getCallable(); 110 int method(); 111 int expectedValue(); 112 } 113 114 public static class TestCaseImpl implements TestCase { 115 private static final int RETURN_VALUE = 42; 116 private static final int RECURSION_DEPTH = 10; 117 private volatile int i; 118 119 @Override 120 public Callable<Integer> getCallable() { 121 return () -> { 122 i = 0; 123 return method(); 124 }; 125 } 126 127 @Override 128 public int method() { 129 ++i; 130 int result = RETURN_VALUE; 131 if (i < RECURSION_DEPTH) { 132 return result + method(); 133 } 134 return result; 135 } 136 137 @Override 138 public int expectedValue() { 139 return RETURN_VALUE * RECURSION_DEPTH; 140 } 141 } 142 143 }