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 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(3)
 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 Identity {
 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 class IdentityInt0 implements InterfaceInt {
 65         public final int value;
 66         public IdentityInt0(int value) {
 67             this.value = value;
 68         }
 69         @Override
 70         public int value() {
 71             return value;
 72         }
 73     }
 74 
 75     public static class IdentityInt1 implements InterfaceInt {
 76         public final int value;
 77         public IdentityInt1(int value) {
 78             this.value = value;
 79         }
 80         @Override
 81         public int value() {
 82             return value;
 83         }
 84     }
 85 
 86     public static class IdentityInt2 implements InterfaceInt {
 87         public final int value;
 88         public IdentityInt2(int value) {
 89             this.value = value;
 90         }
 91         @Override
 92         public int value() {
 93             return value;
 94         }
 95     }
 96 
 97     @State(Scope.Thread)
 98     public static class Int0State {
 99         public InterfaceInt[] arr;
100         @Setup
101         public void setup() {
102             arr = new InterfaceInt[SIZE];
103             for (int i = 0; i < arr.length; i++) {
104                 arr[i] = new IdentityInt0(i);
105             }
106         }
107     }
108 
109     @State(Scope.Thread)
110     public static class Int1State {
111         public InterfaceInt[] arr;
112         @Setup
113         public void setup() {
114             arr = new InterfaceInt[SIZE];
115             for (int i = 0; i < arr.length; i++) {
116                 arr[i] = new IdentityInt1(i);
117             }
118         }
119     }
120 
121     @State(Scope.Thread)
122     public static class Int2State {
123         public InterfaceInt[] arr;
124         @Setup
125         public void setup() {
126             arr = new InterfaceInt[SIZE];
127             for (int i = 0; i < arr.length; i++) {
128                 arr[i] = new IdentityInt2(i);
129             }
130         }
131     }
132 
133     @State(Scope.Thread)
134     public static class Ref0State {
135         public IdentityInt0[] arr;
136         @Setup
137         public void setup() {
138             arr = new IdentityInt0[SIZE];
139             for (int i = 0; i < arr.length; i++) {
140                 arr[i] = new IdentityInt0(i);
141             }
142         }
143     }
144 
145     @State(Scope.Thread)
146     public static class Ref1State {
147         public IdentityInt1[] arr;
148         @Setup
149         public void setup() {
150             arr = new IdentityInt1[SIZE];
151             for (int i = 0; i < arr.length; i++) {
152                 arr[i] = new IdentityInt1(i);
153             }
154         }
155     }
156 
157     @State(Scope.Thread)
158     public static class Ref2State {
159         public IdentityInt2[] arr;
160         @Setup
161         public void setup() {
162             arr = new IdentityInt2[SIZE];
163             for (int i = 0; i < arr.length; i++) {
164                 arr[i] = new IdentityInt2(i);
165             }
166         }
167     }
168 
169 
170     @CompilerControl(CompilerControl.Mode.DONT_INLINE)
171     public int reduce_int(InterfaceInt[] arr) {
172         int r = 0;
173         for (int i = 0; i < arr.length; i++) {
174             r += arr[i].value();
175         }
176         return r;
177     }
178 
179     @CompilerControl(CompilerControl.Mode.DONT_INLINE)
180     public int reduce_ref(IdentityInt0[] arr) {
181         int r = 0;
182         for (int i = 0; i < arr.length; i++) {
183             r += arr[i].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_ref(st0.arr) +
193                reduce_ref(st1.arr) +
194                reduce_ref(st2.arr) +
195                reduce_ref(st3.arr) +
196                reduce_ref(st4.arr) +
197                reduce_ref(st5.arr);
198     }
199 
200     @Benchmark
201     @OperationsPerInvocation(SIZE * 6)
202     @CompilerControl(CompilerControl.Mode.INLINE)
203     public int target1_r(Ref0State st0, Ref0State st1, Ref0State st2, Ref0State st3, Ref0State st4, Ref0State 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 target1_i(Int0State st0, Int0State st1, Int0State st2, Int0State st3, Int0State st4, Int0State 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 target1_ri(Ref0State st0, Int0State st1, Ref0State st2, Int0State st3, Ref0State st4, Int0State 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     @Benchmark
237     @OperationsPerInvocation(SIZE * 6)
238     @CompilerControl(CompilerControl.Mode.INLINE)
239     public int target2_r(Ref0State st0, Ref0State st1, Ref0State st2, Ref1State st3, Ref1State st4, Ref1State st5) {
240         return reduce_int(st0.arr) +
241                reduce_int(st1.arr) +
242                reduce_int(st2.arr) +
243                reduce_int(st3.arr) +
244                reduce_int(st4.arr) +
245                reduce_int(st5.arr);
246     }
247 
248     @Benchmark
249     @OperationsPerInvocation(SIZE * 6)
250     @CompilerControl(CompilerControl.Mode.INLINE)
251     public int target2_i(Int0State st0, Int0State st1, Int0State st2, Int1State st3, Int1State st4, Int1State st5) {
252         return reduce_int(st0.arr) +
253                reduce_int(st1.arr) +
254                reduce_int(st2.arr) +
255                reduce_int(st3.arr) +
256                reduce_int(st4.arr) +
257                reduce_int(st5.arr);
258     }
259 
260     @Benchmark
261     @OperationsPerInvocation(SIZE * 6)
262     @CompilerControl(CompilerControl.Mode.INLINE)
263     public int target2_ri(Ref0State st0, Int0State st1, Ref0State st2, Int1State st3, Ref1State st4, Int1State st5) {
264         return reduce_int(st0.arr) +
265                 reduce_int(st1.arr) +
266                 reduce_int(st2.arr) +
267                 reduce_int(st3.arr) +
268                 reduce_int(st4.arr) +
269                 reduce_int(st5.arr);
270     }
271 
272     @Benchmark
273     @OperationsPerInvocation(SIZE * 6)
274     @CompilerControl(CompilerControl.Mode.INLINE)
275     public int target3_r(Ref0State st0, Ref0State st1, Ref1State st2, Ref1State st3, Ref2State st4, Ref2State st5) {
276         return reduce_int(st0.arr) +
277                 reduce_int(st1.arr) +
278                 reduce_int(st2.arr) +
279                 reduce_int(st3.arr) +
280                 reduce_int(st4.arr) +
281                 reduce_int(st5.arr);
282     }
283 
284     @Benchmark
285     @OperationsPerInvocation(SIZE * 6)
286     @CompilerControl(CompilerControl.Mode.INLINE)
287     public int target3_i(Int0State st0, Int0State st1, Int1State st2, Int1State st3, Int2State st4, Int2State st5) {
288         return reduce_int(st0.arr) +
289                 reduce_int(st1.arr) +
290                 reduce_int(st2.arr) +
291                 reduce_int(st3.arr) +
292                 reduce_int(st4.arr) +
293                 reduce_int(st5.arr);
294     }
295 
296     @Benchmark
297     @OperationsPerInvocation(SIZE * 6)
298     @CompilerControl(CompilerControl.Mode.INLINE)
299     public int target3_ri(Ref0State st0, Int0State st1, Ref1State st2, Int1State st3, Ref2State st4, Int2State st5) {
300         return reduce_int(st0.arr) +
301                 reduce_int(st1.arr) +
302                 reduce_int(st2.arr) +
303                 reduce_int(st3.arr) +
304                 reduce_int(st4.arr) +
305                 reduce_int(st5.arr);
306     }
307 
308 
309 }