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