changeset 9003:a8fea2979e63

eager infopoint mode (fka debug mode)
author Michael Haupt <michael.haupt@oracle.com>
date Thu, 11 Apr 2013 09:53:10 +0200
parents 8ddaac81cb21
children 9f3a77848ea2
files graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InfopointReason.java graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64SafepointOp.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompilationResult.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/InfopointOp.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java src/share/vm/classfile/systemDictionary.hpp src/share/vm/classfile/vmSymbols.hpp src/share/vm/graal/graalCodeInstaller.cpp src/share/vm/graal/graalJavaAccess.hpp
diffstat 23 files changed, 459 insertions(+), 78 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java	Mon Apr 08 18:47:06 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java	Thu Apr 11 09:53:10 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
@@ -52,42 +52,45 @@
     }
 
     /**
-     * Represents a safepoint with associated debug info.
+     * Represents an infopoint with associated debug info. Note that safepoints are also infopoints.
      */
-    public static class Safepoint extends Site implements Comparable<Safepoint> {
+    public static class Infopoint extends Site implements Comparable<Infopoint> {
 
         private static final long serialVersionUID = 2479806696381720162L;
         public final DebugInfo debugInfo;
 
-        public Safepoint(int pcOffset, DebugInfo debugInfo) {
+        public final InfopointReason reason;
+
+        public Infopoint(int pcOffset, DebugInfo debugInfo, InfopointReason reason) {
             super(pcOffset);
             this.debugInfo = debugInfo;
+            this.reason = reason;
         }
 
         @Override
         public String toString() {
             StringBuilder sb = new StringBuilder();
             sb.append(pcOffset);
-            sb.append("[<safepoint>]");
+            sb.append("[<infopoint>]");
             appendDebugInfo(sb, debugInfo);
             return sb.toString();
         }
 
         @Override
-        public int compareTo(Safepoint o) {
+        public int compareTo(Infopoint o) {
             if (pcOffset < o.pcOffset) {
                 return -1;
             } else if (pcOffset > o.pcOffset) {
                 return 1;
             }
-            return 0;
+            return this.reason.compareTo(o.reason);
         }
     }
 
     /**
      * Represents a call in the code.
      */
-    public static final class Call extends Safepoint {
+    public static final class Call extends Infopoint {
 
         private static final long serialVersionUID = 1440741241631046954L;
 
@@ -109,7 +112,7 @@
         public final boolean direct;
 
         public Call(InvokeTarget target, int pcOffset, int size, boolean direct, DebugInfo debugInfo) {
-            super(pcOffset, debugInfo);
+            super(pcOffset, debugInfo, InfopointReason.CALL);
             this.size = size;
             this.target = target;
             this.direct = direct;
@@ -284,7 +287,7 @@
         }
     }
 
-    private final List<Safepoint> safepoints = new ArrayList<>();
+    private final List<Infopoint> infopoints = new ArrayList<>();
     private final List<DataPatch> dataReferences = new ArrayList<>();
     private final List<ExceptionHandler> exceptionHandlers = new ArrayList<>();
     private final List<Mark> marks = new ArrayList<>();
@@ -377,7 +380,7 @@
      */
     public void recordCall(int codePos, int size, InvokeTarget target, DebugInfo debugInfo, boolean direct) {
         final Call call = new Call(target, codePos, size, direct, debugInfo);
-        addSafepoint(call);
+        addInfopoint(call);
     }
 
     /**
@@ -391,22 +394,22 @@
     }
 
     /**
-     * Records a safepoint in the code array.
+     * Records an infopoint in the code array.
      * 
-     * @param codePos the position of the safepoint in the code array
-     * @param debugInfo the debug info for the safepoint
+     * @param codePos the position of the infopoint in the code array
+     * @param debugInfo the debug info for the infopoint
      */
-    public void recordSafepoint(int codePos, DebugInfo debugInfo) {
-        addSafepoint(new Safepoint(codePos, debugInfo));
+    public void recordInfopoint(int codePos, DebugInfo debugInfo, InfopointReason reason) {
+        addInfopoint(new Infopoint(codePos, debugInfo, reason));
     }
 
-    private void addSafepoint(Safepoint safepoint) {
-        // The safepoints list must always be sorted
-        if (!getSafepoints().isEmpty() && getSafepoints().get(getSafepoints().size() - 1).pcOffset >= safepoint.pcOffset) {
+    private void addInfopoint(Infopoint infopoint) {
+        // The infopoints list must always be sorted
+        if (!getInfopoints().isEmpty() && getInfopoints().get(getInfopoints().size() - 1).pcOffset >= infopoint.pcOffset) {
             // This re-sorting should be very rare
-            Collections.sort(getSafepoints());
+            Collections.sort(getInfopoints());
         }
-        getSafepoints().add(safepoint);
+        getInfopoints().add(infopoint);
     }
 
     /**
@@ -522,10 +525,10 @@
     }
 
     /**
-     * @return the list of safepoints, sorted by {@link Site#pcOffset}
+     * @return the list of infopoints, sorted by {@link Site#pcOffset}
      */
-    public List<Safepoint> getSafepoints() {
-        return safepoints;
+    public List<Infopoint> getInfopoints() {
+        return infopoints;
     }
 
     /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/InfopointReason.java	Thu Apr 11 09:53:10 2013 +0200
@@ -0,0 +1,32 @@
+/*
+ * 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.api.code;
+
+/**
+ * A reason for infopoint insertion.
+ */
+public enum InfopointReason {
+
+    UNKNOWN, SAFEPOINT, CALL, IMPLICIT_EXCEPTION, METHOD_START, METHOD_END, LINE_NUMBER;
+
+}
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Mon Apr 08 18:47:06 2013 +0200
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Thu Apr 11 09:53:10 2013 +0200
@@ -926,4 +926,9 @@
         Value[] parameters = visitInvokeArguments(cc, node.arguments);
         append(new AMD64BreakpointOp(parameters));
     }
+
+    @Override
+    public void visitInfopointNode(InfopointNode i) {
+        append(new InfopointOp(stateFor(i.stateAfter(), DeoptimizationReason.None), i.reason));
+    }
 }
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Mon Apr 08 18:47:06 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Thu Apr 11 09:53:10 2013 +0200
@@ -472,4 +472,9 @@
     public void emitNullCheck(ValueNode v, DeoptimizingNode deopting) {
         throw new InternalError("NYI");
     }
+
+    @Override
+    public void visitInfopointNode(InfopointNode i) {
+        throw new InternalError("NYI");
+    }
 }
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Mon Apr 08 18:47:06 2013 +0200
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Thu Apr 11 09:53:10 2013 +0200
@@ -368,4 +368,10 @@
         // SPARC: Auto-generated method stub
 
     }
+
+    @Override
+    public void visitInfopointNode(InfopointNode i) {
+        // SPARC: Auto-generated method stub
+
+    }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Mon Apr 08 18:47:06 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Thu Apr 11 09:53:10 2013 +0200
@@ -400,7 +400,8 @@
                 GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL);
                 phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
                 editPhasePlan(method, graph, phasePlan);
-                CompilationResult compResult = GraalCompiler.compileMethod(runtime(), replacements, backend, runtime().getTarget(), method, graph, null, phasePlan, OptimisticOptimizations.ALL, new SpeculationLog());
+                CompilationResult compResult = GraalCompiler.compileMethod(runtime(), replacements, backend, runtime().getTarget(), method, graph, null, phasePlan, OptimisticOptimizations.ALL,
+                                new SpeculationLog());
                 if (printCompilation) {
                     TTY.println(String.format("@%-6d Graal %-70s %-45s %-50s | %4dms %5dB", id, "", "", "", System.currentTimeMillis() - start, compResult.getTargetCodeSize()));
                 }
@@ -442,25 +443,41 @@
      * Parses a Java method to produce a graph.
      */
     protected StructuredGraph parse(Method m) {
-        ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(m);
-        StructuredGraph graph = new StructuredGraph(javaMethod);
-        new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph);
-        return graph;
+        return parse0(m, GraphBuilderConfiguration.getEagerDefault());
     }
 
     /**
      * Parses a Java method to produce a graph.
      */
     protected StructuredGraph parseProfiled(Method m) {
+        return parse0(m, GraphBuilderConfiguration.getDefault());
+    }
+
+    /**
+     * Parses a Java method in debug mode to produce a graph with extra infopoints.
+     */
+    protected StructuredGraph parseDebug(Method m) {
+        GraphBuilderConfiguration gbConf = GraphBuilderConfiguration.getEagerDefault();
+        gbConf.setEagerInfopointMode(true);
+        return parse0(m, gbConf);
+    }
+
+    private StructuredGraph parse0(Method m, GraphBuilderConfiguration conf) {
         ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(m);
         StructuredGraph graph = new StructuredGraph(javaMethod);
-        new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL).apply(graph);
+        new GraphBuilderPhase(runtime, conf, OptimisticOptimizations.ALL).apply(graph);
         return graph;
     }
 
     protected PhasePlan getDefaultPhasePlan() {
+        return getDefaultPhasePlan(false);
+    }
+
+    protected PhasePlan getDefaultPhasePlan(boolean eagerInfopointMode) {
         PhasePlan plan = new PhasePlan();
-        plan.addPhase(PhasePosition.AFTER_PARSING, new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL));
+        GraphBuilderConfiguration gbConf = GraphBuilderConfiguration.getEagerDefault();
+        gbConf.setEagerInfopointMode(eagerInfopointMode);
+        plan.addPhase(PhasePosition.AFTER_PARSING, new GraphBuilderPhase(runtime, gbConf, OptimisticOptimizations.ALL));
         return plan;
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java	Thu Apr 11 09:53:10 2013 +0200
@@ -0,0 +1,91 @@
+/*
+ * 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.compiler.test;
+
+import static org.junit.Assert.*;
+
+import java.lang.reflect.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.CompilationResult.Call;
+import com.oracle.graal.api.code.CompilationResult.Infopoint;
+import com.oracle.graal.compiler.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.*;
+
+/**
+ * Test that infopoints in {@link CompilationResult}s have correctly assigned reasons.
+ */
+public class InfopointReasonTest extends GraalCompilerTest {
+
+    public static final String[] STRINGS = new String[]{"world", "everyone", "you"};
+
+    public String testMethod() {
+        StringBuilder sb = new StringBuilder("Hello ");
+        for (String s : STRINGS) {
+            sb.append(s).append(", ");
+        }
+        sb.replace(sb.length() - 2, sb.length(), "!");
+        return sb.toString();
+    }
+
+    @Test
+    public void callInfopoints() {
+        final Method method = getMethod("testMethod");
+        final StructuredGraph graph = parse(method);
+        final CompilationResult cr = GraalCompiler.compileMethod(runtime, replacements, backend, runtime.getTarget(), runtime.lookupJavaMethod(method), graph, null, getDefaultPhasePlan(),
+                        OptimisticOptimizations.ALL, new SpeculationLog());
+        for (Infopoint sp : cr.getInfopoints()) {
+            assertNotNull(sp.reason);
+            if (sp instanceof Call) {
+                assertEquals(InfopointReason.CALL, sp.reason);
+            }
+        }
+    }
+
+    @Test
+    public void lineInfopoints() {
+        final Method method = getMethod("testMethod");
+        final StructuredGraph graph = parseDebug(method);
+        int graphLineSPs = 0;
+        for (InfopointNode ipn : graph.getNodes(InfopointNode.class)) {
+            if (ipn.reason == InfopointReason.LINE_NUMBER) {
+                ++graphLineSPs;
+            }
+        }
+        assertTrue(graphLineSPs > 0);
+        final CompilationResult cr = GraalCompiler.compileMethod(runtime, replacements, backend, runtime.getTarget(), runtime.lookupJavaMethod(method), graph, null, getDefaultPhasePlan(true),
+                        OptimisticOptimizations.ALL, new SpeculationLog());
+        int lineSPs = 0;
+        for (Infopoint sp : cr.getInfopoints()) {
+            assertNotNull(sp.reason);
+            if (sp.reason == InfopointReason.LINE_NUMBER) {
+                ++lineSPs;
+            }
+        }
+        assertTrue(lineSPs > 0);
+    }
+
+}
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java	Mon Apr 08 18:47:06 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java	Thu Apr 11 09:53:10 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -41,8 +41,14 @@
 
     @Test
     public void testInvokeStaticInlining() {
-        assertInlined(getGraph("invokeStaticSnippet"));
-        assertInlined(getGraph("invokeStaticOnInstanceSnippet"));
+        assertInlined(getGraph("invokeStaticSnippet", false));
+        assertInlined(getGraph("invokeStaticOnInstanceSnippet", false));
+    }
+
+    @Test
+    public void testInvokeStaticInliningIP() {
+        assertInlineInfopoints(assertInlined(getGraph("invokeStaticSnippet", true)));
+        assertInlineInfopoints(assertInlined(getGraph("invokeStaticOnInstanceSnippet", true)));
     }
 
     @SuppressWarnings("all")
@@ -57,9 +63,16 @@
 
     @Test
     public void testStaticBindableInlining() {
-        assertInlined(getGraph("invokeConstructorSnippet"));
-        assertInlined(getGraph("invokeFinalMethodSnippet"));
-        assertInlined(getGraph("invokeMethodOnFinalClassSnippet"));
+        assertInlined(getGraph("invokeConstructorSnippet", false));
+        assertInlined(getGraph("invokeFinalMethodSnippet", false));
+        assertInlined(getGraph("invokeMethodOnFinalClassSnippet", false));
+    }
+
+    @Test
+    public void testStaticBindableInliningIP() {
+        assertInlineInfopoints(assertInlined(getGraph("invokeConstructorSnippet", true)));
+        assertInlineInfopoints(assertInlined(getGraph("invokeFinalMethodSnippet", true)));
+        assertInlineInfopoints(assertInlined(getGraph("invokeMethodOnFinalClassSnippet", true)));
     }
 
     @SuppressWarnings("all")
@@ -81,14 +94,28 @@
 
     @Test
     public void testClassHierarchyAnalysis() {
-        assertInlined(getGraph("invokeLeafClassMethodSnippet"));
-        assertInlined(getGraph("invokeConcreteMethodSnippet"));
-        assertInlined(getGraph("invokeSingleImplementorInterfaceSnippet"));
-        // assertInlined(getGraph("invokeConcreteInterfaceMethodSnippet"));
+        assertInlined(getGraph("invokeLeafClassMethodSnippet", false));
+        assertInlined(getGraph("invokeConcreteMethodSnippet", false));
+        assertInlined(getGraph("invokeSingleImplementorInterfaceSnippet", false));
+        // assertInlined(getGraph("invokeConcreteInterfaceMethodSnippet", false));
+
+        assertNotInlined(getGraph("invokeOverriddenPublicMethodSnippet", false));
+        assertNotInlined(getGraph("invokeOverriddenProtectedMethodSnippet", false));
+        assertNotInlined(getGraph("invokeOverriddenInterfaceMethodSnippet", false));
+    }
 
-        assertNotInlined(getGraph("invokeOverriddenPublicMethodSnippet"));
-        assertNotInlined(getGraph("invokeOverriddenProtectedMethodSnippet"));
-        assertNotInlined(getGraph("invokeOverriddenInterfaceMethodSnippet"));
+    @Test
+    public void testClassHierarchyAnalysisIP() {
+        assertInlineInfopoints(assertInlined(getGraph("invokeLeafClassMethodSnippet", true)));
+        assertInlineInfopoints(assertInlined(getGraph("invokeConcreteMethodSnippet", true)));
+        assertInlineInfopoints(assertInlined(getGraph("invokeSingleImplementorInterfaceSnippet", true)));
+        //@formatter:off
+        // assertInlineInfopoints(assertInlined(getGraph("invokeConcreteInterfaceMethodSnippet", true)));
+        //@formatter:on
+
+        assertNoInlineInfopoints(assertNotInlined(getGraph("invokeOverriddenPublicMethodSnippet", true)));
+        assertNoInlineInfopoints(assertNotInlined(getGraph("invokeOverriddenProtectedMethodSnippet", true)));
+        assertNoInlineInfopoints(assertNotInlined(getGraph("invokeOverriddenInterfaceMethodSnippet", true)));
     }
 
     @SuppressWarnings("all")
@@ -126,13 +153,13 @@
         return superClass.protectedOverriddenMethod();
     }
 
-    private StructuredGraph getGraph(final String snippet) {
+    private StructuredGraph getGraph(final String snippet, final boolean eagerInfopointMode) {
         return Debug.scope("InliningTest", new DebugDumpScope(snippet), new Callable<StructuredGraph>() {
 
             @Override
             public StructuredGraph call() {
                 StructuredGraph graph = parse(snippet);
-                PhasePlan phasePlan = getDefaultPhasePlan();
+                PhasePlan phasePlan = getDefaultPhasePlan(eagerInfopointMode);
                 Assumptions assumptions = new Assumptions(true);
                 new ComputeProbabilityPhase().apply(graph);
                 Debug.dump(graph, "Graph");
@@ -172,6 +199,31 @@
         return graph;
     }
 
+    private static StructuredGraph assertInlineInfopoints(StructuredGraph graph) {
+        int start = 0;
+        int end = 0;
+        for (InfopointNode ipn : graph.getNodes(InfopointNode.class)) {
+            if (ipn.reason == InfopointReason.METHOD_START) {
+                ++start;
+            } else if (ipn.reason == InfopointReason.METHOD_END) {
+                ++end;
+            }
+        }
+        if (start < 1 || end < 1) {
+            fail(String.format("Graph does not contain required inline infopoints: %d starts, %d ends.", start, end));
+        }
+        return graph;
+    }
+
+    private static StructuredGraph assertNoInlineInfopoints(StructuredGraph graph) {
+        for (InfopointNode ipn : graph.getNodes(InfopointNode.class)) {
+            if (ipn.reason == InfopointReason.METHOD_START || ipn.reason == InfopointReason.METHOD_END) {
+                fail("Graph contains inline infopoints.");
+            }
+        }
+        return graph;
+    }
+
     // some interfaces and classes for testing
     private interface MultipleImplementorsInterface {
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java	Mon Apr 08 18:47:06 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java	Thu Apr 11 09:53:10 2013 +0200
@@ -127,7 +127,7 @@
         if (state.outerFrameState() != null) {
             caller = computeFrameForState(state.outerFrameState());
         }
-        assert state.bci >= 0 || state.bci == FrameState.BEFORE_BCI : "bci == " + state.bci;
+        assert state.bci != FrameState.UNKNOWN_BCI : "bci == " + state.bci;
         return new BytecodeFrame(caller, state.method(), state.bci, state.rethrowException(), state.duringCall(), values, numLocals, numStack, numLocks);
     }
 
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64SafepointOp.java	Mon Apr 08 18:47:06 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64SafepointOp.java	Thu Apr 11 09:53:10 2013 +0200
@@ -63,11 +63,11 @@
         if (config.isPollingPageFar) {
             asm.movq(scratch.getRegister(), config.safepointPollingAddress + offset);
             tasm.recordMark(Marks.MARK_POLL_FAR);
-            tasm.recordSafepoint(pos, state);
+            tasm.recordInfopoint(pos, state, InfopointReason.SAFEPOINT);
             asm.movq(scratch.getRegister(), new AMD64Address(scratch.getRegister()));
         } else {
             tasm.recordMark(Marks.MARK_POLL_NEAR);
-            tasm.recordSafepoint(pos, state);
+            tasm.recordInfopoint(pos, state, InfopointReason.SAFEPOINT);
             // The C++ code transforms the polling page offset into an RIP displacement
             // to the real address at that offset in the polling page.
             asm.movq(scratch.getRegister(), new AMD64Address(rip, offset));
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompilationResult.java	Mon Apr 08 18:47:06 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompilationResult.java	Thu Apr 11 09:53:10 2013 +0200
@@ -67,7 +67,7 @@
     }
 
     private static Site[] getSortedSites(CompilationResult target) {
-        List<?>[] lists = new List<?>[]{target.getSafepoints(), target.getDataReferences(), target.getMarks()};
+        List<?>[] lists = new List<?>[]{target.getInfopoints(), target.getDataReferences(), target.getMarks()};
         int count = 0;
         for (List<?> list : lists) {
             count += list.size();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Mon Apr 08 18:47:06 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Thu Apr 11 09:53:10 2013 +0200
@@ -48,7 +48,7 @@
 import com.oracle.graal.api.code.CompilationResult.Call;
 import com.oracle.graal.api.code.CompilationResult.DataPatch;
 import com.oracle.graal.api.code.CompilationResult.Mark;
-import com.oracle.graal.api.code.CompilationResult.Safepoint;
+import com.oracle.graal.api.code.CompilationResult.Infopoint;
 import com.oracle.graal.api.code.Register.RegisterFlag;
 import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
 import com.oracle.graal.api.meta.*;
@@ -373,18 +373,18 @@
             addExceptionHandlersComment(compResult, hcf);
             Register fp = regConfig.getFrameRegister();
             RefMapFormatter slotFormatter = new RefMapFormatter(target.arch, target.wordSize, fp, 0);
-            for (Safepoint safepoint : compResult.getSafepoints()) {
-                if (safepoint instanceof Call) {
-                    Call call = (Call) safepoint;
+            for (Infopoint infopoint : compResult.getInfopoints()) {
+                if (infopoint instanceof Call) {
+                    Call call = (Call) infopoint;
                     if (call.debugInfo != null) {
                         hcf.addComment(call.pcOffset + call.size, CodeUtil.append(new StringBuilder(100), call.debugInfo, slotFormatter).toString());
                     }
                     addOperandComment(hcf, call.pcOffset, "{" + getTargetName(call) + "}");
                 } else {
-                    if (safepoint.debugInfo != null) {
-                        hcf.addComment(safepoint.pcOffset, CodeUtil.append(new StringBuilder(100), safepoint.debugInfo, slotFormatter).toString());
+                    if (infopoint.debugInfo != null) {
+                        hcf.addComment(infopoint.pcOffset, CodeUtil.append(new StringBuilder(100), infopoint.debugInfo, slotFormatter).toString());
                     }
-                    addOperandComment(hcf, safepoint.pcOffset, "{safepoint}");
+                    addOperandComment(hcf, infopoint.pcOffset, "{infopoint: " + infopoint.reason + "}");
                 }
             }
             for (DataPatch site : compResult.getDataReferences()) {
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java	Mon Apr 08 18:47:06 2013 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java	Thu Apr 11 09:53:10 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -23,6 +23,7 @@
 package com.oracle.graal.java;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
 
 public class GraphBuilderConfiguration {
 
@@ -30,6 +31,13 @@
     private final boolean omitAllExceptionEdges;
     private ResolvedJavaType[] skippedExceptionTypes;
 
+    /**
+     * When the graph builder is in eager infopoint mode, it inserts {@link InfopointNode}s in
+     * places where no safepoints would be inserted: inlining boundaries, and line number switches.
+     * This is relevant when code is to be generated for native, machine-code level debugging.
+     */
+    private boolean eagerInfopointMode;
+
     protected GraphBuilderConfiguration(boolean eagerResolving, boolean omitAllExceptionEdges) {
         this.eagerResolving = eagerResolving;
         this.omitAllExceptionEdges = omitAllExceptionEdges;
@@ -39,6 +47,10 @@
         this.skippedExceptionTypes = skippedExceptionTypes;
     }
 
+    public void setEagerInfopointMode(boolean eagerInfopointMode) {
+        this.eagerInfopointMode = eagerInfopointMode;
+    }
+
     public ResolvedJavaType[] getSkippedExceptionTypes() {
         return skippedExceptionTypes;
     }
@@ -51,6 +63,10 @@
         return omitAllExceptionEdges;
     }
 
+    public boolean eagerInfopointMode() {
+        return eagerInfopointMode;
+    }
+
     public static GraphBuilderConfiguration getDefault() {
         return new GraphBuilderConfiguration(false, false);
     }
@@ -64,9 +80,9 @@
     }
 
     /**
-     * Returns {@code true} if it is an error for a class/field/method resolution to fail.
-     * The default is the same result as returned by {@link #eagerResolving()}.
-     * However, it may be overridden to allow failure even when {@link #eagerResolving} is {@code true}.
+     * Returns {@code true} if it is an error for a class/field/method resolution to fail. The
+     * default is the same result as returned by {@link #eagerResolving()}. However, it may be
+     * overridden to allow failure even when {@link #eagerResolving} is {@code true}.
      */
     public boolean unresolvedIsError() {
         return eagerResolving;
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Mon Apr 08 18:47:06 2013 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Thu Apr 11 09:53:10 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
@@ -75,6 +75,10 @@
      */
     public static final int TRACELEVEL_STATE = 2;
 
+    private LineNumberTable lnt;
+    private int previousLineNumber;
+    private int currentLineNumber;
+
     protected StructuredGraph currentGraph;
 
     private final MetaAccessProvider runtime;
@@ -141,6 +145,10 @@
     @Override
     protected void run(StructuredGraph graph) {
         method = graph.method();
+        if (graphBuilderConfig.eagerInfopointMode()) {
+            lnt = method.getLineNumberTable();
+            previousLineNumber = -1;
+        }
         entryBCI = graph.getEntryBCI();
         profilingInfo = method.getProfilingInfo();
         assert method.getCode() != null : "method must contain bytecodes: " + method;
@@ -193,6 +201,13 @@
         }
         frameState.clearNonLiveLocals(blockMap.startBlock.localsLiveIn);
 
+        if (graphBuilderConfig.eagerInfopointMode()) {
+            ((StateSplit) lastInstr).setStateAfter(frameState.create(0));
+            InfopointNode ipn = currentGraph.add(new InfopointNode(InfopointReason.METHOD_START));
+            lastInstr.setNext(ipn);
+            lastInstr = ipn;
+        }
+
         // finish the start block
         ((StateSplit) lastInstr).setStateAfter(frameState.create(0));
 
@@ -1493,7 +1508,7 @@
     }
 
     private void processBlock(Block block) {
-        // Ignore blocks that have no predecessors by the time it their bytecodes are parsed
+        // Ignore blocks that have no predecessors by the time their bytecodes are parsed
         if (block == null || block.firstInstruction == null) {
             Debug.log("Ignoring block %s", block);
             return;
@@ -1574,6 +1589,12 @@
         }
         ReturnNode returnNode = currentGraph.add(new ReturnNode(x));
 
+        if (graphBuilderConfig.eagerInfopointMode()) {
+            InfopointNode ipn = currentGraph.add(new InfopointNode(InfopointReason.METHOD_END));
+            ipn.setStateAfter(frameState.create(FrameState.AFTER_BCI));
+            append(ipn);
+        }
+
         append(returnNode);
     }
 
@@ -1684,6 +1705,16 @@
         BytecodesParsed.add(block.endBci - bci);
 
         while (bci < endBCI) {
+            if (graphBuilderConfig.eagerInfopointMode() && lnt != null) {
+                currentLineNumber = lnt.getLineNumber(bci);
+                if (currentLineNumber != previousLineNumber) {
+                    InfopointNode ipn = currentGraph.add(new InfopointNode(InfopointReason.LINE_NUMBER));
+                    ipn.setStateAfter(frameState.create(bci));
+                    append(ipn);
+                    previousLineNumber = currentLineNumber;
+                }
+            }
+
             // read the opcode
             int opcode = stream.currentBC();
             traceState();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/InfopointOp.java	Thu Apr 11 09:53:10 2013 +0200
@@ -0,0 +1,49 @@
+/*
+ * 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.lir;
+
+import static com.oracle.graal.lir.LIRInstruction.Opcode;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.lir.asm.*;
+
+/**
+ * Emits an infopoint (only mark the position).
+ */
+@Opcode("INFOPOINT")
+public class InfopointOp extends LIRInstruction {
+
+    @State protected LIRFrameState state;
+
+    private final InfopointReason reason;
+
+    public InfopointOp(LIRFrameState state, InfopointReason reason) {
+        this.state = state;
+        this.reason = reason;
+    }
+
+    @Override
+    public void emitCode(TargetMethodAssembler tasm) {
+        tasm.recordInfopoint(tasm.asm.codeBuffer.position(), state, reason);
+    }
+}
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java	Mon Apr 08 18:47:06 2013 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java	Thu Apr 11 09:53:10 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -101,7 +101,7 @@
 
         Debug.metric("TargetMethods").increment();
         Debug.metric("CodeBytesEmitted").add(compilationResult.getTargetCodeSize());
-        Debug.metric("SafepointsEmitted").add(compilationResult.getSafepoints().size());
+        Debug.metric("SafepointsEmitted").add(compilationResult.getInfopoints().size());
         Debug.metric("DataPatches").add(compilationResult.getDataReferences().size());
         Debug.metric("ExceptionHandlersEmitted").add(compilationResult.getExceptionHandlers().size());
         Debug.log("Finished target method %s, isStub %b", name, isStub);
@@ -122,7 +122,7 @@
     public void recordImplicitException(int pcOffset, LIRFrameState info) {
         // record an implicit exception point
         if (info != null) {
-            compilationResult.recordSafepoint(pcOffset, info.debugInfo());
+            compilationResult.recordInfopoint(pcOffset, info.debugInfo(), InfopointReason.IMPLICIT_EXCEPTION);
             assert info.exceptionEdge == null;
         }
     }
@@ -137,10 +137,10 @@
         compilationResult.recordCall(posBefore, posAfter - posBefore, callTarget, debugInfo, false);
     }
 
-    public void recordSafepoint(int pos, LIRFrameState info) {
-        // safepoints always need debug info
+    public void recordInfopoint(int pos, LIRFrameState info, InfopointReason reason) {
+        // infopoints always need debug info
         DebugInfo debugInfo = info.debugInfo();
-        compilationResult.recordSafepoint(pos, debugInfo);
+        compilationResult.recordInfopoint(pos, debugInfo, reason);
     }
 
     public AbstractAddress recordDataReferenceInCode(Constant data, int alignment, boolean inlined) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java	Thu Apr 11 09:53:10 2013 +0200
@@ -0,0 +1,52 @@
+/*
+ * 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.nodes;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.graph.Node.IterableNodeType;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+/**
+ * Nodes of this type are inserted into the graph to denote points of interest to debugging.
+ */
+public class InfopointNode extends AbstractStateSplit implements LIRLowerable, IterableNodeType {
+
+    public final InfopointReason reason;
+
+    public InfopointNode(InfopointReason reason) {
+        super(StampFactory.forVoid());
+        this.reason = reason;
+    }
+
+    @Override
+    public void generate(LIRGeneratorTool generator) {
+        generator.visitInfopointNode(this);
+    }
+
+    @Override
+    public boolean hasSideEffect() {
+        return false;
+    }
+
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Mon Apr 08 18:47:06 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Thu Apr 11 09:53:10 2013 +0200
@@ -137,4 +137,6 @@
      */
     public void beforeRegisterAllocation() {
     }
+
+    public abstract void visitInfopointNode(InfopointNode i);
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Mon Apr 08 18:47:06 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Thu Apr 11 09:53:10 2013 +0200
@@ -1117,7 +1117,7 @@
             }
             if (node instanceof FrameState) {
                 FrameState frameState = (FrameState) node;
-                assert frameState.bci != FrameState.BEFORE_BCI;
+                assert frameState.bci != FrameState.BEFORE_BCI : frameState;
                 if (frameState.bci == FrameState.AFTER_BCI) {
                     frameState.replaceAndDelete(stateAfter);
                 } else if (frameState.bci == FrameState.AFTER_EXCEPTION_BCI) {
--- a/src/share/vm/classfile/systemDictionary.hpp	Mon Apr 08 18:47:06 2013 +0200
+++ b/src/share/vm/classfile/systemDictionary.hpp	Thu Apr 11 09:53:10 2013 +0200
@@ -209,8 +209,9 @@
   do_klass(CompilationResult_DataPatch_klass,     com_oracle_graal_api_code_CompilationResult_DataPatch,        Opt) \
   do_klass(CompilationResult_ExceptionHandler_klass, com_oracle_graal_api_code_CompilationResult_ExceptionHandler, Opt) \
   do_klass(CompilationResult_Mark_klass,          com_oracle_graal_api_code_CompilationResult_Mark,             Opt) \
-  do_klass(CompilationResult_Safepoint_klass,     com_oracle_graal_api_code_CompilationResult_Safepoint,        Opt) \
+  do_klass(CompilationResult_Infopoint_klass,     com_oracle_graal_api_code_CompilationResult_Infopoint,        Opt) \
   do_klass(CompilationResult_Site_klass,          com_oracle_graal_api_code_CompilationResult_Site,             Opt) \
+  do_klass(InfopointReason_klass,                 com_oracle_graal_api_code_InfopointReason,                    Opt) \
   do_klass(code_Register_klass,                   com_oracle_graal_api_code_Register,                           Opt) \
   do_klass(RegisterValue_klass,                   com_oracle_graal_api_code_RegisterValue,                      Opt) \
   do_klass(StackSlot_klass,                       com_oracle_graal_api_code_StackSlot,                          Opt) \
--- a/src/share/vm/classfile/vmSymbols.hpp	Mon Apr 08 18:47:06 2013 +0200
+++ b/src/share/vm/classfile/vmSymbols.hpp	Thu Apr 11 09:53:10 2013 +0200
@@ -328,8 +328,9 @@
   template(com_oracle_graal_api_code_CompilationResult_DataPatch,    "com/oracle/graal/api/code/CompilationResult$DataPatch")         \
   template(com_oracle_graal_api_code_CompilationResult_ExceptionHandler, "com/oracle/graal/api/code/CompilationResult$ExceptionHandler") \
   template(com_oracle_graal_api_code_CompilationResult_Mark,         "com/oracle/graal/api/code/CompilationResult$Mark")              \
-  template(com_oracle_graal_api_code_CompilationResult_Safepoint,    "com/oracle/graal/api/code/CompilationResult$Safepoint")         \
+  template(com_oracle_graal_api_code_CompilationResult_Infopoint,    "com/oracle/graal/api/code/CompilationResult$Infopoint")         \
   template(com_oracle_graal_api_code_CompilationResult_Site,         "com/oracle/graal/api/code/CompilationResult$Site")              \
+  template(com_oracle_graal_api_code_InfopointReason,                "com/oracle/graal/api/code/InfopointReason")                     \
   template(com_oracle_graal_api_code_BytecodeFrame,                  "com/oracle/graal/api/code/BytecodeFrame")                       \
   template(com_oracle_graal_api_code_BytecodePosition,               "com/oracle/graal/api/code/BytecodePosition")                    \
   template(com_oracle_graal_api_code_DebugInfo,                      "com/oracle/graal/api/code/DebugInfo")                           \
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Mon Apr 08 18:47:06 2013 +0200
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Thu Apr 11 09:53:10 2013 +0200
@@ -416,9 +416,17 @@
     if (site->is_a(CompilationResult_Call::klass())) {
       TRACE_graal_4("call at %i", pc_offset);
       site_Call(buffer, pc_offset, site);
-    } else if (site->is_a(CompilationResult_Safepoint::klass())) {
-      TRACE_graal_4("safepoint at %i", pc_offset);
-      site_Safepoint(buffer, pc_offset, site);
+    } else if (site->is_a(CompilationResult_Infopoint::klass())) {
+      // three reasons for infopoints denote actual safepoints
+      oop reason = CompilationResult_Infopoint::reason(site);
+      if (InfopointReason::SAFEPOINT() == reason || InfopointReason::CALL() == reason || InfopointReason::IMPLICIT_EXCEPTION() == reason) {
+        TRACE_graal_4("safepoint at %i", pc_offset);
+        site_Safepoint(buffer, pc_offset, site);
+      } else {
+        // if the infopoint is not an actual safepoint, it must have one of the other reasons
+        // (safeguard against new safepoint types that require handling above)
+        assert(InfopointReason::METHOD_START() == reason || InfopointReason::METHOD_END() == reason || InfopointReason::LINE_NUMBER() == reason, "");
+      }
     } else if (site->is_a(CompilationResult_DataPatch::klass())) {
       TRACE_graal_4("datapatch at %i", pc_offset);
       site_DataPatch(buffer, pc_offset, site);
@@ -578,7 +586,7 @@
 }
 
 void CodeInstaller::site_Safepoint(CodeBuffer& buffer, jint pc_offset, oop site) {
-  oop debug_info = CompilationResult_Safepoint::debugInfo(site);
+  oop debug_info = CompilationResult_Infopoint::debugInfo(site);
   assert(debug_info != NULL, "debug info expected");
 
   // address instruction = _instructions->start() + pc_offset;
--- a/src/share/vm/graal/graalJavaAccess.hpp	Mon Apr 08 18:47:06 2013 +0200
+++ b/src/share/vm/graal/graalJavaAccess.hpp	Thu Apr 11 09:53:10 2013 +0200
@@ -131,8 +131,18 @@
     int_field(CompilationResult_DataPatch, alignment)                                                                                                          \
     boolean_field(CompilationResult_DataPatch, inlined)                                                                                                        \
   end_class                                                                                                                                                    \
-  start_class(CompilationResult_Safepoint)                                                                                                                     \
-    oop_field(CompilationResult_Safepoint, debugInfo, "Lcom/oracle/graal/api/code/DebugInfo;")                                                                 \
+  start_class(InfopointReason)                                                                                                                                 \
+    static_oop_field(InfopointReason, UNKNOWN, "Lcom/oracle/graal/api/code/InfopointReason;")                                                                  \
+    static_oop_field(InfopointReason, SAFEPOINT, "Lcom/oracle/graal/api/code/InfopointReason;")                                                                \
+    static_oop_field(InfopointReason, CALL, "Lcom/oracle/graal/api/code/InfopointReason;")                                                                     \
+    static_oop_field(InfopointReason, IMPLICIT_EXCEPTION, "Lcom/oracle/graal/api/code/InfopointReason;")                                                       \
+    static_oop_field(InfopointReason, METHOD_START, "Lcom/oracle/graal/api/code/InfopointReason;")                                                             \
+    static_oop_field(InfopointReason, METHOD_END, "Lcom/oracle/graal/api/code/InfopointReason;")                                                               \
+    static_oop_field(InfopointReason, LINE_NUMBER, "Lcom/oracle/graal/api/code/InfopointReason;")                                                              \
+  end_class                                                                                                                                                    \
+  start_class(CompilationResult_Infopoint)                                                                                                                     \
+    oop_field(CompilationResult_Infopoint, debugInfo, "Lcom/oracle/graal/api/code/DebugInfo;")                                                                 \
+    oop_field(CompilationResult_Infopoint, reason, "Lcom/oracle/graal/api/code/InfopointReason;")                                                              \
   end_class                                                                                                                                                    \
   start_class(CompilationResult_ExceptionHandler)                                                                                                              \
     int_field(CompilationResult_ExceptionHandler, handlerPos)                                                                                                  \