changeset 7325:4013a84e1dd0

Merge
author Gilles Duboscq <duboscq@ssw.jku.at>
date Thu, 10 Jan 2013 11:41:10 +0100
parents 9214756f9bbf (current diff) dd1b2da27b38 (diff)
children 6939a5af19d5
files
diffstat 42 files changed, 992 insertions(+), 119 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/ComputeBlockOrder.java	Thu Jan 10 11:40:25 2013 +0100
+++ b/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/ComputeBlockOrder.java	Thu Jan 10 11:41:10 2013 +0100
@@ -163,6 +163,16 @@
         }
         curBit--;
 
+        if (cur.getBeginNode().probability() > 0.5) {
+            weight |= 1 << curBit;
+        }
+        curBit--;
+
+        if (cur.getBeginNode().probability() > 0.05) {
+            weight |= 1 << curBit;
+        }
+        curBit--;
+
         // guarantee that weight is > 0
         weight |= 1;
 
@@ -261,23 +271,26 @@
         // start processing with standard entry block
         assert workList.isEmpty() : "list must be empty before processing";
 
-        assert readyForProcessing(startBlock);
         sortIntoWorkList(startBlock);
 
         do {
             Block cur = workList.remove(workList.size() - 1);
-            appendBlock(cur);
-
-            Node endNode = cur.getEndNode();
-            if (endNode instanceof IfNode && ((IfNode) endNode).probability() < 0.5) {
-                assert cur.numberOfSux() == 2;
-                checkAndSortIntoWorkList(cur.suxAt(1));
-                checkAndSortIntoWorkList(cur.suxAt(0));
-            } else {
-                for (Block sux : cur.getSuccessors()) {
-                    checkAndSortIntoWorkList(sux);
-                }
-            }
+            processBlock(cur);
         } while (workList.size() > 0);
     }
+
+    private void processBlock(Block cur) {
+        appendBlock(cur);
+
+        Node endNode = cur.getEndNode();
+        if (endNode instanceof IfNode && ((IfNode) endNode).probability() < 0.5) {
+            assert cur.numberOfSux() == 2;
+            checkAndSortIntoWorkList(cur.suxAt(1));
+            checkAndSortIntoWorkList(cur.suxAt(0));
+        } else {
+            for (Block sux : cur.getSuccessors()) {
+                checkAndSortIntoWorkList(sux);
+            }
+        }
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/LineNumberTable.java	Thu Jan 10 11:41:10 2013 +0100
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2011, 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.meta;
+
+
+public interface LineNumberTable {
+    int[] getLineNumberEntries();
+    int[] getBciEntries();
+    int getLineNumber(int bci);
+}
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java	Thu Jan 10 11:40:25 2013 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java	Thu Jan 10 11:41:10 2013 +0100
@@ -24,6 +24,7 @@
 
 import java.lang.annotation.*;
 import java.lang.reflect.*;
+import java.lang.reflect.Method;
 import java.util.*;
 
 /**
@@ -159,4 +160,10 @@
      * Returns {@code true} if this method can be inlined.
      */
     boolean canBeInlined();
+
+
+    /**
+     * Returns the LineNumberTable of this method.
+     */
+    LineNumberTable getLineNumberTable();
 }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java	Thu Jan 10 11:40:25 2013 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java	Thu Jan 10 11:41:10 2013 +0100
@@ -241,4 +241,9 @@
      * @return the field with the given offset, or {@code null} if there is no such field.
      */
     ResolvedJavaField findInstanceFieldWithOffset(long offset);
+
+    /**
+     * Returns name of source file of this type.
+     */
+    String getSourceFileName();
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Thu Jan 10 11:40:25 2013 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Thu Jan 10 11:41:10 2013 +0100
@@ -42,6 +42,7 @@
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.PhasePlan.PhasePosition;
 import com.oracle.graal.phases.schedule.*;
+import com.oracle.graal.printer.*;
 
 /**
  * Base class for Graal compiler unit tests.
@@ -68,7 +69,7 @@
     protected final GraalCompiler graalCompiler;
 
     public GraalCompilerTest() {
-        Debug.enable();
+        DebugEnvironment.initialize(System.out);
         this.runtime = Graal.getRequiredCapability(GraalCodeCacheProvider.class);
         this.graalCompiler = Graal.getRequiredCapability(GraalCompiler.class);
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfBoxingEliminationTest.java	Thu Jan 10 11:40:25 2013 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfBoxingEliminationTest.java	Thu Jan 10 11:41:10 2013 +0100
@@ -97,6 +97,7 @@
                 Debug.dump(graph, "Graph");
                 new ExpandBoxingNodesPhase(pool).apply(graph);
                 new CanonicalizerPhase(null, runtime(), assumptions).apply(graph);
+                new CanonicalizerPhase(null, runtime(), assumptions).apply(graph);
                 new DeadCodeEliminationPhase().apply(graph);
                 StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET);
                 new CanonicalizerPhase(null, runtime(), assumptions).apply(referenceGraph);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/DebugFilter.java	Thu Jan 10 11:41:10 2013 +0100
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2012, 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;
+
+import java.util.*;
+import java.util.regex.*;
+
+import com.oracle.graal.debug.*;
+import com.oracle.graal.debug.internal.*;
+import com.oracle.graal.phases.*;
+
+/**
+ * Implements the filter specified by the {@link GraalOptions#Dump},
+ * {@link GraalOptions#Log}, {@link GraalOptions#Meter} and {@link GraalOptions#Time}
+ * options.
+ * <p>
+ * These options enable the associated debug facility if their filter
+ * matches the {@linkplain DebugScope#getQualifiedName() name} of the
+ * {@linkplain Debug#currentScope() current scope}.
+ * <p>
+ * A filter is a list of comma-separated terms. Each term is interpreted
+ * as a glob pattern if it contains a "*" or "?" character. Otherwise, it is
+ * interpreted as a substring. If a term starts with "~", then it is an
+ * positive term. An input is matched by a filter if any of its positive
+ * terms match the input (or it has no positive terms) AND none of its
+ * negative terms match the input (or it has no negative terms).
+ * <p>
+ * Examples of filters include:
+ * <p>
+ * <ul>
+ * <li><pre>""</pre>
+ * Matches any scope.</li>
+ * <li><pre>"*"</pre>
+ * Matches any scope.</li>
+ * <li><pre>"CodeGen,CodeInstall"</pre>
+ * Matches a scope whose name contains "CodeGen" or "CodeInstall".</li>
+ * <li><pre>"Code*"</pre>
+ * Matches a scope whose name starts with "Code".</li>
+ * <li><pre>"Code,~Dead"</pre>
+ * Matches a scope whose name contains "Code" but does not contain "Dead".</li>
+ * </ul>
+ */
+class DebugFilter {
+
+    public static DebugFilter parse(String spec) {
+        if (spec == null) {
+            return null;
+        }
+        return new DebugFilter(spec.split(","));
+    }
+
+    final Term[] positive;
+    final Term[] negative;
+
+    DebugFilter(String[] terms) {
+        List<Term> pos = new ArrayList<>(terms.length);
+        List<Term> neg = new ArrayList<>(terms.length);
+        for (int i = 0; i < terms.length; i++) {
+            String t = terms[i];
+            if (t.startsWith("~")) {
+                neg.add(new Term(t.substring(1)));
+            } else {
+                pos.add(new Term(t));
+            }
+        }
+        this.positive = pos.isEmpty() ? null : pos.toArray(new Term[pos.size()]);
+        this.negative = neg.isEmpty() ? null : neg.toArray(new Term[neg.size()]);
+    }
+
+    /**
+     * Determines if a given input is matched by this filter.
+     */
+    public boolean matches(String input) {
+        boolean match = true;
+        if (positive != null) {
+            match = false;
+            for (Term t : positive) {
+                if (t.matches(input)) {
+                    match = true;
+                    break;
+                }
+            }
+        }
+        if (match && negative != null) {
+            for (Term t : negative) {
+                if (t.matches(input)) {
+                    match = false;
+                    break;
+                }
+            }
+        }
+//        if (match) {
+//            System.out.println(this + " matches " + input);
+//        }
+        return match;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder buf = new StringBuilder("DebugFilter[");
+        String sep = "";
+        if (positive != null) {
+            buf.append(sep).append("pos=").append(Arrays.toString(positive));
+            sep = ", ";
+        }
+        if (negative != null) {
+            buf.append(sep).append("neg=").append(Arrays.toString(negative));
+            sep = ", ";
+        }
+        return buf.append("]").toString();
+    }
+
+    static class Term {
+
+        final Pattern pattern;
+
+        public Term(String filter) {
+            if (filter.isEmpty()) {
+                this.pattern = null;
+            } else if (filter.contains("*") || filter.contains("?")) {
+                this.pattern = Pattern.compile(MethodFilter.createGlobString(filter));
+            } else {
+                this.pattern = Pattern.compile(".*" + MethodFilter.createGlobString(filter) + ".*");
+            }
+        }
+
+        /**
+         * Determines if a given input is matched by this filter.
+         */
+        public boolean matches(String input) {
+            return pattern == null || pattern.matcher(input).matches();
+        }
+
+        @Override
+        public String toString() {
+            return pattern == null ? ".*" : pattern.toString();
+        }
+    }
+}
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Thu Jan 10 11:40:25 2013 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Thu Jan 10 11:41:10 2013 +0100
@@ -168,7 +168,7 @@
         if (GraalOptions.OptFloatingReads) {
             int mark = graph.getMark();
             new FloatingReadPhase().apply(graph);
-            new CanonicalizerPhase(target, runtime, assumptions, mark).apply(graph);
+            new CanonicalizerPhase(target, runtime, assumptions, mark, null).apply(graph);
             if (GraalOptions.OptReadElimination) {
                 new ReadEliminationPhase().apply(graph);
             }
@@ -228,6 +228,7 @@
 
             }
         });
+
     }
 
     public FrameMap emitLIR(final LIR lir, StructuredGraph graph, final ResolvedJavaMethod method) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java	Thu Jan 10 11:41:10 2013 +0100
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2012, 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;
+
+import java.io.*;
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.phases.*;
+
+public class GraalDebugConfig implements DebugConfig {
+
+    private final DebugFilter logFilter;
+    private final DebugFilter meterFilter;
+    private final DebugFilter timerFilter;
+    private final DebugFilter dumpFilter;
+    private final MethodFilter[] methodFilter;
+    private final List<DebugDumpHandler> dumpHandlers;
+    private final PrintStream output;
+    private final Set<Object> extraFilters = new HashSet<>();
+
+    public GraalDebugConfig(String logFilter, String meterFilter, String timerFilter, String dumpFilter, String methodFilter, PrintStream output, List<DebugDumpHandler> dumpHandlers) {
+        this.logFilter = DebugFilter.parse(logFilter);
+        this.meterFilter = DebugFilter.parse(meterFilter);
+        this.timerFilter = DebugFilter.parse(timerFilter);
+        this.dumpFilter = DebugFilter.parse(dumpFilter);
+        if (methodFilter == null || methodFilter.isEmpty()) {
+            this.methodFilter = null;
+        } else {
+            String[] filters = methodFilter.split(",");
+            this.methodFilter = new MethodFilter[filters.length];
+            for (int i = 0; i < filters.length; i++) {
+                this.methodFilter[i] = new MethodFilter(filters[i]);
+            }
+        }
+
+        // Report the filters that have been configured so the user can verify it's what they expect
+        if (logFilter != null || meterFilter != null || timerFilter != null || dumpFilter != null || methodFilter != null) {
+            TTY.println(Thread.currentThread().getName() + ": " + toString());
+        }
+        this.dumpHandlers = dumpHandlers;
+        this.output = output;
+    }
+
+    public boolean isLogEnabled() {
+        return isEnabled(logFilter);
+    }
+
+    public boolean isMeterEnabled() {
+        return isEnabled(meterFilter);
+    }
+
+    public boolean isDumpEnabled() {
+        return isEnabled(dumpFilter);
+    }
+
+    public boolean isTimeEnabled() {
+        return isEnabled(timerFilter);
+    }
+
+    public PrintStream output() {
+        return output;
+    }
+
+    private boolean isEnabled(DebugFilter filter) {
+        return checkDebugFilter(Debug.currentScope(), filter) && checkMethodFilter();
+    }
+
+    private static boolean checkDebugFilter(String currentScope, DebugFilter filter) {
+        return filter != null && filter.matches(currentScope);
+    }
+
+    private boolean checkMethodFilter() {
+        if (methodFilter == null && extraFilters.isEmpty()) {
+            return true;
+        } else {
+            for (Object o : Debug.context()) {
+                if (extraFilters.contains(o)) {
+                    return true;
+                } else if (methodFilter != null) {
+                    if (o instanceof JavaMethod) {
+                        for (MethodFilter filter : methodFilter) {
+                            if (filter.matches((JavaMethod) o)) {
+                                return true;
+                            }
+                        }
+                    }
+                }
+            }
+            return false;
+        }
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("Debug config:");
+        add(sb, "Log", logFilter);
+        add(sb, "Meter", meterFilter);
+        add(sb, "Time", timerFilter);
+        add(sb, "Dump", dumpFilter);
+        add(sb, "MethodFilter", methodFilter);
+        return sb.toString();
+    }
+
+    private static void add(StringBuilder sb, String name, Object filter) {
+        if (filter != null) {
+            sb.append(' ');
+            sb.append(name);
+            sb.append('=');
+            if (filter instanceof Object[]) {
+                sb.append(Arrays.toString((Object[]) filter));
+            } else {
+                sb.append(String.valueOf(filter));
+            }
+        }
+    }
+
+    @Override
+    public RuntimeException interceptException(Throwable e) {
+        if (e instanceof BailoutException) {
+            return null;
+        }
+        Debug.setConfig(Debug.fixedConfig(true, true, false, false, dumpHandlers, output));
+        Debug.log(String.format("Exception occurred in scope: %s", Debug.currentScope()));
+        for (Object o : Debug.context()) {
+            if (o instanceof Graph) {
+                Debug.log("Context obj %s", o);
+                if (GraalOptions.DumpOnError) {
+                    Debug.dump(o, "Exception graph");
+                } else {
+                    Debug.log("Use -G:+DumpOnError to enable dumping of graphs on this error");
+                }
+            } else if (o instanceof Node) {
+                String location = GraphUtil.approxSourceLocation((Node) o);
+                if (location != null) {
+                    Debug.log("Context obj %s (approx. location: %s)", o, location);
+                } else {
+                    Debug.log("Context obj %s", o);
+                }
+            } else {
+                Debug.log("Context obj %s", o);
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public Collection<DebugDumpHandler> dumpHandlers() {
+        return dumpHandlers;
+    }
+
+    @Override
+    public void addToContext(Object o) {
+        extraFilters.add(o);
+    }
+
+    @Override
+    public void removeFromContext(Object o) {
+        extraFilters.remove(o);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/MethodFilter.java	Thu Jan 10 11:41:10 2013 +0100
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2012, 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;
+
+import java.util.*;
+import java.util.regex.*;
+
+import com.oracle.graal.api.meta.*;
+
+/**
+ * This class implements a method filter that can filter based on class name, method name and parameters.
+ * The syntax for the source pattern that is passed to the constructor is as follows:
+ *
+ * <pre>
+ * SourcePattern = [ Class "." ] method [ "(" [ Parameter { ";" Parameter } ] ")" ] .
+ * Parameter = Class | "int" | "long" | "float" | "double" | "short" | "char" | "boolean" .
+ * Class = { package "." } class .
+ * </pre>
+ *
+ *
+ * Glob pattern matching (*, ?) is allowed in all parts of the source pattern. Examples for valid filters are:
+ *
+ * <ul>
+ * <li><pre>visit(Argument;BlockScope)</pre>
+ * Matches all methods named "visit", with the first parameter of type "Argument", and the second parameter of type "BlockScope".
+ * The packages of the parameter types are irrelevant.</li>
+ * <li><pre>arraycopy(Object;;;;)</pre>
+ * Matches all methods named "arraycopy", with the first parameter of type "Object", and four more parameters of any type.
+ * The packages of the parameter types are irrelevant.</li>
+ * <li><pre>com.oracle.graal.compiler.graph.PostOrderNodeIterator.*</pre>
+ * Matches all methods in the class "com.oracle.graal.compiler.graph.PostOrderNodeIterator".</li>
+ * <li><pre>*</pre>
+ * Matches all methods in all classes</li>
+ * <li><pre>com.oracle.graal.compiler.graph.*.visit</pre>
+ * Matches all methods named "visit" in classes in the package "com.oracle.graal.compiler.graph".</pre>
+ * </ul>
+ */
+public class MethodFilter {
+
+    private final Pattern clazz;
+    private final Pattern methodName;
+    private final Pattern[] signature;
+
+    public MethodFilter(String sourcePattern) {
+        String pattern = sourcePattern.trim();
+
+        // extract parameter part
+        int pos = pattern.indexOf('(');
+        if (pos != -1) {
+            if (pattern.charAt(pattern.length() - 1) != ')') {
+                throw new IllegalArgumentException("missing ')' at end of method filter pattern: " + pattern);
+            }
+            String[] signatureClasses = pattern.substring(pos + 1, pattern.length() - 1).split(";", -1);
+            signature = new Pattern[signatureClasses.length];
+            for (int i = 0; i < signatureClasses.length; i++) {
+                signature[i] = createClassGlobPattern(signatureClasses[i].trim());
+            }
+            pattern = pattern.substring(0, pos);
+        } else {
+            signature = null;
+        }
+
+        // If there is at least one "." then everything before the last "." is the class name.
+        // Otherwise, the pattern contains only the method name.
+        pos = pattern.lastIndexOf('.');
+        if (pos != -1) {
+            clazz = createClassGlobPattern(pattern.substring(0, pos));
+            methodName = Pattern.compile(createGlobString(pattern.substring(pos + 1)));
+        } else {
+            clazz = null;
+            methodName = Pattern.compile(createGlobString(pattern));
+        }
+    }
+
+    static String createGlobString(String pattern) {
+        return Pattern.quote(pattern).replace("?", "\\E.\\Q").replace("*", "\\E.*\\Q");
+    }
+
+    private static Pattern createClassGlobPattern(String pattern) {
+        if (pattern.length() == 0) {
+            return null;
+        } else if (pattern.contains(".")) {
+            return Pattern.compile(createGlobString(pattern));
+        } else {
+            return Pattern.compile("([^\\.]*\\.)*" + createGlobString(pattern));
+        }
+    }
+
+    public boolean matches(JavaMethod o) {
+        // check method name first, since MetaUtil.toJavaName is expensive
+        if (methodName != null && !methodName.matcher(o.getName()).matches()) {
+            return false;
+        }
+        if (clazz != null && !clazz.matcher(MetaUtil.toJavaName(o.getDeclaringClass())).matches()) {
+            return false;
+        }
+        if (signature != null) {
+            Signature sig = o.getSignature();
+            if (sig.getParameterCount(false) != signature.length) {
+                return false;
+            }
+            for (int i = 0; i < signature.length; i++) {
+                JavaType type = sig.getParameterType(i, null);
+                String javaName = MetaUtil.toJavaName(type);
+                if (signature[i] != null && !signature[i].matcher(javaName).matches()) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder buf = new StringBuilder("MethodFilter[");
+        String sep = "";
+        if (clazz != null) {
+            buf.append(sep).append("clazz=").append(clazz);
+            sep = ", ";
+        }
+        if (methodName != null) {
+            buf.append(sep).append("methodName=").append(methodName);
+            sep = ", ";
+        }
+        if (signature != null) {
+            buf.append(sep).append("signature=").append(Arrays.toString(signature));
+            sep = ", ";
+        }
+        return buf.append("]").toString();
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilerThread.java	Thu Jan 10 11:40:25 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilerThread.java	Thu Jan 10 11:41:10 2013 +0100
@@ -25,8 +25,10 @@
 import java.io.*;
 import java.util.concurrent.*;
 
+import com.oracle.graal.compiler.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.phases.*;
+import com.oracle.graal.printer.*;
 
 
 public final class CompilerThread extends Thread {
@@ -56,12 +58,10 @@
 
     @Override
     public void run() {
-        HotSpotDebugConfig hotspotDebugConfig = null;
+        GraalDebugConfig hotspotDebugConfig = null;
         if (GraalOptions.Debug) {
-            Debug.enable();
             PrintStream log = HotSpotGraalRuntime.getInstance().getVMToCompiler().log();
-            hotspotDebugConfig = new HotSpotDebugConfig(GraalOptions.Log, GraalOptions.Meter, GraalOptions.Time, GraalOptions.Dump, GraalOptions.MethodFilter, log);
-            Debug.setConfig(hotspotDebugConfig);
+            DebugEnvironment.initialize(log);
         }
         try {
             super.run();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Thu Jan 10 11:40:25 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Thu Jan 10 11:41:10 2013 +0100
@@ -200,4 +200,10 @@
     long[] getDeoptedLeafGraphIds();
 
     String decodePC(long pc);
+
+
+    long[] getLineNumberTable(HotSpotResolvedJavaMethod method);
+
+
+    String getFileName(HotSpotResolvedJavaType method);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Thu Jan 10 11:40:25 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Thu Jan 10 11:41:10 2013 +0100
@@ -142,4 +142,10 @@
 
     @Override
     public native String decodePC(long pc);
+
+    @Override
+    public native long[] getLineNumberTable(HotSpotResolvedJavaMethod method);
+
+    @Override
+    public native String getFileName(HotSpotResolvedJavaType method);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Thu Jan 10 11:40:25 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Thu Jan 10 11:41:10 2013 +0100
@@ -44,6 +44,7 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.PhasePlan.PhasePosition;
+import com.oracle.graal.printer.*;
 import com.oracle.graal.snippets.*;
 
 /**
@@ -123,10 +124,8 @@
             }
         }
 
-        if (GraalOptions.Debug) {
-            Debug.enable();
-            HotSpotDebugConfig hotspotDebugConfig = new HotSpotDebugConfig(GraalOptions.Log, GraalOptions.Meter, GraalOptions.Time, GraalOptions.Dump, GraalOptions.MethodFilter, log);
-            Debug.setConfig(hotspotDebugConfig);
+        if (GraalOptions.Debug && GraalOptions.DebugSnippets) {
+            DebugEnvironment.initialize(log);
         }
         // Install intrinsics.
         GraalCompiler compiler = graalRuntime.getCompiler();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/LineNumberTableImpl.java	Thu Jan 10 11:41:10 2013 +0100
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2011, 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.hotspot.debug;
+
+import com.oracle.graal.api.meta.*;
+
+
+public class LineNumberTableImpl implements LineNumberTable {
+    private final int[] lineNumbers;
+    private final int[] bci;
+
+    public LineNumberTableImpl(int[] lineNumbers, int[] bci) {
+        this.lineNumbers = lineNumbers;
+        this.bci = bci;
+    }
+
+    @Override
+    public int[] getLineNumberEntries() {
+        return lineNumbers;
+    }
+
+    @Override
+    public int[] getBciEntries() {
+        return bci;
+    }
+
+    @Override
+    public int getLineNumber(@SuppressWarnings("hiding") int bci) {
+        for (int i = 0; i < this.bci.length - 1; i++) {
+            if (this.bci[i] <= bci && bci < this.bci[i + 1]) {
+                return lineNumbers[i];
+            }
+        }
+        return lineNumbers[lineNumbers.length - 1];
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Thu Jan 10 11:40:25 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Thu Jan 10 11:41:10 2013 +0100
@@ -34,6 +34,7 @@
 import com.oracle.graal.api.meta.ProfilingInfo.ExceptionSeen;
 import com.oracle.graal.bytecode.*;
 import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.debug.*;
 import com.oracle.graal.phases.*;
 
 /**
@@ -290,6 +291,21 @@
         return HotSpotGraalRuntime.getInstance().getCompilerToVM().isMethodCompilable(metaspaceMethod);
     }
 
+    @Override
+    public LineNumberTable getLineNumberTable() {
+        long[] values = HotSpotGraalRuntime.getInstance().getCompilerToVM().getLineNumberTable(this);
+        assert values.length % 2 == 0;
+        int[] bci = new int[values.length / 2];
+        int[] line = new int[values.length / 2];
+
+        for (int i = 0; i < values.length / 2; i++) {
+            bci[i] = (int) values[i * 2];
+            line[i] = (int) values[i * 2 + 1];
+        }
+
+        return new LineNumberTableImpl(line, bci);
+    }
+
     /**
      * Returns the offset of this method into the v-table.
      * If the holder is not initialized, returns -1
@@ -309,4 +325,5 @@
     public CompilationTask currentTask() {
         return currentTask;
     }
+
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java	Thu Jan 10 11:40:25 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java	Thu Jan 10 11:41:10 2013 +0100
@@ -23,6 +23,7 @@
 package com.oracle.graal.hotspot.meta;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.hotspot.*;
 
 
 public abstract class HotSpotResolvedJavaType extends HotSpotJavaType implements ResolvedJavaType {
@@ -33,4 +34,9 @@
     }
 
     public abstract Class<?> mirror();
+
+    @Override
+    public String getSourceFileName() {
+       return HotSpotGraalRuntime.getInstance().getCompilerToVM().getFileName(this);
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java	Thu Jan 10 11:40:25 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java	Thu Jan 10 11:41:10 2013 +0100
@@ -446,6 +446,11 @@
     }
 
     @Override
+    public String getSourceFileName() {
+       return HotSpotGraalRuntime.getInstance().getCompilerToVM().getFileName(this);
+    }
+
+    @Override
     public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
         return javaMirror.getAnnotation(annotationClass);
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java	Thu Jan 10 11:40:25 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java	Thu Jan 10 11:41:10 2013 +0100
@@ -181,7 +181,12 @@
     }
 
     @Override
-    public Class<?> mirror() {
+    public String getSourceFileName() {
+        throw GraalInternalError.shouldNotReachHere();
+    }
+
+    @Override
+    public Class< ? > mirror() {
         return javaMirror;
     }
 }
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java	Thu Jan 10 11:40:25 2013 +0100
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java	Thu Jan 10 11:41:10 2013 +0100
@@ -60,7 +60,7 @@
         while (!loopBegin.isDeleted()) {
             int mark = graph.getMark();
             peel(loop);
-            new CanonicalizerPhase(null, runtime, assumptions, mark).apply(graph);
+            new CanonicalizerPhase(null, runtime, assumptions, mark, null).apply(graph);
             if (iterations++ > UNROLL_LIMIT || graph.getNodeCount() > GraalOptions.MaximumDesiredSize * 3) {
                 throw new BailoutException("FullUnroll : Graph seems to grow out of proportion");
             }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Thu Jan 10 11:40:25 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Thu Jan 10 11:41:10 2013 +0100
@@ -358,10 +358,13 @@
                 PhiNode oldPhi = (PhiNode) oldMerge.usages().first();
                 PhiNode newPhi = graph().add(new PhiNode(oldPhi.stamp(), newMerge));
 
+                double probability = 0.0;
                 for (EndNode end : ends) {
                     newPhi.addInput(phiValues.get(end));
                     newMerge.addForwardEnd(end);
+                    probability += end.probability();
                 }
+                newMerge.setProbability(probability);
 
                 FrameState stateAfter = oldMerge.stateAfter();
                 if (stateAfter != null) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java	Thu Jan 10 11:40:25 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java	Thu Jan 10 11:41:10 2013 +0100
@@ -65,6 +65,33 @@
 
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
+
+        if (source.isConstant()) {
+            Constant sourceConstant = source.asConstant();
+            switch (sourceKind) {
+                case Boolean:
+                    return ConstantNode.forObject(Boolean.valueOf(sourceConstant.asBoolean()), tool.runtime(), graph());
+                case Byte:
+                    return ConstantNode.forObject(Byte.valueOf((byte) sourceConstant.asInt()), tool.runtime(), graph());
+                case Char:
+                    return ConstantNode.forObject(Character.valueOf((char) sourceConstant.asInt()), tool.runtime(), graph());
+                case Short:
+                    return ConstantNode.forObject(Short.valueOf((short) sourceConstant.asInt()), tool.runtime(), graph());
+                case Int:
+                    return ConstantNode.forObject(Integer.valueOf(sourceConstant.asInt()), tool.runtime(), graph());
+                case Long:
+                    return ConstantNode.forObject(Long.valueOf(sourceConstant.asLong()), tool.runtime(), graph());
+                case Float:
+                    return ConstantNode.forObject(Float.valueOf(sourceConstant.asFloat()), tool.runtime(), graph());
+                case Double:
+                    return ConstantNode.forObject(Double.valueOf(sourceConstant.asDouble()), tool.runtime(), graph());
+                default:
+                    assert false : "Unexpected source kind for boxing";
+                    break;
+
+            }
+        }
+
         for (Node usage : usages()) {
             if (usage != stateAfter()) {
                 return this;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java	Thu Jan 10 11:40:25 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java	Thu Jan 10 11:41:10 2013 +0100
@@ -148,4 +148,13 @@
         }
         return targetMethod().getName();
     }
+
+    public static MethodCallTargetNode find(StructuredGraph graph, ResolvedJavaMethod method) {
+        for (MethodCallTargetNode target : graph.getNodes(MethodCallTargetNode.class)) {
+            if (target.targetMethod == method) {
+                return target;
+            }
+        }
+        return null;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Thu Jan 10 11:40:25 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Thu Jan 10 11:41:10 2013 +0100
@@ -186,30 +186,67 @@
     /**
      * Gets an approximate source code location for a node if possible.
      *
-     * @return a file name and source line number in stack trace format (e.g. "String.java:32")
-     *          if an approximate source location is found, null otherwise
+     * @return the StackTraceElements if an approximate source location is found, null otherwise
      */
-    public static String approxSourceLocation(Node node) {
+    public static StackTraceElement[] approxSourceStackTraceElement(Node node) {
+        ArrayList<StackTraceElement> elements = new ArrayList<>();
         Node n = node;
         while (n != null) {
             if (n instanceof MethodCallTargetNode) {
+                elements.add(((MethodCallTargetNode) n).targetMethod().asStackTraceElement(-1));
                 n = ((MethodCallTargetNode) n).invoke().node();
             }
 
             if (n instanceof StateSplit) {
-                FrameState stateAfter = ((StateSplit) n).stateAfter();
-                if (stateAfter != null) {
-                    ResolvedJavaMethod method = stateAfter.method();
+                FrameState state = ((StateSplit) n).stateAfter();
+                while (state != null) {
+                    ResolvedJavaMethod method = state.method();
                     if (method != null) {
-                        StackTraceElement stackTraceElement = method.asStackTraceElement(stateAfter.bci);
-                        if (stackTraceElement.getFileName() != null && stackTraceElement.getLineNumber() >= 0) {
-                            return stackTraceElement.getFileName() + ":" + stackTraceElement.getLineNumber();
-                        }
+                        elements.add(method.asStackTraceElement(state.bci - 1));
                     }
+                    state = state.outerFrameState();
                 }
+                break;
             }
             n = n.predecessor();
         }
+        return elements.toArray(new StackTraceElement[elements.size()]);
+    }
+
+
+    /**
+     * Gets an approximate source code location for a node, encoded as an exception, if possible.
+     *
+     * @return the exception with the location
+     */
+    public static RuntimeException approxSourceException(Node node, Throwable cause) {
+        final StackTraceElement[] elements = approxSourceStackTraceElement(node);
+        @SuppressWarnings("serial")
+        RuntimeException exception = new RuntimeException(cause.getMessage(), cause) {
+
+            @Override
+            public synchronized Throwable fillInStackTrace() {
+                setStackTrace(elements);
+                return this;
+            }
+        };
+        return exception;
+    }
+
+    /**
+     * Gets an approximate source code location for a node if possible.
+     *
+     * @return a file name and source line number in stack trace format (e.g. "String.java:32") if an approximate source
+     *         location is found, null otherwise
+     */
+    public static String approxSourceLocation(Node node) {
+        StackTraceElement[] stackTraceElements = approxSourceStackTraceElement(node);
+        if (stackTraceElements != null && stackTraceElements.length > 0) {
+            StackTraceElement top = stackTraceElements[0];
+            if (top.getFileName() != null && top.getLineNumber() >= 0) {
+                return top.getFileName() + ":" + top.getLineNumber();
+            }
+        }
         return null;
     }
 
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Thu Jan 10 11:40:25 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Thu Jan 10 11:41:10 2013 +0100
@@ -50,14 +50,19 @@
     private final TargetDescription target;
     private final Assumptions assumptions;
     private final MetaAccessProvider runtime;
+    private final CustomCanonicalizer customCanonicalizer;
     private final Iterable<Node> initWorkingSet;
 
     private NodeWorkList workList;
     private Tool tool;
     private List<Node> snapshotTemp;
 
+    public interface CustomCanonicalizer {
+        ValueNode canonicalize(Node node);
+    }
+
     public CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions) {
-        this(target, runtime, assumptions, null, 0);
+        this(target, runtime, assumptions, null, 0, null);
     }
 
     /**
@@ -65,24 +70,26 @@
      * @param runtime
      * @param assumptions
      * @param workingSet the initial working set of nodes on which the canonicalizer works, should be an auto-grow node bitmap
+     * @param customCanonicalizer
      */
-    public CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions, Iterable<Node> workingSet) {
-        this(target, runtime, assumptions, workingSet, 0);
+    public CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions, Iterable<Node> workingSet, CustomCanonicalizer customCanonicalizer) {
+        this(target, runtime, assumptions, workingSet, 0, customCanonicalizer);
     }
 
     /**
      * @param newNodesMark only the {@linkplain Graph#getNewNodes(int) new nodes} specified by
      *            this mark are processed otherwise all nodes in the graph are processed
      */
-    public CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions, int newNodesMark) {
-        this(target, runtime, assumptions, null, newNodesMark);
+    public CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions, int newNodesMark, CustomCanonicalizer customCanonicalizer) {
+        this(target, runtime, assumptions, null, newNodesMark, customCanonicalizer);
     }
 
-    public CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions, Iterable<Node> workingSet, int newNodesMark) {
+    public CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions, Iterable<Node> workingSet, int newNodesMark, CustomCanonicalizer customCanonicalizer) {
         this.newNodesMark = newNodesMark;
         this.target = target;
         this.assumptions = assumptions;
         this.runtime = runtime;
+        this.customCanonicalizer = customCanonicalizer;
         this.initWorkingSet = workingSet;
         this.snapshotTemp = new ArrayList<>();
     }
@@ -127,7 +134,7 @@
             int mark = graph.getMark();
             if (!tryKillUnused(node)) {
                 node.inputs().filter(GraphUtil.isFloatingNode()).snapshotTo(snapshotTemp);
-                if (!tryCanonicalize(node, graph, tool)) {
+                if (!tryCanonicalize(node, graph)) {
                     tryInferStamp(node, graph);
                 } else {
                     for (Node in : snapshotTemp) {
@@ -168,7 +175,19 @@
         return false;
     }
 
-    public static boolean tryCanonicalize(final Node node, final StructuredGraph graph, final SimplifierTool tool) {
+    public boolean tryCanonicalize(final Node node, final StructuredGraph graph) {
+        boolean result = baseTryCanonicalize(node, graph);
+        if (!result && customCanonicalizer != null) {
+            ValueNode canonical = customCanonicalizer.canonicalize(node);
+            if (canonical == node && customCanonicalizer != null) {
+                canonical = customCanonicalizer.canonicalize(node);
+            }
+            result = performReplacement(node, graph, canonical);
+        }
+        return result;
+    }
+
+    public boolean baseTryCanonicalize(final Node node, final StructuredGraph graph) {
         if (node instanceof Canonicalizable) {
             assert !(node instanceof Simplifiable);
             METRIC_CANONICALIZATION_CONSIDERED_NODES.increment();
@@ -187,52 +206,9 @@
 //                          Fixed-connected|   2    |        X        |       6       |
 //                                         --------------------------------------------
 //       X: must not happen (checked with assertions)
-                    if (canonical == node) {
-                        Debug.log("Canonicalizer: work on %s", node);
-                        return false;
-                    } else {
-                        Debug.log("Canonicalizer: replacing %s with %s", node, canonical);
-                        METRIC_CANONICALIZED_NODES.increment();
-                        if (node instanceof FloatingNode) {
-                            if (canonical == null) {
-                                // case 1
-                                graph.removeFloating((FloatingNode) node);
-                            } else {
-                                // case 2
-                                assert !(canonical instanceof FixedNode) || (canonical.predecessor() != null || canonical instanceof StartNode || canonical instanceof MergeNode) : node + " -> " + canonical +
-                                                " : replacement should be floating or fixed and connected";
-                                graph.replaceFloating((FloatingNode) node, canonical);
-                            }
-                        } else {
-                            assert node instanceof FixedWithNextNode && node.predecessor() != null : node + " -> " + canonical + " : node should be fixed & connected (" + node.predecessor() + ")";
-                            FixedWithNextNode fixedWithNext = (FixedWithNextNode) node;
+
 
-                            // When removing a fixed node, new canonicalization opportunities for its successor may arise
-                            assert fixedWithNext.next() != null;
-                            tool.addToWorkList(fixedWithNext.next());
-
-                            if (canonical == null) {
-                                // case 3
-                                graph.removeFixed(fixedWithNext);
-                            } else if (canonical instanceof FloatingNode) {
-                                // case 4
-                                graph.replaceFixedWithFloating(fixedWithNext, (FloatingNode) canonical);
-                            } else {
-                                assert canonical instanceof FixedNode;
-                                if (canonical.predecessor() == null) {
-                                    assert !canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " shouldn't have successors";
-                                    // case 5
-                                    graph.replaceFixedWithFixed(fixedWithNext, (FixedWithNextNode) canonical);
-                                } else {
-                                    assert canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " should have successors";
-                                    // case 6
-                                    node.replaceAtUsages(canonical);
-                                    graph.removeFixed(fixedWithNext);
-                                }
-                            }
-                        }
-                        return true;
-                    }
+                    return performReplacement(node, graph, canonical);
                 }
             });
         } else if (node instanceof Simplifiable) {
@@ -247,6 +223,55 @@
         return node.isDeleted();
     }
 
+    private boolean performReplacement(final Node node, final StructuredGraph graph, ValueNode canonical) {
+        if (canonical == node) {
+            Debug.log("Canonicalizer: work on %s", node);
+            return false;
+        } else {
+            Debug.log("Canonicalizer: replacing %s with %s", node, canonical);
+            METRIC_CANONICALIZED_NODES.increment();
+            if (node instanceof FloatingNode) {
+                if (canonical == null) {
+                    // case 1
+                    graph.removeFloating((FloatingNode) node);
+                } else {
+                    // case 2
+                    assert !(canonical instanceof FixedNode) || (canonical.predecessor() != null || canonical instanceof StartNode || canonical instanceof MergeNode) : node + " -> " + canonical +
+                                    " : replacement should be floating or fixed and connected";
+                    graph.replaceFloating((FloatingNode) node, canonical);
+                }
+            } else {
+                assert node instanceof FixedWithNextNode && node.predecessor() != null : node + " -> " + canonical + " : node should be fixed & connected (" + node.predecessor() + ")";
+                FixedWithNextNode fixedWithNext = (FixedWithNextNode) node;
+
+                // When removing a fixed node, new canonicalization opportunities for its successor may arise
+                assert fixedWithNext.next() != null;
+                tool.addToWorkList(fixedWithNext.next());
+
+                if (canonical == null) {
+                    // case 3
+                    graph.removeFixed(fixedWithNext);
+                } else if (canonical instanceof FloatingNode) {
+                    // case 4
+                    graph.replaceFixedWithFloating(fixedWithNext, (FloatingNode) canonical);
+                } else {
+                    assert canonical instanceof FixedNode;
+                    if (canonical.predecessor() == null) {
+                        assert !canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " shouldn't have successors";
+                        // case 5
+                        graph.replaceFixedWithFixed(fixedWithNext, (FixedWithNextNode) canonical);
+                    } else {
+                        assert canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " should have successors";
+                        // case 6
+                        node.replaceAtUsages(canonical);
+                        graph.removeFixed(fixedWithNext);
+                    }
+                }
+            }
+            return true;
+        }
+    }
+
     /**
      * Calls {@link ValueNode#inferStamp()} on the node and, if it returns true (which means that the stamp has
      * changed), re-queues the node's usages . If the stamp has changed then this method also checks if the stamp
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Thu Jan 10 11:40:25 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Thu Jan 10 11:41:10 2013 +0100
@@ -32,11 +32,9 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.*;
-import com.oracle.graal.phases.PhasePlan.PhasePosition;
-import com.oracle.graal.phases.common.InliningUtil.InlineInfo;
-import com.oracle.graal.phases.common.InliningUtil.InliningCallback;
-import com.oracle.graal.phases.common.InliningUtil.InliningPolicy;
-import com.oracle.graal.phases.common.InliningUtil.WeightComputationPolicy;
+import com.oracle.graal.phases.PhasePlan.*;
+import com.oracle.graal.phases.common.CanonicalizerPhase.CustomCanonicalizer;
+import com.oracle.graal.phases.common.InliningUtil.*;
 
 public class InliningPhase extends Phase implements InliningCallback {
     /*
@@ -52,6 +50,7 @@
     private final Assumptions assumptions;
     private final GraphCache cache;
     private final InliningPolicy inliningPolicy;
+    private CustomCanonicalizer customCanonicalizer;
 
     // Metrics
     private static final DebugMetric metricInliningPerformed = Debug.metric("InliningPerformed");
@@ -63,6 +62,10 @@
         this(target, runtime, assumptions, cache, plan, createInliningPolicy(assumptions, optimisticOpts, hints));
     }
 
+    public void setCustomCanonicalizer(CustomCanonicalizer customCanonicalizer) {
+        this.customCanonicalizer = customCanonicalizer;
+    }
+
     public InliningPhase(TargetDescription target, GraalCodeCacheProvider runtime, Assumptions assumptions, GraphCache cache, PhasePlan plan, InliningPolicy inliningPolicy) {
         this.target = target;
         this.runtime = runtime;
@@ -90,7 +93,7 @@
                         Debug.dump(graph, "after %s", candidate);
                         Iterable<Node> newNodes = graph.getNewNodes(mark);
                         if (GraalOptions.OptCanonicalizer) {
-                            new CanonicalizerPhase(target, runtime, assumptions, invokeUsages, mark).apply(graph);
+                            new CanonicalizerPhase(target, runtime, assumptions, invokeUsages, mark, customCanonicalizer).apply(graph);
                         }
                         metricInliningPerformed.increment();
 
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Thu Jan 10 11:40:25 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Thu Jan 10 11:41:10 2013 +0100
@@ -886,7 +886,7 @@
      * @param inlineGraph the graph that the invoke will be replaced with
      * @param receiverNullCheck true if a null check needs to be generated for non-static inlinings, false if no such check is required
      */
-    public static void inline(Invoke invoke, StructuredGraph inlineGraph, boolean receiverNullCheck) {
+    public static Map<Node, Node> inline(Invoke invoke, StructuredGraph inlineGraph, boolean receiverNullCheck) {
         NodeInputList<ValueNode> parameters = invoke.callTarget().arguments();
         StructuredGraph graph = (StructuredGraph) invoke.node().graph();
 
@@ -915,7 +915,7 @@
                 }
             }
         }
-        replacements.put(entryPointNode, BeginNode.prevBegin(invoke.node())); // ensure proper anchoring of things that where anchored to the StartNode
+        replacements.put(entryPointNode, BeginNode.prevBegin(invoke.node())); // ensure proper anchoring of things that were anchored to the StartNode
 
         assert invoke.node().successors().first() != null : invoke;
         assert invoke.node().predecessor() != null;
@@ -1018,6 +1018,8 @@
 
         invoke.node().replaceAtUsages(null);
         GraphUtil.killCFG(invoke.node());
+
+        return duplicates;
     }
 
     public static void receiverNullCheck(Invoke invoke) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java	Thu Jan 10 11:40:25 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java	Thu Jan 10 11:41:10 2013 +0100
@@ -55,7 +55,7 @@
             if (canonicalizationRoots.isEmpty()) {
                 break;
             }
-            new CanonicalizerPhase(target, runtime, assumptions, canonicalizationRoots).apply(graph);
+            new CanonicalizerPhase(target, runtime, assumptions, canonicalizationRoots, null).apply(graph);
             canonicalizationRoots.clear();
         }
     }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Thu Jan 10 11:40:25 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Thu Jan 10 11:41:10 2013 +0100
@@ -132,7 +132,7 @@
             deferred = false;
             processBlock(schedule.getCFG().getStartBlock(), graph.createNodeBitMap(), null, schedule, processed);
             Debug.dump(graph, "Lowering iteration %d", i++);
-            new CanonicalizerPhase(null, runtime, assumptions, mark).apply(graph);
+            new CanonicalizerPhase(null, runtime, assumptions, mark, null).apply(graph);
 
             if (!deferred && !containsLowerable(graph.getNewNodes(mark))) {
                 // No new lowerable nodes - done!
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Thu Jan 10 11:40:25 2013 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Thu Jan 10 11:41:10 2013 +0100
@@ -121,6 +121,7 @@
 
     // Debug settings:
     public static boolean Debug                              = true;
+    public static boolean DebugSnippets                      = false;
     public static boolean PerThreadDebugValues               = ____;
     public static boolean SummarizeDebugValues               = ____;
     public static boolean SummarizePerPhase                  = ____;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DebugEnvironment.java	Thu Jan 10 11:41:10 2013 +0100
@@ -0,0 +1,48 @@
+/*
+ * 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.printer;
+
+import java.io.*;
+import java.util.*;
+
+import com.oracle.graal.compiler.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.phases.*;
+
+
+public class DebugEnvironment {
+
+    public static void initialize(PrintStream log) {
+        Debug.enable();
+        List<DebugDumpHandler> dumpHandlers = new ArrayList<>();
+        dumpHandlers.add(new GraphPrinterDumpHandler());
+        if (GraalOptions.PrintCFG) {
+            if (GraalOptions.PrintBinaryGraphs) {
+                TTY.println("CFG dumping slows down PrintBinaryGraphs: use -G:-PrintCFG to disable it");
+            }
+            dumpHandlers.add(new CFGPrinterObserver());
+        }
+        GraalDebugConfig hotspotDebugConfig = new GraalDebugConfig(GraalOptions.Log, GraalOptions.Meter, GraalOptions.Time, GraalOptions.Dump, GraalOptions.MethodFilter, log, dumpHandlers);
+        Debug.setConfig(hotspotDebugConfig);
+    }
+}
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java	Thu Jan 10 11:40:25 2013 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java	Thu Jan 10 11:41:10 2013 +0100
@@ -282,7 +282,7 @@
             new SnippetIntrinsificationPhase(runtime, new BoxingMethodPool(runtime), false).apply(snippetCopy);
             new WordTypeRewriterPhase(runtime, target.wordKind).apply(snippetCopy);
 
-            new CanonicalizerPhase(null, runtime, assumptions, 0).apply(snippetCopy);
+            new CanonicalizerPhase(null, runtime, assumptions, 0, null).apply(snippetCopy);
         }
 
         // Gather the template parameters
@@ -340,7 +340,7 @@
                     LoopEx loop = new LoopsData(snippetCopy).loop(loopBegin);
                     int mark = snippetCopy.getMark();
                     LoopTransformations.fullUnroll(loop, runtime, null);
-                    new CanonicalizerPhase(null, runtime, assumptions, mark).apply(snippetCopy);
+                    new CanonicalizerPhase(null, runtime, assumptions, mark, null).apply(snippetCopy);
                 }
                 FixedNode explodeLoopNext = explodeLoop.next();
                 explodeLoop.clearSuccessors();
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java	Thu Jan 10 11:40:25 2013 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java	Thu Jan 10 11:41:10 2013 +0100
@@ -33,6 +33,7 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.common.CanonicalizerPhase.*;
 import com.oracle.graal.phases.graph.*;
 import com.oracle.graal.phases.schedule.*;
 import com.oracle.graal.virtual.phases.ea.EffectList.Effect;
@@ -42,6 +43,7 @@
     private final TargetDescription target;
     private final MetaAccessProvider runtime;
     private final Assumptions assumptions;
+    private CustomCanonicalizer customCanonicalizer;
     private final boolean iterative;
 
     public PartialEscapeAnalysisPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions, boolean iterative) {
@@ -51,6 +53,10 @@
         this.iterative = iterative;
     }
 
+    public void setCustomCanonicalizer(CustomCanonicalizer customCanonicalizer) {
+        this.customCanonicalizer = customCanonicalizer;
+    }
+
     public static final void trace(String format, Object... obj) {
         if (GraalOptions.TraceEscapeAnalysis) {
             Debug.log(format, obj);
@@ -108,7 +114,7 @@
                         return false;
                     }
                     if (GraalOptions.OptCanonicalizer) {
-                        new CanonicalizerPhase(target, runtime, assumptions).apply(graph);
+                        new CanonicalizerPhase(target, runtime, assumptions, null, customCanonicalizer).apply(graph);
                     }
                     return true;
                 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallTarget.java	Thu Jan 10 11:40:25 2013 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallTarget.java	Thu Jan 10 11:41:10 2013 +0100
@@ -26,12 +26,12 @@
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
 
-final class DefaultCallTarget extends CallTarget {
+public class DefaultCallTarget extends CallTarget {
 
     protected final RootNode rootNode;
     protected final FrameDescriptor frameDescriptor;
 
-    DefaultCallTarget(RootNode function, FrameDescriptor frameDescriptor) {
+    protected DefaultCallTarget(RootNode function, FrameDescriptor frameDescriptor) {
         this.rootNode = function;
         this.frameDescriptor = frameDescriptor;
     }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultVirtualFrame.java	Thu Jan 10 11:40:25 2013 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultVirtualFrame.java	Thu Jan 10 11:41:10 2013 +0100
@@ -27,7 +27,7 @@
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.frame.*;
 
-final class DefaultVirtualFrame implements VirtualFrame {
+public final class DefaultVirtualFrame implements VirtualFrame {
 
     private static final Object UNDEFINED_OBJECT = null;
     private static final Boolean UNDEFINED_BOOLEAN = false;
@@ -43,7 +43,7 @@
     protected Object[] locals;
     protected Class[] tags;
 
-    DefaultVirtualFrame(FrameDescriptor descriptor, PackedFrame caller, Arguments arguments) {
+    public DefaultVirtualFrame(FrameDescriptor descriptor, PackedFrame caller, Arguments arguments) {
         this.descriptor = descriptor;
         this.caller = caller;
         this.arguments = arguments;
--- a/graal/com.oracle.truffle.codegen.processor/src/META-INF/services/javax.annotation.processing.Processor	Thu Jan 10 11:40:25 2013 +0100
+++ b/graal/com.oracle.truffle.codegen.processor/src/META-INF/services/javax.annotation.processing.Processor	Thu Jan 10 11:41:10 2013 +0100
@@ -1,1 +1,1 @@
-com.oracle.truffle.codegen.processor.TruffleProcessor
\ No newline at end of file
+com.oracle.truffle.codegen.processor.TruffleProcessor
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.frame	Thu Jan 10 11:40:25 2013 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.frame	Thu Jan 10 11:41:10 2013 +0100
@@ -46,7 +46,7 @@
     public final Scanner scanner;
     public final Errors errors;
     private final NodeFactory factory;
-	-->declarations
+    -->declarations
     public Parser(Scanner scanner, NodeFactory factory) {
         this.scanner = scanner;
         this.factory = factory;
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Scanner.frame	Thu Jan 10 11:40:25 2013 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Scanner.frame	Thu Jan 10 11:41:10 2013 +0100
@@ -403,7 +403,7 @@
             NextCh();
         }
     }
-	
+
 -->comments
 
     void CheckLiteral() {
@@ -418,7 +418,7 @@
     Token NextToken() {
         while (ch == ' ' || 
 -->scan1
-		) NextCh();
+        ) NextCh();
 -->scan2
         int recKind = noSym;
         int recEnd = pos;
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SimpleLanguage.atg	Thu Jan 10 11:40:25 2013 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SimpleLanguage.atg	Thu Jan 10 11:41:10 2013 +0100
@@ -28,7 +28,7 @@
 =
 Function 
 {
-	 Function
+    Function
 }
 .
 
@@ -86,7 +86,7 @@
 }
 ";"                                             (. result = factory.createPrint(expressions); .)
 .
-							
+
 ReturnStatement<out StatementNode result>
 =
 "return"
@@ -97,8 +97,8 @@
 =
 ValueExpression<out result>
 [
-    ("<" | ">" | "<=" | ">=" | "==" | "!=" )    (.	String op = t.val; .)
-    ValueExpression<out TypedNode right>        (.	result = factory.createBinary(op, result, right); .)
+    ("<" | ">" | "<=" | ">=" | "==" | "!=" )    (.  String op = t.val; .)
+    ValueExpression<out TypedNode right>        (.  result = factory.createBinary(op, result, right); .)
 ]
 .
 
--- a/mx/projects	Thu Jan 10 11:40:25 2013 +0100
+++ b/mx/projects	Thu Jan 10 11:41:10 2013 +0100
@@ -237,7 +237,7 @@
 # graal.compiler.test
 project@com.oracle.graal.compiler.test@subDir=graal
 project@com.oracle.graal.compiler.test@sourceDirs=src
-project@com.oracle.graal.compiler.test@dependencies=JUNIT,com.oracle.graal.compiler,com.oracle.graal.java,com.oracle.graal.api.runtime
+project@com.oracle.graal.compiler.test@dependencies=com.oracle.graal.api.runtime,com.oracle.graal.printer,JUNIT
 project@com.oracle.graal.compiler.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.compiler.test@javaCompliance=1.7
 
--- a/src/cpu/x86/vm/jniTypes_x86.hpp	Thu Jan 10 11:40:25 2013 +0100
+++ b/src/cpu/x86/vm/jniTypes_x86.hpp	Thu Jan 10 11:41:10 2013 +0100
@@ -128,11 +128,25 @@
   static inline jfloat  get_float (intptr_t *from) { return *(jfloat *) from; }
   static inline jdouble get_double(intptr_t *from) { return *(jdouble *)(from + _JNI_SLOT_OFFSET); }
 
-  static inline jint    get_int   (intptr_t *from, int& pos) { return get_int(from + pos++); }
-  static inline jlong   get_long  (intptr_t *from, int& pos) { return get_long(from + pos); pos += 2; }
-  static inline oop     get_obj   (intptr_t *from, int& pos) { return get_obj(from + pos++); }
-  static inline jfloat  get_float (intptr_t *from, int& pos) { return get_float(from + pos++); }
-  static inline jdouble get_double(intptr_t *from, int& pos) { return get_double(from + pos); pos += 2; }
+  static inline jint    get_int   (intptr_t *from, int& pos) {
+    return get_int(from + pos++);
+  }
+  static inline jlong   get_long  (intptr_t *from, int& pos) {
+    jlong result = get_long(from + pos);
+    pos += 2;
+    return result;
+  }
+  static inline oop     get_obj   (intptr_t *from, int& pos) {
+    return get_obj(from + pos++);
+  }
+  static inline jfloat  get_float (intptr_t *from, int& pos) {
+    return get_float(from + pos++);
+  }
+  static inline jdouble get_double(intptr_t *from, int& pos) {
+    jdouble result = get_double(from + pos);
+    pos += 2;
+    return result;
+  }
 #undef _JNI_SLOT_OFFSET
 };
 
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Thu Jan 10 11:40:25 2013 +0100
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Thu Jan 10 11:41:10 2013 +0100
@@ -938,6 +938,47 @@
   return JNIHandles::make_local(result());
 C2V_END
 
+C2V_ENTRY(jlongArray, getLineNumberTable, (JNIEnv *env, jobject, jobject hotspot_method))
+// XXX: Attention: it seEms that the line number table of a method just contains lines that are important, means that
+// empty lines are left out or lines that can't have a breakpoint on it; eg int a; or try {
+  Method* method = getMethodFromHotSpotMethod(JNIHandles::resolve(hotspot_method));
+  if(!method->has_linenumber_table()) {
+    return NULL;
+  }
+  u2 num_entries = 0;
+  CompressedLineNumberReadStream streamForSize(method->compressed_linenumber_table());
+  while (streamForSize.read_pair()) {
+    num_entries++;
+  }
+
+  CompressedLineNumberReadStream stream(method->compressed_linenumber_table());
+  jlongArray result = env->NewLongArray(2 * num_entries);
+
+  int i = 0;
+  jlong value;
+  while (stream.read_pair()) {
+    value = ((long) stream.bci());
+    env->SetLongArrayRegion(result,i,1,&value);
+    value = ((long) stream.line());
+    env->SetLongArrayRegion(result,i + 1,1,&value);
+    i += 2;
+  }
+
+  return result;
+C2V_END
+
+
+C2V_VMENTRY(jobject, getFileName, (JNIEnv *, jobject, jobject klass))
+  ResourceMark rm;
+  InstanceKlass* k = (InstanceKlass*) asKlass(HotSpotResolvedObjectType::metaspaceKlass(klass));
+  Symbol *s = k->source_file_name();
+  int length;
+  jchar *name = s->as_unicode(length);
+
+  Handle result = java_lang_String::create_from_unicode(name, length, CHECK_NULL);
+  return JNIHandles::make_local(result());
+
+C2V_END
 
 #define CC (char*)  /*cast a literal from (const char*)*/
 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(c2v_ ## f))
@@ -960,6 +1001,7 @@
 #define CLASS                 "Ljava/lang/Class;"
 #define STACK_TRACE_ELEMENT   "Ljava/lang/StackTraceElement;"
 #define HS_RESOLVED_TYPE      "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedObjectType;"
+#define HS_RESOLVED_JAVA_TYPE "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedJavaType;"
 #define HS_RESOLVED_METHOD    "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod;"
 #define HS_RESOLVED_FIELD     "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedJavaField;"
 #define HS_COMP_RESULT        "Lcom/oracle/graal/hotspot/HotSpotCompilationResult;"
@@ -1008,6 +1050,8 @@
   {CC"executeCompiledMethodVarargs",  CC"("METASPACE_METHOD NMETHOD "["OBJECT")"OBJECT,                 FN_PTR(executeCompiledMethodVarargs)},
   {CC"getDeoptedLeafGraphIds",        CC"()[J",                                                         FN_PTR(getDeoptedLeafGraphIds)},
   {CC"decodePC",                      CC"(J)"STRING,                                                    FN_PTR(decodePC)},
+  {CC"getLineNumberTable",            CC"("HS_RESOLVED_METHOD")[J",                                     FN_PTR(getLineNumberTable)},
+  {CC"getFileName",                   CC"("HS_RESOLVED_JAVA_TYPE")"STRING,                              FN_PTR(getFileName)},
 };
 
 int CompilerToVM_methods_count() {