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