changeset 10651:192a3b3c7292

Merge.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Mon, 08 Jul 2013 15:54:24 +0200
parents b6e46324233f (diff) 87c441b324e9 (current diff)
children aca7481e71d1
files graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java
diffstat 10 files changed, 120 insertions(+), 127 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeAccessNode.java	Mon Jul 08 14:34:45 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeAccessNode.java	Mon Jul 08 15:54:24 2013 +0200
@@ -24,9 +24,10 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
-public abstract class UnsafeAccessNode extends FixedWithNextNode {
+public abstract class UnsafeAccessNode extends FixedWithNextNode implements Canonicalizable {
 
     @Input private ValueNode object;
     @Input private ValueNode offset;
@@ -57,4 +58,38 @@
     public Kind accessKind() {
         return accessKind;
     }
+
+    @Override
+    public ValueNode canonical(CanonicalizerTool tool) {
+        if (offset().isConstant()) {
+            long constantOffset = offset().asConstant().asLong();
+
+            // Try to canonicalize to a field access.
+            if (object().stamp() instanceof ObjectStamp) {
+                // TODO (gd) remove that once UnsafeAccess only have an object base
+                ObjectStamp receiverStamp = object().objectStamp();
+                ResolvedJavaType receiverType = receiverStamp.type();
+                ResolvedJavaField field = receiverType.findInstanceFieldWithOffset(displacement() + constantOffset);
+
+                // No need for checking that the receiver is non-null. The field access includes the
+                // null check and if a field is found, the offset is so small that this is never a
+                // valid access of an arbitrary address.
+                if (field != null && field.getKind() == this.accessKind()) {
+                    return cloneAsFieldAccess(field);
+                }
+            }
+
+            if (constantOffset != 0 && Integer.MAX_VALUE - displacement() >= constantOffset) {
+                int intDisplacement = (int) (constantOffset + displacement());
+                if (constantOffset == intDisplacement) {
+                    return cloneWithZeroOffset(intDisplacement);
+                }
+            }
+        }
+        return this;
+    }
+
+    protected abstract ValueNode cloneAsFieldAccess(ResolvedJavaField field);
+
+    protected abstract ValueNode cloneWithZeroOffset(int intDisplacement);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java	Mon Jul 08 14:34:45 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java	Mon Jul 08 15:54:24 2013 +0200
@@ -25,7 +25,6 @@
 import static com.oracle.graal.graph.UnsafeAccess.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
@@ -35,7 +34,7 @@
  * Load of a value from a location specified as an offset relative to an object. No null check is
  * performed before the load.
  */
-public class UnsafeLoadNode extends UnsafeAccessNode implements Lowerable, Virtualizable, Canonicalizable {
+public class UnsafeLoadNode extends UnsafeAccessNode implements Lowerable, Virtualizable {
 
     public UnsafeLoadNode(ValueNode object, int displacement, ValueNode offset, boolean nonNull) {
         this(nonNull ? StampFactory.objectNonNull() : StampFactory.object(), object, displacement, offset, Kind.Object);
@@ -70,29 +69,13 @@
     }
 
     @Override
-    public ValueNode canonical(CanonicalizerTool tool) {
-        if (offset().isConstant()) {
-            long constantOffset = offset().asConstant().asLong();
-            if (constantOffset != 0) {
-                int intDisplacement = (int) (constantOffset + displacement());
-                if (constantOffset == intDisplacement) {
-                    Graph graph = this.graph();
-                    return graph.add(new UnsafeLoadNode(this.stamp(), object(), intDisplacement, graph.unique(ConstantNode.forInt(0, graph)), accessKind()));
-                }
-            } else if (object().stamp() instanceof ObjectStamp) { // TODO (gd) remove that once
-                                                                  // UnsafeAccess only have an
-                                                                  // object base
-                ObjectStamp receiverStamp = object().objectStamp();
-                ResolvedJavaType receiverType = receiverStamp.type();
-                if (receiverStamp.nonNull() && receiverType != null) {
-                    ResolvedJavaField field = receiverType.findInstanceFieldWithOffset(displacement());
-                    if (field != null) {
-                        return this.graph().add(new LoadFieldNode(object(), field));
-                    }
-                }
-            }
-        }
-        return this;
+    protected ValueNode cloneAsFieldAccess(ResolvedJavaField field) {
+        return this.graph().add(new LoadFieldNode(object(), field));
+    }
+
+    @Override
+    protected ValueNode cloneWithZeroOffset(int intDisplacement) {
+        return graph().add(new UnsafeLoadNode(this.stamp(), object(), intDisplacement, graph().unique(ConstantNode.forInt(0, graph())), accessKind()));
     }
 
     @SuppressWarnings("unchecked")
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Mon Jul 08 14:34:45 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Mon Jul 08 15:54:24 2013 +0200
@@ -34,7 +34,7 @@
  * Store of a value at a location specified as an offset relative to an object. No null check is
  * performed before the store.
  */
-public class UnsafeStoreNode extends UnsafeAccessNode implements StateSplit, Lowerable, Virtualizable, Canonicalizable, MemoryCheckpoint.Single {
+public class UnsafeStoreNode extends UnsafeAccessNode implements StateSplit, Lowerable, Virtualizable, MemoryCheckpoint.Single {
 
     @Input private ValueNode value;
     @Input(notDataflow = true) private FrameState stateAfter;
@@ -94,32 +94,17 @@
     }
 
     @Override
-    public ValueNode canonical(CanonicalizerTool tool) {
-        if (offset().isConstant()) {
-            long constantOffset = offset().asConstant().asLong();
-            if (constantOffset != 0) {
-                int intDisplacement = (int) (constantOffset + displacement());
-                if (constantOffset == intDisplacement) {
-                    UnsafeStoreNode unsafeStoreNode = graph().add(new UnsafeStoreNode(stamp(), object(), intDisplacement, ConstantNode.forInt(0, graph()), value(), accessKind()));
-                    unsafeStoreNode.setStateAfter(stateAfter());
-                    return unsafeStoreNode;
-                }
-            } else if (object().stamp() instanceof ObjectStamp) { // TODO (gd) remove that once
-                                                                  // UnsafeAccess only have an
-                                                                  // object base
-                ObjectStamp receiverStamp = object().objectStamp();
-                if (receiverStamp.nonNull()) {
-                    ResolvedJavaType receiverType = receiverStamp.type();
-                    ResolvedJavaField field = receiverType.findInstanceFieldWithOffset(displacement());
-                    if (field != null) {
-                        StoreFieldNode storeFieldNode = graph().add(new StoreFieldNode(object(), field, value()));
-                        storeFieldNode.setStateAfter(stateAfter());
-                        return storeFieldNode;
-                    }
-                }
-            }
-        }
-        return this;
+    protected ValueNode cloneAsFieldAccess(ResolvedJavaField field) {
+        StoreFieldNode storeFieldNode = graph().add(new StoreFieldNode(object(), field, value()));
+        storeFieldNode.setStateAfter(stateAfter());
+        return storeFieldNode;
+    }
+
+    @Override
+    protected ValueNode cloneWithZeroOffset(int intDisplacement) {
+        UnsafeStoreNode unsafeStoreNode = graph().add(new UnsafeStoreNode(stamp(), object(), intDisplacement, ConstantNode.forInt(0, graph()), value(), accessKind()));
+        unsafeStoreNode.setStateAfter(stateAfter());
+        return unsafeStoreNode;
     }
 
     // specialized on value type until boxing/unboxing is sorted out in intrinsification
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Mon Jul 08 14:34:45 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Mon Jul 08 15:54:24 2013 +0200
@@ -331,27 +331,7 @@
                 assert inlineable instanceof InlineableMacroNode;
 
                 Class<? extends FixedWithNextNode> macroNodeClass = ((InlineableMacroNode) inlineable).getMacroNodeClass();
-                if (((MethodCallTargetNode) invoke.callTarget()).targetMethod() != concrete) {
-                    assert ((MethodCallTargetNode) invoke.callTarget()).invokeKind() != InvokeKind.Static;
-                    InliningUtil.replaceInvokeCallTarget(invoke, graph, InvokeKind.Special, concrete);
-                }
-
-                FixedWithNextNode macroNode;
-                try {
-                    macroNode = macroNodeClass.getConstructor(Invoke.class).newInstance(invoke);
-                } catch (ReflectiveOperationException | IllegalArgumentException | SecurityException e) {
-                    throw new GraalInternalError(e).addContext(invoke.asNode()).addContext("macroSubstitution", macroNodeClass);
-                }
-
-                CallTargetNode callTarget = invoke.callTarget();
-                if (invoke instanceof InvokeNode) {
-                    graph.replaceFixedWithFixed((InvokeNode) invoke, graph.add(macroNode));
-                } else {
-                    InvokeWithExceptionNode invokeWithException = (InvokeWithExceptionNode) invoke;
-                    invokeWithException.killExceptionEdge();
-                    graph.replaceSplitWithFixed(invokeWithException, graph.add(macroNode), invokeWithException.next());
-                }
-                GraphUtil.killWithUnusedFloatingInputs(callTarget);
+                inlineMacroNode(invoke, concrete, graph, macroNodeClass);
             }
 
             InlinedBytecodes.add(concrete.getCodeSize());
@@ -1480,4 +1460,29 @@
     public static Class<? extends FixedWithNextNode> getMacroNodeClass(Replacements replacements, ResolvedJavaMethod target) {
         return replacements.getMacroSubstitution(target);
     }
+
+    public static FixedWithNextNode inlineMacroNode(Invoke invoke, ResolvedJavaMethod concrete, StructuredGraph graph, Class<? extends FixedWithNextNode> macroNodeClass) throws GraalInternalError {
+        if (((MethodCallTargetNode) invoke.callTarget()).targetMethod() != concrete) {
+            assert ((MethodCallTargetNode) invoke.callTarget()).invokeKind() != InvokeKind.Static;
+            InliningUtil.replaceInvokeCallTarget(invoke, graph, InvokeKind.Special, concrete);
+        }
+
+        FixedWithNextNode macroNode;
+        try {
+            macroNode = macroNodeClass.getConstructor(Invoke.class).newInstance(invoke);
+        } catch (ReflectiveOperationException | IllegalArgumentException | SecurityException e) {
+            throw new GraalInternalError(e).addContext(invoke.asNode()).addContext("macroSubstitution", macroNodeClass);
+        }
+
+        CallTargetNode callTarget = invoke.callTarget();
+        if (invoke instanceof InvokeNode) {
+            graph.replaceFixedWithFixed((InvokeNode) invoke, graph.add(macroNode));
+        } else {
+            InvokeWithExceptionNode invokeWithException = (InvokeWithExceptionNode) invoke;
+            invokeWithException.killExceptionEdge();
+            graph.replaceSplitWithFixed(invokeWithException, graph.add(macroNode), invokeWithException.next());
+        }
+        GraphUtil.killWithUnusedFloatingInputs(callTarget);
+        return macroNode;
+    }
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Mon Jul 08 14:34:45 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java	Mon Jul 08 15:54:24 2013 +0200
@@ -260,7 +260,7 @@
 
                 @Override
                 public boolean visit(Node node) {
-                    if (node instanceof RootNode && node != root) {
+                    if (node instanceof RootNode && visitedCount > 0) {
                         return false;
                     }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluatorCanonicalizer.java	Mon Jul 08 14:34:45 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluatorCanonicalizer.java	Mon Jul 08 15:54:24 2013 +0200
@@ -26,7 +26,6 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.common.*;
@@ -68,41 +67,8 @@
                     return ConstantNode.forObject(value, metaAccessProvider, node.graph());
                 }
             }
-        } else if (node instanceof UnsafeLoadNode) {
-            UnsafeLoadNode unsafeLoadNode = (UnsafeLoadNode) node;
-            if (unsafeLoadNode.offset().isConstant()) {
-                long offset = unsafeLoadNode.offset().asConstant().asLong() + unsafeLoadNode.displacement();
-                ResolvedJavaType type = unsafeLoadNode.object().objectStamp().type();
-                ResolvedJavaField field = recursiveFindFieldWithOffset(type, offset);
-                if (field != null) {
-                    return node.graph().add(new LoadFieldNode(unsafeLoadNode.object(), field));
-                }
-            }
-        } else if (node instanceof UnsafeStoreNode) {
-            UnsafeStoreNode unsafeStoreNode = (UnsafeStoreNode) node;
-            if (unsafeStoreNode.offset().isConstant()) {
-                long offset = unsafeStoreNode.offset().asConstant().asLong() + unsafeStoreNode.displacement();
-                ResolvedJavaType type = unsafeStoreNode.object().objectStamp().type();
-                ResolvedJavaField field = recursiveFindFieldWithOffset(type, offset);
-                if (field != null) {
-                    StoreFieldNode storeFieldNode = node.graph().add(new StoreFieldNode(unsafeStoreNode.object(), field, unsafeStoreNode.value()));
-                    storeFieldNode.setStateAfter(unsafeStoreNode.stateAfter());
-                    return storeFieldNode;
-                }
-            }
         }
 
         return node;
     }
-
-    private ResolvedJavaField recursiveFindFieldWithOffset(ResolvedJavaType type, long offset) {
-        if (type != null) {
-            ResolvedJavaField field = type.findInstanceFieldWithOffset(offset);
-            if (field != null) {
-                return field;
-            }
-            return recursiveFindFieldWithOffset(type.getSuperclass(), offset);
-        }
-        return null;
-    }
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java	Mon Jul 08 14:34:45 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java	Mon Jul 08 15:54:24 2013 +0200
@@ -216,25 +216,25 @@
         if (invoke.callTarget() instanceof MethodCallTargetNode) {
             final MethodCallTargetNode methodCallTargetNode = (MethodCallTargetNode) invoke.callTarget();
             if ((methodCallTargetNode.invokeKind() == InvokeKind.Special || methodCallTargetNode.invokeKind() == InvokeKind.Static) &&
-                            !Modifier.isNative(methodCallTargetNode.targetMethod().getModifiers())) {
-                if (methodCallTargetNode.targetMethod().getAnnotation(ExplodeLoop.class) != null) {
-                    // Do not inline explode loop methods, they need canonicalization and forced
-                    // unrolling.
-                    return invoke.asNode();
-                }
-                StructuredGraph inlinedGraph = Debug.scope("ExpandInvoke", methodCallTargetNode.targetMethod(), new Callable<StructuredGraph>() {
+                            !Modifier.isNative(methodCallTargetNode.targetMethod().getModifiers()) && methodCallTargetNode.targetMethod().getAnnotation(ExplodeLoop.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>() {
 
-                    public StructuredGraph call() {
-                        StructuredGraph inlineGraph = replacements.getMethodSubstitution(methodCallTargetNode.targetMethod());
-                        if (inlineGraph == null) {
-                            inlineGraph = parseGraph(methodCallTargetNode.targetMethod());
+                        public StructuredGraph call() {
+                            StructuredGraph inlineGraph = replacements.getMethodSubstitution(methodCallTargetNode.targetMethod());
+                            if (inlineGraph == null) {
+                                inlineGraph = parseGraph(methodCallTargetNode.targetMethod());
+                            }
+                            return inlineGraph;
                         }
-                        return inlineGraph;
-                    }
-                });
-                FixedNode fixedNode = (FixedNode) invoke.predecessor();
-                InliningUtil.inline(invoke, inlinedGraph, true);
-                return fixedNode;
+                    });
+                    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/nodes/UnsafeCastMacroNode.java	Mon Jul 08 14:34:45 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/UnsafeCastMacroNode.java	Mon Jul 08 15:54:24 2013 +0200
@@ -41,7 +41,10 @@
             Class c = (Class) arguments.get(1).asConstant().asObject();
             ResolvedJavaType lookupJavaType = tool.runtime().lookupJavaType(c);
             Stamp s = StampFactory.declaredNonNull(lookupJavaType);
-            return graph().unique(new UnsafeCastNode(arguments.get(0), s));
+            ValueAnchorNode valueAnchorNode = graph().add(new ValueAnchorNode());
+            UnsafeCastNode unsafeCast = graph().unique(new UnsafeCastNode(arguments.get(0), s, (GuardingNode) valueAnchorNode));
+            this.replaceAtUsages(unsafeCast);
+            return valueAnchorNode;
         }
         return this;
     }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java	Mon Jul 08 14:34:45 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java	Mon Jul 08 15:54:24 2013 +0200
@@ -57,4 +57,7 @@
 
     @MacroSubstitution(macro = BailoutNode.class, isStatic = true)
     public static native void bailout(String reason);
+
+    @MacroSubstitution(macro = UnsafeCastMacroNode.class, isStatic = true)
+    public static native Object unsafeCast(Object value, Class clazz);
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java	Mon Jul 08 14:34:45 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java	Mon Jul 08 15:54:24 2013 +0200
@@ -126,4 +126,17 @@
     @Target({ElementType.METHOD})
     public @interface Unsafe {
     }
+
+    /**
+     * Treats the given value as a value of the given class. The class must evaluate to a constant.
+     * 
+     * @param value the value that is known to have the specified type
+     * @param clazz the specified type of the value
+     * @return the value
+     */
+    @SuppressWarnings("unchecked")
+    @Unsafe
+    public static <T> T unsafeCast(Object value, Class<T> clazz) {
+        return (T) value;
+    }
 }