1 /*
2 * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
3 * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * This code is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 only, as
8 * published by the Free Software Foundation.
9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 *
24 */
25
26 /*
27 * @test
28 * @key randomness
29 * @library /test/lib /
30 * @build jdk.test.whitebox.WhiteBox
31 * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
32 * @run main/othervm -Xbootclasspath/a:. -Xcomp -XX:-TieredCompilation -XX:+UnlockExperimentalVMOptions -XX:+HotCodeHeap -XX:+NMethodRelocation
33 * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:HotCodeIntervalSeconds=0 -XX:HotCodeSampleSeconds=10
34 * -XX:HotCodeStablePercent=-1 -XX:HotCodeSamplePercent=100 -XX:HotCodeStartupDelaySeconds=0
35 * compiler.hotcode.StressHotCodeCollector
36 */
37
38 package compiler.hotcode;
39
40 import java.lang.reflect.Method;
41 import java.util.ArrayList;
42 import java.util.Random;
43 import jdk.test.lib.Utils;
44
45 import jdk.test.lib.compiler.InMemoryJavaCompiler;
46 import jdk.test.whitebox.WhiteBox;
47
48 public class StressHotCodeCollector {
49
50 private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
51 private static final double RUN_MILLIS = 60_000;
52
53 private static TestMethod[] methods = new TestMethod[100];
54
55 private static byte[] num1;
56 private static byte[] num2;
57
58 private static byte[] genNum(Random random, int digitCount) {
59 byte[] num = new byte[digitCount];
60 int d;
61 do {
62 d = random.nextInt(10);
63 } while (d == 0);
64
65 num[0] = (byte)d;
66 for (int i = 1; i < digitCount; ++i) {
67 num[i] = (byte)random.nextInt(10);
68 }
69 return num;
70 }
71
72 private static void initNums() {
73 final long seed = 8374592837465123L;
74 Random random = new Random(seed);
75
76 final int digitCount = 40;
77 num1 = genNum(random, digitCount);
78 num2 = genNum(random, digitCount);
79 }
80
81 private static void generateCode() throws Exception {
82 byte[] result = new byte[num1.length + 1];
83
84 for (int i = 0; i < methods.length; i++) {
85 methods[i] = new TestMethod();
86 }
87 }
88
89 public static void main(String[] args) throws Exception {
90
91 initNums();
92 generateCode();
93
94 long start = System.currentTimeMillis();
95 Random random = Utils.getRandomInstance();
96
97 while (System.currentTimeMillis() - start < RUN_MILLIS) {
98 for (TestMethod m : methods) {
99 if (random.nextInt(100) < 10) {
100 m.deoptimize();
101 }
102
103 byte[] result = new byte[num1.length + 1];
104 m.invoke(num1, num2, result);
105 }
106 }
107 }
108
109 private static final class TestMethod {
110 private static final String CLASS_NAME = "A";
111 private static final String METHOD_TO_COMPILE = "sum";
112 private static final String JAVA_CODE = """
113 public class A {
114
115 public static void sum(byte[] n1, byte[] n2, byte[] out) {
116 long start = System.currentTimeMillis();
117 while (System.currentTimeMillis() - start < 100) {}
118
119 final int digitCount = n1.length;
120 int carry = 0;
121 for (int i = digitCount - 1; i >= 0; --i) {
122 int sum = n1[i] + n2[i] + carry;
123 out[i] = (byte)(sum % 10);
124 carry = sum / 10;
125 }
126 if (carry != 0) {
127 for (int i = digitCount; i > 0; --i) {
128 out[i] = out[i - 1];
129 }
130 out[0] = (byte)carry;
131 }
132 }
133 }""";
134
135 private static final byte[] BYTE_CODE;
136
137 static {
138 BYTE_CODE = InMemoryJavaCompiler.compile(CLASS_NAME, JAVA_CODE);
139 }
140
141 private final Method method;
142
143 private static ClassLoader createClassLoaderFor() {
144 return new ClassLoader() {
145 @Override
146 public Class<?> loadClass(String name) throws ClassNotFoundException {
147 if (!name.equals(CLASS_NAME)) {
148 return super.loadClass(name);
149 }
150
151 return defineClass(name, BYTE_CODE, 0, BYTE_CODE.length);
152 }
153 };
154 }
155
156 public TestMethod() throws Exception {
157 var cl = createClassLoaderFor().loadClass(CLASS_NAME);
158 method = cl.getMethod(METHOD_TO_COMPILE, byte[].class, byte[].class, byte[].class);
159 WHITE_BOX.testSetDontInlineMethod(method, true);
160 }
161
162 public void invoke(byte[] num1, byte[] num2, byte[] result) throws Exception {
163 method.invoke(null, num1, num2, result);
164 }
165
166 public void deoptimize() {
167 WHITE_BOX.deoptimizeMethod(method);
168 }
169 }
170 }