8298809: Clean up vm/compiler/InterfaceCalls JMH
Reviewed-by: kvn
This commit is contained in:
parent
3696711efa
commit
81e23ab340
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -44,250 +44,132 @@ import java.util.concurrent.TimeUnit;
|
||||
@Fork(value = 3)
|
||||
public class InterfaceCalls {
|
||||
|
||||
interface AnInterface {
|
||||
public int getInt();
|
||||
interface FirstInterface {
|
||||
public int getIntFirst();
|
||||
}
|
||||
|
||||
interface SecondInterface {
|
||||
public int get1();
|
||||
public int getIntSecond();
|
||||
}
|
||||
|
||||
interface OnlyHasOneImplInterface {
|
||||
public int getLong();
|
||||
}
|
||||
class FirstClass implements FirstInterface, SecondInterface {
|
||||
public int getIntFirst() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
interface AloneInterface {
|
||||
public int getNumber();
|
||||
}
|
||||
|
||||
class SingleImplementor implements OnlyHasOneImplInterface {
|
||||
public int getLong() {
|
||||
public int getIntSecond() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
class Extender1 extends SingleImplementor {
|
||||
}
|
||||
|
||||
class FirstClass implements AnInterface {
|
||||
public int getInt() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
class SecondClass implements AnInterface {
|
||||
public int getInt() {
|
||||
class SecondClass implements FirstInterface, SecondInterface {
|
||||
public int getIntFirst() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
public int getIntSecond() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
class ThirdClass implements AnInterface {
|
||||
public int getInt() {
|
||||
class ThirdClass implements FirstInterface, SecondInterface {
|
||||
public int getIntFirst() {
|
||||
return -3;
|
||||
}
|
||||
}
|
||||
|
||||
class FourthClass implements AnInterface {
|
||||
public int getInt() {
|
||||
return -4;
|
||||
}
|
||||
}
|
||||
|
||||
class FifthClass implements AnInterface {
|
||||
public int getInt() {
|
||||
return -5;
|
||||
}
|
||||
}
|
||||
|
||||
class MultiClass1 implements AnInterface, SecondInterface {
|
||||
public int get1() {
|
||||
public int getIntSecond() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
public int getInt() {
|
||||
return 2;
|
||||
class FourthClass implements FirstInterface, SecondInterface {
|
||||
public int getIntFirst() {
|
||||
return -4;
|
||||
}
|
||||
|
||||
public int getIntSecond() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
class MultiClass2 implements AnInterface, SecondInterface {
|
||||
public int get1() {
|
||||
return -1;
|
||||
class FifthClass implements FirstInterface, SecondInterface {
|
||||
public int getIntFirst() {
|
||||
return -5;
|
||||
}
|
||||
|
||||
public int getInt() {
|
||||
return -2;
|
||||
public int getIntSecond() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
class Aloner implements AloneInterface {
|
||||
public int getNumber() {
|
||||
return 7;
|
||||
}
|
||||
}
|
||||
final int asLength = 5;
|
||||
public FirstInterface[] as = new FirstInterface[asLength];
|
||||
|
||||
public Object dummy1;
|
||||
|
||||
public Object dummy2;
|
||||
|
||||
public Object dummy3;
|
||||
|
||||
public AnInterface multi1a, multi2a;
|
||||
|
||||
public SecondInterface multi1b, multi2b;
|
||||
|
||||
public Object multic, multic2;
|
||||
|
||||
public AnInterface[] as = new AnInterface[5];
|
||||
|
||||
public AnInterface multi;
|
||||
|
||||
public OnlyHasOneImplInterface single1;
|
||||
|
||||
public OnlyHasOneImplInterface single2;
|
||||
|
||||
public AloneInterface alone;
|
||||
|
||||
int count;
|
||||
|
||||
@Setup
|
||||
public void setupSubclass() {
|
||||
dummy1 = new FirstClass();
|
||||
dummy2 = new SecondClass();
|
||||
dummy3 = new ThirdClass();
|
||||
as[0] = new FirstClass();
|
||||
as[1] = new SecondClass();
|
||||
as[2] = new ThirdClass();
|
||||
as[3] = new FourthClass();
|
||||
as[4] = new FifthClass();
|
||||
MultiClass1 mc1 = new MultiClass1();
|
||||
multi1a = mc1;
|
||||
multi1b = mc1;
|
||||
multic = mc1;
|
||||
MultiClass2 mc2 = new MultiClass2();
|
||||
multi2a = mc2;
|
||||
multi2b = mc2;
|
||||
multic2 = mc2;
|
||||
single1 = new SingleImplementor();
|
||||
single2 = new Extender1();
|
||||
alone = new Aloner();
|
||||
}
|
||||
|
||||
private void swapMultiParts() {
|
||||
AnInterface tmpa = multi1a;
|
||||
SecondInterface tmpb = multi1b;
|
||||
multi1a = multi2a;
|
||||
multi2a = tmpa;
|
||||
multi1b = multi2b;
|
||||
multi2b = tmpb;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private void swapMulti() {
|
||||
Object tmp = multic;
|
||||
multic = multic2;
|
||||
multic2 = tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests a call where there are multiple implementors but only one of the implementors is every used here so the
|
||||
* call-site is monomorphic
|
||||
* Tests a call where there are multiple implementors but only one of the
|
||||
* implementors is every used here so the call-site is monomorphic
|
||||
*/
|
||||
@Benchmark
|
||||
public int testMonomorphic() {
|
||||
return as[0].getInt();
|
||||
return as[0].getIntFirst();
|
||||
}
|
||||
|
||||
/** Tests a interface call that only has one single implementation */
|
||||
@Benchmark
|
||||
public int testSingle() {
|
||||
return alone.getNumber();
|
||||
}
|
||||
int l = 0;
|
||||
|
||||
/**
|
||||
* Tests a call where there is a single implementation but multiple classes that inherit that implementation and both
|
||||
* these implementors are used.
|
||||
* Interface call address computation within loop but the receiver preexists
|
||||
* the loop and the ac can be moved outside of the loop
|
||||
*/
|
||||
@Benchmark
|
||||
public int testSingle2() {
|
||||
OnlyHasOneImplInterface oi;
|
||||
if ((count & 1) == 0) {
|
||||
oi = single1;
|
||||
} else {
|
||||
oi = single2;
|
||||
}
|
||||
count++;
|
||||
return oi.getLong();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests calling two different interface methods in two different interfaces on the same receiver. Make sure to switch
|
||||
* between two different types of receivers to achieve polymorhpism
|
||||
*/
|
||||
@Benchmark
|
||||
public void testCall2Poly2(Blackhole bh) {
|
||||
bh.consume(multi1a.getInt());
|
||||
bh.consume(multi1b.get1());
|
||||
swapMultiParts();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public int testCallMulti1Poly2NoSwap() {
|
||||
return multi1a.getInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* This test goes together with Multi2 below It tests if a class implements multiple interfaces if the different
|
||||
* interfaces take different amounts of time (They do for hotspot)
|
||||
*/
|
||||
@Benchmark
|
||||
public int testCallMulti1Poly2() {
|
||||
swapMultiParts();
|
||||
return multi1a.getInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* This test goes together with Multi2 below It tests if a class implements multiple interfaces if the different
|
||||
* interfaces take different amounts of time (They do for hotspot)
|
||||
*/
|
||||
@Benchmark
|
||||
public int testCallMulti2Poly2() {
|
||||
swapMultiParts();
|
||||
return multi1b.get1();
|
||||
}
|
||||
|
||||
/** Interface call with three different receivers */
|
||||
@Benchmark
|
||||
public void testCallPoly3(Blackhole bh) {
|
||||
for (int kk = 0; kk < 3; kk++) {
|
||||
bh.consume(as[kk].getInt());
|
||||
}
|
||||
}
|
||||
|
||||
/** Interface call with five different receivers. */
|
||||
@Benchmark
|
||||
public void testCallPoly5(Blackhole bh) {
|
||||
for (int kk = 0; kk < 5; kk++) {
|
||||
bh.consume(as[kk].getInt());
|
||||
}
|
||||
}
|
||||
|
||||
int l;
|
||||
|
||||
/**
|
||||
* Interface call address computation within loop but the receiver preexists the loop and the ac can be moved outside
|
||||
* of the loop
|
||||
*/
|
||||
@Benchmark
|
||||
public int testAC1() {
|
||||
AnInterface ai = as[l];
|
||||
public int test1stInt2Types() {
|
||||
FirstInterface ai = as[l];
|
||||
l = 1 - l;
|
||||
return ai.getInt();
|
||||
return ai.getIntFirst();
|
||||
}
|
||||
|
||||
/** Tests an interface cast followed by an interface call. */
|
||||
@Benchmark
|
||||
public int testInterfaceCastAndCall() throws Exception {
|
||||
return ((AnInterface) dummy1).getInt() + ((AnInterface) dummy2).getInt()
|
||||
+ ((AnInterface) dummy3).getInt();
|
||||
public int test1stInt3Types() {
|
||||
FirstInterface ai = as[l];
|
||||
l = ++ l % 3;
|
||||
return ai.getIntFirst();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public int test1stInt5Types() {
|
||||
FirstInterface ai = as[l];
|
||||
l = ++ l % asLength;
|
||||
return ai.getIntFirst();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public int test2ndInt2Types() {
|
||||
SecondInterface ai = (SecondInterface) as[l];
|
||||
l = 1 - l;
|
||||
return ai.getIntSecond();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public int test2ndInt3Types() {
|
||||
SecondInterface ai = (SecondInterface) as[l];
|
||||
l = ++ l % 3;
|
||||
return ai.getIntSecond();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public int test2ndInt5Types() {
|
||||
SecondInterface ai = (SecondInterface) as[l];
|
||||
l = ++ l % asLength;
|
||||
return ai.getIntSecond();
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user