# HG changeset patch # User Michael Van De Vanter # Date 1449461629 28800 # Node ID a6c162686d8129526bf7f21e1f83a13df11c4560 # Parent 64d5619ebbce023ee7dbf4f3ce1e9373738979ce Truffle/Language&Debugger: reimplement completely how the execution stack is gathered and communicated; change the signature of TruffelLanguage.evalInContext() to comply. diff -r 64d5619ebbce -r a6c162686d81 truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java Sun Dec 06 20:12:43 2015 -0800 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java Sun Dec 06 20:13:49 2015 -0800 @@ -33,12 +33,11 @@ import java.lang.annotation.Target; import java.util.Collections; import java.util.Map; +import java.util.Objects; import java.util.WeakHashMap; import com.oracle.truffle.api.debug.Debugger; import com.oracle.truffle.api.debug.SuspendedEvent; -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.impl.Accessor; import com.oracle.truffle.api.impl.FindContextNode; @@ -53,8 +52,6 @@ import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.source.Source; -import java.util.Objects; - /** * An entry point for everyone who wants to implement a Truffle based language. By providing an * implementation of this type and registering it using {@link Registration} annotation, your @@ -395,7 +392,7 @@ * . The names of arguments are parameters for the resulting {#link CallTarget} that allow * the source to reference the actual parameters passed to * {@link CallTarget#call(java.lang.Object...)}. - * + * * @param source the source to evaluate * @param argumentNames the names of {@link CallTarget#call(java.lang.Object...)} arguments * that can be referenced from the source @@ -482,20 +479,13 @@ } @Override - protected Object evalInContext(Object vm, SuspendedEvent ev, String code, FrameInstance frame) throws IOException { - Node n = ev.getNode(); - if (n == null && frame != null) { - n = frame.getCallNode(); - } - if (n == null) { - throw new IOException("Can't determine language for text \"" + code + "\""); - } - RootNode rootNode = n.getRootNode(); + protected Object evalInContext(Object vm, SuspendedEvent ev, String code, Node node, MaterializedFrame frame) throws IOException { + RootNode rootNode = node.getRootNode(); Class languageType = findLanguage(rootNode); final Env env = findLanguage(vm, languageType); final TruffleLanguage lang = findLanguage(env); final Source source = Source.fromText(code, "eval in context"); - return lang.evalInContext(source, n, frame.getFrame(FrameAccess.READ_ONLY, true).materialize()); + return lang.evalInContext(source, node, frame); } @Override diff -r 64d5619ebbce -r a6c162686d81 truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/Debugger.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/Debugger.java Sun Dec 06 20:12:43 2015 -0800 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/Debugger.java Sun Dec 06 20:13:49 2015 -0800 @@ -29,6 +29,7 @@ import java.io.PrintStream; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.List; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; @@ -50,6 +51,7 @@ import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.source.LineLocation; import com.oracle.truffle.api.source.Source; +import com.oracle.truffle.api.source.SourceSection; /** * Represents debugging related state of a {@link com.oracle.truffle.api.vm.PolyglotEngine}. @@ -678,6 +680,9 @@ */ private MaterializedFrame haltedFrame; + /** Subset of the Truffle stack corresponding to the current execution. */ + private List contextStack; + private DebugExecutionContext(Source executionSource, DebugExecutionContext previousContext) { this(executionSource, previousContext, -1); } @@ -748,7 +753,56 @@ // Clean up, just in cased the one-shot breakpoints got confused lineBreaks.disposeOneShots(); - final int contextStackDepth = currentStackDepth() - contextStackBase; + // Includes the "caller" frame (not iterated) + final int contextStackDepth = (currentStackDepth() - contextStackBase) + 1; + + final List recentWarnings = new ArrayList<>(warnings); + warnings.clear(); + + final List 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)); + Truffle.getRuntime().iterateFrames(new FrameInstanceVisitor() { + int stackIndex = 1; + int frameIndex = 1; + + @Override + public FrameInstance visitFrame(FrameInstance frameInstance) { + if (stackIndex < contextStackDepth) { + final Node callNode = frameInstance.getCallNode(); + if (callNode != null) { + final SourceSection sourceSection = callNode.getEncapsulatingSourceSection(); + if (sourceSection != null && sourceSection.getIdentifier() != SourceSection.UNKNOWN) { + frames.add(new FrameDebugDescription(frameIndex, frameInstance)); + frameIndex++; + } else if (TRACE) { + if (callNode != null) { + contextTrace("HIDDEN frame added: " + callNode); + } else { + contextTrace("HIDDEN frame added"); + } + frames.add(new FrameDebugDescription(frameIndex, frameInstance)); + frameIndex++; + } + } else if (TRACE) { + if (callNode != null) { + contextTrace("HIDDEN frame added: " + callNode); + } else { + contextTrace("HIDDEN frame added"); + } + frames.add(new FrameDebugDescription(frameIndex, frameInstance)); + frameIndex++; + } + stackIndex++; + return null; + } + return frameInstance; + } + }); + contextStack = Collections.unmodifiableList(frames); + if (TRACE) { final String reason = haltReason == null ? "" : haltReason + ""; final String where = before ? "BEFORE" : "AFTER"; @@ -757,12 +811,9 @@ // printStack(OUT); } - final List recentWarnings = new ArrayList<>(warnings); - warnings.clear(); - try { // Pass control to the debug client with current execution suspended - ACCESSOR.dispatchEvent(vm, new SuspendedEvent(Debugger.this, astNode, mFrame, recentWarnings, contextStackDepth)); + ACCESSOR.dispatchEvent(vm, new SuspendedEvent(Debugger.this, contextStack, recentWarnings)); // Debug client finished normally, execution resumes // Presume that the client has set a new strategy (or default to Continue) running = true; @@ -840,8 +891,8 @@ debugContext = debugContext.predecessor; } - Object evalInContext(SuspendedEvent ev, String code, FrameInstance frame) throws IOException { - return ACCESSOR.evalInContext(vm, ev, code, frame); + Object evalInContext(SuspendedEvent ev, String code, Node node, MaterializedFrame frame) throws IOException { + return ACCESSOR.evalInContext(vm, ev, code, node, frame); } @SuppressWarnings("rawtypes") @@ -874,8 +925,8 @@ } @Override - protected Object evalInContext(Object vm, SuspendedEvent ev, String code, FrameInstance frame) throws IOException { - return super.evalInContext(vm, ev, code, frame); + protected Object evalInContext(Object vm, SuspendedEvent ev, String code, Node node, MaterializedFrame frame) throws IOException { + return super.evalInContext(vm, ev, code, node, frame); } } diff -r 64d5619ebbce -r a6c162686d81 truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/FrameDebugDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/FrameDebugDescription.java Sun Dec 06 20:13:49 2015 -0800 @@ -0,0 +1,69 @@ +/* + * 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; + } +} diff -r 64d5619ebbce -r a6c162686d81 truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/SuspendedEvent.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/SuspendedEvent.java Sun Dec 06 20:12:43 2015 -0800 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/SuspendedEvent.java Sun Dec 06 20:13:49 2015 -0800 @@ -25,14 +25,11 @@ package com.oracle.truffle.api.debug; import java.io.IOException; -import java.util.ArrayList; +import java.io.PrintStream; import java.util.Collections; import java.util.List; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.Truffle; -import com.oracle.truffle.api.frame.FrameInstance; -import com.oracle.truffle.api.frame.FrameInstanceVisitor; import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.instrument.StandardSyntaxTag; import com.oracle.truffle.api.nodes.Node; @@ -49,37 +46,28 @@ */ @SuppressWarnings("javadoc") public final class SuspendedEvent { - private final List recentWarnings; - private final MaterializedFrame mFrame; - private final Node astNode; - private final List frames; - private final int stackSize; - private final Debugger debugger; + + private static boolean TRACE = false; + private static final String TRACE_PREFIX = "EVENT: "; + private static final PrintStream OUT = System.out; - SuspendedEvent(Debugger prepares, Node astNode, MaterializedFrame mFrame, List recentWarnings, final int stackDepth) { - this.debugger = prepares; - this.astNode = astNode; - this.mFrame = mFrame; - this.recentWarnings = recentWarnings; + private static void trace(String format, Object... args) { + if (TRACE) { + OUT.println(TRACE_PREFIX + String.format(format, args)); + } + } - this.frames = new ArrayList<>(); - // Map the Truffle stack for this execution, ignore nested executions - // The top (current) frame is not produced by the iterator. - frames.add(Truffle.getRuntime().getCurrentFrame()); - Truffle.getRuntime().iterateFrames(new FrameInstanceVisitor() { - int frameCount = 1; + private final Debugger debugger; + private final List stack; + private final List warnings; - @Override - public FrameInstance visitFrame(FrameInstance frameInstance) { - if (frameCount < stackDepth) { - frames.add(frameInstance); - frameCount++; - return null; - } - return frameInstance; - } - }); - stackSize = frames.size(); + SuspendedEvent(Debugger debugger, List stack, List warnings) { + this.debugger = debugger; + this.stack = stack; + this.warnings = warnings; + if (TRACE) { + trace("Execution suspended at Node=" + stack.get(0).node()); + } } /** @@ -95,15 +83,15 @@ } public Node getNode() { - return astNode; + return stack.get(0).node(); } public MaterializedFrame getFrame() { - return mFrame; + return stack.get(0).frame(); } public List getRecentWarnings() { - return Collections.unmodifiableList(recentWarnings); + return Collections.unmodifiableList(warnings); } /** @@ -113,8 +101,8 @@ * @return list of stack frames */ @CompilerDirectives.TruffleBoundary - public List getStack() { - return Collections.unmodifiableList(frames); + public List getStack() { + return stack; } /** @@ -209,11 +197,11 @@ public Object eval(String code, Integer frameNumber) throws IOException { int n = 0; if (frameNumber != null) { - if (frameNumber < 0 || frameNumber >= stackSize) { + if (frameNumber < 0 || frameNumber >= stack.size()) { throw new IOException("invalid frame number"); } n = frameNumber; } - return debugger.evalInContext(this, code, frames.get(n)); + return debugger.evalInContext(this, code, stack.get(n).node(), stack.get(n).frame()); } } diff -r 64d5619ebbce -r a6c162686d81 truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java Sun Dec 06 20:12:43 2015 -0800 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java Sun Dec 06 20:13:49 2015 -0800 @@ -39,7 +39,6 @@ import com.oracle.truffle.api.TruffleLanguage.Env; import com.oracle.truffle.api.debug.Debugger; 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.ASTProber; import com.oracle.truffle.api.instrument.Instrumenter; @@ -157,8 +156,8 @@ return API.eval(l, s); } - protected Object evalInContext(Object vm, SuspendedEvent ev, String code, FrameInstance frame) throws IOException { - return API.evalInContext(vm, ev, code, frame); + protected Object evalInContext(Object vm, SuspendedEvent ev, String code, Node node, MaterializedFrame frame) throws IOException { + return API.evalInContext(vm, ev, code, node, frame); } protected Object importSymbol(Object vm, TruffleLanguage queryingLang, String globalName) { diff -r 64d5619ebbce -r a6c162686d81 truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/REPLRemoteCommand.java --- a/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/REPLRemoteCommand.java Sun Dec 06 20:12:43 2015 -0800 +++ b/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/REPLRemoteCommand.java Sun Dec 06 20:13:49 2015 -0800 @@ -203,7 +203,7 @@ public static final REPLRemoteCommand CALL_CMD = new REPLRemoteCommand("call", null, "call a method/function") { - private final String[] help = {"call : calls a function by name, arguments not yet supported"}; + private final String[] help = {"call : calls a function by name"}; @Override public String[] getHelp() { @@ -242,6 +242,30 @@ } }; + public static final REPLRemoteCommand CALL_STEP_INTO_CMD = new REPLRemoteCommand("call-step-into", "calls", "Call a method/function and step into") { + + private final String[] help = {"call : calls function by name and step into"}; + + @Override + public String[] getHelp() { + return help; + } + + @Override + public REPLMessage createRequest(REPLClientContext context, String[] args) { + final REPLMessage request = CALL_CMD.createRequest(context, args); + if (request != null) { + request.put(REPLMessage.STEP_INTO, REPLMessage.TRUE); + } + return request; + } + + @Override + void processReply(REPLClientContext context, REPLMessage[] replies) { + CALL_CMD.processReply(context, replies); + } + }; + public static final REPLRemoteCommand CLEAR_BREAK_CMD = new REPLRemoteCommand("clear", null, "Clear a breakpoint") { private final String[] help = {"clear : clear breakpoint number "}; @@ -670,13 +694,12 @@ @Override public REPLMessage createRequest(REPLClientContext context, String[] args) { - if (args.length == 1) { - context.displayFailReply("no language specified"); - return null; - } + final REPLMessage request = new REPLMessage(); request.put(REPLMessage.OP, REPLMessage.SET_LANGUAGE); - request.put(REPLMessage.LANG_NAME, args[1]); + if (args.length > 1) { + request.put(REPLMessage.LANG_NAME, args[1]); + } return request; } diff -r 64d5619ebbce -r a6c162686d81 truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/SimpleREPLClient.java --- a/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/SimpleREPLClient.java Sun Dec 06 20:12:43 2015 -0800 +++ b/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/SimpleREPLClient.java Sun Dec 06 20:13:49 2015 -0800 @@ -94,8 +94,8 @@ static final String CODE_LINE_FORMAT = " %3d %s\n"; static final String CODE_LINE_BREAK_FORMAT = "--> %3d %s\n"; - private static final String STACK_FRAME_FORMAT = " %3d: at %s in %s line =\"%s\"\n"; - private static final String STACK_FRAME_SELECTED_FORMAT = "==> %3d: at %s in %s line =\"%s\"\n"; + private static final String STACK_FRAME_FORMAT = " %3d: at %s in %s %s\n"; + private static final String STACK_FRAME_SELECTED_FORMAT = "==> %3d: at %s in %s %s\n"; // Top level commands private final Map commandMap = new HashMap<>(); @@ -158,6 +158,7 @@ addCommand(REPLRemoteCommand.BREAK_AT_THROW_CMD); addCommand(REPLRemoteCommand.BREAK_AT_THROW_ONCE_CMD); addCommand(REPLRemoteCommand.CALL_CMD); + addCommand(REPLRemoteCommand.CALL_STEP_INTO_CMD); addCommand(REPLRemoteCommand.CLEAR_BREAK_CMD); addCommand(REPLRemoteCommand.CONDITION_BREAK_CMD); addCommand(REPLRemoteCommand.CONTINUE_CMD); @@ -309,12 +310,13 @@ if (replies[0].get(REPLMessage.STATUS).equals(REPLMessage.SUCCEEDED)) { languageName = replies[0].get(REPLMessage.LANG_NAME); } + final String showLang = languageName == null ? "() " : "( " + languageName + " )"; if (level == 0) { // 0-level context; no executions halted. if (selectedSource == null) { - currentPrompt = languageName == null ? "() " : "( " + languageName + " ) "; + currentPrompt = showLang + " "; } else { - currentPrompt = "(" + selectedSource.getShortName() + ") "; + currentPrompt = "(" + selectedSource.getShortName() + ") " + showLang + " "; } } else if (selectedSource != null && selectedSource != haltedSource) { // User is focusing somewhere else than the current locn; show no line number. @@ -322,7 +324,7 @@ sb.append("(<" + Integer.toString(level) + "> "); sb.append(selectedSource.getShortName()); sb.append(")"); - sb.append("(" + languageName + ")"); + sb.append(showLang); sb.append(" "); currentPrompt = sb.toString(); } else { @@ -334,7 +336,7 @@ sb.append(":" + Integer.toString(haltedLineNumber)); } sb.append(")"); - sb.append("(" + languageName + ")"); + sb.append(showLang); sb.append(" "); currentPrompt = sb.toString(); } @@ -466,7 +468,9 @@ for (REPLFrame frame : frameList) { String sourceLineText = frame.sourceLineText(); if (sourceLineText == null) { - sourceLineText = ""; + sourceLineText = ""; + } else { + sourceLineText = "line=\"" + sourceLineText + "\""; } if (frame.index() == selectedFrameNumber) { writer.format(STACK_FRAME_SELECTED_FORMAT, frame.index(), frame.locationDescription(), frame.name(), sourceLineText); diff -r 64d5619ebbce -r a6c162686d81 truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/FrameDebugDescription.java --- a/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/FrameDebugDescription.java Sun Dec 06 20:12:43 2015 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +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.tools.debug.shell.server; - -import com.oracle.truffle.api.frame.Frame; -import com.oracle.truffle.api.frame.FrameInstance; -import com.oracle.truffle.api.nodes.Node; - -public final class FrameDebugDescription { - private final int index; - private final Node node; - private final FrameInstance frameInstance; - - FrameDebugDescription(int index, Node node, FrameInstance frameInstance) { - this.index = index; - this.node = node; - this.frameInstance = frameInstance; - } - - /** - * Position in the current stack: {@code 0} at the top. - */ - public int index() { - return index; - } - - /** - * AST location. - */ - public Node node() { - return node; - } - - /** - * Access to the Truffle {@link Frame}. - */ - public FrameInstance frameInstance() { - return frameInstance; - } -} diff -r 64d5619ebbce -r a6c162686d81 truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLHandler.java --- a/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLHandler.java Sun Dec 06 20:12:43 2015 -0800 +++ b/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLHandler.java Sun Dec 06 20:13:49 2015 -0800 @@ -30,9 +30,8 @@ import java.util.List; import com.oracle.truffle.api.debug.Breakpoint; +import com.oracle.truffle.api.debug.FrameDebugDescription; import com.oracle.truffle.api.frame.Frame; -import com.oracle.truffle.api.frame.FrameDescriptor; -import com.oracle.truffle.api.frame.FrameInstance; import com.oracle.truffle.api.frame.FrameSlot; import com.oracle.truffle.api.instrument.ASTPrinter; import com.oracle.truffle.api.instrument.KillException; @@ -123,12 +122,10 @@ return infoMessage; } - protected static final REPLMessage createFrameInfoMessage(final REPLServer replServer, FrameDebugDescription frame) { + protected static final REPLMessage createFrameInfoMessage(final REPLServer replServer, int number, Node node) { final Visualizer visualizer = replServer.getVisualizer(); final REPLMessage infoMessage = new REPLMessage(REPLMessage.OP, REPLMessage.FRAME_INFO); - infoMessage.put(REPLMessage.FRAME_NUMBER, Integer.toString(frame.index())); - final Node node = frame.node(); - + infoMessage.put(REPLMessage.FRAME_NUMBER, Integer.toString(number)); infoMessage.put(REPLMessage.SOURCE_LOCATION, visualizer.displaySourceLocation(node)); infoMessage.put(REPLMessage.METHOD_NAME, visualizer.displayMethodName(node)); @@ -151,18 +148,40 @@ @Override public REPLMessage[] receive(REPLMessage request, REPLServer replServer) { - final REPLMessage reply = createReply(); - final ArrayList frameMessages = new ArrayList<>(); - for (FrameDebugDescription frame : replServer.getCurrentContext().getStack()) { - frameMessages.add(createFrameInfoMessage(replServer, frame)); + final Visualizer visualizer = replServer.getVisualizer(); + final ArrayList replies = new ArrayList<>(); + final List stack = replServer.getCurrentContext().getStack(); + + for (int i = 0; i < stack.size(); i++) { + replies.add(btMessage(i, stack.get(i).node(), visualizer)); } - if (frameMessages.size() > 0) { - return frameMessages.toArray(new REPLMessage[0]); + if (replies.size() > 0) { + return replies.toArray(new REPLMessage[0]); } - return finishReplyFailed(reply, "No stack"); + return finishReplyFailed(new REPLMessage(REPLMessage.OP, REPLMessage.BACKTRACE), "No stack"); } }; + private static REPLMessage btMessage(int index, Node node, Visualizer visualizer) { + final REPLMessage btMessage = new REPLMessage(REPLMessage.OP, REPLMessage.BACKTRACE); + btMessage.put(REPLMessage.FRAME_NUMBER, Integer.toString(index)); + if (node != null) { + btMessage.put(REPLMessage.SOURCE_LOCATION, visualizer.displaySourceLocation(node)); + btMessage.put(REPLMessage.METHOD_NAME, visualizer.displayMethodName(node)); + SourceSection section = node.getSourceSection(); + if (section == null) { + section = node.getEncapsulatingSourceSection(); + } + if (section != null && section.getSource() != null) { + btMessage.put(REPLMessage.FILE_PATH, section.getSource().getPath()); + btMessage.put(REPLMessage.LINE_NUMBER, Integer.toString(section.getStartLine())); + btMessage.put(REPLMessage.SOURCE_LINE_TEXT, section.getSource().getCode(section.getStartLine())); + } + btMessage.put(REPLMessage.STATUS, REPLMessage.SUCCEEDED); + } + return btMessage; + } + public static final REPLHandler BREAK_AT_LINE_HANDLER = new REPLHandler(REPLMessage.BREAK_AT_LINE) { @Override @@ -299,8 +318,9 @@ } argList.add(arg); } + final boolean stepInto = REPLMessage.TRUE.equals(request.get(REPLMessage.STEP_INTO)); try { - final Object result = replServer.call(callName, argList); + final Object result = replServer.getCurrentContext().call(callName, stepInto, argList); reply.put(REPLMessage.VALUE, result == null ? "" : result.toString()); } catch (QuitException ex) { throw ex; @@ -463,20 +483,21 @@ 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.frameInstance().getFrame(FrameInstance.FrameAccess.READ_ONLY, true); - final Visualizer visualizer = replServer.getVisualizer(); - final FrameDescriptor frameDescriptor = frame.getFrameDescriptor(); - final List slots = frameDescriptor.getSlots(); + final Frame frame = frameDescription.frame(); + final Node node = frameDescription.node(); + List slots = frame.getFrameDescriptor().getSlots(); + if (slots.size() == 0) { - final REPLMessage emptyFrameMessage = createFrameInfoMessage(replServer, frameDescription); + final REPLMessage emptyFrameMessage = createFrameInfoMessage(replServer, frameNumber, node); return finishReplySucceeded(emptyFrameMessage, "empty frame"); } final ArrayList replies = new ArrayList<>(); for (FrameSlot slot : slots) { - final REPLMessage slotMessage = createFrameInfoMessage(replServer, frameDescription); + final REPLMessage slotMessage = createFrameInfoMessage(replServer, frameNumber, node); slotMessage.put(REPLMessage.SLOT_INDEX, Integer.toString(slot.getIndex())); slotMessage.put(REPLMessage.SLOT_ID, visualizer.displayIdentifier(slot)); slotMessage.put(REPLMessage.SLOT_VALUE, visualizer.displayValue(frame.getValue(slot), 0)); @@ -580,7 +601,9 @@ final REPLMessage reply = new REPLMessage(REPLMessage.OP, REPLMessage.SET_LANGUAGE); String languageName = request.get(REPLMessage.LANG_NAME); if (languageName == null) { - return finishReplyFailed(reply, "missing language name"); + final String oldLanguageName = replServer.getCurrentContext().getLanguageName(); + reply.put(REPLMessage.LANG_NAME, reply.put(REPLMessage.LANG_NAME, oldLanguageName)); + return finishReplySucceeded(reply, "Language set to " + oldLanguageName); } reply.put(REPLMessage.LANG_NAME, languageName); try { diff -r 64d5619ebbce -r a6c162686d81 truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLServer.java --- a/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLServer.java Sun Dec 06 20:12:43 2015 -0800 +++ b/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLServer.java Sun Dec 06 20:13:49 2015 -0800 @@ -27,7 +27,6 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; @@ -39,10 +38,10 @@ import com.oracle.truffle.api.debug.Breakpoint; 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.LineBreakpoint; import com.oracle.truffle.api.debug.SuspendedEvent; import com.oracle.truffle.api.debug.TagBreakpoint; -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; @@ -313,6 +312,29 @@ return event.getNode(); } + Object call(String name, boolean stepInto, List argList) throws IOException { + Value symbol = engine.findGlobalSymbol(name); + if (symbol == null) { + throw new IOException("symbol \"" + name + "\" not found"); + } + final List args = new ArrayList<>(); + for (String stringArg : argList) { + Integer intArg = null; + try { + intArg = Integer.valueOf(stringArg); + args.add(intArg); + } catch (NumberFormatException e) { + args.add(stringArg); + } + } + this.steppingInto = stepInto; + try { + return symbol.invoke(null, args.toArray(new Object[0])).get(); + } finally { + this.steppingInto = false; + } + } + void eval(Source source, boolean stepInto) throws IOException { this.steppingInto = stepInto; try { @@ -385,17 +407,7 @@ * @return immutable list of stack elements */ List getStack() { - List frames = new ArrayList<>(); - int frameCount = 0; - for (FrameInstance frameInstance : event.getStack()) { - if (frameCount == 1) { - frames.add(new FrameDebugDescription(frameCount, event.getNode(), frameInstance)); - } else { - frames.add(new FrameDebugDescription(frameCount, frameInstance.getCallNode(), frameInstance)); - } - frameCount++; - } - return Collections.unmodifiableList(frames); + return event.getStack(); } public String getLanguageName() { @@ -404,11 +416,20 @@ /** * Case-insensitive; returns actual language name set. + * + * @throws IOException if fails */ - String setLanguage(String name) { + String setLanguage(String name) throws IOException { + assert name != null; final Language language = nameToLanguage.get(name); if (language == null) { - return null; + throw new IOException("Language \" + name + \" not supported"); + } + if (language == currentLanguage) { + return currentLanguage.getName(); + } + if (event != null) { + throw new IOException("Only supported at top level"); } this.currentLanguage = language; return language.getName(); @@ -531,24 +552,6 @@ breakpoints.remove(breakpoint); } - Object call(String name, List argList) throws IOException { - Value symbol = engine.findGlobalSymbol(name); - if (symbol == null) { - throw new IOException("symbol \"" + name + "\" not found"); - } - final List args = new ArrayList<>(); - for (String stringArg : argList) { - Integer intArg = null; - try { - intArg = Integer.valueOf(stringArg); - args.add(intArg); - } catch (NumberFormatException e) { - args.add(stringArg); - } - } - return symbol.invoke(null, args.toArray(new Object[0])).get(); - } - /** * The intention to create a line breakpoint. */