changeset 19730:6f7cb87ac0fa

Add test that ConcreteSubtype works properly for abstract classes
author Tom Rodriguez <tom.rodriguez@oracle.com>
date Mon, 09 Mar 2015 12:44:36 -0700
parents f8147c931ce4
children d0b4f9771622
files graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConcreteSubtypeTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerAssumptionsTest.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java
diffstat 3 files changed, 179 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConcreteSubtypeTest.java	Mon Mar 09 12:44:36 2015 -0700
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2015, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.test;
+
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.code.Assumptions.*;
+import com.oracle.graal.nodes.*;
+
+/**
+ * Ensure that abstract classes with a single implementor are properly optimized and that loading a
+ * subclass below the leaf type triggers invalidation.
+ */
+public class ConcreteSubtypeTest extends GraalCompilerAssumptionsTest {
+    abstract static class AbstractBase {
+        abstract void check();
+    }
+
+    static class Subclass extends AbstractBase {
+        @Override
+        public void check() {
+            throw new InternalError();
+        }
+    }
+
+    static class SubSubclass extends Subclass {
+        @Override
+        public void check() {
+        }
+    }
+
+    public void callAbstractType(AbstractBase object) {
+        object.check();
+    }
+
+    @Override
+    protected void checkGraph(Assumption expectedAssumption, StructuredGraph graph) {
+        super.checkGraph(expectedAssumption, graph);
+        assertTrue(graph.isTrivial());
+    }
+
+    /**
+     * Test that {@link #callAbstractType} gets compiled into an empty method with a
+     * {@link ConcreteSubtype} assumption on {@link AbstractBase} and {@link Subclass}. Then ensures
+     * that loading and initialization of {@link SubSubclass} causes the compiled method to be
+     * invalidated.
+     */
+    @Test
+    public void testLeafAbstractType() {
+        testAssumptionInvalidate("callAbstractType", new ConcreteSubtype(resolveAndInitialize(AbstractBase.class), resolveAndInitialize(Subclass.class)), "SubSubclass");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerAssumptionsTest.java	Mon Mar 09 12:44:36 2015 -0700
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2015, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.test;
+
+import static org.junit.Assert.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.Assumptions.Assumption;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
+
+public abstract class GraalCompilerAssumptionsTest extends GraalCompilerTest {
+
+    public GraalCompilerAssumptionsTest() {
+        super();
+    }
+
+    public GraalCompilerAssumptionsTest(Class<? extends Architecture> arch) {
+        super(arch);
+    }
+
+    protected void testAssumptionInvalidate(String methodName, Assumption expected, String classToLoad) {
+        testAssumption(methodName, expected, classToLoad, true);
+    }
+
+    /**
+     * Checks the behavior of class loading on {@link Assumption invalidation}. {@code methodName}
+     * is compiled and the resulting graph is checked for {@code expectedAssumption}. The code is
+     * installed and optionally {@code classToLoad} is loaded. The class is assumed to be an inner
+     * class of the test class and the name of the class to load is constructed relative to that.
+     *
+     * @param methodName the method to compile
+     * @param expectedAssumption expected {@link Assumption} instance to find in graph
+     * @param classToLoad an optional class to load to trigger an invalidation check
+     * @param willInvalidate true if loading {@code classToLoad} should invalidate the method
+     */
+    protected void testAssumption(String methodName, Assumption expectedAssumption, String classToLoad, boolean willInvalidate) {
+        ResolvedJavaMethod javaMethod = getResolvedJavaMethod(methodName);
+
+        StructuredGraph graph = parseEager(javaMethod, AllowAssumptions.YES);
+        assertTrue(!graph.getAssumptions().isEmpty());
+        checkGraph(expectedAssumption, graph);
+
+        CompilationResult compilationResult = compile(javaMethod, graph);
+        final InstalledCode installedCode = getProviders().getCodeCache().setDefaultMethod(javaMethod, compilationResult);
+        assertTrue(installedCode.isValid());
+        if (classToLoad != null) {
+            String fullName = getClass().getName() + "$" + classToLoad;
+            try {
+                Class.forName(fullName);
+            } catch (ClassNotFoundException e) {
+                assertFalse(String.format("Can't find class %s", fullName), true);
+            }
+            assertTrue(!willInvalidate == installedCode.isValid());
+        }
+    }
+
+    protected void checkGraph(Assumption expectedAssumption, StructuredGraph graph) {
+        boolean found = false;
+        for (Assumption a : graph.getAssumptions()) {
+            if (expectedAssumption.equals(a)) {
+                found = true;
+            }
+        }
+        assertTrue(String.format("Can't find assumption %s", expectedAssumption), found);
+    }
+
+    /**
+     * Converts a {@link Class} to an initialized {@link ResolvedJavaType}.
+     */
+    protected ResolvedJavaType resolveAndInitialize(Class<?> clazz) {
+        ResolvedJavaType type = getMetaAccess().lookupJavaType(clazz);
+        type.initialize();
+        return type;
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Mon Mar 09 12:43:19 2015 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Mon Mar 09 12:44:36 2015 -0700
@@ -534,4 +534,12 @@
     public Set<ResolvedJavaMethod> getInlinedMethods() {
         return inlinedMethods;
     }
+
+    /**
+     *
+     * @return true if the graph contains only a {@link StartNode} and {@link ReturnNode}
+     */
+    public boolean isTrivial() {
+        return !(start.next() instanceof ReturnNode);
+    }
 }