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 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", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED"})
 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     @State(Scope.Thread)
 99     public static class Int0State {
100         public InterfaceInt[] arr;
101         @Setup
102         public void setup() {
103             arr = new InterfaceInt[SIZE];
104             for (int i = 0; i < arr.length; i++) {
105                 arr[i] = new ValueInt0(i);
106             }
107         }
108     }
109 
110     @State(Scope.Thread)
111     public static class Int1State {
112         public InterfaceInt[] arr;
113         @Setup
114         public void setup() {
115             arr = new InterfaceInt[SIZE];
116             for (int i = 0; i < arr.length; i++) {
117                 arr[i] = new ValueInt1(i);
118             }
119         }
120     }
121 
122     @State(Scope.Thread)
123     public static class Int2State {
124         public InterfaceInt[] arr;
125         @Setup
126         public void setup() {
127             arr = new InterfaceInt[SIZE];
128             for (int i = 0; i < arr.length; i++) {
129                 arr[i] = new ValueInt2(i);
130             }
131         }
132     }
133 
134     @State(Scope.Thread)
135     public static class Val0State {
136         public ValueInt0[] arr;
137         @Setup
138         public void setup() {
139             arr = (ValueInt0[]) ValueClass.newNullRestrictedAtomicArray(ValueInt0.class, SIZE, new ValueInt0(0));
140             for (int i = 0; i < arr.length; i++) {
141                 arr[i] = new ValueInt0(i);
142             }
143         }
144     }
145 
146     @State(Scope.Thread)
147     public static class Val1State {
148         public ValueInt1[] arr;
149         @Setup
150         public void setup() {
151             arr = (ValueInt1[]) ValueClass.newNullRestrictedAtomicArray(ValueInt1.class, SIZE, new ValueInt1(0));
152             for (int i = 0; i < arr.length; i++) {
153                 arr[i] = new ValueInt1(i);
154             }
155         }
156     }
157 
158     @State(Scope.Thread)
159     public static class Val22State {
160         public ValueInt2[] arr;
161         @Setup
162         public void setup() {
163             arr = (ValueInt2[]) ValueClass.newNullRestrictedAtomicArray(ValueInt2.class, SIZE, new ValueInt2(0));
164             for (int i = 0; i < arr.length; i++) {
165                 arr[i] = new ValueInt2(i);
166             }
167         }
168     }
169 
170 
171     @CompilerControl(CompilerControl.Mode.DONT_INLINE)
172     public int reduce_int(InterfaceInt[] arr) {
173         int r = 0;
174         for (int i = 0; i < arr.length; i++) {
175             r += arr[i].value();
176         }
177         return r;
178     }
179 
180     @CompilerControl(CompilerControl.Mode.DONT_INLINE)
181     public int reduce_val(ValueInt0[] arr) {
182         int r = 0;
183         for (int i = 0; i < arr.length; i++) {
184             r += arr[i].value();
185         }
186         return r;
187     }
188 
189     @Benchmark
190     @OperationsPerInvocation(SIZE * 6)
191     @CompilerControl(CompilerControl.Mode.INLINE)
192     public int target0(Val0State st0, Val0State st1, Val0State st2, Val0State st3, Val0State st4, Val0State st5) {
193         return reduce_val(st0.arr) +
194                reduce_val(st1.arr) +
195                reduce_val(st2.arr) +
196                reduce_val(st3.arr) +
197                reduce_val(st4.arr) +
198                reduce_val(st5.arr);
199     }
200 
201     @Benchmark
202     @OperationsPerInvocation(SIZE * 6)
203     @CompilerControl(CompilerControl.Mode.INLINE)
204     public int target1_v(Val0State st0, Val0State st1, Val0State st2, Val0State st3, Val0State st4, Val0State st5) {
205         return reduce_int(st0.arr) +
206                reduce_int(st1.arr) +
207                reduce_int(st2.arr) +
208                reduce_int(st3.arr) +
209                reduce_int(st4.arr) +
210                reduce_int(st5.arr);
211     }
212 
213     @Benchmark
214     @OperationsPerInvocation(SIZE * 6)
215     @CompilerControl(CompilerControl.Mode.INLINE)
216     public int target1_i(Int0State st0, Int0State st1, Int0State st2, Int0State st3, Int0State st4, Int0State st5) {
217         return reduce_int(st0.arr) +
218                reduce_int(st1.arr) +
219                reduce_int(st2.arr) +
220                reduce_int(st3.arr) +
221                reduce_int(st4.arr) +
222                reduce_int(st5.arr);
223     }
224 
225     @Benchmark
226     @OperationsPerInvocation(SIZE * 6)
227     @CompilerControl(CompilerControl.Mode.INLINE)
228     public int target1_vi(Val0State st0, Int0State st1, Val0State st2, Int0State st3, Val0State st4, Int0State st5) {
229         return reduce_int(st0.arr) +
230                 reduce_int(st1.arr) +
231                 reduce_int(st2.arr) +
232                 reduce_int(st3.arr) +
233                 reduce_int(st4.arr) +
234                 reduce_int(st5.arr);
235     }
236 
237     @Benchmark
238     @OperationsPerInvocation(SIZE * 6)
239     @CompilerControl(CompilerControl.Mode.INLINE)
240     public int target2_v(Val0State st0, Val0State st1, Val0State st2, Val1State st3, Val1State st4, Val1State st5) {
241         return reduce_int(st0.arr) +
242                reduce_int(st1.arr) +
243                reduce_int(st2.arr) +
244                reduce_int(st3.arr) +
245                reduce_int(st4.arr) +
246                reduce_int(st5.arr);
247     }
248 
249     @Benchmark
250     @OperationsPerInvocation(SIZE * 6)
251     @CompilerControl(CompilerControl.Mode.INLINE)
252     public int target2_i(Int0State st0, Int0State st1, Int0State st2, Int1State st3, Int1State st4, Int1State st5) {
253         return reduce_int(st0.arr) +
254                reduce_int(st1.arr) +
255                reduce_int(st2.arr) +
256                reduce_int(st3.arr) +
257                reduce_int(st4.arr) +
258                reduce_int(st5.arr);
259     }
260 
261     @Benchmark
262     @OperationsPerInvocation(SIZE * 6)
263     @CompilerControl(CompilerControl.Mode.INLINE)
264     public int target2_vi(Val0State st0, Int0State st1, Val0State st2, Int1State st3, Val1State st4, Int1State st5) {
265         return reduce_int(st0.arr) +
266                 reduce_int(st1.arr) +
267                 reduce_int(st2.arr) +
268                 reduce_int(st3.arr) +
269                 reduce_int(st4.arr) +
270                 reduce_int(st5.arr);
271     }
272 
273     @Benchmark
274     @OperationsPerInvocation(SIZE * 6)
275     @CompilerControl(CompilerControl.Mode.INLINE)
276     public int target3_v(Val0State st0, Val0State st1, Val1State st2, Val1State st3, Val22State st4, Val22State st5) {
277         return reduce_int(st0.arr) +
278                 reduce_int(st1.arr) +
279                 reduce_int(st2.arr) +
280                 reduce_int(st3.arr) +
281                 reduce_int(st4.arr) +
282                 reduce_int(st5.arr);
283     }
284 
285     @Benchmark
286     @OperationsPerInvocation(SIZE * 6)
287     @CompilerControl(CompilerControl.Mode.INLINE)
288     public int target3_i(Int0State st0, Int0State st1, Int1State st2, Int1State st3, Int2State st4, Int2State st5) {
289         return reduce_int(st0.arr) +
290                 reduce_int(st1.arr) +
291                 reduce_int(st2.arr) +
292                 reduce_int(st3.arr) +
293                 reduce_int(st4.arr) +
294                 reduce_int(st5.arr);
295     }
296 
297     @Benchmark
298     @OperationsPerInvocation(SIZE * 6)
299     @CompilerControl(CompilerControl.Mode.INLINE)
300     public int target3_vi(Val0State st0, Int0State st1, Val1State st2, Int1State st3, Val22State st4, Int2State st5) {
301         return reduce_int(st0.arr) +
302                 reduce_int(st1.arr) +
303                 reduce_int(st2.arr) +
304                 reduce_int(st3.arr) +
305                 reduce_int(st4.arr) +
306                 reduce_int(st5.arr);
307     }
308 
309 }