1 /*
2 * Copyright (c) 2025, 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 package org.openjdk.bench.valhalla.invoke.array;
24
25 import jdk.internal.value.ValueClass;
26 import org.openjdk.jmh.annotations.Benchmark;
27 import org.openjdk.jmh.annotations.BenchmarkMode;
28 import org.openjdk.jmh.annotations.CompilerControl;
29 import org.openjdk.jmh.annotations.Fork;
30 import org.openjdk.jmh.annotations.Measurement;
31 import org.openjdk.jmh.annotations.Mode;
32 import org.openjdk.jmh.annotations.OperationsPerInvocation;
33 import org.openjdk.jmh.annotations.OutputTimeUnit;
34 import org.openjdk.jmh.annotations.Scope;
35 import org.openjdk.jmh.annotations.Setup;
36 import org.openjdk.jmh.annotations.State;
37 import org.openjdk.jmh.annotations.Warmup;
38
39 import java.util.concurrent.TimeUnit;
40
41 @Fork(value = 3, jvmArgsAppend = {"--enable-preview", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"})
42 @Warmup(iterations = 5, time = 1)
43 @Measurement(iterations = 5, time = 1)
44 @OutputTimeUnit(TimeUnit.NANOSECONDS)
45 @BenchmarkMode(Mode.AverageTime)
46 @State(Scope.Thread)
47 public class ValueNullFree {
48
49 /*
50 virtual method invocations:
51 target0 - statically known target method.
52 target1 - the single invoked method (should be inlined)
53 target2 - two invoked method (should be inlined, cache-inline)
54 target3 - thee invoked method (shouldn't be inlined)
55
56 */
57
58
59 public static final int SIZE = 128;
60
61 public interface InterfaceInt {
62 public int value();
63 }
64
65 public static value class ValueInt0 implements InterfaceInt {
66 public final int value;
67 public ValueInt0(int value) {
68 this.value = value;
69 }
70 @Override
71 public int value() {
72 return value;
73 }
74 }
75
76 public static value class ValueInt1 implements InterfaceInt {
77 public final int value;
78 public ValueInt1(int value) {
79 this.value = value;
80 }
81 @Override
82 public int value() {
83 return value;
84 }
85 }
86
87 public static value class ValueInt2 implements InterfaceInt {
88 public final int value;
89 public ValueInt2(int value) {
90 this.value = value;
91 }
92 @Override
93 public int value() {
94 return value;
95 }
96 }
97
98 @State(Scope.Thread)
99 public static class Int0State {
100 public InterfaceInt[] arr;
101 @Setup
102 public void setup() {
103 arr = new InterfaceInt[SIZE];
104 for (int i = 0; i < arr.length; i++) {
105 arr[i] = new ValueInt0(i);
106 }
107 }
108 }
109
110 @State(Scope.Thread)
111 public static class Int1State {
112 public InterfaceInt[] arr;
113 @Setup
114 public void setup() {
115 arr = new InterfaceInt[SIZE];
116 for (int i = 0; i < arr.length; i++) {
117 arr[i] = new ValueInt1(i);
118 }
119 }
120 }
121
122 @State(Scope.Thread)
123 public static class Int2State {
124 public InterfaceInt[] arr;
125 @Setup
126 public void setup() {
127 arr = new InterfaceInt[SIZE];
128 for (int i = 0; i < arr.length; i++) {
129 arr[i] = new ValueInt2(i);
130 }
131 }
132 }
133
134 @State(Scope.Thread)
135 public static class Val0State {
136 public ValueInt0[] arr;
137 @Setup
138 public void setup() {
139 arr = (ValueInt0[]) ValueClass.newNullRestrictedAtomicArray(ValueInt0.class, SIZE, new ValueInt0(0));
140 for (int i = 0; i < arr.length; i++) {
141 arr[i] = new ValueInt0(i);
142 }
143 }
144 }
145
146 @State(Scope.Thread)
147 public static class Val1State {
148 public ValueInt1[] arr;
149 @Setup
150 public void setup() {
151 arr = (ValueInt1[]) ValueClass.newNullRestrictedAtomicArray(ValueInt1.class, SIZE, new ValueInt1(0));
152 for (int i = 0; i < arr.length; i++) {
153 arr[i] = new ValueInt1(i);
154 }
155 }
156 }
157
158 @State(Scope.Thread)
159 public static class Val22State {
160 public ValueInt2[] arr;
161 @Setup
162 public void setup() {
163 arr = (ValueInt2[]) ValueClass.newNullRestrictedAtomicArray(ValueInt2.class, SIZE, new ValueInt2(0));
164 for (int i = 0; i < arr.length; i++) {
165 arr[i] = new ValueInt2(i);
166 }
167 }
168 }
169
170
171 @CompilerControl(CompilerControl.Mode.DONT_INLINE)
172 public int reduce_int(InterfaceInt[] arr) {
173 int r = 0;
174 for (int i = 0; i < arr.length; i++) {
175 r += arr[i].value();
176 }
177 return r;
178 }
179
180 @CompilerControl(CompilerControl.Mode.DONT_INLINE)
181 public int reduce_val(ValueInt0[] arr) {
182 int r = 0;
183 for (int i = 0; i < arr.length; i++) {
184 r += arr[i].value();
185 }
186 return r;
187 }
188
189 @Benchmark
190 @OperationsPerInvocation(SIZE * 6)
191 @CompilerControl(CompilerControl.Mode.INLINE)
192 public int target0(Val0State st0, Val0State st1, Val0State st2, Val0State st3, Val0State st4, Val0State st5) {
193 return reduce_val(st0.arr) +
194 reduce_val(st1.arr) +
195 reduce_val(st2.arr) +
196 reduce_val(st3.arr) +
197 reduce_val(st4.arr) +
198 reduce_val(st5.arr);
199 }
200
201 @Benchmark
202 @OperationsPerInvocation(SIZE * 6)
203 @CompilerControl(CompilerControl.Mode.INLINE)
204 public int target1_v(Val0State st0, Val0State st1, Val0State st2, Val0State st3, Val0State st4, Val0State st5) {
205 return reduce_int(st0.arr) +
206 reduce_int(st1.arr) +
207 reduce_int(st2.arr) +
208 reduce_int(st3.arr) +
209 reduce_int(st4.arr) +
210 reduce_int(st5.arr);
211 }
212
213 @Benchmark
214 @OperationsPerInvocation(SIZE * 6)
215 @CompilerControl(CompilerControl.Mode.INLINE)
216 public int target1_i(Int0State st0, Int0State st1, Int0State st2, Int0State st3, Int0State st4, Int0State st5) {
217 return reduce_int(st0.arr) +
218 reduce_int(st1.arr) +
219 reduce_int(st2.arr) +
220 reduce_int(st3.arr) +
221 reduce_int(st4.arr) +
222 reduce_int(st5.arr);
223 }
224
225 @Benchmark
226 @OperationsPerInvocation(SIZE * 6)
227 @CompilerControl(CompilerControl.Mode.INLINE)
228 public int target1_vi(Val0State st0, Int0State st1, Val0State st2, Int0State st3, Val0State st4, Int0State st5) {
229 return reduce_int(st0.arr) +
230 reduce_int(st1.arr) +
231 reduce_int(st2.arr) +
232 reduce_int(st3.arr) +
233 reduce_int(st4.arr) +
234 reduce_int(st5.arr);
235 }
236
237 @Benchmark
238 @OperationsPerInvocation(SIZE * 6)
239 @CompilerControl(CompilerControl.Mode.INLINE)
240 public int target2_v(Val0State st0, Val0State st1, Val0State st2, Val1State st3, Val1State st4, Val1State st5) {
241 return reduce_int(st0.arr) +
242 reduce_int(st1.arr) +
243 reduce_int(st2.arr) +
244 reduce_int(st3.arr) +
245 reduce_int(st4.arr) +
246 reduce_int(st5.arr);
247 }
248
249 @Benchmark
250 @OperationsPerInvocation(SIZE * 6)
251 @CompilerControl(CompilerControl.Mode.INLINE)
252 public int target2_i(Int0State st0, Int0State st1, Int0State st2, Int1State st3, Int1State st4, Int1State st5) {
253 return reduce_int(st0.arr) +
254 reduce_int(st1.arr) +
255 reduce_int(st2.arr) +
256 reduce_int(st3.arr) +
257 reduce_int(st4.arr) +
258 reduce_int(st5.arr);
259 }
260
261 @Benchmark
262 @OperationsPerInvocation(SIZE * 6)
263 @CompilerControl(CompilerControl.Mode.INLINE)
264 public int target2_vi(Val0State st0, Int0State st1, Val0State st2, Int1State st3, Val1State st4, Int1State st5) {
265 return reduce_int(st0.arr) +
266 reduce_int(st1.arr) +
267 reduce_int(st2.arr) +
268 reduce_int(st3.arr) +
269 reduce_int(st4.arr) +
270 reduce_int(st5.arr);
271 }
272
273 @Benchmark
274 @OperationsPerInvocation(SIZE * 6)
275 @CompilerControl(CompilerControl.Mode.INLINE)
276 public int target3_v(Val0State st0, Val0State st1, Val1State st2, Val1State st3, Val22State st4, Val22State st5) {
277 return reduce_int(st0.arr) +
278 reduce_int(st1.arr) +
279 reduce_int(st2.arr) +
280 reduce_int(st3.arr) +
281 reduce_int(st4.arr) +
282 reduce_int(st5.arr);
283 }
284
285 @Benchmark
286 @OperationsPerInvocation(SIZE * 6)
287 @CompilerControl(CompilerControl.Mode.INLINE)
288 public int target3_i(Int0State st0, Int0State st1, Int1State st2, Int1State st3, Int2State st4, Int2State st5) {
289 return reduce_int(st0.arr) +
290 reduce_int(st1.arr) +
291 reduce_int(st2.arr) +
292 reduce_int(st3.arr) +
293 reduce_int(st4.arr) +
294 reduce_int(st5.arr);
295 }
296
297 @Benchmark
298 @OperationsPerInvocation(SIZE * 6)
299 @CompilerControl(CompilerControl.Mode.INLINE)
300 public int target3_vi(Val0State st0, Int0State st1, Val1State st2, Int1State st3, Val22State st4, Int2State st5) {
301 return reduce_int(st0.arr) +
302 reduce_int(st1.arr) +
303 reduce_int(st2.arr) +
304 reduce_int(st3.arr) +
305 reduce_int(st4.arr) +
306 reduce_int(st5.arr);
307 }
308
309 }