GetVtableIndexForInterfaceTest.java revision 12772:fbb9c8026495
118334Speter/*
218334Speter * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
318334Speter * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
418334Speter *
518334Speter * This code is free software; you can redistribute it and/or modify it
618334Speter * under the terms of the GNU General Public License version 2 only, as
718334Speter * published by the Free Software Foundation.
818334Speter *
918334Speter * This code is distributed in the hope that it will be useful, but WITHOUT
1018334Speter * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1118334Speter * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1218334Speter * version 2 for more details (a copy is included in the LICENSE file that
1318334Speter * accompanied this code).
1418334Speter *
1518334Speter * You should have received a copy of the GNU General Public License version
1618334Speter * 2 along with this work; if not, write to the Free Software Foundation,
1718334Speter * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1818334Speter *
1918334Speter * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2018334Speter * or visit www.oracle.com if you need additional information or have any
2118334Speter * questions.
2218334Speter */
2318334Speter
2418334Speter/*
2518334Speter * @test
2618334Speter * @bug 8136421
2718334Speter * @requires vm.jvmci
2818334Speter * @library / /test/lib
2918334Speter * @library ../common/patches
3018334Speter * @modules java.base/jdk.internal.misc
3118334Speter * @modules java.base/jdk.internal.org.objectweb.asm
3218334Speter *          java.base/jdk.internal.org.objectweb.asm.tree
3318334Speter *          jdk.internal.vm.ci/jdk.vm.ci.hotspot
3418334Speter *          jdk.internal.vm.ci/jdk.vm.ci.code
3518334Speter * @build jdk.internal.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
3618334Speter * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
3718334Speter *                   -Djvmci.Compiler=null
3818334Speter *                   compiler.jvmci.compilerToVM.GetVtableIndexForInterfaceTest
3918334Speter */
4018334Speter
4118334Speterpackage compiler.jvmci.compilerToVM;
4218334Speter
4318334Speterimport compiler.jvmci.common.CTVMUtilities;
4418334Speterimport compiler.jvmci.common.testcases.AbstractClass;
4518334Speterimport compiler.jvmci.common.testcases.AnotherSingleImplementer;
4618334Speterimport compiler.jvmci.common.testcases.AnotherSingleImplementerInterface;
4718334Speterimport compiler.jvmci.common.testcases.DoNotExtendClass;
4818334Speterimport compiler.jvmci.common.testcases.MultipleAbstractImplementer;
4918334Speterimport compiler.jvmci.common.testcases.MultipleImplementersInterface;
5018334Speterimport compiler.jvmci.common.testcases.MultipleImplementersInterfaceExtender;
5118334Speterimport compiler.jvmci.common.testcases.SingleImplementer;
5218334Speterimport compiler.jvmci.common.testcases.SingleImplementerInterface;
5318334Speterimport compiler.jvmci.common.testcases.SingleSubclass;
5418334Speterimport compiler.jvmci.common.testcases.SingleSubclassedClass;
5518334Speterimport jdk.test.lib.Asserts;
5618334Speterimport jdk.test.lib.Utils;
5718334Speterimport jdk.vm.ci.hotspot.CompilerToVMHelper;
5818334Speterimport jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
5918334Speterimport jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
6018334Speter
6118334Speterimport java.lang.reflect.Method;
6218334Speterimport java.util.HashSet;
6318334Speterimport java.util.Set;
6418334Speterimport java.util.stream.Stream;
6518334Speter
6618334Speterpublic class GetVtableIndexForInterfaceTest {
6718334Speter    private static final int INVALID_VTABLE_INDEX = -4; // see method.hpp: VtableIndexFlag
6818334Speter
6918334Speter    public static void main(String args[]) {
7018334Speter        GetVtableIndexForInterfaceTest test
7118334Speter                = new GetVtableIndexForInterfaceTest();
7218334Speter        try {
7318334Speter            for (TestCase tcase : createTestCases()) {
7418334Speter                test.runTest(tcase);
7518334Speter            }
7618334Speter        } catch (NoSuchMethodException e) {
7718334Speter            throw new Error("TEST BUG: can't find requested method", e);
7818334Speter        }
7918334Speter    }
8018334Speter
8118334Speter    private static Set<TestCase> createTestCases() {
8218334Speter        Set<TestCase> result = new HashSet<>();
8318334Speter        Stream.of(
8418334Speter                    AbstractClass.class,
8518334Speter                    SingleImplementer.class,
8618334Speter                    SingleImplementerInterface.class,
8718334Speter                    MultipleImplementersInterface.class,
8818334Speter                    MultipleImplementersInterfaceExtender.class,
8918334Speter                    SingleSubclass.class,
9018334Speter                    SingleSubclassedClass.class,
9118334Speter                    DoNotExtendClass.class,
9218334Speter                    MultipleAbstractImplementer.class
9318334Speter                )
9418334Speter                .forEach(Utils::ensureClassIsLoaded);
9518334Speter        // non iface method
9618334Speter        result.add(new TestCase(SingleImplementer.class,
9718334Speter                SingleImplementer.class, "nonInterfaceMethod",
9818334Speter                false, InternalError.class));
9918334Speter        // iface method w/o default implementation
10018334Speter        result.add(new TestCase(SingleImplementer.class,
10118334Speter                SingleImplementerInterface.class, "interfaceMethod", false));
10218334Speter        /* another iface which provides default implementation for the
10318334Speter           original iface*/
10418334Speter        result.add(new TestCase(MultipleImplementersInterfaceExtender.class,
10518334Speter                MultipleImplementersInterface.class, "testMethod", false,
10618334Speter                InternalError.class));
10718334Speter        // iface method w/ default implementation
10818334Speter        result.add(new TestCase(SingleImplementer.class,
10918334Speter                SingleImplementerInterface.class, "defaultMethod", true));
11018334Speter        // non iface class
11118334Speter        result.add(new TestCase(SingleSubclass.class,
11218334Speter                SingleSubclassedClass.class, "inheritedMethod", false,
11318334Speter                InternalError.class));
11418334Speter        // class not implementing iface
11518334Speter        result.add(new TestCase(DoNotExtendClass.class,
11618334Speter                SingleImplementerInterface.class, "defaultMethod", false));
11718334Speter        // abstract class which doesn't implement iface
11818334Speter        result.add(new TestCase(AbstractClass.class,
11918334Speter                SingleImplementerInterface.class, "defaultMethod", false));
12018334Speter        // abstract class which implements iface
12118334Speter        result.add(new TestCase(MultipleAbstractImplementer.class,
12218334Speter                MultipleImplementersInterface.class, "defaultMethod", true));
12318334Speter        // class not initialized
12418334Speter        result.add(new TestCase(AnotherSingleImplementer.class,
12518334Speter                AnotherSingleImplementerInterface.class, "defaultMethod",
12618334Speter                false, InternalError.class));
12718334Speter        return result;
12818334Speter    }
12918334Speter
13018334Speter    private void runTest(TestCase tcase) throws NoSuchMethodException {
13118334Speter        System.out.println(tcase);
13218334Speter        Method method = tcase.holder.getDeclaredMethod(tcase.methodName);
13318334Speter        HotSpotResolvedObjectType metaspaceKlass = CompilerToVMHelper
13418334Speter                .lookupType(Utils.toJVMTypeSignature(tcase.receiver),
13518334Speter                        getClass(), /* resolve = */ true);
13618334Speter        HotSpotResolvedJavaMethod metaspaceMethod = CTVMUtilities
13718334Speter                .getResolvedMethod(tcase.holder, method);
13818334Speter        int index = 0;
13918334Speter        try {
14018334Speter            index = CompilerToVMHelper
14118334Speter                    .getVtableIndexForInterfaceMethod(metaspaceKlass,
14218334Speter                            metaspaceMethod);
14318334Speter        } catch (Throwable t) {
14418334Speter            if (tcase.isPositive || tcase.expectedException == null) {
14518334Speter                throw new Error("Caught unexpected exception " + t);
14618334Speter            }
14718334Speter            if (!tcase.expectedException.equals(t.getClass())) {
14818334Speter                throw new Error(String.format("Caught %s while expected %s",
14918334Speter                        t.getClass().getName(),
15018334Speter                        tcase.expectedException.getName()));
15118334Speter            }
15218334Speter            return;
15318334Speter        }
15418334Speter        if (tcase.expectedException != null) {
15518334Speter            throw new AssertionError("Expected exception wasn't caught: "
15618334Speter                    + tcase.expectedException.getName());
15718334Speter        }
15818334Speter        if (tcase.isPositive) {
15918334Speter            Asserts.assertNE(index, INVALID_VTABLE_INDEX,
16018334Speter                    "Unexpected: got invalid index");
16118334Speter        } else {
16218334Speter            Asserts.assertEQ(index, INVALID_VTABLE_INDEX,
16318334Speter                    "Unexpected: got valid index ");
16418334Speter        }
16518334Speter    }
16618334Speter
16718334Speter    private static class TestCase {
16818334Speter        public final Class<?> receiver;
16918334Speter        public final Class<?> holder;
17018334Speter        public final String methodName;
17118334Speter        public final boolean isPositive;
17218334Speter        public final Class<? extends Throwable> expectedException;
17318334Speter
17418334Speter        public TestCase(Class<?> receiver, Class<?> holder, String methodName,
17518334Speter                boolean isPositive,
17618334Speter                Class<? extends Throwable> expectedException) {
17718334Speter            this.receiver = receiver;
17818334Speter            this.holder = holder;
17918334Speter            this.methodName = methodName;
18018334Speter            this.isPositive = isPositive;
18118334Speter            this.expectedException = expectedException;
18218334Speter        }
18318334Speter
18418334Speter        public TestCase(Class<?> receiver, Class<?> holder, String methodName,
18518334Speter                boolean isPositive) {
18618334Speter            this(receiver, holder, methodName, isPositive, null);
18718334Speter        }
18818334Speter
18918334Speter        @Override
19018334Speter        public String toString() {
19118334Speter            return String.format("CASE: receiver=%s, holder=%s, method=%s,"
19218334Speter                    + " isPositive=%s%n", receiver.getName(), holder.getName(),
19318334Speter                    methodName, isPositive);
19418334Speter        }
19518334Speter    }
19618334Speter}
19718334Speter