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