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