changeset 22476:4a83dc15e774

Truffle/Debugging: reorganize Debugger/Suspended event to pass stack as FrameInstances; delete FrameDebugDescription
author Michael Van De Vanter <michael.van.de.vanter@oracle.com>
date Mon, 07 Dec 2015 20:48:29 -0800
parents c434681cd164
children 07f3efb4e321
files truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/Debugger.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/FrameDebugDescription.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/SuspendedEvent.java truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLHandler.java truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLServer.java
diffstat 5 files changed, 73 insertions(+), 110 deletions(-) [+]
line wrap: on
line diff
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/Debugger.java	Mon Dec 07 18:21:03 2015 -0800
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/Debugger.java	Mon Dec 07 20:48:29 2015 -0800
@@ -680,8 +680,11 @@
          */
         private MaterializedFrame haltedFrame;
 
-        /** Subset of the Truffle stack corresponding to the current execution. */
-        private List<FrameDebugDescription> contextStack;
+        /**
+         * Subset of the Truffle stack corresponding to the current execution, not including the
+         * current frame.
+         */
+        private List<FrameInstance> contextStack;
 
         private DebugExecutionContext(Source executionSource, DebugExecutionContext previousContext) {
             this(executionSource, previousContext, -1);
@@ -759,11 +762,10 @@
             final List<String> recentWarnings = new ArrayList<>(warnings);
             warnings.clear();
 
-            final List<FrameDebugDescription> frames = new ArrayList<>();
+            final List<FrameInstance> frames = new ArrayList<>();
             // Map the Truffle stack for this execution, ignore nested executions
             // Ignore frames for which no CallNode is available.
-            // The top/current/0 frame is not produced by the iterator.
-            frames.add(new FrameDebugDescription(0, haltedNode, haltedFrame));
+            // The top/current/0 frame is not produced by the iterator; reported separately
             Truffle.getRuntime().iterateFrames(new FrameInstanceVisitor<FrameInstance>() {
                 int stackIndex = 1;
                 int frameIndex = 1;
@@ -775,7 +777,7 @@
                         if (callNode != null) {
                             final SourceSection sourceSection = callNode.getEncapsulatingSourceSection();
                             if (sourceSection != null && !sourceSection.getIdentifier().equals("<unknown>")) {
-                                frames.add(new FrameDebugDescription(frameIndex, frameInstance));
+                                frames.add(frameInstance);
                                 frameIndex++;
                             } else if (TRACE) {
                                 if (callNode != null) {
@@ -783,7 +785,7 @@
                                 } else {
                                     contextTrace("HIDDEN frame added");
                                 }
-                                frames.add(new FrameDebugDescription(frameIndex, frameInstance));
+                                frames.add(frameInstance);
                                 frameIndex++;
                             }
                         } else if (TRACE) {
@@ -792,7 +794,7 @@
                             } else {
                                 contextTrace("HIDDEN frame added");
                             }
-                            frames.add(new FrameDebugDescription(frameIndex, frameInstance));
+                            frames.add(frameInstance);
                             frameIndex++;
                         }
                         stackIndex++;
@@ -813,7 +815,7 @@
 
             try {
                 // Pass control to the debug client with current execution suspended
-                ACCESSOR.dispatchEvent(vm, new SuspendedEvent(Debugger.this, contextStack, recentWarnings));
+                ACCESSOR.dispatchEvent(vm, new SuspendedEvent(Debugger.this, haltedNode, haltedFrame, contextStack, recentWarnings));
                 // Debug client finished normally, execution resumes
                 // Presume that the client has set a new strategy (or default to Continue)
                 running = true;
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/FrameDebugDescription.java	Mon Dec 07 18:21:03 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2015, 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.debug;
-
-import com.oracle.truffle.api.frame.FrameInstance;
-import com.oracle.truffle.api.frame.FrameInstance.FrameAccess;
-import com.oracle.truffle.api.frame.MaterializedFrame;
-import com.oracle.truffle.api.nodes.Node;
-
-/**
- * Summary of information about a frame for use by debugging clients.
- */
-public final class FrameDebugDescription {
-    private final int index;
-    private final Node node;
-    private final MaterializedFrame frame;
-
-    FrameDebugDescription(int index, Node node, MaterializedFrame frame) {
-        this.index = index;
-        this.node = node;
-        this.frame = frame;
-    }
-
-    FrameDebugDescription(int index, FrameInstance frameInstance) {
-        this.index = index;
-        this.node = frameInstance.getCallNode();
-        this.frame = frameInstance.getFrame(FrameAccess.MATERIALIZE, true).materialize();
-    }
-
-    /**
-     * Position in the current stack: {@code 0} at the top.
-     */
-    public int index() {
-        return index;
-    }
-
-    /**
-     * AST location of the call that created the frame.
-     */
-    public Node node() {
-        return node;
-    }
-
-    public MaterializedFrame frame() {
-        return frame;
-    }
-}
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/SuspendedEvent.java	Mon Dec 07 18:21:03 2015 -0800
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/SuspendedEvent.java	Mon Dec 07 20:48:29 2015 -0800
@@ -30,6 +30,8 @@
 import java.util.List;
 
 import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.frame.FrameInstance;
+import com.oracle.truffle.api.frame.FrameInstance.FrameAccess;
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.instrument.StandardSyntaxTag;
 import com.oracle.truffle.api.nodes.Node;
@@ -58,15 +60,19 @@
     }
 
     private final Debugger debugger;
-    private final List<FrameDebugDescription> stack;
+    private final Node haltedNode;
+    private final MaterializedFrame haltedFrame;
+    private final List<FrameInstance> stack;
     private final List<String> warnings;
 
-    SuspendedEvent(Debugger debugger, List<FrameDebugDescription> stack, List<String> warnings) {
+    SuspendedEvent(Debugger debugger, Node haltedNode, MaterializedFrame haltedFrame, List<FrameInstance> stack, List<String> warnings) {
         this.debugger = debugger;
+        this.haltedNode = haltedNode;
+        this.haltedFrame = haltedFrame;
         this.stack = stack;
         this.warnings = warnings;
         if (TRACE) {
-            trace("Execution suspended at Node=" + stack.get(0).node());
+            trace("Execution suspended at Node=" + haltedNode);
         }
     }
 
@@ -83,11 +89,11 @@
     }
 
     public Node getNode() {
-        return stack.get(0).node();
+        return haltedNode;
     }
 
     public MaterializedFrame getFrame() {
-        return stack.get(0).frame();
+        return haltedFrame;
     }
 
     public List<String> getRecentWarnings() {
@@ -96,12 +102,13 @@
 
     /**
      * Gets the stack frames from the currently halted
-     * {@link com.oracle.truffle.api.vm.PolyglotEngine} execution.
+     * {@link com.oracle.truffle.api.vm.PolyglotEngine} execution, not counting the Node and Frame
+     * where halted.
      *
      * @return list of stack frames
      */
     @CompilerDirectives.TruffleBoundary
-    public List<FrameDebugDescription> getStack() {
+    public List<FrameInstance> getStack() {
         return stack;
     }
 
@@ -188,20 +195,20 @@
      * Evaluates given code snippet in the context of currently suspended execution.
      *
      * @param code the snippet to evaluate
-     * @param frameNumber <code>null</code> in case the evaluation should happen in top most frame,
-     *            non-null value to specify a frame from those {@link #getStack() currently on
-     *            stack} to perform the evaluation in context of
+     * @param frameNumber specify a frame from those {@link #getStack() currently on stack} to
+     *            perform the evaluation in context of
      * @return the computed value
      * @throws IOException in case an evaluation goes wrong
      */
     public Object eval(String code, Integer frameNumber) throws IOException {
-        int n = 0;
-        if (frameNumber != null) {
-            if (frameNumber < 0 || frameNumber >= stack.size()) {
-                throw new IOException("invalid frame number");
-            }
-            n = frameNumber;
+        if (frameNumber < 0 || frameNumber >= stack.size()) {
+            throw new IOException("invalid frame number");
         }
-        return debugger.evalInContext(this, code, stack.get(n).node(), stack.get(n).frame());
+        if (frameNumber == 0) {
+            return debugger.evalInContext(this, code, haltedNode, haltedFrame);
+        }
+        final FrameInstance instance = stack.get(frameNumber - 1);
+        final MaterializedFrame frame = instance.getFrame(FrameAccess.MATERIALIZE, true).materialize();
+        return debugger.evalInContext(this, code, instance.getCallNode(), frame);
     }
 }
--- a/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLHandler.java	Mon Dec 07 18:21:03 2015 -0800
+++ b/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLHandler.java	Mon Dec 07 20:48:29 2015 -0800
@@ -29,9 +29,10 @@
 import java.util.Collection;
 import java.util.List;
 
-import com.oracle.truffle.api.debug.FrameDebugDescription;
-import com.oracle.truffle.api.frame.Frame;
+import com.oracle.truffle.api.frame.FrameInstance;
+import com.oracle.truffle.api.frame.FrameInstance.FrameAccess;
 import com.oracle.truffle.api.frame.FrameSlot;
+import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.instrument.ASTPrinter;
 import com.oracle.truffle.api.instrument.KillException;
 import com.oracle.truffle.api.instrument.QuitException;
@@ -150,10 +151,11 @@
         public REPLMessage[] receive(REPLMessage request, REPLServer replServer) {
             final Visualizer visualizer = replServer.getVisualizer();
             final ArrayList<REPLMessage> replies = new ArrayList<>();
-            final List<FrameDebugDescription> stack = replServer.getCurrentContext().getStack();
-
-            for (int i = 0; i < stack.size(); i++) {
-                replies.add(btMessage(i, stack.get(i).node(), visualizer));
+            final Context currentContext = replServer.getCurrentContext();
+            final List<FrameInstance> stack = currentContext.getStack();
+            replies.add(btMessage(0, currentContext.getNode(), visualizer));
+            for (int i = 1; i <= stack.size(); i++) {
+                replies.add(btMessage(i, stack.get(i - 1).getCallNode(), visualizer));
             }
             if (replies.size() > 0) {
                 return replies.toArray(new REPLMessage[0]);
@@ -469,17 +471,24 @@
             if (frameNumber == null) {
                 return finishReplyFailed(createReply(), "no frame number specified");
             }
-            final List<FrameDebugDescription> stack = replServer.getCurrentContext().getStack();
-            if (frameNumber < 0 || frameNumber >= stack.size()) {
+            final Context currentContext = replServer.getCurrentContext();
+            final List<FrameInstance> stack = currentContext.getStack();
+            if (frameNumber < 0 || frameNumber > stack.size()) {
                 return finishReplyFailed(createReply(), "frame number " + frameNumber + " out of range");
             }
             final Visualizer visualizer = replServer.getVisualizer();
 
-            final FrameDebugDescription frameDescription = stack.get(frameNumber);
-            final Frame frame = frameDescription.frame();
-            final Node node = frameDescription.node();
+            MaterializedFrame frame;
+            Node node;
+            if (frameNumber == 0) {
+                frame = currentContext.getFrame();
+                node = currentContext.getNode();
+            } else {
+                final FrameInstance instance = stack.get(frameNumber - 1);
+                frame = instance.getFrame(FrameAccess.MATERIALIZE, true).materialize();
+                node = instance.getCallNode();
+            }
             List<? extends FrameSlot> slots = frame.getFrameDescriptor().getSlots();
-
             if (slots.size() == 0) {
                 final REPLMessage emptyFrameMessage = createFrameInfoMessage(replServer, frameNumber, node);
                 return finishReplySucceeded(emptyFrameMessage, "empty frame");
--- a/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLServer.java	Mon Dec 07 18:21:03 2015 -0800
+++ b/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLServer.java	Mon Dec 07 20:48:29 2015 -0800
@@ -39,8 +39,8 @@
 import com.oracle.truffle.api.debug.Breakpoint.State;
 import com.oracle.truffle.api.debug.Debugger;
 import com.oracle.truffle.api.debug.ExecutionEvent;
-import com.oracle.truffle.api.debug.FrameDebugDescription;
 import com.oracle.truffle.api.debug.SuspendedEvent;
+import com.oracle.truffle.api.frame.FrameInstance;
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.instrument.StandardSyntaxTag;
 import com.oracle.truffle.api.instrument.SyntaxTag;
@@ -377,11 +377,25 @@
         }
 
         /**
-         * Provides access to the execution stack.
+         * @return Node where halted
+         */
+        Node getNode() {
+            return event.getNode();
+        }
+
+        /**
+         * @return Frame where halted
+         */
+        MaterializedFrame getFrame() {
+            return event.getFrame();
+        }
+
+        /**
+         * Provides access to the execution stack, not counting the node/frame where halted.
          *
          * @return immutable list of stack elements
          */
-        List<FrameDebugDescription> getStack() {
+        List<FrameInstance> getStack() {
             return event.getStack();
         }