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.LooselyConsistentValue;
26 import jdk.internal.vm.annotation.NullRestricted;
27 import jdk.internal.vm.annotation.Strict;
28 import org.openjdk.jmh.annotations.Benchmark;
29 import org.openjdk.jmh.annotations.BenchmarkMode;
30 import org.openjdk.jmh.annotations.CompilerControl;
31 import org.openjdk.jmh.annotations.Fork;
32 import org.openjdk.jmh.annotations.Measurement;
33 import org.openjdk.jmh.annotations.Mode;
34 import org.openjdk.jmh.annotations.OperationsPerInvocation;
35 import org.openjdk.jmh.annotations.OutputTimeUnit;
36 import org.openjdk.jmh.annotations.Scope;
37 import org.openjdk.jmh.annotations.Setup;
38 import org.openjdk.jmh.annotations.State;
39 import org.openjdk.jmh.annotations.Warmup;
40
41 import java.util.concurrent.TimeUnit;
42
43 @Fork(value = 3, jvmArgsAppend = {"--enable-preview"})
44 @Warmup(iterations = 5, time = 1)
45 @Measurement(iterations = 5, time = 1)
46 @OutputTimeUnit(TimeUnit.NANOSECONDS)
47 @BenchmarkMode(Mode.AverageTime)
48 @State(Scope.Thread)
49 public class ValueNullFreeNonAtomic {
50
51 /*
52 virtual method invocations:
53 target0 - statically known target method.
54 target1 - the single invoked method (should be inlined)
55 target2 - two invoked method (should be inlined, cache-inline)
56 target3 - thee invoked method (shouldn't be inlined)
57
58 */
59
60
61 public static final int SIZE = 128;
62
63 public interface InterfaceInt {
64 public int value();
65 }
66
67 @LooselyConsistentValue
68 public static value class ValueInt0 implements InterfaceInt {
69 public final int value;
70 public ValueInt0(int value) {
71 this.value = value;
72 }
73 @Override
74 public int value() {
75 return value;
76 }
77 }
78
79 @LooselyConsistentValue
80 public static value class ValueInt1 implements InterfaceInt {
81 public final int value;
82 public ValueInt1(int value) {
83 this.value = value;
84 }
85 @Override
86 public int value() {
87 return value;
88 }
89 }
90
91 @LooselyConsistentValue
92 public static value class ValueInt2 implements InterfaceInt {
93 public final int value;
94 public ValueInt2(int value) {
95 this.value = value;
96 }
97 @Override
98 public int value() {
99 return value;
100 }
101 }
102
103 public static class IntWrapper {
104 final InterfaceInt f;
105
106 public IntWrapper(InterfaceInt f) {
107 this.f = f;
108 }
109 }
110
111 public static class ValWrapper {
112 @Strict
113 @NullRestricted
114 final ValueInt0 f;
115
116 public ValWrapper(ValueInt0 f) {
117 this.f = f;
118 }
119 }
120
121 @State(Scope.Thread)
122 public static class Int0State {
123 public IntWrapper[] arr;
124 @Setup
125 public void setup() {
126 arr = new IntWrapper[SIZE];
127 for (int i = 0; i < arr.length; i++) {
128 arr[i] = new IntWrapper(new ValueInt0(i));
129 }
130 }
131 }
132
133 @State(Scope.Thread)
134 public static class Int1State {
135 public IntWrapper[] arr;
136 @Setup
137 public void setup() {
138 arr = new IntWrapper[SIZE];
139 for (int i = 0; i < arr.length; i++) {
140 arr[i] = new IntWrapper(new ValueInt1(i));
141 }
142 }
143 }
144
145 @State(Scope.Thread)
146 public static class Int2State {
147 public IntWrapper[] arr;
148 @Setup
149 public void setup() {
150 arr = new IntWrapper[SIZE];
151 for (int i = 0; i < arr.length; i++) {
152 arr[i] = new IntWrapper(new ValueInt2(i));
153 }
154 }
155 }
156
157 @State(Scope.Thread)
158 public static class Ref0State {
159 public ValWrapper[] arr;
160 @Setup
161 public void setup() {
162 arr = new ValWrapper[SIZE];
163 for (int i = 0; i < arr.length; i++) {
164 arr[i] = new ValWrapper(new ValueInt0(i));
165 }
166 }
167 }
168
169
170 @CompilerControl(CompilerControl.Mode.DONT_INLINE)
171 public int reduce_int(IntWrapper[] arr) {
172 int r = 0;
173 for (int i = 0; i < arr.length; i++) {
174 r += arr[i].f.value();
175 }
176 return r;
177 }
178
179 @CompilerControl(CompilerControl.Mode.DONT_INLINE)
180 public int reduce_val(ValWrapper[] arr) {
181 int r = 0;
182 for (int i = 0; i < arr.length; i++) {
183 r += arr[i].f.value();
184 }
185 return r;
186 }
187
188 @Benchmark
189 @OperationsPerInvocation(SIZE * 6)
190 @CompilerControl(CompilerControl.Mode.INLINE)
191 public int target0(Ref0State st0, Ref0State st1, Ref0State st2, Ref0State st3, Ref0State st4, Ref0State 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(Int0State st0, Int0State st1, Int0State st2, Int0State st3, Int0State st4, Int0State 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 target2(Int0State st0, Int0State st1, Int0State st2, Int1State st3, Int1State st4, Int1State 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 target3(Int0State st0, Int0State st1, Int1State st2, Int1State st3, Int2State st4, Int2State 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 }