Path: blob/master/test/micro/org/openjdk/bench/vm/compiler/InterfaceCalls.java
41161 views
/*1* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/22package org.openjdk.bench.vm.compiler;2324import org.openjdk.jmh.annotations.Benchmark;25import org.openjdk.jmh.annotations.BenchmarkMode;26import org.openjdk.jmh.annotations.Mode;27import org.openjdk.jmh.annotations.OutputTimeUnit;28import org.openjdk.jmh.annotations.Scope;29import org.openjdk.jmh.annotations.Setup;30import org.openjdk.jmh.annotations.State;31import org.openjdk.jmh.infra.Blackhole;3233import java.util.concurrent.TimeUnit;3435@BenchmarkMode(Mode.AverageTime)36@OutputTimeUnit(TimeUnit.NANOSECONDS)37@State(Scope.Thread)38public class InterfaceCalls {3940interface AnInterface {41public int getInt();42}4344interface SecondInterface {45public int get1();46}4748interface OnlyHasOneImplInterface {49public int getLong();50}5152interface AloneInterface {53public int getNumber();54}5556class SingleImplementor implements OnlyHasOneImplInterface {57public int getLong() {58return 1;59}60}6162class Extender1 extends SingleImplementor {63}6465class FirstClass implements AnInterface {66public int getInt() {67return 1;68}69}7071class SecondClass implements AnInterface {72public int getInt() {73return 2;74}75}7677class ThirdClass implements AnInterface {78public int getInt() {79return -3;80}81}8283class FourthClass implements AnInterface {84public int getInt() {85return -4;86}87}8889class FifthClass implements AnInterface {90public int getInt() {91return -5;92}93}9495class MultiClass1 implements AnInterface, SecondInterface {96public int get1() {97return 1;98}99100public int getInt() {101return 2;102}103}104105class MultiClass2 implements AnInterface, SecondInterface {106public int get1() {107return -1;108}109110public int getInt() {111return -2;112}113}114115class Aloner implements AloneInterface {116public int getNumber() {117return 7;118}119}120121public Object dummy1;122123public Object dummy2;124125public Object dummy3;126127public AnInterface multi1a, multi2a;128129public SecondInterface multi1b, multi2b;130131public Object multic, multic2;132133public AnInterface[] as = new AnInterface[5];134135public AnInterface multi;136137public OnlyHasOneImplInterface single1;138139public OnlyHasOneImplInterface single2;140141public AloneInterface alone;142143int count;144145@Setup146public void setupSubclass() {147dummy1 = new FirstClass();148dummy2 = new SecondClass();149dummy3 = new ThirdClass();150as[0] = new FirstClass();151as[1] = new SecondClass();152as[2] = new ThirdClass();153as[3] = new FourthClass();154as[4] = new FifthClass();155MultiClass1 mc1 = new MultiClass1();156multi1a = mc1;157multi1b = mc1;158multic = mc1;159MultiClass2 mc2 = new MultiClass2();160multi2a = mc2;161multi2b = mc2;162multic2 = mc2;163single1 = new SingleImplementor();164single2 = new Extender1();165alone = new Aloner();166}167168private void swapMultiParts() {169AnInterface tmpa = multi1a;170SecondInterface tmpb = multi1b;171multi1a = multi2a;172multi2a = tmpa;173multi1b = multi2b;174multi2b = tmpb;175}176177@SuppressWarnings("unused")178private void swapMulti() {179Object tmp = multic;180multic = multic2;181multic2 = tmp;182}183184/**185* Tests a call where there are multiple implementors but only one of the implementors is every used here so the186* call-site is monomorphic187*/188@Benchmark189public int testMonomorphic() {190return as[0].getInt();191}192193/** Tests a interface call that only has one single implementation */194@Benchmark195public int testSingle() {196return alone.getNumber();197}198199/**200* Tests a call where there is a single implementation but multiple classes that inherit that implementation and both201* these implementors are used.202*/203@Benchmark204public int testSingle2() {205OnlyHasOneImplInterface oi;206if ((count & 1) == 0) {207oi = single1;208} else {209oi = single2;210}211count++;212return oi.getLong();213}214215/**216* Tests calling two different interface methods in two different interfaces on the same receiver. Make sure to switch217* between two different types of receivers to achieve polymorhpism218*/219@Benchmark220public void testCall2Poly2(Blackhole bh) {221bh.consume(multi1a.getInt());222bh.consume(multi1b.get1());223swapMultiParts();224}225226@Benchmark227public int testCallMulti1Poly2NoSwap() {228return multi1a.getInt();229}230231/**232* This test goes together with Multi2 below It tests if a class implements multiple interfaces if the different233* interfaces take different amounts of time (They do for hotspot)234*/235@Benchmark236public int testCallMulti1Poly2() {237swapMultiParts();238return multi1a.getInt();239}240241/**242* This test goes together with Multi2 below It tests if a class implements multiple interfaces if the different243* interfaces take different amounts of time (They do for hotspot)244*/245@Benchmark246public int testCallMulti2Poly2() {247swapMultiParts();248return multi1b.get1();249}250251/** Interface call with three different receivers */252@Benchmark253public void testCallPoly3(Blackhole bh) {254for (int kk = 0; kk < 3; kk++) {255bh.consume(as[kk].getInt());256}257}258259/** Interface call with five different receivers. */260@Benchmark261public void testCallPoly5(Blackhole bh) {262for (int kk = 0; kk < 5; kk++) {263bh.consume(as[kk].getInt());264}265}266267int l;268269/**270* Interface call address computation within loop but the receiver preexists the loop and the ac can be moved outside271* of the loop272*/273@Benchmark274public int testAC1() {275AnInterface ai = as[l];276l = 1 - l;277return ai.getInt();278}279280/** Tests an interface cast followed by an interface call. */281@Benchmark282public int testInterfaceCastAndCall() throws Exception {283return ((AnInterface) dummy1).getInt() + ((AnInterface) dummy2).getInt()284+ ((AnInterface) dummy3).getInt();285}286}287288289