Path: blob/master/test/hotspot/jtreg/compiler/cha/AbstractRootMethod.java
64474 views
/*1* Copyright (c) 2021, 2022, 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*/2223/*24* @test25* @requires !vm.graal.enabled & vm.opt.final.UseVtableBasedCHA == true26* @modules java.base/jdk.internal.org.objectweb.asm27* java.base/jdk.internal.misc28* java.base/jdk.internal.vm.annotation29* @library /test/lib /30* @compile Utils.java31* @build sun.hotspot.WhiteBox32* @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox33*34* @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions35* -XX:+PrintCompilation -XX:+PrintInlining -XX:+TraceDependencies -verbose:class -XX:CompileCommand=quiet36* -XX:CompileCommand=compileonly,*::m37* -XX:CompileCommand=compileonly,*::test -XX:CompileCommand=dontinline,*::test38* -Xbatch -Xmixed -XX:+WhiteBoxAPI39* -XX:-TieredCompilation40* compiler.cha.AbstractRootMethod41*42* @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions43* -XX:+PrintCompilation -XX:+PrintInlining -XX:+TraceDependencies -verbose:class -XX:CompileCommand=quiet44* -XX:CompileCommand=compileonly,*::m45* -XX:CompileCommand=compileonly,*::test -XX:CompileCommand=dontinline,*::test46* -Xbatch -Xmixed -XX:+WhiteBoxAPI47* -XX:+TieredCompilation -XX:TieredStopAtLevel=148* compiler.cha.AbstractRootMethod49*/50package compiler.cha;5152import java.lang.invoke.MethodHandle;53import java.lang.invoke.MethodHandles;5455import static compiler.cha.Utils.*;5657public class AbstractRootMethod {58public static void main(String[] args) {59run(AbstractClass.class);60run(AbstractInterface.class);6162// Implementation limitation: CHA is not performed by C1 during inlining through MH linkers.63if (!sun.hotspot.code.Compiler.isC1Enabled()) {64run(AbstractClass.TestMH.class, AbstractClass.class);65run(AbstractInterface.TestMH.class, AbstractInterface.class);66}6768System.out.println("TEST PASSED");69}7071public static class AbstractClass extends ATest<AbstractClass.C> {72public AbstractClass() {73super(C.class, D.class);74}7576interface I1 { Object m(); }77interface I2 { default Object m() { return "I2.m"; } }7879static abstract class C { public abstract Object m(); }8081static abstract class D extends C {82final Object ret = CORRECT;83public Object m() {84return ret;85}86}8788static abstract class E1 extends C { /* empty */ }89static abstract class E2 extends C { public abstract Object m(); }90static abstract class E3 extends C { public Object m() { return "E3.m"; } }9192static abstract class F1 extends C implements I1 { }93static abstract class F2 extends C implements I2 { }9495static class G extends C { public Object m() { return CORRECT; } }9697@Override98public Object test(C obj) {99return obj.m(); // invokevirtual C.m()100}101102@Override103public void checkInvalidReceiver() {104// nothing to do: concrete class types are enforced by the verifier105}106107@TestCase108public void test() {109// 0. Trigger compilation of a megamorphic call site110compile(megamorphic()); // Dn <: D.m <: C.m ABSTRACT111assertCompiled();112113// Dependency: type = unique_concrete_method, context = C, method = D.m114115// 1. No invalidation: abstract classes don't participate in CHA.116initialize(E1.class, // ABSTRACT E1 <: C.m ABSTRACT117E2.class, // ABSTRACT E2.m ABSTRACT <: C.m ABSTRACT118E3.class, // ABSTRACT E3.m <: C.m ABSTRACT119F1.class, // ABSTRACT F1 <: C.m ABSTRACT, I1.m ABSTRACT120F2.class); // ABSTRACT F2 <: C.m ABSTRACT, I2.m DEFAULT121assertCompiled();122123// 2. Dependency invalidation: G.m <: C.m ABSTRACT124load(G.class);125assertCompiled();126127// 3. Dependency invalidation: G.m <: C.m ABSTRACT128initialize(G.class);129assertNotCompiled();130131// 4. Recompilation: no inlining, no dependencies132compile(megamorphic());133call(new C() { public Object m() { return CORRECT; } }); // Cn.m <: C.m ABSTRACT134call(new G() { public Object m() { return CORRECT; } }); // Gn <: G.m <: C.m ABSTRACT135assertCompiled();136}137138public static class TestMH extends AbstractClass {139static final MethodHandle TEST_MH = findVirtualHelper(C.class, "m", Object.class, MethodHandles.lookup());140141@Override142public Object test(C obj) {143try {144return TEST_MH.invokeExact(obj); // invokevirtual C.m()145} catch (Throwable e) {146throw new InternalError(e);147}148}149}150}151152public static class AbstractInterface extends ATest<AbstractInterface.C> {153public AbstractInterface() {154super(C.class, D.class);155}156157interface I1 { Object m(); }158interface I2 extends I { default Object m() { return "I2.m"; } }159160interface I { Object m(); }161162static abstract class C implements I { /* inherited from I */}163164static abstract class D extends C {165final Object ret = CORRECT;166public Object m() {167return ret;168}169}170171static abstract class E1 extends C { /* empty */ }172static abstract class E2 extends C { public abstract Object m(); }173static abstract class E3 extends C { public Object m() { return "E3.m"; } }174175static abstract class F1 extends C implements I1 { }176static abstract class F2 extends C implements I2 { }177178static class G extends C { public Object m() { return CORRECT; } }179180@Override181public Object test(C obj) {182return obj.m(); // invokevirtual C.m()183}184185@Override186public void checkInvalidReceiver() {187// nothing to do: concrete class types are enforced by the verifier188}189190@TestCase191public void test() {192// 0. Trigger compilation of a megamorphic call site193compile(megamorphic()); // Dn <: D.m <: C <: I.m ABSTRACT194assertCompiled();195196// Dependency: type = unique_concrete_method, context = C, method = D.m197198// 1. No invalidation: abstract classes don't participate in CHA.199initialize(E1.class, // ABSTRACT E1 <: C <: I.m ABSTRACT200E2.class, // ABSTRACT E2.m ABSTRACT <: C <: I.m ABSTRACT201E3.class, // ABSTRACT E3.m <: C <: I.m ABSTRACT202F1.class, // ABSTRACT F1 <: C <: I.m ABSTRACT, I1.m ABSTRACT203F2.class); // ABSTRACT F2 <: C <: I.m ABSTRACT, I2.m DEFAULT204assertCompiled();205206// 2. Dependency invalidation: G.m <: C <: I.m ABSTRACT207load(G.class);208assertCompiled();209210// 3. Dependency invalidation: G.m <: C <: I.m ABSTRACT211initialize(G.class);212assertNotCompiled();213214// 4. Recompilation: no inlining, no dependencies215compile(megamorphic());216call(new C() { public Object m() { return CORRECT; } }); // Cn.m <: C <: I.m ABSTRACT217call(new G() { public Object m() { return CORRECT; } }); // Gn <: G.m <: C <: I.m ABSTRACT218assertCompiled();219}220221public static class TestMH extends AbstractInterface {222static final MethodHandle TEST_MH = findVirtualHelper(C.class, "m", Object.class, MethodHandles.lookup());223224@Override225public Object test(C obj) {226try {227return TEST_MH.invokeExact(obj); // invokevirtual C.m()228} catch (Throwable e) {229throw new InternalError(e);230}231}232}233}234}235236237