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 }