changeset 23019:e3bcc6af1bcc

Fix handling of FrameStates with intrinsic bcis during partial evaluation
author Christian Wimmer <christian.wimmer@oracle.com>
date Wed, 18 Nov 2015 12:01:29 -0800
parents 31f1578ea3ab
children 4af472d10ad6
files graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/PEGraphDecoder.java graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/SimplePartialEvaluationTest.java graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/ObjectHashCodeNode.java
diffstat 5 files changed, 90 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java	Wed Nov 18 11:52:05 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java	Wed Nov 18 12:01:29 2015 -0800
@@ -137,11 +137,16 @@
         this.stateDuring = stateDuring;
     }
 
+    public int getBci() {
+        return bci;
+    }
+
     /**
      * Set the {@code bci} of the invoke bytecode for use when converting a stateAfter into a
      * stateDuring.
      */
     public void setBci(int bci) {
+        assert this.bci == BytecodeFrame.UNKNOWN_BCI || this.bci == bci;
         this.bci = bci;
     }
 
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java	Wed Nov 18 11:52:05 2015 -0800
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java	Wed Nov 18 12:01:29 2015 -0800
@@ -516,13 +516,14 @@
                 if (outerFrameState == null) {
                     outerFrameState = stateAtReturn.duplicateModifiedDuringCall(invoke.bci(), invokeReturnKind);
                 }
-                processFrameState(frameState, invoke, inlineGraph.method(), stateAtExceptionEdge, outerFrameState, alwaysDuplicateStateAfter);
+                processFrameState(frameState, invoke, inlineGraph.method(), stateAtExceptionEdge, outerFrameState, alwaysDuplicateStateAfter, invoke.callTarget().targetMethod(),
+                                invoke.callTarget().arguments());
             }
         }
     }
 
     public static FrameState processFrameState(FrameState frameState, Invoke invoke, ResolvedJavaMethod inlinedMethod, FrameState stateAtExceptionEdge, FrameState outerFrameState,
-                    boolean alwaysDuplicateStateAfter) {
+                    boolean alwaysDuplicateStateAfter, ResolvedJavaMethod invokeTargetMethod, List<ValueNode> invokeArgsList) {
 
         FrameState stateAtReturn = invoke.stateAfter();
         JavaKind invokeReturnKind = invoke.asNode().getStackKind();
@@ -569,10 +570,9 @@
             // This is an intrinsic. Deoptimizing within an intrinsic
             // must re-execute the intrinsified invocation
             assert frameState.outerFrameState() == null;
-            NodeInputList<ValueNode> invokeArgsList = invoke.callTarget().arguments();
             ValueNode[] invokeArgs = invokeArgsList.isEmpty() ? NO_ARGS : invokeArgsList.toArray(new ValueNode[invokeArgsList.size()]);
-            ResolvedJavaMethod targetMethod = invoke.callTarget().targetMethod();
-            FrameState stateBeforeCall = stateAtReturn.duplicateModifiedBeforeCall(invoke.bci(), invokeReturnKind, targetMethod.getSignature().toParameterKinds(!targetMethod.isStatic()), invokeArgs);
+            FrameState stateBeforeCall = stateAtReturn.duplicateModifiedBeforeCall(invoke.bci(), invokeReturnKind, invokeTargetMethod.getSignature().toParameterKinds(!invokeTargetMethod.isStatic()),
+                            invokeArgs);
             frameState.replaceAndDelete(stateBeforeCall);
             return stateBeforeCall;
         } else {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/PEGraphDecoder.java	Wed Nov 18 11:52:05 2015 -0800
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/PEGraphDecoder.java	Wed Nov 18 12:01:29 2015 -0800
@@ -28,12 +28,14 @@
 import static jdk.vm.ci.common.JVMCIError.unimplemented;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
 import jdk.vm.ci.code.Architecture;
 import jdk.vm.ci.code.BailoutException;
+import jdk.vm.ci.code.BytecodeFrame;
 import jdk.vm.ci.code.BytecodePosition;
 import jdk.vm.ci.meta.ConstantReflectionProvider;
 import jdk.vm.ci.meta.DeoptimizationAction;
@@ -83,6 +85,7 @@
 import com.oracle.graal.nodes.StructuredGraph;
 import com.oracle.graal.nodes.UnwindNode;
 import com.oracle.graal.nodes.ValueNode;
+import com.oracle.graal.nodes.extended.ForeignCallNode;
 import com.oracle.graal.nodes.extended.IntegerSwitchNode;
 import com.oracle.graal.nodes.java.MethodCallTargetNode;
 import com.oracle.graal.nodes.java.MonitorIdNode;
@@ -630,6 +633,12 @@
         PEMethodScope methodScope = (PEMethodScope) s;
         if (node instanceof SimpleInfopointNode && methodScope.isInlinedMethod()) {
             InliningUtil.addSimpleInfopointCaller((SimpleInfopointNode) node, methodScope.getBytecodePosition());
+
+        } else if (node instanceof ForeignCallNode) {
+            ForeignCallNode foreignCall = (ForeignCallNode) node;
+            if (foreignCall.getBci() == BytecodeFrame.UNKNOWN_BCI) {
+                foreignCall.setBci(methodScope.invokeData.invoke.bci());
+            }
         }
 
         BytecodePosition pos = node.getNodeContext(BytecodePosition.class);
@@ -734,7 +743,16 @@
                 if (frameState.bci < 0) {
                     ensureExceptionStateDecoded(methodScope);
                 }
-                return InliningUtil.processFrameState(frameState, methodScope.invokeData.invoke, methodScope.method, methodScope.exceptionState, methodScope.outerState, true);
+                List<ValueNode> invokeArgsList = null;
+                if (frameState.bci == BytecodeFrame.BEFORE_BCI) {
+                    /*
+                     * We know that the argument list is only used in this case, so avoid the List
+                     * allocation for "normal" bcis.
+                     */
+                    invokeArgsList = Arrays.asList(methodScope.arguments);
+                }
+                return InliningUtil.processFrameState(frameState, methodScope.invokeData.invoke, methodScope.method, methodScope.exceptionState, methodScope.outerState, true, methodScope.method,
+                                invokeArgsList);
 
             } else if (node instanceof MonitorIdNode) {
                 ensureOuterStateDecoded(methodScope);
--- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/SimplePartialEvaluationTest.java	Wed Nov 18 11:52:05 2015 -0800
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/SimplePartialEvaluationTest.java	Wed Nov 18 12:01:29 2015 -0800
@@ -42,6 +42,7 @@
 import com.oracle.graal.truffle.test.nodes.NestedExplodedLoopTestNode;
 import com.oracle.graal.truffle.test.nodes.NeverPartOfCompilationTestNode;
 import com.oracle.graal.truffle.test.nodes.ObjectEqualsNode;
+import com.oracle.graal.truffle.test.nodes.ObjectHashCodeNode;
 import com.oracle.graal.truffle.test.nodes.RecursionTestNode;
 import com.oracle.graal.truffle.test.nodes.RootTestNode;
 import com.oracle.graal.truffle.test.nodes.StoreLocalTestNode;
@@ -228,4 +229,22 @@
 
         Assert.assertEquals(42, compilable.call(new Object[0]));
     }
+
+    @Test
+    public void intrinsicHashCode() {
+        /*
+         * The intrinsic for Object.hashCode() is inlined late during Truffle partial evaluation,
+         * because we call hashCode() on a value whose exact type Object is only known during
+         * partial evaluation.
+         */
+        FrameDescriptor fd = new FrameDescriptor();
+        Object testObject = new Object();
+        AbstractTestNode result = new ObjectHashCodeNode(testObject);
+        RootNode rootNode = new RootTestNode(fd, "intrinsicHashCode", result);
+        OptimizedCallTarget compilable = compileHelper("intrinsicHashCode", rootNode, new Object[0]);
+
+        int actual = (Integer) compilable.call(new Object[0]);
+        int expected = testObject.hashCode();
+        Assert.assertEquals(expected, actual);
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/ObjectHashCodeNode.java	Wed Nov 18 12:01:29 2015 -0800
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015, 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.truffle.test.nodes;
+
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.nodes.NodeInfo;
+
+@NodeInfo
+public class ObjectHashCodeNode extends AbstractTestNode {
+
+    @CompilationFinal private Object o1;
+
+    public ObjectHashCodeNode(Object o1) {
+        this.o1 = o1;
+    }
+
+    @Override
+    public int execute(VirtualFrame frame) {
+        return o1.hashCode();
+    }
+}