changeset 11712:0d16339188ef

Improvements to the Truffle cache.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Thu, 19 Sep 2013 04:11:20 +0200
parents f12b418ebc74
children 972f2e2c797a
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassCastNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassSubstitutions.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/SlowPathExceptionSubstitutions.java
diffstat 6 files changed, 110 insertions(+), 80 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassCastNode.java	Thu Sep 19 04:11:20 2013 +0200
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2013, 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.hotspot.meta.*;
+import com.oracle.graal.hotspot.replacements.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.replacements.nodes.*;
+
+/**
+ * {@link MacroNode Macro node} for {@link Class#cast(Object)}.
+ * 
+ * @see ClassSubstitutions#isInstance(Class, Object)
+ */
+public class ClassCastNode extends MacroNode implements Canonicalizable {
+
+    public ClassCastNode(Invoke invoke) {
+        super(invoke);
+    }
+
+    private ValueNode getJavaClass() {
+        return arguments.get(0);
+    }
+
+    private ValueNode getObject() {
+        return arguments.get(1);
+    }
+
+    public ValueNode canonical(CanonicalizerTool tool) {
+        ValueNode javaClass = getJavaClass();
+        if (javaClass.isConstant()) {
+            ValueNode object = getObject();
+            Class c = (Class) javaClass.asConstant().asObject();
+            if (c != null && !c.isPrimitive()) {
+                HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) HotSpotResolvedObjectType.fromClass(c);
+                CheckCastNode checkcast = graph().add(new CheckCastNode(type, object, null, false));
+                return checkcast;
+            }
+        }
+        return this;
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassSubstitutions.java	Thu Sep 19 02:20:46 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassSubstitutions.java	Thu Sep 19 04:11:20 2013 +0200
@@ -121,4 +121,7 @@
     public static boolean isInstance(final Class<?> thisObj, Object obj) {
         return !isPrimitive(thisObj) && ConditionalNode.materializeIsInstance(thisObj, obj);
     }
+
+    @MacroSubstitution(macro = ClassCastNode.class, isStatic = false)
+    public static native Object cast(final Class<?> thisObj, Object obj);
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Thu Sep 19 02:20:46 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Thu Sep 19 04:11:20 2013 +0200
@@ -1308,6 +1308,9 @@
         UnwindNode unwindNode = null;
         final StartNode entryPointNode = inlineGraph.start();
         FixedNode firstCFGNode = entryPointNode.next();
+        if (firstCFGNode == null) {
+            throw new IllegalStateException("Inlined graph is in invalid state");
+        }
         for (Node node : inlineGraph.getNodes()) {
             if (node == entryPointNode || node == entryPointNode.stateAfter() || node instanceof LocalNode) {
                 // Do nothing.
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java	Thu Sep 19 02:20:46 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java	Thu Sep 19 04:11:20 2013 +0200
@@ -32,11 +32,13 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.Node;
 import com.oracle.graal.java.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
@@ -115,10 +117,23 @@
                 for (MethodCallTargetNode methodCallTarget : graph.getNodes(MethodCallTargetNode.class)) {
                     if (graph.getMark() != mark) {
                         canonicalizerPhase.applyIncremental(graph, context, mark);
+
+                        // Make sure macro substitutions such as
+                        // CompilerDirectives.transferToInterpreter get processed first.
+                        for (Node newNode : graph.getNewNodes(mark)) {
+                            if (newNode instanceof MethodCallTargetNode) {
+                                MethodCallTargetNode methodCallTargetNode = (MethodCallTargetNode) newNode;
+                                Class<? extends FixedWithNextNode> macroSubstitution = replacements.getMacroSubstitution(methodCallTargetNode.targetMethod());
+                                if (macroSubstitution != null) {
+                                    InliningUtil.inlineMacroNode(methodCallTargetNode.invoke(), methodCallTargetNode.targetMethod(), methodCallTargetNode.graph(), macroSubstitution);
+                                }
+                            }
+                        }
                         mark = graph.getMark();
                     }
-                    String name = methodCallTarget.targetName();
-                    expandInvoke(methodCallTarget.invoke());
+                    if (methodCallTarget.isAlive() && methodCallTarget.invoke() != null) {
+                        expandInvoke(methodCallTarget.invoke());
+                    }
                 }
 
                 // Convert deopt to guards.
@@ -148,28 +163,33 @@
             if ((methodCallTargetNode.invokeKind() == InvokeKind.Special || methodCallTargetNode.invokeKind() == InvokeKind.Static) &&
                             !Modifier.isNative(methodCallTargetNode.targetMethod().getModifiers()) && methodCallTargetNode.targetMethod().getAnnotation(ExplodeLoop.class) == null &&
                             methodCallTargetNode.targetMethod().getAnnotation(CompilerDirectives.SlowPath.class) == null) {
-                Class<? extends FixedWithNextNode> macroSubstitution = replacements.getMacroSubstitution(methodCallTargetNode.targetMethod());
-                if (macroSubstitution != null) {
-                    return InliningUtil.inlineMacroNode(invoke, methodCallTargetNode.targetMethod(), methodCallTargetNode.graph(), macroSubstitution);
-                } else {
-                    StructuredGraph inlinedGraph = Debug.scope("ExpandInvoke", methodCallTargetNode.targetMethod(), new Callable<StructuredGraph>() {
+                if (methodCallTargetNode.targetMethod().isConstructor()) {
+                    ResolvedJavaType runtimeException = metaAccessProvider.lookupJavaType(RuntimeException.class);
+                    if (runtimeException.isAssignableFrom(methodCallTargetNode.targetMethod().getDeclaringClass())) {
+                        DeoptimizeNode deoptNode = invoke.asNode().graph().add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.UnreachedCode));
+                        FixedNode invokeNode = methodCallTargetNode.invoke().asNode();
+                        invokeNode.replaceAtPredecessor(deoptNode);
+                        GraphUtil.killCFG(invokeNode);
+                        return deoptNode;
+                    }
+                }
+                StructuredGraph inlinedGraph = Debug.scope("ExpandInvoke", methodCallTargetNode.targetMethod(), new Callable<StructuredGraph>() {
 
-                        public StructuredGraph call() {
-                            StructuredGraph inlineGraph = replacements.getMethodSubstitution(methodCallTargetNode.targetMethod());
-                            if (inlineGraph == null) {
-                                inlineGraph = TruffleCache.this.lookup(methodCallTargetNode.targetMethod(), methodCallTargetNode.arguments(), null, null);
-                            }
-                            return inlineGraph;
+                    public StructuredGraph call() {
+                        StructuredGraph inlineGraph = replacements.getMethodSubstitution(methodCallTargetNode.targetMethod());
+                        if (inlineGraph == null) {
+                            inlineGraph = TruffleCache.this.lookup(methodCallTargetNode.targetMethod(), methodCallTargetNode.arguments(), null, null);
                         }
-                    });
-                    if (inlinedGraph == null) {
-                        // Can happen for recursive calls.
-                        return invoke.asNode();
+                        return inlineGraph;
                     }
-                    FixedNode fixedNode = (FixedNode) invoke.predecessor();
-                    InliningUtil.inline(invoke, inlinedGraph, true);
-                    return fixedNode;
+                });
+                if (inlinedGraph == this.markerGraph) {
+                    // Can happen for recursive calls.
+                    throw new IllegalStateException("Found illegal recursive call to " + methodCallTargetNode.targetMethod() + ", must annotate such calls with @CompilerDirectives.Slowpath!");
                 }
+                FixedNode fixedNode = (FixedNode) invoke.predecessor();
+                InliningUtil.inline(invoke, inlinedGraph, true);
+                return fixedNode;
             }
         }
         return invoke.asNode();
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java	Thu Sep 19 02:20:46 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java	Thu Sep 19 04:11:20 2013 +0200
@@ -56,7 +56,6 @@
         truffleReplacements.registerSubstitutions(CompilerDirectivesSubstitutions.class);
         truffleReplacements.registerSubstitutions(ExactMathSubstitutions.class);
         truffleReplacements.registerSubstitutions(UnexpectedResultExceptionSubstitutions.class);
-        truffleReplacements.registerSubstitutions(SlowPathExceptionSubstitutions.class);
         truffleReplacements.registerSubstitutions(FrameWithoutBoxingSubstitutions.class);
         truffleReplacements.registerSubstitutions(OptimizedAssumptionSubstitutions.class);
         truffleReplacements.registerSubstitutions(OptimizedCallTargetSubstitutions.class);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/SlowPathExceptionSubstitutions.java	Thu Sep 19 02:20:46 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2013, 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.truffle.substitutions;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.replacements.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Deoptimize on creation of a new SlowPathException instance.
- */
-@ClassSubstitution(SlowPathException.class)
-public class SlowPathExceptionSubstitutions {
-
-    @MethodSubstitution(value = "<init>")
-    public static void init() {
-        DeoptimizeNode.deopt(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.UnreachedCode);
-    }
-
-    @SuppressWarnings("unused")
-    @MethodSubstitution(value = "<init>")
-    public static void init(String result, Throwable cause) {
-        DeoptimizeNode.deopt(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.UnreachedCode);
-    }
-
-    @SuppressWarnings("unused")
-    @MethodSubstitution(value = "<init>")
-    public static void init(String result) {
-        DeoptimizeNode.deopt(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.UnreachedCode);
-    }
-
-    @SuppressWarnings("unused")
-    @MethodSubstitution(value = "<init>")
-    public static void init(Throwable cause) {
-        DeoptimizeNode.deopt(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.UnreachedCode);
-    }
-}