changeset 22983:5241b25e39a8

add per-node source info to nodes and assembly instructions
author Tom Rodriguez <tom.rodriguez@oracle.com>
date Thu, 12 Nov 2015 23:16:19 +0100
parents e8fb2acecb0c
children 4a617fccbae4
files graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugCloseable.java graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeParser.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerator.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGeneratorTool.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GraphDecoder.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GraphEncoder.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SimpleInfopointNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeLIRBuilderTool.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.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 mx.graal/suite.py
diffstat 16 files changed, 268 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java	Thu Nov 12 11:48:17 2015 -0800
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java	Thu Nov 12 23:16:19 2015 +0100
@@ -230,6 +230,13 @@
     @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> CanOmitFrame = new OptionValue<>(true);
 
+    // This and OldInfopoints only exist while developing per-node context info (GRAAL-1305)
+    @Option(help = "", type = OptionType.Debug)
+    public static final OptionValue<Boolean> NewInfopoints = new OptionValue<>(false);
+
+    @Option(help = "", type = OptionType.Debug)
+    public static final OptionValue<Boolean> OldInfopoints = new OptionValue<>(true);
+
     // Ahead of time compilation
     @Option(help = "Try to avoid emitting code where patching is required", type = OptionType.Expert)
     public static final OptionValue<Boolean> ImmutableCode = new OptionValue<>(false);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java	Thu Nov 12 11:48:17 2015 -0800
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java	Thu Nov 12 23:16:19 2015 +0100
@@ -36,7 +36,9 @@
 import java.util.Map;
 import java.util.Map.Entry;
 
+import jdk.vm.ci.code.BytecodePosition;
 import jdk.vm.ci.code.CallingConvention;
+import jdk.vm.ci.code.InfopointReason;
 import jdk.vm.ci.code.StackSlot;
 import jdk.vm.ci.code.ValueUtil;
 import jdk.vm.ci.common.JVMCIError;
@@ -48,6 +50,7 @@
 import jdk.vm.ci.meta.PlatformKind;
 import jdk.vm.ci.meta.Value;
 
+import com.oracle.graal.compiler.common.GraalOptions;
 import com.oracle.graal.compiler.common.calc.Condition;
 import com.oracle.graal.compiler.common.cfg.BlockMap;
 import com.oracle.graal.compiler.common.type.Stamp;
@@ -94,7 +97,6 @@
 import com.oracle.graal.nodes.LoweredCallTargetNode;
 import com.oracle.graal.nodes.ParameterNode;
 import com.oracle.graal.nodes.PhiNode;
-import com.oracle.graal.nodes.SimpleInfopointNode;
 import com.oracle.graal.nodes.StructuredGraph;
 import com.oracle.graal.nodes.ValueNode;
 import com.oracle.graal.nodes.ValuePhiNode;
@@ -124,6 +126,8 @@
     private ValueNode currentInstruction;
     private ValueNode lastInstructionPrinted; // Debugging only
 
+    private BytecodePosition lastPosition;
+
     private final NodeMatchRules nodeMatchRules;
     private Map<Class<? extends Node>, List<MatchStatement>> matchRules;
 
@@ -313,6 +317,7 @@
     @SuppressWarnings("try")
     public void doBlock(Block block, StructuredGraph graph, BlockMap<List<Node>> blockMap) {
         try (BlockScope blockScope = gen.getBlockScope(block)) {
+            lastPosition = null;
 
             if (block == gen.getResult().getLIR().getControlFlowGraph().getStartBlock()) {
                 assert block.getPredecessorCount() == 0;
@@ -441,6 +446,13 @@
         if (Debug.isLogEnabled() && node.stamp().isEmpty()) {
             Debug.log("This node has an empty stamp, we are emitting dead code(?): %s", node);
         }
+        if (GraalOptions.NewInfopoints.getValue()) {
+            BytecodePosition position = node.getNodeContext(BytecodePosition.class);
+            if (position != null && (lastPosition == null || !lastPosition.equals(position))) {
+                lastPosition = position;
+                recordSimpleInfopoint(InfopointReason.LINE_NUMBER, position);
+            }
+        }
         if (node instanceof LIRLowerable) {
             ((LIRLowerable) node).generate(this);
         } else {
@@ -758,8 +770,8 @@
     }
 
     @Override
-    public void visitSimpleInfopointNode(SimpleInfopointNode i) {
-        append(new SimpleInfopointOp(i.getReason(), i.getPosition()));
+    public void recordSimpleInfopoint(InfopointReason reason, BytecodePosition position) {
+        append(new SimpleInfopointOp(reason, position));
     }
 
     @Override
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugCloseable.java	Thu Nov 12 11:48:17 2015 -0800
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugCloseable.java	Thu Nov 12 23:16:19 2015 +0100
@@ -23,8 +23,7 @@
 package com.oracle.graal.debug;
 
 /**
- * An object returned by {@link DebugTimer#start()} that when closed, stops the associated timer and
- * adds the elapsed time since {@code start()} to the total for the timer.
+ * An {@link AutoCloseable} whose {@link #close()} does not throw a checked exception.
  */
 public interface DebugCloseable extends AutoCloseable {
 
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Thu Nov 12 11:48:17 2015 -0800
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Thu Nov 12 23:16:19 2015 +0100
@@ -65,6 +65,16 @@
     Node[] nodes;
 
     /**
+     * Extra context information to be added to newly created nodes.
+     */
+    Object currentNodeContext;
+
+    /**
+     * Records if context information exists (or existed) for any nodes in this graph.
+     */
+    boolean seenNodeContext;
+
+    /**
      * The number of valid entries in {@link #nodes}.
      */
     int nodesSize;
@@ -144,6 +154,59 @@
         }
     }
 
+    private class NodeContextScope implements DebugCloseable {
+        private final Object previous;
+
+        NodeContextScope(Object context) {
+            previous = currentNodeContext;
+            currentNodeContext = context;
+            seenNodeContext = true;
+        }
+
+        public void close() {
+            currentNodeContext = previous;
+        }
+    }
+
+    /**
+     * Opens a scope in which the context information from {@code node} is copied into nodes created
+     * within the scope. If {@code node} has no context information, no scope is opened and
+     * {@code null} is returned.
+     *
+     * @return a {@link DebugCloseable} for managing the opened scope or {@code null} if no scope
+     *         was opened
+     */
+    public DebugCloseable withNodeContext(Node node) {
+        return node.nodeContext != null ? new NodeContextScope(node.nodeContext) : null;
+    }
+
+    /**
+     * Opens a scope in which {@code context} is copied into nodes created within the scope. If
+     * {@code context == null}, no scope is opened and {@code null} is returned.
+     *
+     * @return a {@link DebugCloseable} for managing the opened scope or {@code null} if no scope
+     *         was opened
+     */
+    public DebugCloseable withNodeContext(Object context) {
+        return context != null ? new NodeContextScope(context) : null;
+    }
+
+    /**
+     * Opens a scope in which newly created nodes do not get any context information added.
+     *
+     * @return a {@link DebugCloseable} for managing the opened scope
+     */
+    public DebugCloseable withoutNodeContext() {
+        return new NodeContextScope(null);
+    }
+
+    /**
+     * Determines if this graph might contain nodes with extra context.
+     */
+    public boolean mayHaveNodeContext() {
+        return seenNodeContext;
+    }
+
     /**
      * Creates an empty Graph with no name.
      */
@@ -855,6 +918,9 @@
         }
         int id = nodesSize;
         nodes[id] = node;
+        if (currentNodeContext != null) {
+            node.setNodeContext(currentNodeContext);
+        }
         nodesSize++;
 
         updateNodeCaches(node);
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Thu Nov 12 11:48:17 2015 -0800
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Thu Nov 12 23:16:19 2015 +0100
@@ -29,6 +29,7 @@
 
 import java.lang.annotation.ElementType;
 import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.EnumSet;
@@ -43,6 +44,7 @@
 import java.util.function.BiConsumer;
 import java.util.function.Predicate;
 
+import jdk.vm.ci.code.BytecodePosition;
 import sun.misc.Unsafe;
 
 import com.oracle.graal.compiler.common.CollectionsFactory;
@@ -556,6 +558,90 @@
         });
     }
 
+    /**
+     * Per node information tracking extra context for a node. Can be used to track the original
+     * source of a node (e.g., method and bytecode position) or any other piece of information. It's
+     * typed as {@link Object} because not all information to track is under our control so
+     * requiring a particular interface would require wrapping the object, adding overhead. It's
+     * also possible to capture multiple different types of information so the value may be an
+     * {@code Object[]} when multiple objects have been captured.
+     */
+    Object nodeContext;
+
+    /**
+     * @return the uninterpreted context for this node
+     */
+    public Object getRawNodeContext() {
+        return nodeContext;
+    }
+
+    /**
+     * Gets the context information of exact type {@code theClass} stored by this node or null if it
+     * doesn't exist.
+     *
+     * @param theClass the exact type of the context being requested
+     * @return a context of exact type {@code theClass} or {@code null}
+     */
+    @SuppressWarnings("unchecked")
+    public <T> T getNodeContext(Class<T> theClass) {
+        if (nodeContext == null) {
+            return null;
+        }
+        if (nodeContext.getClass() == theClass) {
+            return (T) nodeContext;
+        }
+        if (nodeContext instanceof Object[]) {
+            for (Object info : (Object[]) nodeContext) {
+                if (info.getClass() == theClass) {
+                    return (T) info;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Replaces the entire current context with {@code context}.
+     */
+    public void setNodeContext(Object context) {
+        nodeContext = context;
+    }
+
+    /**
+     * Adds some given context to this node. Existing context of the same exact type as
+     * {@code newContext} will be replaced by the latter. All other context will be merged with the
+     * existing context.
+     */
+    public void updateNodeContext(Object newContext) {
+        // This is the common case with a single type of information captured
+        if (nodeContext == null || nodeContext.getClass() == newContext.getClass()) {
+            nodeContext = newContext;
+            return;
+        }
+        if (newContext instanceof Object[]) {
+            for (Object context : (Object[]) newContext) {
+                updateNodeContext(context);
+            }
+            return;
+        }
+        if (nodeContext instanceof Object[]) {
+            Object[] contextArray = (Object[]) nodeContext;
+            for (int i = 0; i < contextArray.length; i++) {
+                if (contextArray[i].getClass() == newContext.getClass()) {
+                    contextArray[i] = newContext;
+                    return;
+                }
+            }
+            contextArray = Arrays.copyOf(contextArray, contextArray.length + 1);
+            contextArray[contextArray.length - 1] = newContext;
+        } else {
+            Object[] contextArray = new Object[2];
+            contextArray[0] = nodeContext;
+            contextArray[1] = newContext;
+            nodeContext = contextArray;
+        }
+    }
+
     public final NodeClass<? extends Node> getNodeClass() {
         return nodeClass;
     }
@@ -852,6 +938,9 @@
         if (into != null && useIntoLeafNodeCache) {
             into.putNodeIntoCache(newNode);
         }
+        if (graph != null && into != null) {
+            newNode.nodeContext = nodeContext;
+        }
         newNode.afterClone(this);
         return newNode;
     }
@@ -987,6 +1076,10 @@
         for (int i = 0; i < properties.getCount(); i++) {
             map.put(properties.getName(i), properties.get(this, i));
         }
+        BytecodePosition pos = getNodeContext(BytecodePosition.class);
+        if (pos != null) {
+            map.put("debugPosition", pos);
+        }
         return map;
     }
 
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeParser.java	Thu Nov 12 11:48:17 2015 -0800
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeParser.java	Thu Nov 12 23:16:19 2015 +0100
@@ -226,6 +226,7 @@
 import static com.oracle.graal.bytecode.Bytecodes.TABLESWITCH;
 import static com.oracle.graal.bytecode.Bytecodes.nameOf;
 import static com.oracle.graal.compiler.common.GraalOptions.DeoptALot;
+import static com.oracle.graal.compiler.common.GraalOptions.NewInfopoints;
 import static com.oracle.graal.compiler.common.GraalOptions.PrintProfilingInformation;
 import static com.oracle.graal.compiler.common.GraalOptions.ResolveClassBeforeStaticInvoke;
 import static com.oracle.graal.compiler.common.GraalOptions.StressInvokeWithExceptionNode;
@@ -302,6 +303,7 @@
 import com.oracle.graal.compiler.common.type.StampFactory;
 import com.oracle.graal.debug.Debug;
 import com.oracle.graal.debug.Debug.Scope;
+import com.oracle.graal.debug.DebugCloseable;
 import com.oracle.graal.debug.DebugMetric;
 import com.oracle.graal.debug.Indent;
 import com.oracle.graal.debug.TTY;
@@ -739,7 +741,7 @@
 
             finishPrepare(lastInstr);
 
-            if (graphBuilderConfig.insertNonSafepointDebugInfo() && !parsingIntrinsic()) {
+            if (GraalOptions.OldInfopoints.getValue() && graphBuilderConfig.insertNonSafepointDebugInfo() && !parsingIntrinsic()) {
                 genInfoPointNode(InfopointReason.METHOD_START, null);
             }
 
@@ -1384,7 +1386,7 @@
     }
 
     protected void genThrow() {
-        if (graphBuilderConfig.insertNonSafepointDebugInfo() && !parsingIntrinsic()) {
+        if (GraalOptions.OldInfopoints.getValue() && graphBuilderConfig.insertNonSafepointDebugInfo() && !parsingIntrinsic()) {
             genInfoPointNode(InfopointReason.LINE_NUMBER, null);
         }
 
@@ -1976,7 +1978,7 @@
                 append(new RegisterFinalizerNode(receiver));
             }
         }
-        if (graphBuilderConfig.insertNonSafepointDebugInfo() && !parsingIntrinsic()) {
+        if (GraalOptions.OldInfopoints.getValue() && graphBuilderConfig.insertNonSafepointDebugInfo() && !parsingIntrinsic()) {
             genInfoPointNode(InfopointReason.METHOD_END, x);
         }
 
@@ -2582,6 +2584,7 @@
         }
     }
 
+    @SuppressWarnings("try")
     protected void iterateBytecodesForBlock(BciBlock block) {
         if (block.isLoopHeader && !explodeLoops) {
             // Create the loop header block, which later will merge the backward branches of
@@ -2632,7 +2635,7 @@
         }
 
         while (bci < endBCI) {
-            if (graphBuilderConfig.insertNonSafepointDebugInfo() && !parsingIntrinsic()) {
+            if (GraalOptions.OldInfopoints.getValue() && graphBuilderConfig.insertNonSafepointDebugInfo() && !parsingIntrinsic()) {
                 currentLineNumber = lnt != null ? lnt.getLineNumber(bci) : (graphBuilderConfig.insertFullDebugInfo() ? -1 : bci);
                 if (currentLineNumber != previousLineNumber) {
                     genInfoPointNode(InfopointReason.LINE_NUMBER, null);
@@ -2653,7 +2656,7 @@
                 x.setStateAfter(createFrameState(bci, x));
             }
 
-            try {
+            try (DebugCloseable context = openNodeContext()) {
                 processBytecode(bci, opcode);
             } catch (BailoutException e) {
                 // Don't wrap bailouts as parser errors
@@ -2684,6 +2687,13 @@
         }
     }
 
+    private DebugCloseable openNodeContext() {
+        if (NewInfopoints.getValue() && graphBuilderConfig.insertNonSafepointDebugInfo() && !parsingIntrinsic()) {
+            return graph.withNodeContext(createBytecodePosition());
+        }
+        return null;
+    }
+
     /* Also a hook for subclasses. */
     protected boolean forceLoopPhis() {
         return graph.isOSR();
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerator.java	Thu Nov 12 11:48:17 2015 -0800
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerator.java	Thu Nov 12 23:16:19 2015 +0100
@@ -34,8 +34,10 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import jdk.vm.ci.code.BytecodePosition;
 import jdk.vm.ci.code.CallingConvention;
 import jdk.vm.ci.code.CodeCacheProvider;
+import jdk.vm.ci.code.InfopointReason;
 import jdk.vm.ci.code.Register;
 import jdk.vm.ci.code.RegisterAttributes;
 import jdk.vm.ci.code.TargetDescription;
@@ -66,6 +68,7 @@
 import com.oracle.graal.lir.LIRInstruction;
 import com.oracle.graal.lir.LIRVerifier;
 import com.oracle.graal.lir.LabelRef;
+import com.oracle.graal.lir.SimpleInfopointOp;
 import com.oracle.graal.lir.StandardOp;
 import com.oracle.graal.lir.StandardOp.BlockEndOp;
 import com.oracle.graal.lir.StandardOp.LabelOp;
@@ -257,13 +260,26 @@
         return reg.asValue(lirKind);
     }
 
+    BytecodePosition currentInfo;
+
+    public void setInfo(BytecodePosition position) {
+        currentInfo = position;
+    }
+
     public <I extends LIRInstruction> I append(I op) {
         if (Options.PrintIRWithLIR.getValue() && !TTY.isSuppressed()) {
             TTY.println(op.toStringWithIdPrefix());
             TTY.println();
         }
         assert LIRVerifier.verify(op);
-        res.getLIR().getLIRforBlock(getCurrentBlock()).add(op);
+        List<LIRInstruction> lirForBlock = res.getLIR().getLIRforBlock(getCurrentBlock());
+        if (op instanceof SimpleInfopointOp) {
+            currentInfo = null;
+        } else if (currentInfo != null) {
+            lirForBlock.add(new SimpleInfopointOp(InfopointReason.LINE_NUMBER, currentInfo));
+            currentInfo = null;
+        }
+        lirForBlock.add(op);
         return op;
     }
 
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGeneratorTool.java	Thu Nov 12 11:48:17 2015 -0800
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGeneratorTool.java	Thu Nov 12 23:16:19 2015 +0100
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.lir.gen;
 
+import jdk.vm.ci.code.BytecodePosition;
 import jdk.vm.ci.code.CallingConvention;
 import jdk.vm.ci.code.CodeCacheProvider;
 import jdk.vm.ci.code.Register;
@@ -222,6 +223,8 @@
 
     <I extends LIRInstruction> I append(I op);
 
+    void setInfo(BytecodePosition position);
+
     void emitJump(LabelRef label);
 
     void emitCompareBranch(PlatformKind cmpKind, Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination,
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GraphDecoder.java	Thu Nov 12 11:48:17 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GraphDecoder.java	Thu Nov 12 23:16:19 2015 +0100
@@ -757,6 +757,7 @@
     }
 
     protected void readProperties(MethodScope methodScope, Node node) {
+        node.setNodeContext(readObject(methodScope));
         Fields fields = node.getNodeClass().getData();
         for (int pos = 0; pos < fields.getCount(); pos++) {
             if (fields.getType(pos).isPrimitive()) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GraphEncoder.java	Thu Nov 12 11:48:17 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GraphEncoder.java	Thu Nov 12 23:16:19 2015 +0100
@@ -168,6 +168,7 @@
             nodeClasses.addObject(node.getNodeClass());
 
             NodeClass<?> nodeClass = node.getNodeClass();
+            objects.addObject(node.getRawNodeContext());
             for (int i = 0; i < nodeClass.getData().getCount(); i++) {
                 if (!nodeClass.getData().getType(i).isPrimitive()) {
                     objects.addObject(nodeClass.getData().get(node, i));
@@ -347,6 +348,7 @@
     }
 
     protected void writeProperties(Node node, Fields fields) {
+        writeObjectId(node.getRawNodeContext());
         for (int idx = 0; idx < fields.getCount(); idx++) {
             if (fields.getType(idx).isPrimitive()) {
                 long primitive = fields.getRawPrimitive(node, idx);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SimpleInfopointNode.java	Thu Nov 12 11:48:17 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SimpleInfopointNode.java	Thu Nov 12 23:16:19 2015 +0100
@@ -45,7 +45,7 @@
 
     @Override
     public void generate(NodeLIRBuilderTool generator) {
-        generator.visitSimpleInfopointNode(this);
+        generator.recordSimpleInfopoint(getReason(), getPosition());
     }
 
     public BytecodePosition getPosition() {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeLIRBuilderTool.java	Thu Nov 12 11:48:17 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeLIRBuilderTool.java	Thu Nov 12 23:16:19 2015 +0100
@@ -25,7 +25,9 @@
 import java.util.Collection;
 import java.util.List;
 
+import jdk.vm.ci.code.BytecodePosition;
 import jdk.vm.ci.code.CallingConvention;
+import jdk.vm.ci.code.InfopointReason;
 import jdk.vm.ci.meta.Value;
 
 import com.oracle.graal.compiler.common.cfg.BlockMap;
@@ -43,7 +45,6 @@
 import com.oracle.graal.nodes.Invoke;
 import com.oracle.graal.nodes.LoopEndNode;
 import com.oracle.graal.nodes.SafepointNode;
-import com.oracle.graal.nodes.SimpleInfopointNode;
 import com.oracle.graal.nodes.StructuredGraph;
 import com.oracle.graal.nodes.ValueNode;
 import com.oracle.graal.nodes.calc.ConditionalNode;
@@ -78,7 +79,7 @@
 
     void visitFullInfopointNode(FullInfopointNode i);
 
-    void visitSimpleInfopointNode(SimpleInfopointNode i);
+    void recordSimpleInfopoint(InfopointReason reason, BytecodePosition position);
 
     LIRGeneratorTool getLIRGeneratorTool();
 
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Thu Nov 12 11:48:17 2015 -0800
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Thu Nov 12 23:16:19 2015 +0100
@@ -42,6 +42,7 @@
 import jdk.vm.ci.meta.MetaAccessProvider;
 
 import com.oracle.graal.compiler.common.type.StampFactory;
+import com.oracle.graal.debug.DebugCloseable;
 import com.oracle.graal.graph.Graph.Mark;
 import com.oracle.graal.graph.Node;
 import com.oracle.graal.graph.NodeBitMap;
@@ -351,6 +352,7 @@
             }
         }
 
+        @SuppressWarnings("try")
         private AnchoringNode process(final Block b, final NodeBitMap activeGuards, final AnchoringNode startAnchor) {
 
             final LoweringToolImpl loweringTool = new LoweringToolImpl(context, startAnchor, activeGuards, b.getBeginNode());
@@ -377,7 +379,9 @@
                     Collection<Node> unscheduledUsages = null;
                     assert (unscheduledUsages = getUnscheduledUsages(node)) != null;
                     Mark preLoweringMark = node.graph().getMark();
-                    ((Lowerable) node).lower(loweringTool);
+                    try (DebugCloseable s = node.graph().withNodeContext(node)) {
+                        ((Lowerable) node).lower(loweringTool);
+                    }
                     if (loweringTool.guardAnchor.asNode().isDeleted()) {
                         // TODO nextNode could be deleted but this is not currently supported
                         assert nextNode.isAlive();
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java	Thu Nov 12 11:48:17 2015 -0800
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java	Thu Nov 12 23:16:19 2015 +0100
@@ -23,6 +23,7 @@
 package com.oracle.graal.phases.common.inlining;
 
 import static com.oracle.graal.compiler.common.GraalOptions.HotSpotPrintInlining;
+import static com.oracle.graal.compiler.common.GraalOptions.NewInfopoints;
 import static com.oracle.graal.compiler.common.GraalOptions.UseGraalInstrumentation;
 import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateReprofile;
 import static jdk.vm.ci.meta.DeoptimizationReason.NullCheckException;
@@ -31,6 +32,7 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 
 import jdk.vm.ci.code.BytecodeFrame;
 import jdk.vm.ci.code.BytecodePosition;
@@ -464,7 +466,20 @@
         return graph.method().format("%H.%n(%p)");
     }
 
+    @SuppressWarnings("try")
     private static void processSimpleInfopoints(Invoke invoke, StructuredGraph inlineGraph, Map<Node, Node> duplicates) {
+        if (NewInfopoints.getValue()) {
+            if (inlineGraph.mayHaveNodeContext() && invoke.stateAfter() != null) {
+                BytecodePosition outerPos = new BytecodePosition(FrameState.toBytecodePosition(invoke.stateAfter().outerFrameState()), invoke.asNode().graph().method(), invoke.bci());
+                for (Entry<Node, Node> entry : duplicates.entrySet()) {
+                    BytecodePosition pos = entry.getKey().getNodeContext(BytecodePosition.class);
+                    if (pos != null) {
+                        BytecodePosition newPos = pos.addCaller(outerPos);
+                        entry.getValue().setNodeContext(newPos);
+                    }
+                }
+            }
+        }
         if (inlineGraph.getNodes(SimpleInfopointNode.TYPE).isEmpty()) {
             return;
         }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/PEGraphDecoder.java	Thu Nov 12 11:48:17 2015 -0800
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/PEGraphDecoder.java	Thu Nov 12 23:16:19 2015 +0100
@@ -47,6 +47,7 @@
 
 import com.oracle.graal.compiler.common.type.StampFactory;
 import com.oracle.graal.debug.Debug;
+import com.oracle.graal.debug.DebugCloseable;
 import com.oracle.graal.graph.Node;
 import com.oracle.graal.graph.NodeClass;
 import com.oracle.graal.graph.spi.Canonicalizable;
@@ -623,13 +624,28 @@
 
     protected abstract EncodedGraph lookupEncodedGraph(ResolvedJavaMethod method, boolean isIntrinsic);
 
+    @SuppressWarnings("try")
     @Override
     protected void handleFixedNode(MethodScope s, LoopScope loopScope, int nodeOrderId, FixedNode node) {
         PEMethodScope methodScope = (PEMethodScope) s;
         if (node instanceof SimpleInfopointNode && methodScope.isInlinedMethod()) {
             InliningUtil.addSimpleInfopointCaller((SimpleInfopointNode) node, methodScope.getBytecodePosition());
         }
-        super.handleFixedNode(s, loopScope, nodeOrderId, node);
+
+        BytecodePosition pos = node.getNodeContext(BytecodePosition.class);
+        if (pos != null && methodScope.isInlinedMethod()) {
+            BytecodePosition newPosition = pos.addCaller(methodScope.getBytecodePosition());
+            try (DebugCloseable scope = node.graph().withoutNodeContext()) {
+                super.handleFixedNode(s, loopScope, nodeOrderId, node);
+            }
+            if (node.isAlive()) {
+                node.setNodeContext(newPosition);
+                node.verify();
+            }
+        } else {
+            super.handleFixedNode(s, loopScope, nodeOrderId, node);
+        }
+
     }
 
     @Override
@@ -705,6 +721,12 @@
         PEMethodScope methodScope = (PEMethodScope) s;
 
         if (methodScope.isInlinedMethod()) {
+            BytecodePosition pos = node.getNodeContext(BytecodePosition.class);
+            if (pos != null) {
+                BytecodePosition bytecodePosition = methodScope.getBytecodePosition();
+                node.setNodeContext(pos.addCaller(bytecodePosition));
+                node.verify();
+            }
             if (node instanceof FrameState) {
                 FrameState frameState = (FrameState) node;
 
--- a/mx.graal/suite.py	Thu Nov 12 11:48:17 2015 -0800
+++ b/mx.graal/suite.py	Thu Nov 12 23:16:19 2015 +0100
@@ -39,7 +39,7 @@
             {
                "name" : "jvmci",
                "optional" : "true",
-               "version" : "372cb6e59b0da698111b72a773d4d566635855a3",
+               "version" : "ab84ba890aa4063c113b0afe1cebf91791bde94a",
                "urls" : [
                     {"url" : "http://lafo.ssw.uni-linz.ac.at/hg/graal-jvmci-8", "kind" : "hg"},
                     {"url" : "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind" : "binary"},