changeset 13738:b9c5875e3a36

Merge.
author Doug Simon <doug.simon@oracle.com>
date Fri, 24 Jan 2014 00:33:56 +0100
parents 3424bc098ca0 (current diff) 64fa70319890 (diff)
children ac1e626432f9
files graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/debug/DebugNodes.java graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/MethodLocal.java graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyBreakAfterLineProbe.java graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyBreakAfterLocalProbe.java graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyBreakBeforeLineProbe.java graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyCallProbe.java graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyDebugManager.java graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyLineProbe.java graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyLocalProbe.java graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyProcAfterLineProbe.java graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyProcAfterLocalProbe.java graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyProcBeforeLineProbe.java graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/debug/DebugTests.java
diffstat 37 files changed, 378 insertions(+), 1909 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java	Wed Jan 22 18:46:38 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java	Fri Jan 24 00:33:56 2014 +0100
@@ -148,7 +148,7 @@
             }
 
             private boolean canOffloadToGPU(ResolvedJavaMethod method) {
-                return method.getName().contains("lambda$main$") & method.isSynthetic();
+                return method.getName().contains("lambda$") & method.isSynthetic();
             }
         };
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Wed Jan 22 18:46:38 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Fri Jan 24 00:33:56 2014 +0100
@@ -556,9 +556,8 @@
                 int id = allocateCompileTaskId(method, entryBCI);
                 HotSpotBackend backend = runtime.getHostBackend();
                 CompilationTask task = new CompilationTask(backend, method, entryBCI, id);
-                boolean isLambdaMethod = (method.getName().contains("lambda$main$") & method.isSynthetic());
 
-                if (blocking || isLambdaMethod) {
+                if (blocking) {
                     task.runCompilation(true);
                 } else {
                     try {
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/DebugManager.java	Wed Jan 22 18:46:38 2014 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/DebugManager.java	Fri Jan 24 00:33:56 2014 +0100
@@ -27,7 +27,7 @@
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.api.nodes.instrument.*;
-import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.api.nodes.instrument.InstrumentationProbeNode.ProbeChain;
 
 /**
  * Language-agnostic access to AST-based debugging support.
@@ -37,42 +37,29 @@
 public interface DebugManager {
 
     /**
-     * Gets a list of current breakpoints.
-     */
-    LineBreakpoint[] getBreakpoints();
-
-    /**
-     * Sets a breakpoint at a line-based location.
+     * Informs the {@link DebugManager} that the Guest Language runtime is starting to load a
+     * source. Care should be taken to ensure that under any circumstance there is always a
+     * following call to {@link #notifyFinishedLoading(Source)} with the same argument.
      */
-    LineBreakpoint setBreakpoint(SourceLineLocation lineLocation);
-
-    /**
-     * Sets a breakpoint at a line-based location with a boolean expression in the guest language to
-     * serve as a break condition.
-     */
-    LineBreakpoint setConditionalBreakpoint(SourceLineLocation lineLocation, String condition);
+    void notifyStartLoading(Source source);
 
     /**
-     * Sets a breakpoint at a line-based location that will remove itself when hit.
+     * Informs the {@link DebugManager} that the Guest Language runtime has finished loading a
+     * source. Care should be taken to ensure that under any circumstance there is always a prior
+     * call to {@link #notifyStartLoading(Source)} with the same argument.
      */
-    LineBreakpoint setOneShotBreakpoint(SourceLineLocation lineLocation);
-
-    /**
-     * Is there a line-based breakpoint set at a location?
-     */
-    boolean hasBreakpoint(SourceLineLocation lineLocation);
+    void notifyFinishedLoading(Source source);
 
     /**
-     * Removes a breakpoint at a line-based location.
+     * Return a reference to the (canonical) instrumentation site associated with a particular
+     * source code location; this site will have effect on any Truffle/AST implementation
+     * corresponding to the source location, even if the AST is copied multiple times.
      */
-    void removeBreakpoint(SourceLineLocation lineLocation);
+    ProbeChain getProbeChain(SourceSection sourceSection);
 
     /**
-     * Notification from Truffle execution that execution should halt in a debugging context.
-     */
-    /**
-     * Receives notification of a suspended execution context; execution resumes when this method
-     * returns.
+     * Informs the {@link DebugManager} that Truffle execution has halted; execution will resume
+     * when this method returns.
      * 
      * @param astNode a guest language AST node that represents the current execution site, assumed
      *            not to be any kind of {@link InstrumentationNode},
@@ -80,14 +67,4 @@
      */
     void haltedAt(Node astNode, MaterializedFrame frame);
 
-    /**
-     * Description of a line-based breakpoint.
-     */
-    interface LineBreakpoint {
-
-        SourceLineLocation getSourceLineLocation();
-
-        String getDebugStatus();
-    }
-
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/ExecutionContext.java	Wed Jan 22 18:46:38 2014 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/ExecutionContext.java	Fri Jan 24 00:33:56 2014 +0100
@@ -42,9 +42,4 @@
      */
     DebugManager getDebugManager();
 
-    /**
-     * Gets access to utilities for printing different aspects of a Truffle AST.
-     */
-    ASTPrinter getASTPrinter();
-
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultDebugManager.java	Fri Jan 24 00:33:56 2014 +0100
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2013, 2014, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.truffle.api.impl;
+
+import java.util.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.nodes.instrument.InstrumentationProbeNode.ProbeChain;
+import com.oracle.truffle.api.source.*;
+
+/**
+ * A minimal, language-agnostic implementation that tracks loaded sources, and keeps maps describing
+ * what locations in the source have instrumentation available.
+ */
+public class DefaultDebugManager implements DebugManager {
+
+    private final Set<Source> loadedSources = new HashSet<>();
+
+    private Source beingLoaded = null;
+
+    /**
+     * Map: SourceSection ==> probe chain associated with that source section in an AST.
+     */
+    private final Map<SourceSection, ProbeChain> srcToProbeChain = new HashMap<>();
+
+    /**
+     * Map: Source lines ==> probe chains associated with source sections starting on the line.
+     */
+    private final Map<SourceLineLocation, Set<ProbeChain>> lineToProbeChains = new HashMap<>();
+
+    private final ExecutionContext context;
+
+    public DefaultDebugManager(ExecutionContext context) {
+        this.context = context;
+    }
+
+    /**
+     * Gets the {@linkplain ProbeChain probe} associated with a particular {@link SourceSection
+     * source location}, creating a new one if needed. There should only be one probe associated
+     * with each {@linkplain SourceSection source location}.
+     */
+    public ProbeChain getProbeChain(SourceSection sourceSection) {
+        assert sourceSection != null;
+        assert sourceSection.getSource().equals(beingLoaded);
+
+        ProbeChain probeChain = srcToProbeChain.get(sourceSection);
+
+        if (probeChain != null) {
+            return probeChain;
+        }
+        probeChain = new ProbeChain(context, sourceSection, null);
+
+        // Register new ProbeChain by unique SourceSection
+        srcToProbeChain.put(sourceSection, probeChain);
+
+        // Register new ProbeChain by source line, there may be more than one
+        // Create line location for map key
+        final SourceLineLocation lineLocation = new SourceLineLocation(sourceSection.getSource(), sourceSection.getStartLine());
+
+        Set<ProbeChain> probeChains = lineToProbeChains.get(lineLocation);
+        if (probeChains == null) {
+            probeChains = new HashSet<>();
+            lineToProbeChains.put(lineLocation, probeChains);
+        }
+        probeChains.add(probeChain);
+
+        return probeChain;
+    }
+
+    public void notifyStartLoading(Source source) {
+        assert beingLoaded == null;
+        beingLoaded = source;
+    }
+
+    public void notifyFinishedLoading(Source source) {
+        assert source == beingLoaded;
+        loadedSources.add(source);
+        beingLoaded = null;
+    }
+
+    public void haltedAt(Node astNode, MaterializedFrame frame) {
+    }
+
+}
--- a/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/CoreMethodNodeManager.java	Wed Jan 22 18:46:38 2014 +0100
+++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/CoreMethodNodeManager.java	Fri Jan 24 00:33:56 2014 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This
+ * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. This
  * code is released under a tri EPL/GPL/LGPL license. You can use it,
  * redistribute it and/or modify it under the terms of the:
  *
@@ -17,7 +17,6 @@
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.ruby.nodes.*;
 import com.oracle.truffle.ruby.nodes.control.*;
-import com.oracle.truffle.ruby.nodes.debug.*;
 import com.oracle.truffle.ruby.nodes.methods.arguments.*;
 import com.oracle.truffle.ruby.nodes.objects.*;
 import com.oracle.truffle.ruby.runtime.*;
@@ -48,7 +47,6 @@
         getMethods(methods, ClassNodesFactory.getFactories());
         getMethods(methods, ContinuationNodesFactory.getFactories());
         getMethods(methods, ComparableNodesFactory.getFactories());
-        getMethods(methods, DebugNodesFactory.getFactories());
         getMethods(methods, DirNodesFactory.getFactories());
         getMethods(methods, ExceptionNodesFactory.getFactories());
         getMethods(methods, FalseClassNodesFactory.getFactories());
--- a/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/debug/DebugNodes.java	Wed Jan 22 18:46:38 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,191 +0,0 @@
-/*
- * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This
- * code is released under a tri EPL/GPL/LGPL license. You can use it,
- * redistribute it and/or modify it under the terms of the:
- *
- * Eclipse Public License version 1.0
- * GNU General Public License version 2
- * GNU Lesser General Public License version 2.1
- */
-package com.oracle.truffle.ruby.nodes.debug;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.ruby.nodes.call.*;
-import com.oracle.truffle.ruby.nodes.core.*;
-import com.oracle.truffle.ruby.runtime.*;
-import com.oracle.truffle.ruby.runtime.control.*;
-import com.oracle.truffle.ruby.runtime.core.*;
-import com.oracle.truffle.ruby.runtime.methods.*;
-
-@CoreClass(name = "Debug")
-public abstract class DebugNodes {
-
-    @CoreMethod(names = "break", isModuleMethod = true, needsSelf = false, needsBlock = true, appendCallNode = true, minArgs = 0, maxArgs = 3)
-    public abstract static class BreakNode extends CoreMethodNode {
-
-        public BreakNode(RubyContext context, SourceSection sourceSection) {
-            super(context, sourceSection);
-        }
-
-        public BreakNode(BreakNode prev) {
-            super(prev);
-        }
-
-        @Specialization(order = 1)
-        public NilPlaceholder debugBreak(VirtualFrame frame, Node callNode, @SuppressWarnings("unused") UndefinedPlaceholder undefined0, @SuppressWarnings("unused") UndefinedPlaceholder undefined1,
-                        @SuppressWarnings("unused") UndefinedPlaceholder block) {
-            final RubyContext context = getContext();
-            if (context.getConfiguration().getDebug()) {
-                Node realCallNode = callNode;
-                while (realCallNode != null && !(realCallNode instanceof CallNode)) {
-                    realCallNode = realCallNode.getParent();
-                }
-                context.getDebugManager().haltedAt(realCallNode, frame.materialize());
-            }
-            return NilPlaceholder.INSTANCE;
-        }
-
-        @Specialization(order = 2)
-        public NilPlaceholder debugBreak(RubyString fileName, int line, @SuppressWarnings("unused") Node callNode, @SuppressWarnings("unused") UndefinedPlaceholder block) {
-            final RubyContext context = getContext();
-            if (context.getConfiguration().getDebug()) {
-                final Source source = context.getSourceManager().get(fileName.toString());
-                final SourceLineLocation lineLocation = new SourceLineLocation(source, line);
-                context.getDebugManager().setBreakpoint(lineLocation);
-            }
-            return NilPlaceholder.INSTANCE;
-        }
-
-        @Specialization(order = 3)
-        public NilPlaceholder debugBreak(RubyString fileName, int line, @SuppressWarnings("unused") Node callNode, RubyProc block) {
-            final RubyContext context = getContext();
-            if (context.getConfiguration().getDebug()) {
-                final Source source = context.getSourceManager().get(fileName.toString());
-                final SourceLineLocation lineLocation = new SourceLineLocation(source, line);
-                context.getDebugManager().setLineProc(lineLocation, block);
-            }
-            return NilPlaceholder.INSTANCE;
-        }
-
-        @Specialization(order = 4)
-        public NilPlaceholder debugBreak(RubySymbol methodName, RubySymbol localName, @SuppressWarnings("unused") Node callNode, @SuppressWarnings("unused") UndefinedPlaceholder block) {
-            final RubyContext context = getContext();
-            if (context.getConfiguration().getDebug()) {
-                final RubyMethod method = context.getCoreLibrary().getMainObject().getLookupNode().lookupMethod(methodName.toString());
-                context.getDebugManager().setLocalBreak(method.getUniqueIdentifier(), localName.toString());
-            }
-            return NilPlaceholder.INSTANCE;
-        }
-
-        @Specialization(order = 5)
-        public NilPlaceholder debugBreak(RubySymbol methodName, RubySymbol localName, @SuppressWarnings("unused") Node callNode, RubyProc block) {
-            final RubyContext context = getContext();
-            if (context.getConfiguration().getDebug()) {
-                final RubyMethod method = context.getCoreLibrary().getMainObject().getLookupNode().lookupMethod(methodName.toString());
-                context.getDebugManager().setLocalProc(method.getUniqueIdentifier(), localName.toString(), block);
-            }
-            return NilPlaceholder.INSTANCE;
-        }
-
-    }
-
-    @CoreMethod(names = "continue", isModuleMethod = true, needsSelf = false, maxArgs = 0)
-    public abstract static class ContinueNode extends CoreMethodNode {
-
-        public ContinueNode(RubyContext context, SourceSection sourceSection) {
-            super(context, sourceSection);
-        }
-
-        public ContinueNode(ContinueNode prev) {
-            super(prev);
-        }
-
-        @Specialization
-        public Object debugContinue() {
-            if (getContext().getConfiguration().getDebug()) {
-                throw new BreakShellException();
-            }
-            return NilPlaceholder.INSTANCE;
-        }
-
-    }
-
-    @CoreMethod(names = "enabled?", isModuleMethod = true, needsSelf = false, maxArgs = 0)
-    public abstract static class EnabledNode extends CoreMethodNode {
-
-        public EnabledNode(RubyContext context, SourceSection sourceSection) {
-            super(context, sourceSection);
-        }
-
-        public EnabledNode(ContinueNode prev) {
-            super(prev);
-        }
-
-        @Specialization
-        public boolean enabled() {
-            return getContext().getConfiguration().getDebug();
-        }
-
-    }
-
-    @CoreMethod(names = "where", isModuleMethod = true, needsSelf = false, appendCallNode = true, minArgs = 1, maxArgs = 1)
-    public abstract static class WhereNode extends CoreMethodNode {
-
-        public WhereNode(RubyContext context, SourceSection sourceSection) {
-            super(context, sourceSection);
-        }
-
-        public WhereNode(WhereNode prev) {
-            super(prev);
-        }
-
-        @Specialization
-        public NilPlaceholder where(Node callNode) {
-            final RubyContext context = getContext();
-            if (context.getConfiguration().getDebug()) {
-                context.getConfiguration().getStandardOut().println(callNode.getSourceSection());
-            }
-            return NilPlaceholder.INSTANCE;
-        }
-
-    }
-
-    @CoreMethod(names = "remove", isModuleMethod = true, needsSelf = false, needsBlock = true, minArgs = 2, maxArgs = 2)
-    public abstract static class RemoveNode extends CoreMethodNode {
-
-        public RemoveNode(RubyContext context, SourceSection sourceSection) {
-            super(context, sourceSection);
-        }
-
-        public RemoveNode(RemoveNode prev) {
-            super(prev);
-        }
-
-        @Specialization
-        public NilPlaceholder debugRemove(RubyString fileName, int line) {
-            final RubyContext context = getContext();
-            if (context.getConfiguration().getDebug()) {
-                final Source source = context.getSourceManager().get(fileName.toString());
-                final SourceLineLocation lineLocation = new SourceLineLocation(source, line);
-                context.getDebugManager().removeBreakpoint(lineLocation);
-            }
-            return NilPlaceholder.INSTANCE;
-        }
-
-        @Specialization
-        public NilPlaceholder debugRemove(RubySymbol methodName, RubySymbol localName) {
-            final RubyContext context = getContext();
-            if (context.getConfiguration().getDebug()) {
-                final RubyMethod method = context.getCoreLibrary().getMainObject().getLookupNode().lookupMethod(methodName.toString());
-                context.getDebugManager().removeLocalProbe(method.getUniqueIdentifier(), localName.toString());
-            }
-            return NilPlaceholder.INSTANCE;
-        }
-
-    }
-
-}
--- a/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/debug/RubyProxyNode.java	Wed Jan 22 18:46:38 2014 +0100
+++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/debug/RubyProxyNode.java	Fri Jan 24 00:33:56 2014 +0100
@@ -19,6 +19,7 @@
 import com.oracle.truffle.api.nodes.instrument.InstrumentationProbeNode.ProbeChain;
 import com.oracle.truffle.ruby.nodes.*;
 import com.oracle.truffle.ruby.runtime.*;
+import com.oracle.truffle.ruby.runtime.control.*;
 import com.oracle.truffle.ruby.runtime.core.*;
 import com.oracle.truffle.ruby.runtime.core.array.*;
 
@@ -69,6 +70,8 @@
         try {
             result = child.execute(frame);
             probeChain.notifyLeave(child, frame, result);
+        } catch (BreakShellException e) {
+            throw (e);
         } catch (Exception e) {
             probeChain.notifyLeaveExceptional(child, frame, e);
             throw (e);
@@ -86,6 +89,8 @@
         try {
             result = child.executeArray(frame);
             probeChain.notifyLeave(child, frame, result);
+        } catch (BreakShellException e) {
+            throw (e);
         } catch (Exception e) {
             probeChain.notifyLeaveExceptional(child, frame, e);
             throw (e);
@@ -103,6 +108,8 @@
         try {
             result = child.executeBignum(frame);
             probeChain.notifyLeave(child, frame, result);
+        } catch (BreakShellException e) {
+            throw (e);
         } catch (Exception e) {
             probeChain.notifyLeaveExceptional(child, frame, e);
             throw (e);
@@ -120,6 +127,8 @@
         try {
             result = child.executeBoolean(frame);
             probeChain.notifyLeave(child, frame, result);
+        } catch (BreakShellException e) {
+            throw (e);
         } catch (Exception e) {
             probeChain.notifyLeaveExceptional(child, frame, e);
             throw (e);
@@ -142,6 +151,8 @@
         try {
             result = child.executeFixnum(frame);
             probeChain.notifyLeave(child, frame, result);
+        } catch (BreakShellException e) {
+            throw (e);
         } catch (Exception e) {
             probeChain.notifyLeaveExceptional(child, frame, e);
             throw (e);
@@ -159,6 +170,8 @@
         try {
             result = child.executeFloat(frame);
             probeChain.notifyLeave(child, frame, result);
+        } catch (BreakShellException e) {
+            throw (e);
         } catch (Exception e) {
             probeChain.notifyLeaveExceptional(child, frame, e);
             throw (e);
@@ -176,6 +189,8 @@
         try {
             result = child.executeString(frame);
             probeChain.notifyLeave(child, frame, result);
+        } catch (BreakShellException e) {
+            throw (e);
         } catch (Exception e) {
             probeChain.notifyLeaveExceptional(child, frame, e);
             throw (e);
@@ -191,6 +206,8 @@
         try {
             child.executeVoid(frame);
             probeChain.notifyLeave(child, frame);
+        } catch (BreakShellException e) {
+            throw (e);
         } catch (Exception e) {
             probeChain.notifyLeaveExceptional(child, frame, e);
             throw (e);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.ruby.parser/src/com/oracle/truffle/ruby/parser/DefaultRubyNodeInstrumenter.java	Fri Jan 24 00:33:56 2014 +0100
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. This
+ * code is released under a tri EPL/GPL/LGPL license. You can use it,
+ * redistribute it and/or modify it under the terms of the:
+ *
+ * Eclipse Public License version 1.0
+ * GNU General Public License version 2
+ * GNU Lesser General Public License version 2.1
+ */
+package com.oracle.truffle.ruby.parser;
+
+import com.oracle.truffle.api.nodes.instrument.*;
+import com.oracle.truffle.ruby.nodes.*;
+import com.oracle.truffle.ruby.nodes.debug.*;
+import com.oracle.truffle.ruby.runtime.*;
+import com.oracle.truffle.ruby.runtime.debug.*;
+import com.oracle.truffle.ruby.runtime.methods.*;
+
+/**
+ * Utility for instrumenting Ruby AST nodes to support the language's built-in <A
+ * href="http://www.ruby-doc.org/core-2.0.0/Kernel.html#method-i-set_trace_func">tracing
+ * facility</A>. It ignores nodes other than {@linkplain NodePhylum#STATEMENT statements}.
+ */
+final class DefaultRubyNodeInstrumenter implements RubyNodeInstrumenter {
+
+    public DefaultRubyNodeInstrumenter() {
+    }
+
+    public RubyNode instrumentAsStatement(RubyNode rubyNode) {
+        assert rubyNode != null;
+        assert !(rubyNode instanceof RubyProxyNode);
+        final RubyContext context = rubyNode.getContext();
+        if (context.getConfiguration().getTrace()) {
+            final RubyProxyNode proxy = new RubyProxyNode(context, rubyNode);
+            proxy.markAs(NodePhylum.STATEMENT);
+            proxy.getProbeChain().appendProbe(new RubyTraceProbe(context));
+            return proxy;
+        }
+        return rubyNode;
+    }
+
+    public RubyNode instrumentAsCall(RubyNode node, String callName) {
+        return node;
+    }
+
+    public RubyNode instrumentAsLocalAssignment(RubyNode node, UniqueMethodIdentifier methodIdentifier, String localName) {
+        return node;
+    }
+
+}
--- a/graal/com.oracle.truffle.ruby.parser/src/com/oracle/truffle/ruby/parser/JRubyParser.java	Wed Jan 22 18:46:38 2014 +0100
+++ b/graal/com.oracle.truffle.ruby.parser/src/com/oracle/truffle/ruby/parser/JRubyParser.java	Fri Jan 24 00:33:56 2014 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This
+ * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. This
  * code is released under a tri EPL/GPL/LGPL license. You can use it,
  * redistribute it and/or modify it under the terms of the:
  *
@@ -21,15 +21,26 @@
 import com.oracle.truffle.ruby.runtime.*;
 import com.oracle.truffle.ruby.runtime.control.*;
 import com.oracle.truffle.ruby.runtime.core.*;
-import com.oracle.truffle.ruby.runtime.debug.*;
 import com.oracle.truffle.ruby.runtime.methods.*;
 
 public class JRubyParser implements RubyParser {
 
     private long nextReturnID = 0;
 
+    private final RubyNodeInstrumenter instrumenter;
+
+    public JRubyParser() {
+        this(new DefaultRubyNodeInstrumenter());
+    }
+
+    public JRubyParser(RubyNodeInstrumenter instrumenter) {
+        assert instrumenter != null;
+        this.instrumenter = instrumenter;
+    }
+
     @Override
     public RubyParserResult parse(RubyContext context, Source source, ParserContext parserContext, MaterializedFrame parentFrame) {
+
         // Set up the JRuby parser
 
         final org.jrubyparser.Parser parser = new org.jrubyparser.Parser();
@@ -100,7 +111,7 @@
 
         RubyNode truffleNode;
 
-        final RubyDebugManager debugManager = context.getDebugManager();
+        final DebugManager debugManager = context.getDebugManager();
         try {
             if (debugManager != null) {
                 debugManager.notifyStartLoading(source);
@@ -171,6 +182,10 @@
         return allocated;
     }
 
+    public RubyNodeInstrumenter getNodeInstrumenter() {
+        return instrumenter;
+    }
+
     private TranslatorEnvironment environmentForFrame(RubyContext context, MaterializedFrame frame) {
         if (frame == null) {
             return null;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.ruby.parser/src/com/oracle/truffle/ruby/parser/RubyNodeInstrumenter.java	Fri Jan 24 00:33:56 2014 +0100
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2014, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.truffle.ruby.parser;
+
+import com.oracle.truffle.api.nodes.instrument.*;
+import com.oracle.truffle.ruby.nodes.*;
+import com.oracle.truffle.ruby.runtime.methods.*;
+
+public interface RubyNodeInstrumenter {
+
+    /**
+     * Adds instrumentation support at a node that should be considered a member of
+     * {@link NodePhylum#STATEMENT}, possibly returning a new {@link InstrumentationProxyNode} that
+     * holds the original as its child.
+     */
+    RubyNode instrumentAsStatement(RubyNode node);
+
+    /**
+     * Adds instrumentation support at a node that should be considered a member of
+     * {@link NodePhylum#CALL}, possibly returning a new {@link InstrumentationProxyNode} that holds
+     * the original as its child.
+     */
+    RubyNode instrumentAsCall(RubyNode node, String callName);
+
+    /**
+     * Adds instrumentation support at a node that should be considered a member of
+     * {@link NodePhylum#ASSIGNMENT}, possibly returning a new {@link InstrumentationProxyNode} that
+     * holds the original as its child.
+     */
+    RubyNode instrumentAsLocalAssignment(RubyNode node, UniqueMethodIdentifier methodIdentifier, String localName);
+
+}
--- a/graal/com.oracle.truffle.ruby.parser/src/com/oracle/truffle/ruby/parser/Translator.java	Wed Jan 22 18:46:38 2014 +0100
+++ b/graal/com.oracle.truffle.ruby.parser/src/com/oracle/truffle/ruby/parser/Translator.java	Fri Jan 24 00:33:56 2014 +0100
@@ -16,15 +16,12 @@
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.impl.*;
-import com.oracle.truffle.api.nodes.instrument.*;
-import com.oracle.truffle.api.nodes.instrument.InstrumentationProbeNode.ProbeChain;
 import com.oracle.truffle.ruby.nodes.*;
 import com.oracle.truffle.ruby.nodes.call.*;
 import com.oracle.truffle.ruby.nodes.cast.*;
 import com.oracle.truffle.ruby.nodes.constants.*;
 import com.oracle.truffle.ruby.nodes.control.*;
 import com.oracle.truffle.ruby.nodes.core.*;
-import com.oracle.truffle.ruby.nodes.debug.*;
 import com.oracle.truffle.ruby.nodes.literal.*;
 import com.oracle.truffle.ruby.nodes.literal.array.*;
 import com.oracle.truffle.ruby.nodes.methods.*;
@@ -35,7 +32,6 @@
 import com.oracle.truffle.ruby.runtime.*;
 import com.oracle.truffle.ruby.runtime.core.*;
 import com.oracle.truffle.ruby.runtime.core.range.*;
-import com.oracle.truffle.ruby.runtime.debug.*;
 import com.oracle.truffle.ruby.runtime.methods.*;
 
 /**
@@ -50,6 +46,7 @@
     protected final RubyContext context;
     protected final TranslatorEnvironment environment;
     protected final Source source;
+    protected final RubyNodeInstrumenter instrumenter;
 
     private boolean translatingForStatement = false;
 
@@ -89,15 +86,6 @@
         nodeDefinedNames.put(org.jrubyparser.ast.DVarNode.class, "local-variable");
     }
 
-    private static final Set<String> debugIgnoredCalls = new HashSet<>();
-
-    static {
-        debugIgnoredCalls.add("downto");
-        debugIgnoredCalls.add("each");
-        debugIgnoredCalls.add("times");
-        debugIgnoredCalls.add("upto");
-    }
-
     /**
      * Global variables which in common usage have frame local semantics.
      */
@@ -108,6 +96,7 @@
         this.parent = parent;
         this.environment = environment;
         this.source = source;
+        this.instrumenter = environment.getNodeInstrumenter();
     }
 
     @Override
@@ -302,18 +291,7 @@
 
         RubyNode translated = new CallNode(context, sourceSection, node.getName(), receiverTranslated, argumentsAndBlock.getBlock(), argumentsAndBlock.isSplatted(), argumentsAndBlock.getArguments());
 
-        if (context.getConfiguration().getDebug()) {
-            final CallNode callNode = (CallNode) translated;
-            if (!debugIgnoredCalls.contains(callNode.getName())) {
-
-                final RubyProxyNode proxy = new RubyProxyNode(context, translated);
-                proxy.markAs(NodePhylum.CALL);
-                proxy.getProbeChain().appendProbe(new RubyCallProbe(context, node.getName()));
-                translated = proxy;
-            }
-        }
-
-        return translated;
+        return instrumenter.instrumentAsCall(translated, node.getName());
     }
 
     protected class ArgumentsAndBlockTranslation {
@@ -1162,22 +1140,9 @@
 
         RubyNode translated = ((ReadNode) lhs).makeWriteNode(rhs);
 
-        if (context.getConfiguration().getDebug()) {
-            final UniqueMethodIdentifier methodIdentifier = environment.findMethodForLocalVar(node.getName());
-
-            RubyProxyNode proxy;
-            if (translated instanceof RubyProxyNode) {
-                proxy = (RubyProxyNode) translated;
-            } else {
-                proxy = new RubyProxyNode(context, translated);
-            }
-            proxy.markAs(NodePhylum.ASSIGNMENT);
-            context.getDebugManager().registerLocalDebugProxy(methodIdentifier, node.getName(), proxy.getProbeChain());
-
-            translated = proxy;
-        }
-
-        return translated;
+        final UniqueMethodIdentifier methodIdentifier = environment.findMethodForLocalVar(node.getName());
+
+        return instrumenter.instrumentAsLocalAssignment(translated, methodIdentifier, node.getName());
     }
 
     @Override
@@ -1476,39 +1441,7 @@
     @Override
     public Object visitNewlineNode(org.jrubyparser.ast.NewlineNode node) {
         RubyNode translated = (RubyNode) node.getNextNode().accept(this);
-
-        if (context.getConfiguration().getDebug()) {
-
-            RubyProxyNode proxy;
-            if (translated instanceof RubyProxyNode) {
-                proxy = (RubyProxyNode) translated;
-                if (proxy.getChild() instanceof CallNode) {
-                    // Special case; replace proxy with one registered by line, merge in information
-                    final CallNode callNode = (CallNode) proxy.getChild();
-                    final ProbeChain probeChain = proxy.getProbeChain();
-
-                    proxy = new RubyProxyNode(context, callNode, probeChain);
-                }
-            } else {
-                proxy = new RubyProxyNode(context, translated);
-            }
-            proxy.markAs(NodePhylum.STATEMENT);
-            translated = proxy;
-        }
-
-        if (context.getConfiguration().getTrace()) {
-            RubyProxyNode proxy;
-            if (translated instanceof RubyProxyNode) {
-                proxy = (RubyProxyNode) translated;
-            } else {
-                proxy = new RubyProxyNode(context, translated);
-            }
-            proxy.getProbeChain().appendProbe(new RubyTraceProbe(context));
-
-            translated = proxy;
-        }
-
-        return translated;
+        return instrumenter.instrumentAsStatement(translated);
     }
 
     @Override
--- a/graal/com.oracle.truffle.ruby.parser/src/com/oracle/truffle/ruby/parser/TranslatorEnvironment.java	Wed Jan 22 18:46:38 2014 +0100
+++ b/graal/com.oracle.truffle.ruby.parser/src/com/oracle/truffle/ruby/parser/TranslatorEnvironment.java	Fri Jan 24 00:33:56 2014 +0100
@@ -224,4 +224,8 @@
     public List<FrameSlot> getFlipFlopStates() {
         return flipFlopStates;
     }
+
+    public RubyNodeInstrumenter getNodeInstrumenter() {
+        return parser.getNodeInstrumenter();
+    }
 }
--- a/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/RubyContext.java	Wed Jan 22 18:46:38 2014 +0100
+++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/RubyContext.java	Fri Jan 24 00:33:56 2014 +0100
@@ -16,12 +16,12 @@
 
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.impl.*;
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.ruby.runtime.configuration.*;
 import com.oracle.truffle.ruby.runtime.control.*;
 import com.oracle.truffle.ruby.runtime.core.*;
-import com.oracle.truffle.ruby.runtime.debug.*;
 import com.oracle.truffle.ruby.runtime.methods.*;
 import com.oracle.truffle.ruby.runtime.objects.*;
 import com.oracle.truffle.ruby.runtime.subsystems.*;
@@ -40,7 +40,7 @@
     private final ThreadManager threadManager;
     private final FiberManager fiberManager;
     private final AtExitManager atExitManager;
-    private final RubyDebugManager debugManager;
+    private final DebugManager debugManager;
     private final SourceManager sourceManager;
     private final ASTPrinter astPrinter;
 
@@ -76,7 +76,7 @@
         atExitManager = new AtExitManager();
         sourceManager = new SourceManager();
 
-        debugManager = configuration.getDebug() ? new RubyDebugManager(this) : null;
+        debugManager = new DefaultDebugManager(this);
 
         // Must initialize threads before fibers
 
@@ -84,11 +84,11 @@
         fiberManager = new FiberManager(this);
     }
 
-    public String getLanguageShortName() {
-        return "Ruby";
+    public final String getLanguageShortName() {
+        return "Ruby " + CoreLibrary.RUBY_VERSION;
     }
 
-    public RubyDebugManager getDebugManager() {
+    public DebugManager getDebugManager() {
         return debugManager;
     }
 
--- a/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/MethodLocal.java	Wed Jan 22 18:46:38 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This
- * code is released under a tri EPL/GPL/LGPL license. You can use it,
- * redistribute it and/or modify it under the terms of the:
- *
- * Eclipse Public License version 1.0
- * GNU General Public License version 2
- * GNU Lesser General Public License version 2.1
- */
-package com.oracle.truffle.ruby.runtime.debug;
-
-import com.oracle.truffle.ruby.runtime.methods.*;
-
-/**
- * A method and local variable identifier tuple.
- */
-public class MethodLocal {
-
-    private final UniqueMethodIdentifier method;
-    private final String local;
-
-    public MethodLocal(UniqueMethodIdentifier method, String local) {
-        super();
-        this.method = method;
-        this.local = local;
-    }
-
-    @Override
-    public String toString() {
-        return "MethodLocal [method=" + method + ", local=" + local + "]";
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + ((local == null) ? 0 : local.hashCode());
-        result = prime * result + ((method == null) ? 0 : method.hashCode());
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (!(obj instanceof MethodLocal)) {
-            return false;
-        }
-        MethodLocal other = (MethodLocal) obj;
-        if (local == null) {
-            if (other.local != null) {
-                return false;
-            }
-        } else if (!local.equals(other.local)) {
-            return false;
-        }
-        if (method == null) {
-            if (other.method != null) {
-                return false;
-            }
-        } else if (!method.equals(other.method)) {
-            return false;
-        }
-        return true;
-    }
-
-}
--- a/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyBreakAfterLineProbe.java	Wed Jan 22 18:46:38 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. This
- * code is released under a tri EPL/GPL/LGPL license. You can use it,
- * redistribute it and/or modify it under the terms of the:
- *
- * Eclipse Public License version 1.0
- * GNU General Public License version 2
- * GNU Lesser General Public License version 2.1
- */
-package com.oracle.truffle.ruby.runtime.debug;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.ruby.runtime.*;
-
-/**
- * A Ruby probe for halting execution at a line after a child execution method completes.
- */
-public final class RubyBreakAfterLineProbe extends RubyLineProbe {
-
-    /**
-     * Creates a probe that will cause a halt when child execution is complete; a {@code oneShot}
-     * probe will remove itself the first time it halts.
-     */
-    public RubyBreakAfterLineProbe(RubyContext context, SourceLineLocation location, boolean oneShot) {
-        super(context, location, oneShot);
-    }
-
-    @Override
-    public void leave(Node astNode, VirtualFrame frame) {
-        if (oneShot) {
-            // One-shot breakpoints retire after one activation.
-            context.getDebugManager().retireLineProbe(location, this);
-        }
-        context.getDebugManager().haltedAt(astNode, frame.materialize());
-    }
-
-    @Override
-    public void leave(Node astNode, VirtualFrame frame, boolean result) {
-        leave(astNode, frame);
-    }
-
-    @Override
-    public void leave(Node astNode, VirtualFrame frame, int result) {
-        leave(astNode, frame);
-    }
-
-    @Override
-    public void leave(Node astNode, VirtualFrame frame, double result) {
-        leave(astNode, frame);
-    }
-
-    @Override
-    public void leave(Node astNode, VirtualFrame frame, Object result) {
-        leave(astNode, frame);
-    }
-
-    @Override
-    public void leaveExceptional(Node astNode, VirtualFrame frame, Exception e) {
-        leave(astNode, frame);
-    }
-
-}
--- a/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyBreakAfterLocalProbe.java	Wed Jan 22 18:46:38 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. This
- * code is released under a tri EPL/GPL/LGPL license. You can use it,
- * redistribute it and/or modify it under the terms of the:
- *
- * Eclipse Public License version 1.0
- * GNU General Public License version 2
- * GNU Lesser General Public License version 2.1
- */
-package com.oracle.truffle.ruby.runtime.debug;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.ruby.runtime.*;
-
-/**
- * A Ruby probe for halting execution after a local assignment.
- */
-public final class RubyBreakAfterLocalProbe extends RubyLocalProbe {
-
-    public RubyBreakAfterLocalProbe(RubyContext context, MethodLocal local) {
-        super(context, local, false);
-    }
-
-    @Override
-    public void leave(Node astNode, VirtualFrame frame) {
-        context.getDebugManager().haltedAt(astNode, frame.materialize());
-    }
-
-    @Override
-    public void leave(Node astNode, VirtualFrame frame, boolean result) {
-        context.getDebugManager().haltedAt(astNode, frame.materialize());
-    }
-
-    @Override
-    public void leave(Node astNode, VirtualFrame frame, int result) {
-        context.getDebugManager().haltedAt(astNode, frame.materialize());
-    }
-
-    @Override
-    public void leave(Node astNode, VirtualFrame frame, double result) {
-        context.getDebugManager().haltedAt(astNode, frame.materialize());
-    }
-
-    @Override
-    public void leave(Node astNode, VirtualFrame frame, Object result) {
-        context.getDebugManager().haltedAt(astNode, frame.materialize());
-    }
-
-    @Override
-    public void leaveExceptional(Node astNode, VirtualFrame frame, Exception e) {
-        context.getDebugManager().haltedAt(astNode, frame.materialize());
-    }
-
-}
--- a/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyBreakBeforeLineProbe.java	Wed Jan 22 18:46:38 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. This
- * code is released under a tri EPL/GPL/LGPL license. You can use it,
- * redistribute it and/or modify it under the terms of the:
- *
- * Eclipse Public License version 1.0
- * GNU General Public License version 2
- * GNU Lesser General Public License version 2.1
- */
-package com.oracle.truffle.ruby.runtime.debug;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.ruby.runtime.*;
-
-/**
- * A probe for halting execution at a line before a child execution method.
- */
-public final class RubyBreakBeforeLineProbe extends RubyLineProbe {
-
-    /**
-     * Creates a probe that will cause a halt just before child execution starts; a {@code oneShot}
-     * probe will remove itself the first time it halts.
-     */
-    public RubyBreakBeforeLineProbe(RubyContext context, SourceLineLocation location, boolean oneShot) {
-        super(context, location, oneShot);
-    }
-
-    @Override
-    public void enter(Node astNode, VirtualFrame frame) {
-
-        if (!isStepping()) {
-            // Ordinary line breakpoints ignored during stepping so no double halts.
-            if (oneShot) {
-                // One-shot breakpoints retire after one activation.
-                context.getDebugManager().retireLineProbe(location, this);
-            }
-            context.getDebugManager().haltedAt(astNode, frame.materialize());
-        }
-    }
-}
--- a/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyCallProbe.java	Wed Jan 22 18:46:38 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. This
- * code is released under a tri EPL/GPL/LGPL license. You can use it,
- * redistribute it and/or modify it under the terms of the:
- *
- * Eclipse Public License version 1.0
- * GNU General Public License version 2
- * GNU Lesser General Public License version 2.1
- */
-package com.oracle.truffle.ruby.runtime.debug;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.ruby.runtime.*;
-
-public final class RubyCallProbe extends RubyProbe {
-
-    private final String name;
-
-    public RubyCallProbe(RubyContext context, String name) {
-        super(context, false);
-        this.name = name;
-    }
-
-    @Override
-    public void enter(Node astNode, VirtualFrame frame) {
-        context.getDebugManager().notifyCallEntry(astNode, name);
-    }
-
-    @Override
-    public void leave(Node astNode, VirtualFrame frame) {
-        context.getDebugManager().notifyCallExit(astNode, name);
-    }
-
-    @Override
-    public void leave(Node astNode, VirtualFrame frame, boolean result) {
-        context.getDebugManager().notifyCallExit(astNode, name);
-    }
-
-    @Override
-    public void leave(Node astNode, VirtualFrame frame, int result) {
-        context.getDebugManager().notifyCallExit(astNode, name);
-    }
-
-    @Override
-    public void leave(Node astNode, VirtualFrame frame, double result) {
-        context.getDebugManager().notifyCallExit(astNode, name);
-    }
-
-    @Override
-    public void leave(Node astNode, VirtualFrame frame, Object result) {
-        context.getDebugManager().notifyCallExit(astNode, name);
-    }
-
-    @Override
-    public void leaveExceptional(Node astNode, VirtualFrame frame, Exception e) {
-        context.getDebugManager().notifyCallExit(astNode, name);
-    }
-}
--- a/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyDebugManager.java	Wed Jan 22 18:46:38 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,862 +0,0 @@
-/*
- * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. This
- * code is released under a tri EPL/GPL/LGPL license. You can use it,
- * redistribute it and/or modify it under the terms of the:
- *
- * Eclipse Public License version 1.0
- * GNU General Public License version 2
- * GNU Lesser General Public License version 2.1
- */
-package com.oracle.truffle.ruby.runtime.debug;
-
-import java.io.*;
-import java.util.*;
-import java.util.Map.Entry;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.nodes.instrument.InstrumentationProbeNode.ProbeChain;
-import com.oracle.truffle.api.nodes.instrument.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.ruby.runtime.*;
-import com.oracle.truffle.ruby.runtime.core.*;
-import com.oracle.truffle.ruby.runtime.methods.*;
-
-/**
- * Manager for Ruby AST execution under debugging control.
- */
-public final class RubyDebugManager implements DebugManager {
-
-    // TODO (mlvdv) no REPL support yet for debugging "locals" (assignment to local variables); only
-    // line-based step/next/return
-
-    private static final boolean TRACE = false;
-    private static final PrintStream OUT = System.out;
-
-    private static enum ExecutionMode {
-
-        /**
-         * Context: ordinary debugging execution, e.g. in response to a "Continue" request or a
-         * "Load-Run" request.
-         * <ul>
-         * <li>User breakpoints are enabled.</li>
-         * <li>Continue until either:
-         * <ol>
-         * <li>execution arrives at a node with attached user breakpoint, <strong>or:</strong></li>
-         * <li>execution completes.</li>
-         * </ol>
-         * </ul>
-         */
-        CONTINUE,
-
-        /**
-         * Context: per-statement stepping execution, e.g. in response to a "Step" request.
-         * <ul>
-         * <li>User breakpoints are disabled.</li>
-         * <li>Continue until either:
-         * <ol>
-         * <li>execution arrives at a "Statement" node, <strong>or:</strong></li>
-         * <li>execution completes.</li>
-         * </ol>
-         * </ul>
-         */
-        STEP,
-
-        /**
-         * Context: per-statement stepping in response to a "Next" request and when not nested in
-         * any function/method call.
-         * <ul>
-         * <li>User breakpoints are disabled.</li>
-         * <li>Continue until either:
-         * <ol>
-         * <li>execution arrives at a "Statement" node <strong>or:</strong></li>
-         * <li>the program completes <strong>or:</strong></li>
-         * <li>execution arrives at a function/method entry, in which case the mode changes to
-         * {@link #NEXT_NESTED} and execution continues.</li>
-         * </ol>
-         * </ul>
-         */
-        NEXT,
-
-        /**
-         * Context: ordinary debugging execution in response to a "Next" requested and when nested
-         * at least one deep in function/method calls.
-         * <ul>
-         * <li>User breakpoints are enabled.</li>
-         * <li>Execute until either:
-         * <ol>
-         * <li>execution arrives at a node with attached user breakpoint, <strong>or:</strong></li>
-         * <li>execution completes, <strong>or:</strong></li>
-         * <li>execution returns from all nested function/method calls, in which case the mode
-         * changes to {@link #NEXT} and execution continues.</li>
-         * </ol>
-         * </ul>
-         */
-        NEXT_NESTED;
-    }
-
-    private static enum BreakpointStatus {
-
-        /**
-         * Created for a source location but not yet attached for some legitimate reason: perhaps
-         * newly created and not yet attached; perhaps newly created and the source file hasn't been
-         * loaded yet; perhaps old and the source file is in the process of being reloaded.
-         */
-        PENDING("Pending"),
-
-        /**
-         * Has a {@link RubyProbe}, which is attached to a {@linkplain ProbeChain known location} in
-         * the AST.
-         */
-        ACTIVE("Active"),
-
-        /**
-         * Has a {@link RubyProbe}, which is associated with a {@linkplain ProbeChain known
-         * location} in the AST, but which has been temporarily removed.
-         */
-        DISABLED("Disabled"),
-
-        /**
-         * Should be attached, but the line location cannot be found in the source.
-         */
-        ERROR("Error: line not found"),
-
-        /**
-         * Abandoned, not attached.
-         */
-        RETIRED("Retired");
-
-        private final String name;
-
-        BreakpointStatus(String name) {
-            this.name = name;
-        }
-
-        @Override
-        public String toString() {
-            return name;
-        }
-    }
-
-    private final Set<Source> loadedSources = new HashSet<>();
-
-    private Source beingLoaded = null;
-
-    /**
-     * The current mode of execution.
-     */
-    private ExecutionMode executionMode = ExecutionMode.CONTINUE;
-
-    /**
-     * When running in "step" mode, this is the number of steps that haven't yet completed.
-     */
-    private int unfinishedStepCount = 0;
-
-    /**
-     * When running in "next" mode, this is the number of steps that haven't yet completed.
-     */
-    private int unfinishedNextCount = 0;
-    /**
-     * When running in "next" mode, this is non-null when running a function/method that must be
-     * continued across.
-     */
-    private Node nextNestedInCallNode = null;
-
-    /**
-     * Map: SourceSection ==> probe chain associated with that source section in an AST.
-     */
-    private final Map<SourceSection, ProbeChain> srcToProbeChain = new HashMap<>();
-
-    /**
-     * Map: Source lines ==> probe chains associated with source sections starting on the line.
-     */
-    private final Map<SourceLineLocation, Set<ProbeChain>> lineToProbeChains = new HashMap<>();
-
-    /**
-     * Map: Source lines ==> attached Breakpoints/procs to be activated before execution at line.
-     * There should be no more than one line breakpoint associated with a line.
-     */
-    private final Map<SourceLineLocation, RubyLineBreakpoint> lineToBreakpoint = new TreeMap<>();
-
-    /**
-     * Map: Method locals in AST ==> Method local assignments where breakpoints can be attached.
-     */
-    private final Map<MethodLocal, ProbeChain> localsToProbeChains = new HashMap<>();
-
-    /**
-     * Map: Method locals ==> Breakpoints & procs to be activated after assignment to a local.
-     */
-    private final Map<MethodLocal, RubyProbe> localsToAttachedBreakpoints = new HashMap<>();
-
-    private final RubyContext context;
-
-    public RubyDebugManager(RubyContext context) {
-        this.context = context;
-    }
-
-    /**
-     * Gets the {@linkplain ProbeChain probe} associated with a particular {@link SourceSection
-     * source location}, creating a new one if needed. There should only be one probe associated
-     * with each {@linkplain SourceSection source location}.
-     */
-    public ProbeChain getProbeChain(SourceSection sourceSection) {
-        assert sourceSection != null;
-        assert sourceSection.getSource().equals(beingLoaded);
-
-        ProbeChain probeChain = srcToProbeChain.get(sourceSection);
-
-        if (probeChain != null) {
-            return probeChain;
-        }
-        probeChain = new ProbeChain(context, sourceSection, null);
-
-        // Register new ProbeChain by unique SourceSection
-        srcToProbeChain.put(sourceSection, probeChain);
-
-        // Register new ProbeChain by source line, there may be more than one
-        // Create line location for map key
-        final SourceLineLocation lineLocation = new SourceLineLocation(sourceSection.getSource(), sourceSection.getStartLine());
-
-        Set<ProbeChain> probeChains = lineToProbeChains.get(lineLocation);
-        if (probeChains == null) {
-            probeChains = new HashSet<>();
-            lineToProbeChains.put(lineLocation, probeChains);
-        }
-        probeChains.add(probeChain);
-
-        return probeChain;
-    }
-
-    public void notifyStartLoading(Source source) {
-
-        beingLoaded = source;
-
-        /**
-         * We'd like to know when we're reloading a file if the old AST is completely dead, so that
-         * we can correctly identify the state of breakpoints related to it, but that doesn't seem
-         * possible.
-         * 
-         * Before we start, find any breakpoints that never got attached, which get reported as
-         * errors. Revert them to "pending", in case their lines are found this time around.
-         */
-        for (RubyLineBreakpoint breakpoint : lineToBreakpoint.values()) {
-            if (breakpoint.getSourceLineLocation().getSource().equals(beingLoaded)) {
-                if (breakpoint.status == BreakpointStatus.ERROR) {
-                    // It was an error, which means we have not yet found that line for this Source.
-                    // It might show up while loading this time, so make it pending.
-                    breakpoint.setPending();
-                }
-            }
-        }
-    }
-
-    public void notifyFinishedLoading(Source source) {
-        assert source == beingLoaded;
-
-        // Update any pending breakpoints associated with this source
-
-        for (RubyLineBreakpoint breakpoint : lineToBreakpoint.values()) {
-            if (breakpoint.getSourceLineLocation().getSource().equals(beingLoaded)) {
-                if (breakpoint.status == BreakpointStatus.PENDING) {
-                    final ProbeChain probeChain = findProbeChain(breakpoint.location);
-                    if (probeChain == null) {
-                        breakpoint.setError();
-                    } else {
-                        breakpoint.attach(probeChain);
-                    }
-                }
-            }
-        }
-        loadedSources.add(source);
-        beingLoaded = null;
-    }
-
-    /**
-     * Returns a {@link ProbeChain} associated with source that starts on a specified line; if there
-     * are more than one, return the one with the first character location.
-     */
-    private ProbeChain findProbeChain(SourceLineLocation lineLocation) {
-        ProbeChain probeChain = null;
-        final Set<ProbeChain> probeChains = lineToProbeChains.get(lineLocation);
-        if (probeChains != null) {
-            assert probeChains.size() > 0;
-            for (ProbeChain chain : probeChains) {
-                if (probeChain == null) {
-                    probeChain = chain;
-                } else if (chain.getProbedSourceSection().getCharIndex() < probeChain.getProbedSourceSection().getCharIndex()) {
-                    probeChain = chain;
-                }
-            }
-        }
-        return probeChain;
-    }
-
-    /**
-     * Remove a probe from a line location and retire it permanently.
-     */
-    public void retireLineProbe(SourceLineLocation location, RubyLineProbe probe) {
-        final RubyLineBreakpoint breakpoint = lineToBreakpoint.get(location);
-        lineToBreakpoint.remove(location);
-        breakpoint.retire(probe);
-    }
-
-    @Override
-    public LineBreakpoint[] getBreakpoints() {
-        return lineToBreakpoint.values().toArray(new LineBreakpoint[0]);
-    }
-
-    @Override
-    public RubyLineBreakpoint setBreakpoint(SourceLineLocation lineLocation) {
-
-        RubyLineBreakpoint breakpoint = lineToBreakpoint.get(lineLocation);
-
-        if (breakpoint != null) {
-            switch (breakpoint.status) {
-                case ACTIVE:
-                    throw new RuntimeException("Breakpoint already set at line " + lineLocation);
-
-                case PENDING:
-                case ERROR:
-                    throw new RuntimeException("Breakpoint already pending at line " + lineLocation);
-
-                default:
-                    assert false;
-            }
-        } else {
-            breakpoint = new RubyLineBreakpoint(lineLocation, new RubyBreakBeforeLineProbe(context, lineLocation, false));
-            lineToBreakpoint.put(lineLocation, breakpoint);
-
-            final ProbeChain probeChain = findProbeChain(lineLocation);
-            if (probeChain != null) {
-                breakpoint.attach(probeChain);
-            }
-        }
-
-        return breakpoint;
-    }
-
-    @Override
-    public RubyLineBreakpoint setConditionalBreakpoint(SourceLineLocation lineLocation, String condition) {
-        throw new UnsupportedOperationException("conditional breakpoints not yet supported");
-    }
-
-    @Override
-    public LineBreakpoint setOneShotBreakpoint(SourceLineLocation lineLocation) {
-        RubyLineBreakpoint breakpoint = lineToBreakpoint.get(lineLocation);
-
-        if (breakpoint != null) {
-            switch (breakpoint.status) {
-                case ACTIVE:
-                    throw new RuntimeException("Breakpoint already set at line " + lineLocation);
-
-                case PENDING:
-                case ERROR:
-                    throw new RuntimeException("Breakpoint already pending at line " + lineLocation);
-
-                default:
-                    assert false;
-            }
-        } else {
-            breakpoint = new RubyLineBreakpoint(lineLocation, new RubyBreakBeforeLineProbe(context, lineLocation, true));
-            lineToBreakpoint.put(lineLocation, breakpoint);
-
-            final ProbeChain probeChain = findProbeChain(lineLocation);
-            if (probeChain != null) {
-                breakpoint.attach(probeChain);
-            }
-        }
-
-        return breakpoint;
-    }
-
-    public boolean hasBreakpoint(SourceLineLocation lineLocation) {
-        return lineToBreakpoint.get(lineLocation) != null;
-    }
-
-    @Override
-    public void removeBreakpoint(SourceLineLocation lineLocation) {
-        final RubyLineBreakpoint breakpoint = lineToBreakpoint.get(lineLocation);
-        if (breakpoint == null) {
-            throw new RuntimeException("No break/proc located at line " + lineLocation);
-        }
-        lineToBreakpoint.remove(lineLocation);
-        breakpoint.retire();
-    }
-
-    private void removeOneShotBreakpoints() {
-        for (Entry<SourceLineLocation, RubyLineBreakpoint> entry : lineToBreakpoint.entrySet()) {
-            final RubyLineBreakpoint breakpoint = entry.getValue();
-            if (breakpoint.probe.isOneShot()) {
-                lineToBreakpoint.remove(entry.getKey());
-                breakpoint.retire();
-            }
-        }
-    }
-
-    /**
-     * Prepare to execute a "Continue":
-     * <ul>
-     * <li>Execution will continue until either:
-     * <ol>
-     * <li>execution arrives at a node to which a breakpoint is attached, <strong>or:</strong></li>
-     * <li>execution completes.</li>
-     * </ol>
-     * </ul>
-     */
-    public void setContinue() {
-        // Nothing to do here; "Continue" is the default, which should be restored after each halt.
-    }
-
-    /**
-     * Prepare to execute a "Step":
-     * <ul>
-     * <li>User breakpoints are disabled.</li>
-     * <li>Execution will continue until either:
-     * <ol>
-     * <li>execution arrives at a "Statement" node, <strong>or:</strong></li>
-     * <li>execution completes.</li>
-     * </ol>
-     * This status persists only through one execution, and reverts to
-     * {@link ExecutionMode#CONTINUE}.
-     * </ul>
-     */
-    public void setStep(int stepCount) {
-        assert executionMode == ExecutionMode.CONTINUE;
-        disableLineBreakpoints();
-        setStepping(true);
-        unfinishedStepCount = stepCount;
-        setMode(ExecutionMode.STEP);
-    }
-
-    /**
-     * Prepare to execute a "Next":
-     * <ul>
-     * <li>Execution will continue until either:
-     * <ol>
-     * <li>execution arrives at a "Statement" node when not nested in one or more function/method
-     * calls, <strong>or:</strong></li>
-     * <li>execution arrives at a node to which a breakpoint is attached and when nested in one or
-     * more function/method calls, <strong>or:</strong></li>
-     * <li>execution completes.</li>
-     * </ol>
-     * This status persists only through one execution, and reverts to
-     * {@link ExecutionMode#CONTINUE}.
-     * </ul>
-     */
-    public void setNext(int nextCount) {
-        assert executionMode == ExecutionMode.CONTINUE;
-        disableLineBreakpoints();
-        setStepping(true);
-        unfinishedNextCount = nextCount;
-        setMode(ExecutionMode.NEXT);
-    }
-
-    private void disableLineBreakpoints() {
-        for (RubyLineBreakpoint breakpoint : lineToBreakpoint.values()) {
-            if (breakpoint.status == BreakpointStatus.ACTIVE) {
-                breakpoint.disable();
-            }
-        }
-    }
-
-    private void enableLineBreakpoints() {
-        for (RubyLineBreakpoint breakpoint : lineToBreakpoint.values()) {
-            if (breakpoint.status == BreakpointStatus.DISABLED) {
-                breakpoint.enable();
-            }
-        }
-    }
-
-    private void setStepping(boolean isStepping) {
-        // Set the "stepping" flag on every statement probe.
-        for (ProbeChain probeChain : srcToProbeChain.values()) {
-            if (probeChain.isMarkedAs(NodePhylum.STATEMENT)) {
-                probeChain.setStepping(isStepping);
-            }
-        }
-    }
-
-    private void setMode(ExecutionMode mode) {
-        if (TRACE) {
-            OUT.println("DebugManager: " + executionMode.toString() + "-->" + mode.toString());
-        }
-        executionMode = mode;
-    }
-
-    /**
-     * Sets a Ruby proc of no arguments to be run before a specified line is executed.
-     */
-    public void setLineProc(SourceLineLocation lineLocation, RubyProc proc) {
-
-        RubyLineBreakpoint breakpoint = lineToBreakpoint.get(lineLocation);
-
-        if (breakpoint != null) {
-            switch (breakpoint.status) {
-                case ACTIVE:
-                    throw new RuntimeException("Breakpoint already set at line " + lineLocation);
-
-                case PENDING:
-                case ERROR:
-                    throw new RuntimeException("Breakpoint already pending at line " + lineLocation);
-
-                default:
-                    assert false;
-            }
-        } else {
-            breakpoint = new RubyLineBreakpoint(lineLocation, new RubyProcBeforeLineProbe(context, lineLocation, proc));
-            lineToBreakpoint.put(lineLocation, breakpoint);
-
-            final ProbeChain probeChain = findProbeChain(lineLocation);
-            if (probeChain != null) {
-                breakpoint.attach(probeChain);
-            }
-        }
-    }
-
-    // TODO (mlvdv) rework locals (watchpoints) to work like breaks; I doubt it is even correct now
-    /**
-     * Registers the chain of probes associated with a method local variable assignment in the AST.
-     */
-    public void registerLocalDebugProxy(UniqueMethodIdentifier methodIdentifier, String localName, ProbeChain probeChain) {
-        final MethodLocal methodLocal = new MethodLocal(methodIdentifier, localName);
-        localsToProbeChains.put(methodLocal, probeChain);
-    }
-
-    /**
-     * Sets a breakpoint after assignment to a method local variable in the AST.
-     */
-    public void setLocalBreak(UniqueMethodIdentifier methodIdentifier, String localName) {
-        final MethodLocal methodLocal = new MethodLocal(methodIdentifier, localName);
-        ProbeChain probeChain = localsToProbeChains.get(methodLocal);
-        if (probeChain == null) {
-            throw new RuntimeException("Can't find method local " + methodLocal);
-        }
-        RubyProbe probe = localsToAttachedBreakpoints.get(methodLocal);
-        if (probe != null) {
-            throw new RuntimeException("Breakpoint already set on method local " + methodLocal);
-        }
-        probe = new RubyBreakAfterLocalProbe(context, methodLocal);
-        localsToAttachedBreakpoints.put(methodLocal, probe);
-        probeChain.appendProbe(probe);
-    }
-
-    /**
-     * Sets a Ruby proc of one argument to be run after a method local assignment, passed the new
-     * value.
-     */
-    public void setLocalProc(UniqueMethodIdentifier methodIdentifier, String localName, RubyProc proc) {
-        final MethodLocal methodLocal = new MethodLocal(methodIdentifier, localName);
-        ProbeChain probeChain = localsToProbeChains.get(methodLocal);
-        if (probeChain == null) {
-            throw new RuntimeException("Can't find method local " + methodLocal);
-        }
-        RubyProbe probe = localsToAttachedBreakpoints.get(methodLocal);
-        if (probe != null) {
-            throw new RuntimeException("Assignment proc already set on method local " + methodLocal);
-        }
-        probe = new RubyProcAfterLocalProbe(context, methodLocal, proc);
-        localsToAttachedBreakpoints.put(methodLocal, probe);
-        probeChain.appendProbe(probe);
-    }
-
-    /**
-     * Removes a break or proc on assignment to a method local variable in the AST.
-     */
-    public void removeLocalProbe(UniqueMethodIdentifier methodIdentifier, String localName) {
-        final MethodLocal methodLocal = new MethodLocal(methodIdentifier, localName);
-        RubyProbe probe = localsToAttachedBreakpoints.get(methodLocal);
-        if (probe == null) {
-            throw new RuntimeException("No breakpoint set on method local " + methodLocal);
-        }
-        localsToProbeChains.get(methodLocal).removeProbe(probe);
-        localsToAttachedBreakpoints.remove(methodLocal);
-    }
-
-    public void haltedAt(Node astNode, MaterializedFrame frame) {
-        switch (executionMode) {
-            case CONTINUE:
-            case NEXT_NESTED:
-                // User breakpoints should already be enabled
-                // Stepping should be false
-                nextNestedInCallNode = null;
-                break;
-            case STEP:
-                unfinishedStepCount--;
-                if (unfinishedStepCount > 0) {
-                    return;
-                }
-                // Revert to default mode.
-                enableLineBreakpoints();
-                setStepping(false);
-                break;
-            case NEXT:
-                unfinishedNextCount--;
-                if (unfinishedNextCount > 0) {
-                    return;
-                }
-                // Revert to default mode.
-                enableLineBreakpoints();
-                setStepping(false);
-                break;
-            default:
-                assert false;  // Should not happen
-                break;
-
-        }
-        // Clean up, just in cased the one-shot breakpoints got confused
-        removeOneShotBreakpoints();
-
-        setMode(ExecutionMode.CONTINUE);
-
-        // Return control to the debug client
-        context.haltedAt(astNode, frame);
-
-    }
-
-    private RubyProbe createReplacement(RubyProbe probe) {
-        // Should be a specialized replacement for any kind of probe created.
-        // Ugly, but there's no other way to reset the parent pointer and reuse a probe node.
-        if (probe instanceof RubyBreakBeforeLineProbe) {
-            final RubyBreakBeforeLineProbe oldProbe = (RubyBreakBeforeLineProbe) probe;
-            return new RubyBreakBeforeLineProbe(context, oldProbe.getLineLocation(), oldProbe.isOneShot());
-        }
-        if (probe instanceof RubyProcBeforeLineProbe) {
-            final RubyProcBeforeLineProbe oldProbe = (RubyProcBeforeLineProbe) probe;
-            return new RubyProcBeforeLineProbe(context, oldProbe.getLineLocation(), oldProbe.getProc());
-        }
-        assert false;
-        return null;
-    }
-
-    /**
-     * A breakpoint of the sort that would be created by a client, with a life-cycle represented by
-     * {@link BreakpointStatus}.
-     */
-    private final class RubyLineBreakpoint implements DebugManager.LineBreakpoint, Comparable {
-
-        private final SourceLineLocation location;
-
-        private RubyProbe probe;  // non-null until RETIRED, but may get replaced.
-        private ProbeChain probeChain = null;
-        private BreakpointStatus status = BreakpointStatus.PENDING;
-
-        public RubyLineBreakpoint(SourceLineLocation location, RubyProbe probe) {
-            this.location = location;
-            this.probe = probe;
-        }
-
-        public SourceLineLocation getSourceLineLocation() {
-            return location;
-        }
-
-        // ensure sorted by location
-        public int compareTo(Object o) {
-            final RubyLineBreakpoint other = (RubyLineBreakpoint) o;
-            return location.compareTo(other.location);
-        }
-
-        @Override
-        public String getDebugStatus() {
-            String result = status == null ? "<none>" : status.name;
-            if (probe.isOneShot()) {
-                result = result + ", " + "One-Shot";
-            }
-            return result;
-        }
-
-        private void attach(ProbeChain chain) {
-            assert status == BreakpointStatus.PENDING;
-
-            probeChain = chain;
-            probeChain.appendProbe(probe);
-
-            status = BreakpointStatus.ACTIVE;
-        }
-
-        private void disable() {
-            assert status == BreakpointStatus.ACTIVE;
-
-            probeChain.removeProbe(probe);
-            status = BreakpointStatus.DISABLED;
-        }
-
-        private void enable() {
-            assert status == BreakpointStatus.DISABLED;
-
-            // Can't re-attach to probe chain, because can't re-assign parent.
-            probe = createReplacement(probe);
-            probeChain.appendProbe(probe);
-            status = BreakpointStatus.ACTIVE;
-        }
-
-        private void setPending() {
-            assert status == BreakpointStatus.ERROR;
-
-            status = BreakpointStatus.PENDING;
-        }
-
-        public void setError() {
-            assert status == BreakpointStatus.PENDING;
-
-            status = BreakpointStatus.ERROR;
-        }
-
-        private void retire() {
-
-            if (status == BreakpointStatus.ACTIVE) {
-                probeChain.removeProbe(probe);
-            }
-            probe = null;
-            probeChain = null;
-
-            status = BreakpointStatus.RETIRED;
-        }
-
-        private void retire(RubyProbe retiredProbe) {
-
-            assert this.probe == retiredProbe;
-            retire();
-        }
-    }
-
-    private static final class CallRecord {
-
-        final SourceSection section;
-        @SuppressWarnings("unused") final String name;
-        final CallRecord predecessor;
-
-        public CallRecord(SourceSection section, String name, CallRecord predecessor) {
-            this.section = section;
-            this.name = name;
-            this.predecessor = predecessor;
-        }
-    }
-
-    private CallRecord callStack = null;
-
-    public void notifyCallEntry(Node astNode, String name) {
-        if (TRACE) {
-            OUT.println("DebugManager: ENTER \"" + name + "\" " + nodeToString(astNode));
-        }
-        if (executionMode == ExecutionMode.NEXT && nextNestedInCallNode == null) {
-            // In "Next" mode, where we have been "stepping", but are about to enter a call.
-            // Switch modes to be like "Continue" until/if return from this call
-            nextNestedInCallNode = astNode;
-            enableLineBreakpoints();
-            setStepping(false);
-            setMode(ExecutionMode.NEXT_NESTED);
-        }
-
-        callStack = new CallRecord(astNode.getSourceSection(), name, callStack);
-    }
-
-    public void notifyCallExit(Node astNode, String name) {
-        if (TRACE) {
-            OUT.println("DebugManager: EXIT \"" + name + "\" " + nodeToString(astNode));
-        }
-
-        if (executionMode == ExecutionMode.NEXT_NESTED) {
-            assert nextNestedInCallNode != null;
-            if (nextNestedInCallNode == astNode) {
-                // In "Next" mode while nested in a function/method call, but about to return.
-                // Switch modes to be like "Step" until/if enter another function/method call.
-                nextNestedInCallNode = null;
-                disableLineBreakpoints();
-                setStepping(true);
-                setMode(ExecutionMode.NEXT);
-            }
-        }
-
-        final SourceSection section = astNode.getSourceSection();
-        if (section instanceof NullSourceSection) {
-            if (TRACE) {
-                OUT.println("Ignoring call exit \"" + name + "\" " + nodeToString(astNode));
-            }
-        }
-        callStack = callStack.predecessor;
-    }
-
-    /**
-     * Sets a one-shot breakpoint to halt just after the completion of the call site at the top of
-     * the current call stack.
-     */
-    public boolean setReturnBreakpoint() {
-        if (callStack == null) {
-            return false;
-        }
-        final SourceLineLocation lineLocation = new SourceLineLocation(callStack.section);
-        RubyLineBreakpoint breakpoint = lineToBreakpoint.get(lineLocation);
-        if (breakpoint != null) {
-            return true;
-        }
-        final ProbeChain probeChain = findProbeChain(lineLocation);
-        if (probeChain != null) {
-            breakpoint = new RubyLineBreakpoint(lineLocation, new RubyBreakAfterLineProbe(context, lineLocation, true));
-            lineToBreakpoint.put(lineLocation, breakpoint);
-            breakpoint.attach(probeChain);
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Notifies that a new execution is about to start, i.e. running a program or an eval.
-     */
-    @SuppressWarnings("static-method")
-    public void startExecution(String name) {
-        if (TRACE) {
-            OUT.println("RubyDebugManager: START " + name);
-        }
-        // TODO (mlvdv) push the current call stack onto a stack; start new empty call stack
-    }
-
-    /**
-     * Notifies that the current execution has ended.
-     */
-    public void endExecution(String name) {
-        if (TRACE) {
-            OUT.println("RubyDebugManager: END " + name);
-        }
-
-        // TODO (mlvdv) pop the current call stack, restore previous
-
-        switch (executionMode) {
-            case CONTINUE:
-            case NEXT_NESTED:
-                // User breakpoints should already be enabled
-                // Stepping should be false
-                nextNestedInCallNode = null;
-                break;
-            case STEP:
-                // Revert to default mode.
-                enableLineBreakpoints();
-                setStepping(false);
-                unfinishedStepCount = 0;
-                break;
-            case NEXT:
-                // Revert to default mode.
-                enableLineBreakpoints();
-                setStepping(false);
-                unfinishedNextCount = 0;
-                break;
-            default:
-                assert false;  // Should not happen
-                break;
-        }
-        // Clean up, just in cased the one-shot breakpoints got confused
-        removeOneShotBreakpoints();
-
-        setMode(ExecutionMode.CONTINUE);
-    }
-
-    @SuppressWarnings("static-method")
-    private String nodeToString(Node astNode) {
-        final SourceSection sourceSection = astNode.getSourceSection();
-        if (sourceSection != null) {
-            return Integer.toString(sourceSection.getStartLine()) + ":" + astNode;
-        }
-        return astNode.toString();
-    }
-
-}
--- a/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyLineProbe.java	Wed Jan 22 18:46:38 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. This
- * code is released under a tri EPL/GPL/LGPL license. You can use it,
- * redistribute it and/or modify it under the terms of the:
- *
- * Eclipse Public License version 1.0
- * GNU General Public License version 2
- * GNU Lesser General Public License version 2.1
- */
-package com.oracle.truffle.ruby.runtime.debug;
-
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.ruby.runtime.*;
-
-/**
- * A Ruby probe situated at a Ruby "line".
- */
-public abstract class RubyLineProbe extends RubyProbe {
-
-    protected final SourceLineLocation location;
-
-    /**
-     * Creates a probe that will cause a halt just before child execution starts; a {@code oneShot}
-     * probe will remove itself the first time it halts.
-     */
-    public RubyLineProbe(RubyContext context, SourceLineLocation location, boolean oneShot) {
-        super(context, oneShot);
-        this.location = location;
-    }
-
-    public SourceLineLocation getLineLocation() {
-        return location;
-    }
-
-}
--- a/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyLocalProbe.java	Wed Jan 22 18:46:38 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. This
- * code is released under a tri EPL/GPL/LGPL license. You can use it,
- * redistribute it and/or modify it under the terms of the:
- *
- * Eclipse Public License version 1.0
- * GNU General Public License version 2
- * GNU Lesser General Public License version 2.1
- */
-package com.oracle.truffle.ruby.runtime.debug;
-
-import com.oracle.truffle.ruby.runtime.*;
-
-/**
- * A Ruby probe situated at a Ruby local assignment.
- */
-public abstract class RubyLocalProbe extends RubyProbe {
-
-    protected final MethodLocal local;
-
-    public RubyLocalProbe(RubyContext context, MethodLocal local, boolean oneShot) {
-        super(context, oneShot);
-        this.local = local;
-    }
-
-}
--- a/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyProcAfterLineProbe.java	Wed Jan 22 18:46:38 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. This
- * code is released under a tri EPL/GPL/LGPL license. You can use it,
- * redistribute it and/or modify it under the terms of the:
- *
- * Eclipse Public License version 1.0
- * GNU General Public License version 2
- * GNU Lesser General Public License version 2.1
- */
-package com.oracle.truffle.ruby.runtime.debug;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.ruby.runtime.*;
-import com.oracle.truffle.ruby.runtime.core.*;
-
-/**
- * A probe for instrumenting a Ruby program with a Ruby procedure to run on the return value from
- * node execution at a line.
- */
-public final class RubyProcAfterLineProbe extends RubyLineProbe {
-
-    private final RubyProc proc;
-
-    public RubyProcAfterLineProbe(RubyContext context, SourceLineLocation location, RubyProc proc) {
-        super(context, location, false);
-        this.proc = proc;
-    }
-
-    @Override
-    public void leave(Node astNode, VirtualFrame frame) {
-        proc.call(frame.pack());
-    }
-
-    @Override
-    public void leave(Node astNode, VirtualFrame frame, boolean result) {
-        proc.call(frame.pack(), result);
-    }
-
-    @Override
-    public void leave(Node astNode, VirtualFrame frame, int result) {
-        proc.call(frame.pack(), result);
-    }
-
-    @Override
-    public void leave(Node astNode, VirtualFrame frame, double result) {
-        proc.call(frame.pack(), result);
-    }
-
-    @Override
-    public void leave(Node astNode, VirtualFrame frame, Object result) {
-        proc.call(frame.pack(), result);
-    }
-
-    @Override
-    public void leaveExceptional(Node astNode, VirtualFrame frame, Exception e) {
-        proc.call(frame.pack());
-    }
-}
--- a/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyProcAfterLocalProbe.java	Wed Jan 22 18:46:38 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This
- * code is released under a tri EPL/GPL/LGPL license. You can use it,
- * redistribute it and/or modify it under the terms of the:
- *
- * Eclipse Public License version 1.0
- * GNU General Public License version 2
- * GNU Lesser General Public License version 2.1
- */
-package com.oracle.truffle.ruby.runtime.debug;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.ruby.runtime.*;
-import com.oracle.truffle.ruby.runtime.core.*;
-
-/**
- * A probe for instrumenting a Ruby program with a Ruby procedure to run on the return value from a
- * local assignment.
- */
-public final class RubyProcAfterLocalProbe extends RubyLocalProbe {
-
-    private final RubyProc proc;
-
-    public RubyProcAfterLocalProbe(RubyContext context, MethodLocal local, RubyProc proc) {
-        super(context, local, false);
-        this.proc = proc;
-    }
-
-    @Override
-    public void leave(Node astNode, VirtualFrame frame) {
-        proc.call(frame.pack());
-    }
-
-    @Override
-    public void leave(Node astNode, VirtualFrame frame, boolean result) {
-        proc.call(frame.pack(), result);
-    }
-
-    @Override
-    public void leave(Node astNode, VirtualFrame frame, int result) {
-        proc.call(frame.pack(), result);
-    }
-
-    @Override
-    public void leave(Node astNode, VirtualFrame frame, double result) {
-        proc.call(frame.pack(), result);
-    }
-
-    @Override
-    public void leave(Node astNode, VirtualFrame frame, Object result) {
-        proc.call(frame.pack(), result);
-    }
-
-    @Override
-    public void leaveExceptional(Node astNode, VirtualFrame frame, Exception e) {
-        proc.call(frame.pack());
-    }
-}
--- a/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyProcBeforeLineProbe.java	Wed Jan 22 18:46:38 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved. This
- * code is released under a tri EPL/GPL/LGPL license. You can use it,
- * redistribute it and/or modify it under the terms of the:
- *
- * Eclipse Public License version 1.0
- * GNU General Public License version 2
- * GNU Lesser General Public License version 2.1
- */
-package com.oracle.truffle.ruby.runtime.debug;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.ruby.runtime.*;
-import com.oracle.truffle.ruby.runtime.core.*;
-
-/**
- * A probe for instrumenting a Ruby program with a Ruby procedure to run before a calling a child
- * node at a line.
- */
-public final class RubyProcBeforeLineProbe extends RubyLineProbe {
-
-    private final RubyProc proc;
-
-    public RubyProcBeforeLineProbe(RubyContext context, SourceLineLocation location, RubyProc proc) {
-        super(context, location, false);
-        this.proc = proc;
-    }
-
-    @Override
-    public void enter(Node astNode, VirtualFrame frame) {
-        proc.call(frame.pack());
-    }
-
-    public RubyProc getProc() {
-        return proc;
-    }
-
-}
--- a/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/debug/DebugTests.java	Wed Jan 22 18:46:38 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,133 +0,0 @@
-/*
- * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This
- * code is released under a tri EPL/GPL/LGPL license. You can use it,
- * redistribute it and/or modify it under the terms of the:
- *
- * Eclipse Public License version 1.0
- * GNU General Public License version 2
- * GNU Lesser General Public License version 2.1
- */
-package com.oracle.truffle.ruby.test.debug;
-
-import org.junit.*;
-
-import com.oracle.truffle.ruby.runtime.configuration.*;
-import com.oracle.truffle.ruby.test.*;
-
-/**
- * Test the debugger.
- */
-public class DebugTests extends RubyTests {
-
-    @Test
-    public void testBreakContinue() {
-        final ConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
-        configurationBuilder.setDebug(true);
-        final Configuration configuration = new Configuration(configurationBuilder);
-
-        final String fakeFileName = "test.rb";
-        final String code = "Debug.break; puts 2";
-        final String input = "puts 1 \n Debug.continue \n puts 'error' \n puts 'error'";
-        final String expected = "1\n=> \n2\n";
-
-        assertPrints(configuration, expected, fakeFileName, code, input, new String[]{});
-    }
-
-    @Test
-    public void testLineBreak() {
-        final ConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
-        configurationBuilder.setDebug(true);
-        final Configuration configuration = new Configuration(configurationBuilder);
-
-        final String fakeFileName = "test.rb";
-        final String code = "Debug.break(\"test.rb\", 2) \n puts 2 \n puts 3";
-        final String input = "puts 1 \n Debug.continue \n puts 'error' \n puts 'error'";
-        final String expected = "1\n=> \n2\n3\n";
-
-        assertPrints(configuration, expected, fakeFileName, code, input, new String[]{});
-    }
-
-    @Test
-    public void testLineCustomBreak() {
-        final ConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
-        configurationBuilder.setDebug(true);
-        final Configuration configuration = new Configuration(configurationBuilder);
-
-        final String fakeFileName = "test.rb";
-        final String code = "Debug.break('test.rb', 2) { puts 1; Debug.break }\nputs 3\nputs 4";
-        final String input = "puts 2 \n Debug.continue \n puts 'error' \n puts 'error'";
-        final String expected = "1\n2\n=> \n3\n4\n";
-
-        assertPrints(configuration, expected, fakeFileName, code, input, new String[]{});
-    }
-
-    @Test
-    public void testLocalBreak() {
-        final ConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
-        configurationBuilder.setDebug(true);
-        final Configuration configuration = new Configuration(configurationBuilder);
-
-        final String fakeFileName = "test.rb";
-        final String code = "def foo \n puts 0 \n x = 14 \n end \n Debug.break(:foo, :x) \n foo \n puts 2";
-        final String input = "puts 1 \n Debug.continue \n puts 'error' \n puts 'error'";
-        final String expected = "0\n1\n=> \n2\n";
-
-        assertPrints(configuration, expected, fakeFileName, code, input, new String[]{});
-    }
-
-    @Test
-    public void testLocalCustomBreak() {
-        final ConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
-        configurationBuilder.setDebug(true);
-        final Configuration configuration = new Configuration(configurationBuilder);
-
-        final String fakeFileName = "test.rb";
-        final String code = "def foo \n puts 0 \n x = 14 \n end \n Debug.break(:foo, :x) { |v| puts v; Debug.break } \n foo \n puts 2";
-        final String input = "puts 1 \n Debug.continue \n puts 'error' \n puts 'error'";
-        final String expected = "0\n14\n1\n=> \n2\n";
-
-        assertPrints(configuration, expected, fakeFileName, code, input, new String[]{});
-    }
-
-    @Test
-    public void testRemoveLineBreak() {
-        final ConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
-        configurationBuilder.setDebug(true);
-        final Configuration configuration = new Configuration(configurationBuilder);
-
-        final String fakeFileName = "test.rb";
-        final String code = "Debug.break('test.rb', 3) \n Debug.remove('test.rb', 3) \n puts 2 \n puts 3";
-        final String input = "puts 1 \n Debug.continue \n puts 'error' \n puts 'error'";
-        final String expected = "2\n3\n";
-
-        assertPrints(configuration, expected, fakeFileName, code, input, new String[]{});
-    }
-
-    @Test
-    public void testRemoveLocalBreak() {
-        final ConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
-        configurationBuilder.setDebug(true);
-        final Configuration configuration = new Configuration(configurationBuilder);
-
-        final String fakeFileName = "test.rb";
-        final String code = "def foo \n puts 0 \n x = 14 \n end \n Debug.break(:foo, :x) \n foo \n Debug.remove(:foo, :x) \n foo \n puts 2";
-        final String input = "puts 1 \n Debug.continue \n puts 'error' \n puts 'error'";
-        final String expected = "0\n1\n=> \n0\n2\n";
-
-        assertPrints(configuration, expected, fakeFileName, code, input, new String[]{});
-    }
-
-    @Test
-    public void testWhere() {
-        final ConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
-        configurationBuilder.setDebug(true);
-        final Configuration configuration = new Configuration(configurationBuilder);
-
-        final String fakeFileName = "test.rb";
-        final String code = "puts 1 \n Debug.where \n puts 2";
-        final String expected = "1\ntest.rb:2\n2\n";
-
-        assertPrints(configuration, expected, fakeFileName, code, "", new String[]{});
-    }
-
-}
--- a/make/bsd/makefiles/vm.make	Wed Jan 22 18:46:38 2014 +0100
+++ b/make/bsd/makefiles/vm.make	Fri Jan 24 00:33:56 2014 +0100
@@ -222,20 +222,22 @@
 
 ifneq ($(INCLUDE_GRAAL), true)
   GRAAL_SPECIFIC_FILES   := graal\*
+  GRAAL_SPECIFIC_GPU_FILES  := gpu\* ptx\* hsail\*
 else
   GRAAL_SPECIFIC_FILES   :=
+  GRAAL_SPECIFIC_GPU_FILES  :=
 endif
 
 # Always exclude these.
 Src_Files_EXCLUDE += jsig.c jvmtiEnvRecommended.cpp jvmtiEnvStub.cpp
 
 # Exclude per type.
-Src_Files_EXCLUDE/CORE      := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) ciTypeFlow.cpp
-Src_Files_EXCLUDE/COMPILER1 := $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) ciTypeFlow.cpp
-Src_Files_EXCLUDE/COMPILER2 := $(COMPILER1_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES)
-Src_Files_EXCLUDE/TIERED    := $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES)
-Src_Files_EXCLUDE/ZERO      := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) ciTypeFlow.cpp
-Src_Files_EXCLUDE/SHARK     := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES)
+Src_Files_EXCLUDE/CORE      := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) $(GRAAL_SPECIFIC_GPU_FILES) ciTypeFlow.cpp
+Src_Files_EXCLUDE/COMPILER1 := $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) $(GRAAL_SPECIFIC_GPU_FILES) ciTypeFlow.cpp
+Src_Files_EXCLUDE/COMPILER2 := $(COMPILER1_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) $(GRAAL_SPECIFIC_GPU_FILES)
+Src_Files_EXCLUDE/TIERED    := $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) $(GRAAL_SPECIFIC_GPU_FILES)
+Src_Files_EXCLUDE/ZERO      := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) $(GRAAL_SPECIFIC_GPU_FILES) ciTypeFlow.cpp
+Src_Files_EXCLUDE/SHARK     := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) $(GRAAL_SPECIFIC_GPU_FILES)
 Src_Files_EXCLUDE/GRAAL     := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) ciTypeFlow.cpp
 
 Src_Files_EXCLUDE +=  $(Src_Files_EXCLUDE/$(TYPE))
--- a/make/linux/makefiles/vm.make	Wed Jan 22 18:46:38 2014 +0100
+++ b/make/linux/makefiles/vm.make	Fri Jan 24 00:33:56 2014 +0100
@@ -201,21 +201,23 @@
 ZERO_SPECIFIC_FILES      := zero
 
 ifneq ($(INCLUDE_GRAAL), true)
-  GRAAL_SPECIFIC_FILES   := graal\*
+  GRAAL_SPECIFIC_FILES   := graal\* 
+  GRAAL_SPECIFIC_GPU_FILES  := gpu\* ptx\* hsail\*
 else
   GRAAL_SPECIFIC_FILES   :=
+  GRAAL_SPECIFIC_GPU_FILES   :=
 endif
 
 # Always exclude these.
 Src_Files_EXCLUDE += jsig.c jvmtiEnvRecommended.cpp jvmtiEnvStub.cpp
 
 # Exclude per type.
-Src_Files_EXCLUDE/CORE      := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) ciTypeFlow.cpp
-Src_Files_EXCLUDE/COMPILER1 := $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) ciTypeFlow.cpp
-Src_Files_EXCLUDE/COMPILER2 := $(COMPILER1_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES)
-Src_Files_EXCLUDE/TIERED    := $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES)
-Src_Files_EXCLUDE/ZERO      := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) ciTypeFlow.cpp
-Src_Files_EXCLUDE/SHARK     := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES)
+Src_Files_EXCLUDE/CORE      := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) $(GRAAL_SPECIFIC_GPU_FILES) ciTypeFlow.cpp
+Src_Files_EXCLUDE/COMPILER1 := $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) $(GRAAL_SPECIFIC_GPU_FILES) ciTypeFlow.cpp
+Src_Files_EXCLUDE/COMPILER2 := $(COMPILER1_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) $(GRAAL_SPECIFIC_GPU_FILES)
+Src_Files_EXCLUDE/TIERED    := $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) $(GRAAL_SPECIFIC_GPU_FILES)
+Src_Files_EXCLUDE/ZERO      := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) $(GRAAL_SPECIFIC_GPU_FILES) ciTypeFlow.cpp
+Src_Files_EXCLUDE/SHARK     := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) $(GRAAL_SPECIFIC_GPU_FILES)
 Src_Files_EXCLUDE/GRAAL     := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) ciTypeFlow.cpp
 
 Src_Files_EXCLUDE +=  $(Src_Files_EXCLUDE/$(TYPE))
--- a/make/solaris/makefiles/vm.make	Wed Jan 22 18:46:38 2014 +0100
+++ b/make/solaris/makefiles/vm.make	Fri Jan 24 00:33:56 2014 +0100
@@ -219,17 +219,18 @@
 SHARK_SPECIFIC_FILES     := shark
 ZERO_SPECIFIC_FILES      := zero
 GRAAL_SPECIFIC_FILES     := graal
+GRAAL_SPECIFIC_GPU_FILES  := gpu\* ptx\* hsail\*
 
 # Always exclude these.
 Src_Files_EXCLUDE := dtrace jsig.c jvmtiEnvRecommended.cpp jvmtiEnvStub.cpp
 
 # Exclude per type.
-Src_Files_EXCLUDE/CORE      := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) ciTypeFlow.cpp
-Src_Files_EXCLUDE/COMPILER1 := $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) ciTypeFlow.cpp
-Src_Files_EXCLUDE/COMPILER2 := $(COMPILER1_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES)
-Src_Files_EXCLUDE/TIERED    := $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES)
-Src_Files_EXCLUDE/ZERO      := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) ciTypeFlow.cpp
-Src_Files_EXCLUDE/SHARK     := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES)
+Src_Files_EXCLUDE/CORE      := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) $(GRAAL_SPECIFIC_GPU_FILES) ciTypeFlow.cpp
+Src_Files_EXCLUDE/COMPILER1 := $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) $(GRAAL_SPECIFIC_GPU_FILES) ciTypeFlow.cpp
+Src_Files_EXCLUDE/COMPILER2 := $(COMPILER1_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) $(GRAAL_SPECIFIC_GPU_FILES)
+Src_Files_EXCLUDE/TIERED    := $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) $(GRAAL_SPECIFIC_GPU_FILES)
+Src_Files_EXCLUDE/ZERO      := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) $(GRAAL_SPECIFIC_GPU_FILES) ciTypeFlow.cpp
+Src_Files_EXCLUDE/SHARK     := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) $(GRAAL_SPECIFIC_GPU_FILES)
 Src_Files_EXCLUDE/GRAAL     := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) ciTypeFlow.cpp
 
 Src_Files_EXCLUDE +=  $(Src_Files_EXCLUDE/$(TYPE))
--- a/src/share/vm/compiler/compileBroker.cpp	Wed Jan 22 18:46:38 2014 +0100
+++ b/src/share/vm/compiler/compileBroker.cpp	Fri Jan 24 00:33:56 2014 +0100
@@ -1144,7 +1144,9 @@
   }
 #ifdef GRAALVM
   if (!JavaThread::current()->is_graal_compiling()) {
-    GraalCompiler::instance()->compile_method(method, osr_bci, is_compile_blocking(method, osr_bci));
+    bool blockingCompilation = is_compile_blocking(method, osr_bci) ||
+      CompilationPolicy::can_be_offloaded_to_gpu(method);
+    GraalCompiler::instance()->compile_method(method, osr_bci, blockingCompilation);
   } else {
     // Recursive compile request => ignore.
   }
--- a/src/share/vm/graal/graalGlobals.hpp	Wed Jan 22 18:46:38 2014 +0100
+++ b/src/share/vm/graal/graalGlobals.hpp	Fri Jan 24 00:33:56 2014 +0100
@@ -79,6 +79,12 @@
   develop(bool, TraceUncollectedSpeculations, false,                        \
           "Print message when a failed speculation was not collected")      \
                                                                             \
+  product(bool, GPUOffload, false,                                          \
+          "Offload execution to GPU whenever possible")                     \
+                                                                            \
+  product(bool, TraceGPUInteraction, false,                                 \
+          "Trace external GPU Interaction")                                 \
+                                                                            \
 
 
 // Read default values for Graal globals
--- a/src/share/vm/oops/method.cpp	Wed Jan 22 18:46:38 2014 +0100
+++ b/src/share/vm/oops/method.cpp	Fri Jan 24 00:33:56 2014 +0100
@@ -2025,28 +2025,3 @@
   guarantee(md == NULL ||
       md->is_methodData(), "should be method data");
 }
-
-#ifdef GRAAL
-
-// Return true if the name of the method indicates that this is a
-// lambda method other than <init>. Lambda method is one with a name 
-// that starts with lambda$ and is synthetic.
-
-bool Method::is_lambda() const {
-  Symbol * klass_name = method_holder()->name();
-  Symbol * method_name = name();
-  ResourceMark rm;
-  if (klass_name != NULL) {
-    if (klass_name != NULL && method_name != NULL) {
-      const char* lambdaPrefix = "lambda$main$";
-      char* methodPrefix = strstr(method_name->as_C_string(), lambdaPrefix);
-      if (methodPrefix != 0) {
-        if ((strncmp(lambdaPrefix, methodPrefix, strlen(lambdaPrefix)) == 0) && is_synthetic()) {
-          return true;
-        }
-      }
-    }
-  }
-  return false;
-}
-#endif
--- a/src/share/vm/oops/method.hpp	Wed Jan 22 18:46:38 2014 +0100
+++ b/src/share/vm/oops/method.hpp	Fri Jan 24 00:33:56 2014 +0100
@@ -617,11 +617,6 @@
   // simultaneously. Use with caution.
   bool has_compiled_code() const                 { return code() != NULL; }
 
-#ifdef GRAAL
-  // Return true if the name of the method indicates that this is a
-  // lambda method other than <init>.
-  bool is_lambda() const;
-#endif
   // sizing
   static int header_size()                       { return sizeof(Method)/HeapWordSize; }
   static int size(bool is_native);
--- a/src/share/vm/runtime/compilationPolicy.cpp	Wed Jan 22 18:46:38 2014 +0100
+++ b/src/share/vm/runtime/compilationPolicy.cpp	Fri Jan 24 00:33:56 2014 +0100
@@ -105,30 +105,7 @@
 
   if (m->has_compiled_code()) return false;       // already compiled
 
-#ifdef GRAAL
-  // Check if this is a Lambda method that can be compiled to a GPU.
-  if (m->is_lambda()) {
-    // If GPU is available and the necessary linkage is available
-    // rerurn true indicatin that this method must be compiled.
-    if (gpu::is_available() && gpu::has_gpu_linkage()) {
-      if (TraceGPUInteraction) {
-        tty->print("Compiling Lambda method");
-        m->print_short_name();
-        switch (gpu::get_target_il_type()) {
-        case gpu::PTX :
-          tty->print_cr(" to PTX");
-          break;
-        case gpu::HSAIL :
-          tty->print_cr(" to HSAIL");
-          break;
-        default :
-          tty->print_cr(" to Unknown GPU!!!");
-        }
-      }
-      return true;
-    }
-  }
-#endif
+  if (CompilationPolicy::can_be_offloaded_to_gpu(m)) return true;
 
   if (!can_be_compiled(m, comp_level)) return false;
 
@@ -184,6 +161,58 @@
   return (result && can_be_compiled(m, comp_level));
 }
 
+bool CompilationPolicy::can_be_offloaded_to_gpu(methodHandle m) {
+#ifdef GRAAL
+  if (GPUOffload) {
+    // Check if this method can be offloaded to GPU.
+    // 1. Offload it to GPU if it is a Lambda method
+    if (m->is_synthetic()) {
+      // A lambda method is a syntheric method.
+      Symbol * klass_name = m->method_holder()->name();
+      Symbol * method_name = m->name();
+      bool offloadToGPU = false;
+      {
+        ResourceMark rm;
+        if (klass_name != NULL) {
+          if (klass_name != NULL && method_name != NULL) {
+            const char* lambdaPrefix = "lambda$";
+            char* methodPrefix = strstr(method_name->as_C_string(), lambdaPrefix);
+            if (methodPrefix != 0) {
+              if ((strncmp(lambdaPrefix, methodPrefix, strlen(lambdaPrefix)) == 0)) {
+                offloadToGPU = true;
+              }
+            }
+          }
+        }
+      }
+      if (offloadToGPU) {
+        // If GPU is available and the necessary linkage is available
+        // return true indicatin that this method must be compiled.
+        if (gpu::is_available() && gpu::has_gpu_linkage()) {
+          if (TraceGPUInteraction) {
+            tty->print("Compiling Lambda method ");
+            m->print_short_name();
+            switch (gpu::get_target_il_type()) {
+            case gpu::PTX :
+              tty->print_cr("to PTX");
+              break;
+            case gpu::HSAIL :
+              tty->print_cr("to HSAIL");
+              break;
+            default :
+              tty->print_cr("to Unknown GPU!!!");
+            }
+          }
+          return true;
+        }
+      }
+    }
+  }
+#endif
+
+  return false;
+}
+
 bool CompilationPolicy::is_compilation_enabled() {
   // NOTE: CompileBroker::should_compile_new_jobs() checks for UseCompiler
   return !delay_compilation_during_startup() && CompileBroker::should_compile_new_jobs();
--- a/src/share/vm/runtime/compilationPolicy.hpp	Wed Jan 22 18:46:38 2014 +0100
+++ b/src/share/vm/runtime/compilationPolicy.hpp	Fri Jan 24 00:33:56 2014 +0100
@@ -58,6 +58,9 @@
   static void set_policy(CompilationPolicy* policy) { _policy = policy; }
   static CompilationPolicy* policy()                { return _policy; }
 
+  // m is allowed to be offloaded to a gpu
+  static bool can_be_offloaded_to_gpu(methodHandle m);
+
   // Profiling
   elapsedTimer* accumulated_time() { return &_accumulated_time; }
   void print_time() PRODUCT_RETURN;
--- a/src/share/vm/runtime/globals.hpp	Wed Jan 22 18:46:38 2014 +0100
+++ b/src/share/vm/runtime/globals.hpp	Fri Jan 24 00:33:56 2014 +0100
@@ -3840,9 +3840,6 @@
   product(bool , AllowNonVirtualCalls, false,                               \
           "Obey the ACC_SUPER flag and allow invokenonvirtual calls")       \
                                                                             \
-  product(bool, TraceGPUInteraction, false,                                 \
-          "Trace external GPU Interaction")                                 \
-                                                                            \
   product(bool, UseHSAILSimulator, false,                                   \
           "Run code on HSAIL Simulator")                                    \
                                                                             \
--- a/src/share/vm/runtime/thread.cpp	Wed Jan 22 18:46:38 2014 +0100
+++ b/src/share/vm/runtime/thread.cpp	Fri Jan 24 00:33:56 2014 +0100
@@ -3394,9 +3394,13 @@
   jint parse_result = Arguments::parse(args);
   if (parse_result != JNI_OK) return parse_result;
 
-  // Probe for existance of supported GPU and initialize it if one
-  // exists.
-  gpu::init();
+#ifdef GRAAL
+  if (GPUOffload) {
+    // Probe for existance of supported GPU and initialize it if one
+    // exists.
+    gpu::init();
+  }
+#endif
 
   os::init_before_ergo();