changeset 18492:f39180e681b8

ClassSubstitutions: macro for Class.isAssignable
author Bernhard Urban <bernhard.urban@jku.at>
date Mon, 24 Nov 2014 16:30:28 +0100
parents 8d9c1a018e77
children 11bc91bcc525
files graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/ClassSubstitutionsTests.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsAssignableFromNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassSubstitutions.java
diffstat 3 files changed, 145 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/ClassSubstitutionsTests.java	Mon Nov 24 15:06:49 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/ClassSubstitutionsTests.java	Mon Nov 24 16:30:28 2014 +0100
@@ -127,6 +127,58 @@
         return true;
     }
 
+    private static class A {
+    }
+
+    private static class B extends A {
+    }
+
+    private static class C {
+    }
+
+    private static final A a = new A();
+    private static final B b = new B();
+    private static final C c = new C();
+
+    public boolean classIsAssignable1() {
+        return a.getClass().isAssignableFrom(a.getClass());
+    }
+
+    public boolean classIsAssignable2() {
+        return a.getClass().isAssignableFrom(b.getClass());
+    }
+
+    public boolean classIsAssignable3() {
+        return a.getClass().isAssignableFrom(c.getClass());
+    }
+
+    public boolean classIsAssignable4() {
+        return b.getClass().isAssignableFrom(a.getClass());
+    }
+
+    public boolean classIsAssignable5() {
+        return c.getClass().isAssignableFrom(b.getClass());
+    }
+
+    public boolean classIsAssignable6() {
+        return int.class.isAssignableFrom(b.getClass());
+    }
+
+    public boolean classIsAssignable7() {
+        return int.class.isAssignableFrom(int.class);
+    }
+
+    @Test
+    public void testClassIsAssignable() {
+        testConstantReturn("classIsAssignable1", 1);
+        testConstantReturn("classIsAssignable2", 1);
+        testConstantReturn("classIsAssignable3", 0);
+        testConstantReturn("classIsAssignable4", 0);
+        testConstantReturn("classIsAssignable5", 0);
+        testConstantReturn("classIsAssignable6", 0);
+        testConstantReturn("classIsAssignable7", 1);
+    }
+
     private void testConstantReturn(String name, Object value) {
         StructuredGraph result = test(name);
         ReturnNode ret = result.getNodes(ReturnNode.class).first();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsAssignableFromNode.java	Mon Nov 24 16:30:28 2014 +0100
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2014, 2014, 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.hotspot.nodes;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.hotspot.replacements.*;
+import com.oracle.graal.nodeinfo.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.replacements.nodes.*;
+
+/**
+ * {@link MacroNode Macro node} for {@link Class#isAssignableFrom(Class)}.
+ *
+ * @see ClassSubstitutions#isAssignableFrom(Class, Class)
+ */
+@NodeInfo
+public class ClassIsAssignableFromNode extends MacroStateSplitNode implements Canonicalizable {
+    public static ClassIsAssignableFromNode create(Invoke invoke) {
+        return new ClassIsAssignableFromNode(invoke);
+    }
+
+    protected ClassIsAssignableFromNode(Invoke invoke) {
+        super(invoke);
+    }
+
+    private ValueNode getJavaClass() {
+        return arguments.get(0);
+    }
+
+    private ValueNode getOtherClass() {
+        return arguments.get(1);
+    }
+
+    @Override
+    public Node canonical(CanonicalizerTool tool) {
+        ValueNode javaClass = getJavaClass();
+        ValueNode otherClass = getOtherClass();
+        if (javaClass.isConstant() && otherClass.isConstant()) {
+            ConstantReflectionProvider constantReflection = tool.getConstantReflection();
+            ResolvedJavaType thisType = constantReflection.asJavaType(javaClass.asJavaConstant());
+            ResolvedJavaType otherType = constantReflection.asJavaType(otherClass.asJavaConstant());
+            if (thisType != null && otherType != null) {
+                return ConstantNode.forBoolean(thisType.isAssignableFrom(otherType));
+            }
+        }
+        return this;
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassSubstitutions.java	Mon Nov 24 15:06:49 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassSubstitutions.java	Mon Nov 24 16:30:28 2014 +0100
@@ -27,10 +27,13 @@
 
 import java.lang.reflect.*;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.hotspot.word.*;
+import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.word.*;
 
@@ -130,6 +133,26 @@
         return ConditionalNode.materializeIsInstance(thisObj, obj);
     }
 
+    @MacroSubstitution(macro = ClassIsAssignableFromNode.class, isStatic = false)
+    @MethodSubstitution(isStatic = false)
+    public static boolean isAssignableFrom(Class<?> thisClass, Class<?> otherClass) {
+        if (BranchProbabilityNode.probability(BranchProbabilityNode.NOT_LIKELY_PROBABILITY, otherClass == null)) {
+            DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.NullCheckException);
+            return false;
+        }
+        GuardingNode anchorNode = SnippetAnchorNode.anchor();
+        KlassPointer thisHub = ClassGetHubNode.readClass(thisClass, anchorNode);
+        KlassPointer otherHub = ClassGetHubNode.readClass(otherClass, anchorNode);
+        if (thisHub.isNull() || otherHub.isNull()) {
+            // primitive types, only true if equal.
+            return thisClass == otherClass;
+        }
+        if (!TypeCheckSnippetUtils.checkUnknownSubType(thisHub.asWord(), otherHub.asWord())) {
+            return false;
+        }
+        return true;
+    }
+
     @MacroSubstitution(macro = ClassCastNode.class, isStatic = false)
     public static native Object cast(final Class<?> thisObj, Object obj);
 }