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