changeset 21364:600d37d28494

cleaned up and improved documentation for IntrinsicScope
author Doug Simon <doug.simon@oracle.com>
date Wed, 13 May 2015 13:11:17 +0200
parents ead75077228b
children 27cd1491237f
files graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/GraphBuilderContext.java graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultGenericInvocationPlugin.java
diffstat 4 files changed, 94 insertions(+), 56 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/GraphBuilderContext.java	Wed May 13 10:54:14 2015 +0200
+++ b/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/GraphBuilderContext.java	Wed May 13 13:11:17 2015 +0200
@@ -178,7 +178,7 @@
      * Gets the first ancestor parsing context that is not parsing a
      * {@linkplain #parsingIntrinsic() intrinsic}.
      */
-    default GraphBuilderContext getNonReplacementAncestor() {
+    default GraphBuilderContext getNonIntrinsicAncestor() {
         GraphBuilderContext ancestor = getParent();
         while (ancestor != null && ancestor.parsingIntrinsic()) {
             ancestor = ancestor.getParent();
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java	Wed May 13 10:54:14 2015 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java	Wed May 13 13:11:17 2015 +0200
@@ -208,11 +208,14 @@
         }
 
         // Skip intrinsic frames
-        BytecodeParser parent = (BytecodeParser) parser.getNonReplacementAncestor();
-        return create(bci, parent, false);
+        return create(bci, parser.getNonIntrinsicAncestor(), false, (ValueNode[]) null);
     }
 
-    public FrameState create(int bci, BytecodeParser parent, boolean duringCall) {
+    /**
+     * @param pushedValues if non-null, values to {@link #push(Kind, ValueNode)} to the stack before
+     *            creating the {@link FrameState}
+     */
+    public FrameState create(int bci, BytecodeParser parent, boolean duringCall, ValueNode... pushedValues) {
         if (outerFrameState == null && parent != null) {
             outerFrameState = parent.getFrameStateBuilder().create(parent.bci(), null);
         }
@@ -223,7 +226,18 @@
         if (bci == BytecodeFrame.INVALID_FRAMESTATE_BCI) {
             throw GraalInternalError.shouldNotReachHere();
         }
-        return graph.add(new FrameState(outerFrameState, method, bci, locals, stack, stackSize, lockedObjects, Arrays.asList(monitorIds), rethrowException, duringCall));
+
+        if (pushedValues != null) {
+            int stackSizeToRestore = stackSize;
+            for (ValueNode arg : pushedValues) {
+                push(arg.getKind(), arg);
+            }
+            FrameState res = graph.add(new FrameState(outerFrameState, method, bci, locals, stack, stackSize, lockedObjects, Arrays.asList(monitorIds), rethrowException, duringCall));
+            stackSize = stackSizeToRestore;
+            return res;
+        } else {
+            return graph.add(new FrameState(outerFrameState, method, bci, locals, stack, stackSize, lockedObjects, Arrays.asList(monitorIds), rethrowException, duringCall));
+        }
     }
 
     public BytecodePosition createBytecodePosition(int bci) {
@@ -234,7 +248,7 @@
                 return new BytecodePosition(parent.getFrameStateBuilder().createBytecodePosition(parent.bci()), parser.intrinsicContext.getOriginalMethod(), -1);
             }
             // Skip intrinsic frames
-            parent = (BytecodeParser) parser.getNonReplacementAncestor();
+            parent = parser.getNonIntrinsicAncestor();
         }
         return create(null, bci, parent);
     }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Wed May 13 10:54:14 2015 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Wed May 13 13:11:17 2015 +0200
@@ -207,35 +207,38 @@
         return graphBuilderConfig;
     }
 
+    /**
+     * A scoped object for tasks to be performed after parsing an intrinsic such as processing
+     * {@linkplain BytecodeFrame#isPlaceholderBci(int) placeholder} frames states.
+     */
     static class IntrinsicScope implements AutoCloseable {
         FrameState stateBefore;
         final Mark mark;
         final BytecodeParser parser;
 
-        static IntrinsicScope create(boolean enteringIntrinsic, BytecodeParser parser, FrameStateBuilder currentFrameState, ValueNode[] args) {
-            if (enteringIntrinsic) {
-                return new IntrinsicScope(parser, currentFrameState, args);
-            }
-            return null;
-        }
-
-        public IntrinsicScope(BytecodeParser parser, FrameStateBuilder currentFrameState, ValueNode[] args) {
+        /**
+         * Creates a scope for root parsing an intrinsic.
+         *
+         * @param parser the parsing context of the intrinsic
+         */
+        public IntrinsicScope(BytecodeParser parser) {
             this.parser = parser;
-            if (args == null) {
-                assert parser.parent == null;
-                assert parser.bci() == 0;
-                mark = null;
-            } else {
-                mark = parser.getGraph().getMark();
-                for (ValueNode arg : args) {
-                    currentFrameState.push(arg.getKind(), arg);
-                }
-                stateBefore = currentFrameState.create(parser.bci(), null);
-                for (int i = args.length - 1; i >= 0; i--) {
-                    ValueNode arg = args[i];
-                    currentFrameState.pop(arg.getKind());
-                }
-            }
+            assert parser.parent == null;
+            assert parser.bci() == 0;
+            mark = null;
+        }
+
+        /**
+         * Creates a scope for parsing an intrinsic during graph builder inlining.
+         *
+         * @param parser the parsing context of the (non-intrinsic) method calling the intrinsic
+         * @param args the arguments to the call
+         */
+        public IntrinsicScope(BytecodeParser parser, ValueNode[] args) {
+            assert !parser.parsingIntrinsic();
+            this.parser = parser;
+            mark = parser.getGraph().getMark();
+            stateBefore = parser.frameState.create(parser.bci(), parser.getNonIntrinsicAncestor(), false, args);
         }
 
         public void close() {
@@ -244,43 +247,56 @@
                 return;
             }
 
+            processPlaceholderFrameStates(intrinsic);
+        }
+
+        /**
+         * Fixes up the {@linkplain BytecodeFrame#isPlaceholderBci(int) placeholder} frame states
+         * added to the graph while parsing/inlining the intrinsic for which this object exists.
+         */
+        private void processPlaceholderFrameStates(IntrinsicContext intrinsic) {
             FrameState stateAfterReturn = null;
             StructuredGraph graph = parser.getGraph();
             for (Node node : graph.getNewNodes(mark)) {
                 if (node instanceof FrameState) {
-                    FrameState fs = (FrameState) node;
-                    if (BytecodeFrame.isPlaceholderBci(fs.bci)) {
-                        if (fs.bci == BytecodeFrame.AFTER_BCI) {
-                            if (fs.stackSize() != 0) {
-                                assert fs.usages().count() == 1;
-                                ValueNode returnVal = fs.stackAt(0);
-                                assert returnVal == fs.usages().first();
-
-                                ValueNode tos = parser.frameState.pop(returnVal.getKind());
-                                parser.frameState.push(returnVal.getKind(), returnVal);
-                                FrameState newFs = parser.frameState.create(parser.stream.nextBCI(), null);
-                                fs.replaceAndDelete(newFs);
-                                parser.frameState.pop(returnVal.getKind());
-                                parser.frameState.push(tos.getKind(), tos);
+                    FrameState frameState = (FrameState) node;
+                    if (BytecodeFrame.isPlaceholderBci(frameState.bci)) {
+                        if (frameState.bci == BytecodeFrame.AFTER_BCI) {
+                            FrameStateBuilder frameStateBuilder = parser.frameState;
+                            if (frameState.stackSize() != 0) {
+                                assert frameState.usages().count() == 1;
+                                ValueNode returnVal = frameState.stackAt(0);
+                                assert returnVal == frameState.usages().first();
+
+                                /*
+                                 * Swap the top-of-stack value with the side-effect return value
+                                 * using the frame state.
+                                 */
+                                ValueNode tos = frameStateBuilder.pop(returnVal.getKind());
+                                assert tos.getKind() == returnVal.getKind();
+                                FrameState newFrameState = frameStateBuilder.create(parser.stream.nextBCI(), parser.getNonIntrinsicAncestor(), false, returnVal);
+                                frameState.replaceAndDelete(newFrameState);
+                                frameStateBuilder.push(tos.getKind(), tos);
                             } else {
                                 if (stateAfterReturn == null) {
-                                    if (intrinsic != null && intrinsic.isCompilationRoot()) {
+                                    if (intrinsic != null) {
+                                        assert intrinsic.isCompilationRoot();
                                         stateAfterReturn = graph.add(new FrameState(BytecodeFrame.INVALID_FRAMESTATE_BCI));
                                     } else {
-                                        stateAfterReturn = parser.frameState.create(parser.stream.nextBCI(), null);
+                                        stateAfterReturn = frameStateBuilder.create(parser.stream.nextBCI(), null);
                                     }
                                 }
-                                fs.replaceAndDelete(stateAfterReturn);
+                                frameState.replaceAndDelete(stateAfterReturn);
                             }
-                        } else if (fs.bci == BytecodeFrame.BEFORE_BCI) {
+                        } else if (frameState.bci == BytecodeFrame.BEFORE_BCI) {
                             if (stateBefore == null) {
                                 stateBefore = graph.start().stateAfter();
                             }
-                            if (stateBefore != fs) {
-                                fs.replaceAndDelete(stateBefore);
+                            if (stateBefore != frameState) {
+                                frameState.replaceAndDelete(stateBefore);
                             }
                         } else {
-                            assert fs.bci == BytecodeFrame.INVALID_FRAMESTATE_BCI;
+                            assert frameState.bci == BytecodeFrame.INVALID_FRAMESTATE_BCI;
                         }
                     }
                 }
@@ -328,7 +344,7 @@
 
                 frameState.initializeForMethodStart(graphBuilderConfig.eagerResolving() || intrinsicContext != null, graphBuilderConfig.getPlugins().getParameterPlugin());
 
-                try (IntrinsicScope s = IntrinsicScope.create(intrinsicContext != null, parser, frameState, null)) {
+                try (IntrinsicScope s = intrinsicContext != null ? new IntrinsicScope(parser) : null) {
                     parser.build(graph.start(), frameState);
                 }
                 GraphUtil.normalizeLoops(graph);
@@ -1571,7 +1587,7 @@
             }
 
             private void parseAndInlineCallee(ResolvedJavaMethod targetMethod, ValueNode[] args, IntrinsicContext calleeIntrinsicContext) {
-                try (IntrinsicScope s = IntrinsicScope.create(calleeIntrinsicContext != null && !parsingIntrinsic(), this, frameState, args)) {
+                try (IntrinsicScope s = calleeIntrinsicContext != null && !parsingIntrinsic() ? new IntrinsicScope(this, args) : null) {
 
                     BytecodeParser parser = new BytecodeParser(this, metaAccess, targetMethod, graphBuilderConfig, optimisticOpts, INVOCATION_ENTRY_BCI, calleeIntrinsicContext);
                     FrameStateBuilder startFrameState = new FrameStateBuilder(parser, targetMethod, graph);
@@ -3563,6 +3579,14 @@
             public boolean parsingIntrinsic() {
                 return intrinsicContext != null;
             }
+
+            public BytecodeParser getNonIntrinsicAncestor() {
+                BytecodeParser ancestor = parent;
+                while (ancestor != null && ancestor.parsingIntrinsic()) {
+                    ancestor = ancestor.parent;
+                }
+                return ancestor;
+            }
         }
     }
 
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultGenericInvocationPlugin.java	Wed May 13 10:54:14 2015 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultGenericInvocationPlugin.java	Wed May 13 13:11:17 2015 +0200
@@ -148,12 +148,12 @@
             /*
              * Need to update the BCI of a ForeignCallNode so that it gets the stateDuring in the
              * case that the foreign call can deoptimize. As with all deoptimization, we need a
-             * state in a normal method as opposed to an intrinsic.
+             * state in a non-intrinsic method.
              */
-            GraphBuilderContext ancestor = b.getNonReplacementAncestor();
-            if (ancestor != null) {
+            GraphBuilderContext nonIntrinsicAncestor = b.getNonIntrinsicAncestor();
+            if (nonIntrinsicAncestor != null) {
                 ForeignCallNode foreign = (ForeignCallNode) res;
-                foreign.setBci(ancestor.bci());
+                foreign.setBci(nonIntrinsicAncestor.bci());
             }
         }