1 /*
  2  * Copyright (c) 2020, 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.callconv;
 24 
 25 import org.openjdk.bench.valhalla.types.Q64byte;
 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(3)
 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 Inline64byte {
 48 
 49     public static final int SIZE = 96;  // must be divisible by 2 and 3 and around 100
 50 
 51     public abstract static class InvocationLogic {
 52         public abstract Q64byte compute(Q64byte v1);
 53         public abstract Q64byte compute(Q64byte v1, Q64byte v2);
 54         public abstract Q64byte compute(Q64byte v1, Q64byte v2, Q64byte v3, Q64byte v4);
 55         public abstract Q64byte compute(Q64byte v1, Q64byte v2, Q64byte v3, Q64byte v4, Q64byte v5, Q64byte v6, Q64byte v7, Q64byte v8);
 56     }
 57 
 58     public static class InvokeImpl1 extends InvocationLogic {
 59 
 60         @Override
 61         public Q64byte compute(Q64byte v1) {
 62             return v1;
 63         }
 64 
 65         @Override
 66         public Q64byte compute(Q64byte v1, Q64byte v2) {
 67             return v1;
 68         }
 69 
 70         @Override
 71         public Q64byte compute(Q64byte v1, Q64byte v2, Q64byte v3, Q64byte v4) {
 72             return v1;
 73         }
 74 
 75         @Override
 76         public Q64byte compute(Q64byte v1, Q64byte v2, Q64byte v3, Q64byte v4, Q64byte v5, Q64byte v6, Q64byte v7, Q64byte v8) {
 77             return v1;
 78         }
 79 
 80     }
 81 
 82     public static class InvokeImpl2 extends InvocationLogic {
 83 
 84         @Override
 85         public Q64byte compute(Q64byte v1) {
 86             return v1;
 87         }
 88 
 89         @Override
 90         public Q64byte compute(Q64byte v1, Q64byte v2) {
 91             return v1;
 92         }
 93 
 94         @Override
 95         public Q64byte compute(Q64byte v1, Q64byte v2, Q64byte v3, Q64byte v4) {
 96             return v1;
 97         }
 98 
 99         @Override
100         public Q64byte compute(Q64byte v1, Q64byte v2, Q64byte v3, Q64byte v4, Q64byte v5, Q64byte v6, Q64byte v7, Q64byte v8) {
101             return v1;
102         }
103 
104     }
105 
106     public static class InvokeImpl3 extends InvocationLogic {
107 
108         @Override
109         public Q64byte compute(Q64byte v1) {
110             return v1;
111         }
112 
113         @Override
114         public Q64byte compute(Q64byte v1, Q64byte v2) {
115             return v1;
116         }
117 
118         @Override
119         public Q64byte compute(Q64byte v1, Q64byte v2, Q64byte v3, Q64byte v4) {
120             return v1;
121         }
122 
123         @Override
124         public Q64byte compute(Q64byte v1, Q64byte v2, Q64byte v3, Q64byte v4, Q64byte v5, Q64byte v6, Q64byte v7, Q64byte v8) {
125             return v1;
126         }
127 
128     }
129 
130 
131     private static InvocationLogic getImpl(int i, int targets) {
132         switch (i % targets) {
133             case 0:
134                 return new InvokeImpl1();
135             case 1:
136                 return new InvokeImpl2();
137             case 2:
138                 return new InvokeImpl3();
139         }
140         return null;
141     }
142 
143     @State(Scope.Thread)
144     public static class StateTargets0 {
145         InvokeImpl1[] arr;
146         @Setup
147         public void setup() {
148             arr = new InvokeImpl1[SIZE];
149             for(int i=0; i < arr.length; i++) {
150                 arr[i] = new InvokeImpl1();
151             }
152         }
153     }
154 
155     @State(Scope.Thread)
156     public static abstract class StateTargets {
157         InvocationLogic[] arr;
158 
159         public void init(int targets) {
160             arr = new InvocationLogic[SIZE];
161             for(int i=0; i < arr.length; i++) {
162                 arr[i] = getImpl(i, targets);
163             }
164         }
165     }
166 
167     public static class StateTargets1 extends StateTargets {
168         @Setup
169         public void setup() {
170             init(1);
171         }
172     }
173 
174     public static class StateTargets2 extends StateTargets {
175         @Setup
176         public void setup() {
177             init(2);
178         }
179     }
180 
181     public static class StateTargets3 extends StateTargets {
182         @Setup
183         public void setup() {
184             init(3);
185         }
186     }
187 
188     Q64byte a0 = new Q64byte(42);
189     Q64byte a1 = new Q64byte(43);
190     Q64byte a2 = new Q64byte(44);
191     Q64byte a3 = new Q64byte(45);
192     Q64byte a4 = new Q64byte(46);
193     Q64byte a5 = new Q64byte(47);
194     Q64byte a6 = new Q64byte(48);
195     Q64byte a7 = new Q64byte(49);
196 
197     @CompilerControl(CompilerControl.Mode.INLINE)
198     public long args1(InvocationLogic[] logic) {
199         long r = 0;
200         for(InvocationLogic t : logic) {
201             r += t.compute(a0).longValue();
202         }
203         return r;
204     }
205 
206     @CompilerControl(CompilerControl.Mode.INLINE)
207     public long args2(InvocationLogic[] logic) {
208         long r = 0;
209         for(InvocationLogic t : logic) {
210             r += t.compute(a0, a1).longValue();
211         }
212         return r;
213     }
214 
215     @CompilerControl(CompilerControl.Mode.INLINE)
216     public long args4(InvocationLogic[] logic) {
217         long r = 0;
218         for(InvocationLogic t : logic) {
219             r += t.compute(a0, a1, a2, a3).longValue();
220         }
221         return r;
222     }
223 
224     @CompilerControl(CompilerControl.Mode.INLINE)
225     public long args8(InvocationLogic[] logic) {
226         long r = 0;
227         for(InvocationLogic t : logic) {
228             r += t.compute(a0, a1, a2, a3, a4, a5, a6, a7).longValue();
229         }
230         return r;
231     }
232 
233     @Benchmark
234     @OperationsPerInvocation(SIZE)
235     @CompilerControl(CompilerControl.Mode.DONT_INLINE)
236     public long Q64byte_args1_targets0(StateTargets0 st) {
237         InvokeImpl1[] arr = st.arr;
238         long r = 0;
239         for(InvocationLogic t : arr) {
240             r += t.compute(a0).longValue();
241         }
242         return r;
243     }
244 
245     @Benchmark
246     @OperationsPerInvocation(SIZE)
247     @CompilerControl(CompilerControl.Mode.DONT_INLINE)
248     public long Q64byte_args2_targets0(StateTargets0 st) {
249         InvokeImpl1[] arr = st.arr;
250         long r = 0;
251         for(InvocationLogic t : arr) {
252             r += t.compute(a0, a1).longValue();
253         }
254         return r;
255     }
256 
257     @Benchmark
258     @OperationsPerInvocation(SIZE)
259     @CompilerControl(CompilerControl.Mode.DONT_INLINE)
260     public long Q64byte_args4_targets0(StateTargets0 st) {
261         InvokeImpl1[] arr = st.arr;
262         long r = 0;
263         for(InvocationLogic t : arr) {
264             r += t.compute(a0, a1, a2, a3).longValue();
265         }
266         return r;
267     }
268 
269     @Benchmark
270     @OperationsPerInvocation(SIZE)
271     @CompilerControl(CompilerControl.Mode.DONT_INLINE)
272     public long Q64byte_args8_targets0(StateTargets0 st) {
273         InvokeImpl1[] arr = st.arr;
274         long r = 0;
275         for(InvocationLogic t : arr) {
276             r += t.compute(a0, a1, a2, a3, a4, a5, a6, a7).longValue();
277         }
278         return r;
279     }
280 
281     @Benchmark
282     @OperationsPerInvocation(SIZE)
283     @CompilerControl(CompilerControl.Mode.DONT_INLINE)
284     public long Q64byte_args1_targets1(StateTargets1 st) {
285         return args1(st.arr);
286     }
287 
288     @Benchmark
289     @OperationsPerInvocation(SIZE)
290     @CompilerControl(CompilerControl.Mode.DONT_INLINE)
291     public long Q64byte_args2_targets1(StateTargets1 st) {
292         return args2(st.arr);
293     }
294 
295     @Benchmark
296     @OperationsPerInvocation(SIZE)
297     @CompilerControl(CompilerControl.Mode.DONT_INLINE)
298     public long Q64byte_args4_targets1(StateTargets1 st) {
299         return args4(st.arr);
300     }
301 
302     @Benchmark
303     @OperationsPerInvocation(SIZE)
304     @CompilerControl(CompilerControl.Mode.DONT_INLINE)
305     public long Q64byte_args8_targets1(StateTargets1 st) {
306         return args8(st.arr);
307     }
308 
309     @Benchmark
310     @OperationsPerInvocation(SIZE)
311     @CompilerControl(CompilerControl.Mode.DONT_INLINE)
312     public long Q64byte_args1_targets2(StateTargets2 st) {
313         return args1(st.arr);
314     }
315 
316     @Benchmark
317     @OperationsPerInvocation(SIZE)
318     @CompilerControl(CompilerControl.Mode.DONT_INLINE)
319     public long Q64byte_args2_targets2(StateTargets2 st) {
320         return args2(st.arr);
321     }
322 
323     @Benchmark
324     @OperationsPerInvocation(SIZE)
325     @CompilerControl(CompilerControl.Mode.DONT_INLINE)
326     public long Q64byte_args4_targets2(StateTargets2 st) {
327         return args4(st.arr);
328     }
329 
330     @Benchmark
331     @OperationsPerInvocation(SIZE)
332     @CompilerControl(CompilerControl.Mode.DONT_INLINE)
333     public long Q64byte_args8_targets2(StateTargets2 st) {
334         return args8(st.arr);
335     }
336 
337     @Benchmark
338     @OperationsPerInvocation(SIZE)
339     @CompilerControl(CompilerControl.Mode.DONT_INLINE)
340     public long Q64byte_args1_targets3(StateTargets3 st) {
341         return args1(st.arr);
342     }
343 
344     @Benchmark
345     @OperationsPerInvocation(SIZE)
346     @CompilerControl(CompilerControl.Mode.DONT_INLINE)
347     public long Q64byte_args2_targets3(StateTargets3 st) {
348         return args2(st.arr);
349     }
350 
351     @Benchmark
352     @OperationsPerInvocation(SIZE)
353     @CompilerControl(CompilerControl.Mode.DONT_INLINE)
354     public long Q64byte_args4_targets3(StateTargets3 st) {
355         return args4(st.arr);
356     }
357 
358     @Benchmark
359     @OperationsPerInvocation(SIZE)
360     @CompilerControl(CompilerControl.Mode.DONT_INLINE)
361     public long Q64byte_args8_targets3(StateTargets3 st) {
362         return args8(st.arr);
363     }
364 
365 
366 }