1 /*
  2  * Copyright (c) 2014, 2023, 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 OverloadCompileQueueTest
 26  * @key stress randomness
 27  * @summary stressing code cache by overloading compile queues
 28  * @library /test/lib /
 29  * @modules java.base/jdk.internal.misc
 30  *          java.management
 31  *
 32  * @build jdk.test.whitebox.WhiteBox
 33  *        compiler.codecache.stress.TestCaseImpl
 34  * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
 35  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
 36  *                   -XX:+WhiteBoxAPI
 37  *                   -XX:CompileCommand=dontinline,compiler.codecache.stress.Helper$TestCase::method
 38  *                   -XX:CompileCommand=exclude,java.lang.Thread::sleep
 39  *                   -XX:CompileCommand=exclude,java.lang.Thread::sleepNanos
 40  *                   -XX:CompileCommand=exclude,java.lang.Thread::beforeSleep
 41  *                   -XX:CompileCommand=exclude,java.lang.Thread::afterSleep
 42  *                   -XX:CompileCommand=exclude,java.lang.Math::min
 43  *                   -XX:CompileCommand=exclude,jdk.internal.event.ThreadSleepEvent::*
 44  *                   -XX:CompileCommand=exclude,jdk.internal.event.SleepEvent::*
 45  *                   -XX:CompileCommand=exclude,jdk.internal.event.Event::*
 46  *                   -XX:-SegmentedCodeCache
 47  *                   compiler.codecache.stress.OverloadCompileQueueTest
 48  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
 49  *                   -XX:+WhiteBoxAPI
 50  *                   -XX:CompileCommand=dontinline,compiler.codecache.stress.Helper$TestCase::method
 51  *                   -XX:CompileCommand=exclude,java.lang.Thread::sleep
 52  *                   -XX:CompileCommand=exclude,java.lang.Thread::sleepNanos
 53  *                   -XX:CompileCommand=exclude,java.lang.Thread::beforeSleep
 54  *                   -XX:CompileCommand=exclude,java.lang.Thread::afterSleep
 55  *                   -XX:CompileCommand=exclude,java.lang.Math::min
 56  *                   -XX:CompileCommand=exclude,jdk.internal.event.ThreadSleepEvent::*
 57  *                   -XX:CompileCommand=exclude,jdk.internal.event.SleepEvent::*
 58  *                   -XX:CompileCommand=exclude,jdk.internal.event.Event::*
 59  *                   -XX:+SegmentedCodeCache
 60  *                   compiler.codecache.stress.OverloadCompileQueueTest
 61  */
 62 
 63 package compiler.codecache.stress;
 64 
 65 import jdk.test.lib.Platform;
 66 import jdk.test.lib.Utils;
 67 
 68 import java.lang.reflect.Method;
 69 import java.util.stream.IntStream;
 70 import java.util.Random;
 71 
 72 class LockUnlockThread extends Thread {
 73     private static final int MAX_SLEEP = 10000;
 74     private static final int DELAY_BETWEEN_LOCKS = 100;
 75     private final Random rng = Utils.getRandomInstance();
 76 
 77     public volatile boolean isActive = true;
 78 
 79     @Override
 80     public void run() {
 81         try {
 82             while (isActive) {
 83                 int timeInLockedState = rng.nextInt(MAX_SLEEP);
 84                 Helper.WHITE_BOX.lockCompilation();
 85                 Thread.sleep(timeInLockedState);
 86                 Helper.WHITE_BOX.unlockCompilation();
 87                 Thread.sleep(DELAY_BETWEEN_LOCKS);
 88             }
 89         } catch (InterruptedException e) {
 90             if (isActive) {
 91                 throw new Error("TESTBUG: LockUnlockThread was unexpectedly interrupted", e);
 92             }
 93         } finally {
 94             Helper.WHITE_BOX.unlockCompilation();
 95         }
 96     }
 97 }
 98 
 99 public class OverloadCompileQueueTest implements Runnable {
100     private static final String METHOD_TO_ENQUEUE = "method";
101     private static final int LEVEL_SIMPLE = 1;
102     private static final int LEVEL_FULL_OPTIMIZATION = 4;
103     private static final boolean TIERED_COMPILATION
104             = Helper.WHITE_BOX.getBooleanVMFlag("TieredCompilation");
105     private static final int TIERED_STOP_AT_LEVEL
106             = Helper.WHITE_BOX.getIntxVMFlag("TieredStopAtLevel").intValue();
107     private static final int[] AVAILABLE_LEVELS;
108     static {
109         if (TIERED_COMPILATION) {
110             AVAILABLE_LEVELS = IntStream
111                     .rangeClosed(LEVEL_SIMPLE, TIERED_STOP_AT_LEVEL)
112                     .toArray();
113         } else if (Platform.isServer() && !Platform.isEmulatedClient()) {
114             AVAILABLE_LEVELS = new int[] { LEVEL_FULL_OPTIMIZATION };
115         } else if (Platform.isClient() || Platform.isMinimal() || Platform.isEmulatedClient()) {
116             AVAILABLE_LEVELS = new int[] { LEVEL_SIMPLE };
117         } else {
118             throw new Error("TESTBUG: unknown VM: " + Platform.vmName);
119         }
120     }
121 
122     public static void main(String[] args) throws InterruptedException {
123         LockUnlockThread lockUnlockThread = new LockUnlockThread();
124         lockUnlockThread.start();
125 
126         if (Platform.isInt()) {
127             throw new Error("TESTBUG: test can not be run in interpreter");
128         }
129         new CodeCacheStressRunner(new OverloadCompileQueueTest()).runTest();
130 
131         lockUnlockThread.isActive = false;
132         lockUnlockThread.interrupt();
133         lockUnlockThread.join();
134     }
135 
136     @Override
137     public void run() {
138         Helper.TestCase obj = Helper.TestCase.get();
139         Class clazz = obj.getClass();
140         Method mEnqueue;
141         try {
142             mEnqueue = clazz.getMethod(METHOD_TO_ENQUEUE);
143         } catch (NoSuchMethodException | SecurityException e) {
144             throw new Error(String.format(
145                     "TESTBUG: cannot get method '%s' of class %s",
146                     METHOD_TO_ENQUEUE, clazz.getName()), e);
147         }
148         for (int compLevel : AVAILABLE_LEVELS) {
149             Helper.WHITE_BOX.enqueueMethodForCompilation(mEnqueue, compLevel);
150         }
151     }
152 
153 }