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