1 /*
2 * Copyright (c) 2025, 2026, 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.field;
24
25 import jdk.internal.vm.annotation.NullRestricted;
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"})
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 public static class IntWrapper {
99 final InterfaceInt f;
100
101 public IntWrapper(InterfaceInt f) {
102 this.f = f;
103 }
104 }
105
106 public static class ValWrapper {
107 @NullRestricted
108 final ValueInt0 f;
109
110 public ValWrapper(ValueInt0 f) {
111 this.f = f;
112 super();
113 }
114 }
115
116 @State(Scope.Thread)
117 public static class Int0State {
118 public IntWrapper[] arr;
119 @Setup
120 public void setup() {
121 arr = new IntWrapper[SIZE];
122 for (int i = 0; i < arr.length; i++) {
123 arr[i] = new IntWrapper(new ValueInt0(i));
124 }
125 }
126 }
127
128 @State(Scope.Thread)
129 public static class Int1State {
130 public IntWrapper[] arr;
131 @Setup
132 public void setup() {
133 arr = new IntWrapper[SIZE];
134 for (int i = 0; i < arr.length; i++) {
135 arr[i] = new IntWrapper(new ValueInt1(i));
136 }
137 }
138 }
139
140 @State(Scope.Thread)
141 public static class Int2State {
142 public IntWrapper[] arr;
143 @Setup
144 public void setup() {
145 arr = new IntWrapper[SIZE];
146 for (int i = 0; i < arr.length; i++) {
147 arr[i] = new IntWrapper(new ValueInt2(i));
148 }
149 }
150 }
151
152 @State(Scope.Thread)
153 public static class Ref0State {
154 public ValWrapper[] arr;
155 @Setup
156 public void setup() {
157 arr = new ValWrapper[SIZE];
158 for (int i = 0; i < arr.length; i++) {
159 arr[i] = new ValWrapper(new ValueInt0(i));
160 }
161 }
162 }
163
164
165 @CompilerControl(CompilerControl.Mode.DONT_INLINE)
166 public int reduce_int(IntWrapper[] arr) {
167 int r = 0;
168 for (int i = 0; i < arr.length; i++) {
169 r += arr[i].f.value();
170 }
171 return r;
172 }
173
174 @CompilerControl(CompilerControl.Mode.DONT_INLINE)
175 public int reduce_val(ValWrapper[] arr) {
176 int r = 0;
177 for (int i = 0; i < arr.length; i++) {
178 r += arr[i].f.value();
179 }
180 return r;
181 }
182
183 @Benchmark
184 @OperationsPerInvocation(SIZE * 6)
185 @CompilerControl(CompilerControl.Mode.INLINE)
186 public int target0(Ref0State st0, Ref0State st1, Ref0State st2, Ref0State st3, Ref0State st4, Ref0State st5) {
187 return reduce_val(st0.arr) +
188 reduce_val(st1.arr) +
189 reduce_val(st2.arr) +
190 reduce_val(st3.arr) +
191 reduce_val(st4.arr) +
192 reduce_val(st5.arr);
193 }
194
195 @Benchmark
196 @OperationsPerInvocation(SIZE * 6)
197 @CompilerControl(CompilerControl.Mode.INLINE)
198 public int target1(Int0State st0, Int0State st1, Int0State st2, Int0State st3, Int0State st4, Int0State st5) {
199 return reduce_int(st0.arr) +
200 reduce_int(st1.arr) +
201 reduce_int(st2.arr) +
202 reduce_int(st3.arr) +
203 reduce_int(st4.arr) +
204 reduce_int(st5.arr);
205 }
206
207 @Benchmark
208 @OperationsPerInvocation(SIZE * 6)
209 @CompilerControl(CompilerControl.Mode.INLINE)
210 public int target2(Int0State st0, Int0State st1, Int0State st2, Int1State st3, Int1State st4, Int1State st5) {
211 return reduce_int(st0.arr) +
212 reduce_int(st1.arr) +
213 reduce_int(st2.arr) +
214 reduce_int(st3.arr) +
215 reduce_int(st4.arr) +
216 reduce_int(st5.arr);
217 }
218
219 @Benchmark
220 @OperationsPerInvocation(SIZE * 6)
221 @CompilerControl(CompilerControl.Mode.INLINE)
222 public int target3(Int0State st0, Int0State st1, Int1State st2, Int1State st3, Int2State st4, Int2State st5) {
223 return reduce_int(st0.arr) +
224 reduce_int(st1.arr) +
225 reduce_int(st2.arr) +
226 reduce_int(st3.arr) +
227 reduce_int(st4.arr) +
228 reduce_int(st5.arr);
229 }
230
231 }