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 * @ignore
29 * @key randomness
30 * @library /test/lib /
31 * @build jdk.test.whitebox.WhiteBox
32 * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
33 * @run main/othervm -Xbootclasspath/a:. -Xcomp -XX:-TieredCompilation -XX:+UnlockExperimentalVMOptions -XX:+HotCodeHeap -XX:+NMethodRelocation
34 * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:HotCodeIntervalSeconds=0 -XX:HotCodeSampleSeconds=10
35 * -XX:HotCodeStablePercent=-1 -XX:HotCodeSamplePercent=100 -XX:HotCodeStartupDelaySeconds=0
36 * compiler.hotcode.StressHotCodeCollector
37 */
38
39 package compiler.hotcode;
40
41 import java.lang.reflect.Method;
42 import java.util.ArrayList;
43 import java.util.Random;
44 import jdk.test.lib.Utils;
45
46 import jdk.test.lib.compiler.InMemoryJavaCompiler;
47 import jdk.test.whitebox.WhiteBox;
48
49 public class StressHotCodeCollector {
50
51 private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
52 private static final double RUN_MILLIS = 60_000;
53
54 private static TestMethod[] methods = new TestMethod[100];
55
56 private static byte[] num1;
57 private static byte[] num2;
58
59 private static byte[] genNum(Random random, int digitCount) {
60 byte[] num = new byte[digitCount];
61 int d;
62 do {
63 d = random.nextInt(10);
64 } while (d == 0);
65
66 num[0] = (byte)d;
67 for (int i = 1; i < digitCount; ++i) {
68 num[i] = (byte)random.nextInt(10);
69 }
70 return num;
71 }
72
73 private static void initNums() {
74 final long seed = 8374592837465123L;
75 Random random = new Random(seed);
76
77 final int digitCount = 40;
78 num1 = genNum(random, digitCount);
79 num2 = genNum(random, digitCount);
80 }
81
82 private static void generateCode() throws Exception {
83 byte[] result = new byte[num1.length + 1];
84
85 for (int i = 0; i < methods.length; i++) {
86 methods[i] = new TestMethod();
87 }
88 }
89
90 public static void main(String[] args) throws Exception {
91
92 initNums();
93 generateCode();
94
95 long start = System.currentTimeMillis();
96 Random random = Utils.getRandomInstance();
97
98 while (System.currentTimeMillis() - start < RUN_MILLIS) {
99 for (TestMethod m : methods) {
100 if (random.nextInt(100) < 10) {
101 m.deoptimize();
102 }
103
104 byte[] result = new byte[num1.length + 1];
105 m.invoke(num1, num2, result);
106 }
107 }
108 }
109
110 private static final class TestMethod {
111 private static final String CLASS_NAME = "A";
112 private static final String METHOD_TO_COMPILE = "sum";
113 private static final String JAVA_CODE = """
114 public class A {
115
116 public static void sum(byte[] n1, byte[] n2, byte[] out) {
117 long start = System.currentTimeMillis();
118 while (System.currentTimeMillis() - start < 100) {}
119
120 final int digitCount = n1.length;
121 int carry = 0;
122 for (int i = digitCount - 1; i >= 0; --i) {
123 int sum = n1[i] + n2[i] + carry;
124 out[i] = (byte)(sum % 10);
125 carry = sum / 10;
126 }
127 if (carry != 0) {
128 for (int i = digitCount; i > 0; --i) {
129 out[i] = out[i - 1];
130 }
131 out[0] = (byte)carry;
132 }
133 }
134 }""";
135
136 private static final byte[] BYTE_CODE;
137
138 static {
139 BYTE_CODE = InMemoryJavaCompiler.compile(CLASS_NAME, JAVA_CODE);
140 }
141
142 private final Method method;
143
144 private static ClassLoader createClassLoaderFor() {
145 return new ClassLoader() {
146 @Override
147 public Class<?> loadClass(String name) throws ClassNotFoundException {
148 if (!name.equals(CLASS_NAME)) {
149 return super.loadClass(name);
150 }
151
152 return defineClass(name, BYTE_CODE, 0, BYTE_CODE.length);
153 }
154 };
155 }
156
157 public TestMethod() throws Exception {
158 var cl = createClassLoaderFor().loadClass(CLASS_NAME);
159 method = cl.getMethod(METHOD_TO_COMPILE, byte[].class, byte[].class, byte[].class);
160 WHITE_BOX.testSetDontInlineMethod(method, true);
161 }
162
163 public void invoke(byte[] num1, byte[] num2, byte[] result) throws Exception {
164 method.invoke(null, num1, num2, result);
165 }
166
167 public void deoptimize() {
168 WHITE_BOX.deoptimizeMethod(method);
169 }
170 }
171 }