1 /*
2  * Copyright (c) 2014, 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.java.lang.invoke;
24 
25 import org.openjdk.jmh.annotations.Benchmark;
26 import org.openjdk.jmh.annotations.BenchmarkMode;
27 import org.openjdk.jmh.annotations.Mode;
28 import org.openjdk.jmh.annotations.OutputTimeUnit;
29 import org.openjdk.jmh.annotations.Scope;
30 import org.openjdk.jmh.annotations.Setup;
31 import org.openjdk.jmh.annotations.State;
32 
33 import java.lang.invoke.MethodHandle;
34 import java.lang.invoke.MethodHandles;
35 import java.lang.invoke.MethodType;
36 import java.util.concurrent.TimeUnit;
37 
38 /**
39  * Benchmark assesses runtime argument conversion performance for MethodHandles.
40  * This particular test checks the widening conversion.
41  */
42 @BenchmarkMode(Mode.AverageTime)
43 @OutputTimeUnit(TimeUnit.NANOSECONDS)
44 @State(Scope.Thread)
45 public class MethodHandleConvertWidening {
46 
47     /*
48      * Implementation notes:
49      *
50      * Baseline is invokeExact call, which presumably measures the performance without argument conversion.
51      *
52      * The test is subdivided into three subtests, gradually doing more work:
53      *   - 1_Convert: calls MH.asType to do actual conversion
54      *   - 2_MTConvert: instantiates MT, and then calls MH.asType to do actual conversion
55      *   - 3_Call: calls MH.invoke, requesting argument conversion
56      *
57      * Calling static method as to minimize virtual dispatch overheads.
58      */
59 
60     private long valueLong;
61     private int valueInt;
62 
63     private MethodHandle mh;
64     private MethodType newType;
65 
66     @Setup
setup()67     public void setup() throws Throwable {
68         mh = MethodHandles.lookup().findStatic(MethodHandleConvertWidening.class, "target", MethodType.methodType(long.class, long.class));
69         newType = MethodType.methodType(long.class, int.class);
70         valueInt = 42;
71         valueLong = 42L;
72     }
73 
74     @Benchmark
baselineExact()75     public long baselineExact() throws Throwable {
76         return (long) mh.invokeExact(valueLong);
77     }
78 
79     @Benchmark
test_1_Convert()80     public MethodHandle test_1_Convert() throws Throwable {
81         return mh.asType(newType);
82     }
83 
84     @Benchmark
test_2_MTConvert()85     public MethodHandle test_2_MTConvert() throws Throwable {
86         return mh.asType(MethodType.methodType(long.class, int.class));
87     }
88 
89     @Benchmark
test_3_Call()90     public long test_3_Call() throws Throwable {
91         return (long) mh.invoke(valueInt);
92     }
93 
target(long value)94     public static long target(long value) {
95         return value + 1;
96     }
97 
98 }
99