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 }