This is an automated email from the ASF dual-hosted git repository. skygo pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/netbeans.git
The following commit(s) were added to refs/heads/master by this push: new 4243806 NETBEANS-4209: Update Truffle debugging for GraalVM 20.1.0, fixed a number of issues including NETBEANS-4208 and small corrections. new 5222352 Merge pull request #2100 from entlicher/TruffleDebugUpdate2020-04 4243806 is described below commit 4243806f737510f1909272e49c7cd91710f7d253 Author: Martin Entlicher <martin.entlic...@oracle.com> AuthorDate: Thu Apr 23 15:18:51 2020 +0200 NETBEANS-4209: Update Truffle debugging for GraalVM 20.1.0, fixed a number of issues including NETBEANS-4208 and small corrections. --- .../debugger/jpda/truffle/DebugManagerHandler.java | 55 ++++++++++++- .../debugger/jpda/truffle/LanguageName.java | 73 ++++++++++++++++++ .../jpda/truffle/access/TruffleAccess.java | 48 ++++++++---- .../jpda/truffle/access/TruffleStrataProvider.java | 4 +- .../debugger/jpda/truffle/ast/TruffleNode.java | 34 ++++---- .../jpda/truffle/ast/model/ASTNodeModel.java | 10 +-- .../truffle/ast/model/ASTTreeExpansionModel.java | 2 +- .../breakpoints/TruffleBreakpointsHandler.java | 11 ++- .../jpda/truffle/frames/TruffleStackFrame.java | 18 +++-- .../models/DebuggingTruffleActionsProvider.java | 2 +- .../frames/models/DebuggingTruffleTreeModel.java | 2 +- .../jpda/truffle/source/SourcePosition.java | 36 +++++++-- .../jpda/truffle/vars/TruffleStackVariable.java | 35 ++++++++- .../jpda/truffle/vars/TruffleVariable.java | 9 ++- .../jpda/truffle/vars/TruffleVariableImpl.java | 44 ++++++++++- .../TruffleVariablesActionsProviderFilter.java | 50 ++++++------ .../vars/models/TruffleVariablesTableModel.java | 90 +++++++++++++++++----- .../vars/models/TruffleVariablesTreeModel.java | 3 +- .../modules/debugger/jpda/truffle/DebugSLTest.java | 4 +- .../debugger/jpda/truffle/testapps/SLApp.java | 2 +- .../debugger/jpda/backend/truffle/FrameInfo.java | 8 +- .../debugger/jpda/backend/truffle/GuestObject.java | 62 ++++++++------- .../jpda/backend/truffle/JPDATruffleAccessor.java | 47 +++++++---- .../backend/truffle/JPDATruffleDebugManager.java | 27 +++---- .../jpda/backend/truffle/SourcePosition.java | 19 +++-- .../debugger/jpda/backend/truffle/TruffleAST.java | 29 ++++--- 26 files changed, 530 insertions(+), 194 deletions(-) diff --git a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/DebugManagerHandler.java b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/DebugManagerHandler.java index a6b2e81..385b411 100644 --- a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/DebugManagerHandler.java +++ b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/DebugManagerHandler.java @@ -33,6 +33,8 @@ import com.sun.jdi.ThreadReference; import com.sun.jdi.Value; import com.sun.jdi.VirtualMachine; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import java.beans.PropertyVetoException; import java.io.IOException; import java.util.Arrays; @@ -64,6 +66,7 @@ import org.netbeans.modules.debugger.jpda.models.JPDAThreadImpl; import org.netbeans.modules.debugger.jpda.truffle.access.TruffleAccess; import static org.netbeans.modules.debugger.jpda.truffle.access.TruffleAccess.BASIC_CLASS_NAME; import org.netbeans.modules.debugger.jpda.truffle.breakpoints.TruffleBreakpointsHandler; +import org.netbeans.modules.debugger.jpda.truffle.options.TruffleOptions; import org.netbeans.modules.javascript2.debug.breakpoints.JSLineBreakpoint; import org.openide.util.Exceptions; @@ -78,8 +81,10 @@ final class DebugManagerHandler { private static final String ACCESSOR_LOOP_RUNNING_FIELD = "accessLoopRunning"; // NOI18N private static final String ACCESSOR_SET_UP_DEBUG_MANAGER_FOR = "setUpDebugManagerFor"; // NOI18N private static final String ACCESSOR_SET_UP_DEBUG_MANAGER_FOR_SGN = - "(L"+Object.class.getName().replace('.', '/')+";Z)"+ // NOI18N + "(L"+Object.class.getName().replace('.', '/')+";ZZ)"+ // NOI18N "Lorg/netbeans/modules/debugger/jpda/backend/truffle/JPDATruffleDebugManager;"; // NOI18N + private static final String ACCESSOR_SET_INCLUDE_INTERNAL = "setIncludeInternal"; // NOI18N + private static final String ACCESSOR_SET_INCLUDE_INTERNAL_SGN = "(Z)V"; // NOI18N private static final Map<JPDADebugger, Boolean> dbgStepInto = Collections.synchronizedMap(new WeakHashMap<JPDADebugger, Boolean>()); @@ -90,10 +95,12 @@ final class DebugManagerHandler { private final Object accessorClassLock = new Object(); //private ObjectReference debugManager; private final TruffleBreakpointsHandler breakpointsHandler; + private final PropertyChangeListener optionsChangeListener = new OptionsChangeListener(); public DebugManagerHandler(JPDADebugger debugger) { this.debugger = debugger; this.breakpointsHandler = new TruffleBreakpointsHandler(debugger); + TruffleOptions.onLanguageDeveloperModeChange(optionsChangeListener); } static void execStepInto(JPDADebugger debugger, boolean doStepInto) { @@ -127,13 +134,14 @@ final class DebugManagerHandler { if (vm == null) { return ; } + BooleanValue includeInternal = vm.mirrorOf(TruffleOptions.isLanguageDeveloperMode()); BooleanValue doStepInto = vm.mirrorOf(isStepInto()); Method debugManagerMethod = ClassTypeWrapper.concreteMethodByName( accessorClass, ACCESSOR_SET_UP_DEBUG_MANAGER_FOR, ACCESSOR_SET_UP_DEBUG_MANAGER_FOR_SGN); ThreadReference tr = thread.getThreadReference(); - List<Value> dmArgs = Arrays.asList(engine, doStepInto); + List<Value> dmArgs = Arrays.asList(engine, includeInternal, doStepInto); LOG.log(Level.FINE, "Setting engine and step into = {0}", isStepInto()); Object ret = ClassTypeWrapper.invokeMethod(accessorClass, tr, debugManagerMethod, dmArgs, ObjectReference.INVOKE_SINGLE_THREADED); if (ret instanceof ObjectReference) { // Can be null when an existing debug manager is reused. @@ -286,4 +294,47 @@ final class DebugManagerHandler { void breakpointRemoved(JSLineBreakpoint jsLineBreakpoint) { breakpointsHandler.breakpointRemoved(jsLineBreakpoint); } + + private final class OptionsChangeListener implements PropertyChangeListener { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (accessorClass == null) { + // No accessor + return ; + } + if (TruffleOptions.PROPERTY_LANG_DEV_MODE.equals(evt.getPropertyName())) { + JPDADebuggerImpl debuggerImpl = (JPDADebuggerImpl) debugger; + debuggerImpl.getRequestProcessor().post(() -> { + VirtualMachine vm = debuggerImpl.getVirtualMachine(); + if (vm == null) { + return ; + } + BooleanValue includeInternal = vm.mirrorOf(TruffleOptions.isLanguageDeveloperMode()); + try { + Method debugManagerMethod = ClassTypeWrapper.concreteMethodByName( + accessorClass, + ACCESSOR_SET_INCLUDE_INTERNAL, + ACCESSOR_SET_INCLUDE_INTERNAL_SGN); + TruffleAccess.methodCallingAccess(debugger, new TruffleAccess.MethodCallsAccess() { + @Override + public void callMethods(JPDAThread thread) throws InvocationException { + ThreadReference tr = ((JPDAThreadImpl) thread).getThreadReference(); + List<Value> dmArgs = Arrays.asList(includeInternal); + LOG.log(Level.FINE, "Setting includeInternal to {0}", includeInternal.value()); + try { + ClassTypeWrapper.invokeMethod(accessorClass, tr, debugManagerMethod, dmArgs, ObjectReference.INVOKE_SINGLE_THREADED); + } catch (Exception ex) { + Exceptions.printStackTrace(ex); + } + } + }); + } catch (ClassNotPreparedExceptionWrapper | InternalExceptionWrapper | VMDisconnectedExceptionWrapper ex) { + Exceptions.printStackTrace(ex); + } + }); + } + } + + } } diff --git a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/LanguageName.java b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/LanguageName.java new file mode 100644 index 0000000..889a2d5 --- /dev/null +++ b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/LanguageName.java @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.debugger.jpda.truffle; + +import java.util.Objects; + +/** + * + * @author Martin + */ +public final class LanguageName { + + public static final LanguageName NONE = new LanguageName("", ""); + + private final String id; + private final String name; + + private LanguageName(String id, String name) { + this.id = id; + this.name = name; + } + + public static LanguageName parse(String string) { + string = string.trim(); + if (string.isEmpty()) { + return NONE; + } + int i = string.indexOf(" "); + assert i > 0 : string; + return new LanguageName(string.substring(0, i), string.substring(i + 1)); + } + + public String getName() { + return name; + } + + @Override + public int hashCode() { + return Objects.hashCode(this.id); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final LanguageName other = (LanguageName) obj; + return this.id.equals(other.id); + } + +} diff --git a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/access/TruffleAccess.java b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/access/TruffleAccess.java index 386d565..7450372 100644 --- a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/access/TruffleAccess.java +++ b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/access/TruffleAccess.java @@ -57,6 +57,7 @@ import org.netbeans.modules.debugger.jpda.expr.InvocationExceptionTranslated; import org.netbeans.modules.debugger.jpda.expr.JDIVariable; import org.netbeans.modules.debugger.jpda.models.JPDAClassTypeImpl; import org.netbeans.modules.debugger.jpda.models.JPDAThreadImpl; +import org.netbeans.modules.debugger.jpda.truffle.LanguageName; import org.netbeans.modules.debugger.jpda.truffle.RemoteServices; import org.netbeans.modules.debugger.jpda.truffle.TruffleDebugManager; import org.netbeans.modules.debugger.jpda.truffle.actions.StepActionProvider; @@ -90,7 +91,7 @@ public class TruffleAccess implements JPDABreakpointListener { private static final String VAR_SRC_URI = "uri"; // NOI18N private static final String VAR_SRC_NAME = "name"; // NOI18N private static final String VAR_SRC_PATH = "path"; // NOI18N - private static final String VAR_SRC_LINE = "line"; // NOI18N + private static final String VAR_SRC_SOURCESECTION = "sourceSection"; // NOI18N private static final String VAR_SRC_CODE = "code"; private static final String VAR_STACK_TRACE = "stackTrace"; private static final String VAR_TOP_FRAME = "topFrame"; // NOI18N @@ -231,7 +232,7 @@ public class TruffleAccess implements JPDABreakpointListener { TruffleStackFrame topFrame = new TruffleStackFrame(debugger, thread, 0, frame, topFrameDescription, null/*code*/, scopes, thisObject, true); TruffleStackInfo stack = new TruffleStackInfo(debugger, thread, stackTrace); return new CurrentPCInfo(haltedInfo.stepCmd, thread, sp, scopes, topFrame, stack, depth -> { - return getTruffleAST(debugger, (JPDAThreadImpl) thread, depth, sp.getLine(), stack); + return getTruffleAST(debugger, (JPDAThreadImpl) thread, depth, sp, stack); }); } catch (AbsentInformationException | IllegalStateException ex) { Exceptions.printStackTrace(ex); @@ -239,7 +240,7 @@ public class TruffleAccess implements JPDABreakpointListener { } } - private static TruffleNode getTruffleAST(JPDADebugger debugger, JPDAThreadImpl thread, int depth, int topLine, TruffleStackInfo stack) { + private static TruffleNode getTruffleAST(JPDADebugger debugger, JPDAThreadImpl thread, int depth, SourcePosition topPosition, TruffleStackInfo stack) { JPDAClassType debugAccessor = TruffleDebugManager.getDebugAccessorJPDAClass(debugger); Lock lock = thread.accessLock.writeLock(); lock.lock(); @@ -273,8 +274,17 @@ public class TruffleAccess implements JPDABreakpointListener { METHOD_GET_AST_SGN, new Variable[] { debugger.createMirrorVar(depth, true) }); Variable[] astInfo = ((ObjectVariable) ast).getFields(0, Integer.MAX_VALUE); - int line = (depth == 0) ? topLine : stack.getStackFrames(true)[depth].getSourcePosition().getLine(); - return TruffleNode.newBuilder().nodes((String) astInfo[0].createMirrorObject()).currentLine(line).build(); + SourcePosition position; + if (depth == 0) { + position = topPosition; + } else { + TruffleStackFrame[] stackFrames = stack.getStackFrames(true); + if (depth >= stackFrames.length) { + return null; + } + position = stackFrames[depth].getSourcePosition(); + } + return TruffleNode.newBuilder().nodes((String) astInfo[0].createMirrorObject()).currentPosition(position).build(); } catch (InvalidExpressionException | InvalidObjectException | NoSuchMethodException ex) { Exceptions.printStackTrace(ex); return null; @@ -292,7 +302,7 @@ public class TruffleAccess implements JPDABreakpointListener { return null; } long id = (Long) varSrcId.createMirrorObject(); - int line = (Integer) sourcePositionVar.getField(VAR_SRC_LINE).createMirrorObject(); + String sourceSection = (String) sourcePositionVar.getField(VAR_SRC_SOURCESECTION).createMirrorObject(); Source src = Source.getExistingSource(debugger, id); if (src == null) { String name = (String) sourcePositionVar.getField(VAR_SRC_NAME).createMirrorObject(); @@ -301,7 +311,7 @@ public class TruffleAccess implements JPDABreakpointListener { StringReference codeRef = (StringReference) ((JDIVariable) sourcePositionVar.getField(VAR_SRC_CODE)).getJDIValue(); src = Source.getSource(debugger, id, name, path, uri, codeRef); } - return new SourcePosition(debugger, id, src, line); + return new SourcePosition(debugger, id, src, sourceSection); } private static TruffleScope[] createScopes(JPDADebugger debugger, ObjectVariable varsArrVar) { @@ -335,21 +345,27 @@ public class TruffleAccess implements JPDABreakpointListener { private static int fillVars(JPDADebugger debugger, TruffleVariable[] vars, Field[] varsArr, int i) { for (int vi = 0; vi < vars.length; vi++) { String name = (String) varsArr[i++].createMirrorObject(); + LanguageName language = LanguageName.parse((String) varsArr[i++].createMirrorObject()); String type = (String) varsArr[i++].createMirrorObject(); boolean readable = (Boolean) varsArr[i++].createMirrorObject(); boolean writable = (Boolean) varsArr[i++].createMirrorObject(); boolean internal = (Boolean) varsArr[i++].createMirrorObject(); String valueStr = (String) varsArr[i++].createMirrorObject(); + ObjectVariable valueSourceDef = (ObjectVariable) varsArr[i++]; Supplier<SourcePosition> valueSource = parseSourceLazy(debugger, - varsArr[i++], + valueSourceDef, (JDIVariable) varsArr[i++]); + ObjectVariable typeSourceDef = (ObjectVariable) varsArr[i++]; Supplier<SourcePosition> typeSource = parseSourceLazy(debugger, - varsArr[i++], + typeSourceDef, (JDIVariable) varsArr[i++]); ObjectVariable value = (ObjectVariable) varsArr[i++]; - vars[vi] = new TruffleStackVariable(debugger, name, type, readable, + vars[vi] = new TruffleStackVariable(debugger, name, language, type, readable, writable, internal, valueStr, - valueSource, typeSource, value); + valueSourceDef.getUniqueID() != 0L, + valueSource, + typeSourceDef.getUniqueID() != 0L, + typeSource, value); } return i; } @@ -392,7 +408,7 @@ public class TruffleAccess implements JPDABreakpointListener { String sourceName; String sourcePath; URI sourceURI; - int sourceLine; + String sourceSection; try { int i1 = 0; int i2 = sourceDef.indexOf('\n', i1); @@ -411,12 +427,16 @@ public class TruffleAccess implements JPDABreakpointListener { throw new IllegalStateException("Bad URI: "+sourceDef.substring(i1, i2), usex); } i1 = i2 + 1; - sourceLine = Integer.parseInt(sourceDef.substring(i1)); + i2 = sourceDef.indexOf('\n', i1); + if (i2 < 0) { + i2 = sourceDef.length(); + } + sourceSection = sourceDef.substring(i1, i2); } catch (IndexOutOfBoundsException ioob) { throw new IllegalStateException("var source definition='"+sourceDef+"'", ioob); } Source src = Source.getSource(debugger, sourceId, sourceName, sourcePath, sourceURI, codeRef); - return new SourcePosition(debugger, sourceId, src, sourceLine); + return new SourcePosition(debugger, sourceId, src, sourceSection); } public static TruffleScope[] createFrameScopes(final JPDADebugger debugger, diff --git a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/access/TruffleStrataProvider.java b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/access/TruffleStrataProvider.java index a50f8bb..8a50fed 100644 --- a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/access/TruffleStrataProvider.java +++ b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/access/TruffleStrataProvider.java @@ -60,10 +60,10 @@ public class TruffleStrataProvider implements StrataProvider { @Override public int getStrataLineNumber(CallStackFrameImpl csf, String stratum) { - if (TRUFFLE_STRATUM.equals(stratum)) { + if (TRUFFLE_STRATUM.equals(stratum) && isInTruffleAccessPoint(csf)) { CurrentPCInfo currentPCInfo = TruffleAccess.getCurrentPCInfo(csf.getThread()); if (currentPCInfo != null) { - return currentPCInfo.getSourcePosition().getLine(); + return currentPCInfo.getSourcePosition().getStartLine(); } } return csf.getLineNumber(stratum); diff --git a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/ast/TruffleNode.java b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/ast/TruffleNode.java index 0eaeea1..134534a 100644 --- a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/ast/TruffleNode.java +++ b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/ast/TruffleNode.java @@ -19,6 +19,8 @@ package org.netbeans.modules.debugger.jpda.truffle.ast; +import org.netbeans.modules.debugger.jpda.truffle.source.SourcePosition; + /** * A representation of Truffle Node class. */ @@ -34,6 +36,7 @@ public final class TruffleNode { private final String tags; private final TruffleNode[] ch; private boolean current; + private boolean currentEncapsulating; public TruffleNode(String className, String description, String sourceURI, int l1, int c1, int l2, int c2, String tags, int numCh) { this.className = className; @@ -101,6 +104,10 @@ public final class TruffleNode { return current; } + public boolean isCurrentEncapsulating() { + return currentEncapsulating; + } + public static Builder newBuilder() { return new Builder(); } @@ -108,7 +115,7 @@ public final class TruffleNode { public static class Builder { private TruffleNode node; - private int currentLine; + private SourcePosition currentPosition; private Builder() {} @@ -119,29 +126,26 @@ public final class TruffleNode { } public TruffleNode build() { - if (currentLine > 0) { - markCurrent(node, currentLine); + if (currentPosition != null) { + markCurrent(node, currentPosition); } return node; } /** Mark all node paths which are currently being executed as current. */ - private boolean markCurrent(TruffleNode node, int currentLine) { - if (node.getChildren().length == 0) { - if (node.getStartLine() <= currentLine && currentLine <= node.getEndLine()) { - node.current = true; - return true; - } else { - return false; - } + private static boolean markCurrent(TruffleNode node, SourcePosition currentPosition) { + if (node.getStartLine() == currentPosition.getStartLine() && node.getEndLine() == currentPosition.getEndLine() && + node.getStartColumn() == currentPosition.getStartColumn() && node.getEndColumn() == currentPosition.getEndColumn()) { + node.current = true; + return true; } else { boolean isSomeCurrent = false; for (TruffleNode ch : node.getChildren()) { - if (markCurrent(ch, currentLine)) { + if (markCurrent(ch, currentPosition)) { isSomeCurrent = true; } } - node.current = isSomeCurrent; + node.currentEncapsulating = isSomeCurrent; return isSomeCurrent; } } @@ -180,8 +184,8 @@ public final class TruffleNode { return node; } - public Builder currentLine(int line) { - this.currentLine = line; + public Builder currentPosition(SourcePosition position) { + this.currentPosition = position; return this; } diff --git a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/ast/model/ASTNodeModel.java b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/ast/model/ASTNodeModel.java index 87a4317..5596c1f 100644 --- a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/ast/model/ASTNodeModel.java +++ b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/ast/model/ASTNodeModel.java @@ -46,19 +46,17 @@ public class ASTNodeModel implements NodeModel { String label = ast.getClassSimpleName(); String tags = ast.getTags(); if (!tags.isEmpty()) { - label = '[' + tags + "] " + label; + label = '(' + tags + ") " + label; } int l1 = ast.getStartLine(); if (l1 >= 0) { int c1 = ast.getStartColumn(); int l2 = ast.getEndLine(); int c2 = ast.getEndColumn(); - label += " <"+l1+":"+c1+"-"+l2+":"+c2+">"; + label += " ["+l1+":"+c1+"-"+l2+":"+c2+"]"; } - if (ast.getChildren().length == 0) { - if (ast.isCurrent()) { - label = "<html><b>" + label + "</b></html>"; - } + if (ast.isCurrent()) { + label = "<html><b>" + label + "</b></html>"; } return label; } else { diff --git a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/ast/model/ASTTreeExpansionModel.java b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/ast/model/ASTTreeExpansionModel.java index 85792b5..8dc3f20 100644 --- a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/ast/model/ASTTreeExpansionModel.java +++ b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/ast/model/ASTTreeExpansionModel.java @@ -42,7 +42,7 @@ public class ASTTreeExpansionModel implements TreeExpansionModel { public boolean isExpanded(Object node) throws UnknownTypeException { if (node instanceof TruffleNode) { TruffleNode ast = (TruffleNode) node; - return ast.isCurrent(); + return ast.isCurrentEncapsulating() || ast.isCurrent(); } else { return false; } diff --git a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/breakpoints/TruffleBreakpointsHandler.java b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/breakpoints/TruffleBreakpointsHandler.java index d9df0bb..f658577 100644 --- a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/breakpoints/TruffleBreakpointsHandler.java +++ b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/breakpoints/TruffleBreakpointsHandler.java @@ -245,11 +245,14 @@ public class TruffleBreakpointsHandler { } } bp.addPropertyChangeListener(breakpointsChangeListener); - List<Value> values = bpRef[0].getValues(); Set<ObjectReference> breakpoints = new HashSet<>(); - for (Value v : values) { - if (v instanceof ObjectReference) { - breakpoints.add((ObjectReference) v); + ArrayReference bpArray = bpRef[0]; + if (bpArray != null) { + List<Value> values = bpArray.getValues(); + for (Value v : values) { + if (v instanceof ObjectReference) { + breakpoints.add((ObjectReference) v); + } } } if (!breakpoints.isEmpty()) { diff --git a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/frames/TruffleStackFrame.java b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/frames/TruffleStackFrame.java index d3e6c44..6ef5d69 100644 --- a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/frames/TruffleStackFrame.java +++ b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/frames/TruffleStackFrame.java @@ -30,9 +30,9 @@ import org.netbeans.api.debugger.jpda.InvalidExpressionException; import org.netbeans.api.debugger.jpda.JPDADebugger; import org.netbeans.api.debugger.jpda.JPDAThread; import org.netbeans.api.debugger.jpda.ObjectVariable; +import org.netbeans.modules.debugger.jpda.truffle.LanguageName; import org.netbeans.modules.debugger.jpda.truffle.access.CurrentPCInfo; import org.netbeans.modules.debugger.jpda.truffle.access.TruffleAccess; -import org.netbeans.modules.debugger.jpda.truffle.actions.StepActionProvider; import org.netbeans.modules.debugger.jpda.truffle.source.Source; import org.netbeans.modules.debugger.jpda.truffle.source.SourcePosition; import org.netbeans.modules.debugger.jpda.truffle.vars.TruffleScope; @@ -51,13 +51,14 @@ public final class TruffleStackFrame { private final int depth; private final ObjectVariable frameInstance; private final String methodName; + private final LanguageName language; private final String sourceLocation; private final int sourceId; private final String sourceName; private final String sourcePath; private final URI sourceURI; - private final int sourceLine; + private final String sourceSection; private final StringReference codeRef; private TruffleScope[] scopes; private final ObjectVariable thisObject; @@ -89,6 +90,9 @@ public final class TruffleStackFrame { methodName = frameDefinition.substring(i1, i2); i1 = i2 + 1; i2 = frameDefinition.indexOf('\n', i1); + language = LanguageName.parse(frameDefinition.substring(i1, i2)); + i1 = i2 + 1; + i2 = frameDefinition.indexOf('\n', i1); sourceLocation = frameDefinition.substring(i1, i2); i1 = i2 + 1; i2 = frameDefinition.indexOf('\n', i1); @@ -109,11 +113,11 @@ public final class TruffleStackFrame { i1 = i2 + 1; if (includeInternal) { i2 = frameDefinition.indexOf('\n', i1); - sourceLine = Integer.parseInt(frameDefinition.substring(i1, i2)); + sourceSection = frameDefinition.substring(i1, i2); i1 = i2 + 1; internalFrame = Boolean.valueOf(frameDefinition.substring(i1)); } else { - sourceLine = Integer.parseInt(frameDefinition.substring(i1)); + sourceSection = frameDefinition.substring(i1); } } catch (IndexOutOfBoundsException ioob) { throw new IllegalStateException("frameDefinition='"+frameDefinition+"'", ioob); @@ -140,6 +144,10 @@ public final class TruffleStackFrame { return methodName; } + public LanguageName getLanguage() { + return language; + } + public String getSourceLocation() { return sourceLocation; } @@ -157,7 +165,7 @@ public final class TruffleStackFrame { if (src == null) { src = Source.getSource(debugger, sourceId, sourceName, sourcePath, sourceURI, codeRef); } - SourcePosition sp = new SourcePosition(debugger, sourceId, src, sourceLine); + SourcePosition sp = new SourcePosition(debugger, sourceId, src, sourceSection); return sp; } diff --git a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/frames/models/DebuggingTruffleActionsProvider.java b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/frames/models/DebuggingTruffleActionsProvider.java index 18a80fb..dc0acf1 100644 --- a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/frames/models/DebuggingTruffleActionsProvider.java +++ b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/frames/models/DebuggingTruffleActionsProvider.java @@ -107,7 +107,7 @@ public class DebuggingTruffleActionsProvider implements NodeActionsProviderFilte public void run () { EditorContextBridge.getContext().showSource ( sourcePosition.getSource().getUrl().toExternalForm(), - sourcePosition.getLine(), + sourcePosition.getStartLine(), f.getDebugger() ); } diff --git a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/frames/models/DebuggingTruffleTreeModel.java b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/frames/models/DebuggingTruffleTreeModel.java index 2a62257..d5451fa 100644 --- a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/frames/models/DebuggingTruffleTreeModel.java +++ b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/frames/models/DebuggingTruffleTreeModel.java @@ -47,7 +47,7 @@ import org.netbeans.spi.viewmodel.UnknownTypeException; types={ TreeModelFilter.class }) public class DebuggingTruffleTreeModel implements TreeModelFilter { - private static final Predicate<String> PREDICATE1 = Pattern.compile("^((com|org)\\.\\p{Alpha}*\\.truffle|(com|org)\\.graalvm)\\..*$").asPredicate(); + private static final Predicate<String> PREDICATE1 = Pattern.compile("^((com|org)\\.\\p{Alpha}*\\.truffle|(com|org)(\\.graalvm|\\.truffleruby))\\..*$").asPredicate(); private static final String FILTER1 = "com.[A-z]*.truffle."; // NOI18N private static final String FILTER2 = "com.oracle.graal."; // NOI18N private static final String FILTER3 = "org.netbeans.modules.debugger.jpda.backend."; // NOI18N diff --git a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/source/SourcePosition.java b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/source/SourcePosition.java index 8a553a0..4e702a0 100644 --- a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/source/SourcePosition.java +++ b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/source/SourcePosition.java @@ -28,20 +28,44 @@ public class SourcePosition { private final long id; private final Source src; - private final int line; + private final int startLine; + private final int startColumn; + private final int endLine; + private final int endColumn; - public SourcePosition(JPDADebugger debugger, long id, Source src, int line) { + public SourcePosition(JPDADebugger debugger, long id, Source src, String sourceSection) { this.id = id; this.src = src; - this.line = line; + int i1 = 0, i2 = sourceSection.indexOf(','); + this.startLine = Integer.parseInt(sourceSection.substring(i1, i2)); + i1 = i2 + 1; + i2 = sourceSection.indexOf(',', i1); + this.startColumn = Integer.parseInt(sourceSection.substring(i1, i2)); + i1 = i2 + 1; + i2 = sourceSection.indexOf(',', i1); + this.endLine = Integer.parseInt(sourceSection.substring(i1, i2)); + i1 = i2 + 1; + this.endColumn = Integer.parseInt(sourceSection.substring(i1)); } public Source getSource() { return src; } - - public int getLine() { - return line; + + public int getStartLine() { + return startLine; + } + + public int getStartColumn() { + return startColumn; } + public int getEndLine() { + return endLine; + } + + public int getEndColumn() { + return endColumn; + } + } diff --git a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/vars/TruffleStackVariable.java b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/vars/TruffleStackVariable.java index ce5e8fd..62903ba 100644 --- a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/vars/TruffleStackVariable.java +++ b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/vars/TruffleStackVariable.java @@ -22,17 +22,21 @@ package org.netbeans.modules.debugger.jpda.truffle.vars; import java.util.function.Supplier; import org.netbeans.api.debugger.jpda.JPDADebugger; import org.netbeans.api.debugger.jpda.ObjectVariable; +import org.netbeans.modules.debugger.jpda.truffle.LanguageName; import org.netbeans.modules.debugger.jpda.truffle.source.SourcePosition; public class TruffleStackVariable implements TruffleVariable { private final JPDADebugger debugger; private final String name; + private final LanguageName language; private String type; private final boolean readable; private final boolean writable; private final boolean internal; private String valueStr; + private boolean hasValueSource; + private boolean hasTypeSource; private Supplier<SourcePosition> valueSourceSupp; private Supplier<SourcePosition> typeSourceSupp; private SourcePosition valueSource; @@ -40,18 +44,21 @@ public class TruffleStackVariable implements TruffleVariable { private ObjectVariable guestObj; private boolean leaf; - public TruffleStackVariable(JPDADebugger debugger, String name, String type, - boolean readable, boolean writable, boolean internal, - String valueStr, Supplier<SourcePosition> valueSource, - Supplier<SourcePosition> typeSource, + public TruffleStackVariable(JPDADebugger debugger, String name, LanguageName language, + String type, boolean readable, boolean writable, boolean internal, + String valueStr, boolean hasValueSource, Supplier<SourcePosition> valueSource, + boolean hasTypeSource, Supplier<SourcePosition> typeSource, ObjectVariable truffleObj) { this.debugger = debugger; this.name = name; + this.language = language; this.type = type; this.readable = readable; this.writable = writable; this.internal = internal; this.valueStr = valueStr; + this.hasValueSource = hasValueSource; + this.hasTypeSource = hasTypeSource; this.valueSourceSupp = valueSource; this.typeSourceSupp = typeSource; this.guestObj = truffleObj; @@ -64,6 +71,11 @@ public class TruffleStackVariable implements TruffleVariable { } @Override + public LanguageName getLanguage() { + return language; + } + + @Override public String getType() { return type; } @@ -90,6 +102,9 @@ public class TruffleStackVariable implements TruffleVariable { @Override public ObjectVariable setValue(JPDADebugger debugger, String newExpression) { + if (this.valueStr.equals(newExpression)) { + return null; + } ObjectVariable newGuestObject = TruffleVariableImpl.setValue(debugger, guestObj, newExpression); if (newGuestObject != null) { this.guestObj = newGuestObject; @@ -97,6 +112,8 @@ public class TruffleStackVariable implements TruffleVariable { this.type = newVar.getType(); this.valueStr = newVar.getValue().toString(); this.valueSource = this.typeSource = null; + this.hasValueSource = newVar.hasValueSource(); + this.hasTypeSource = newVar.hasTypeSource(); this.valueSourceSupp = () -> newVar.getValueSource(); this.typeSourceSupp = () -> newVar.getTypeSource(); this.leaf = TruffleVariableImpl.isLeaf(guestObj); @@ -105,6 +122,11 @@ public class TruffleStackVariable implements TruffleVariable { } @Override + public boolean hasValueSource() { + return hasValueSource; + } + + @Override public synchronized SourcePosition getValueSource() { if (valueSource == null) { valueSource = valueSourceSupp.get(); @@ -113,6 +135,11 @@ public class TruffleStackVariable implements TruffleVariable { } @Override + public boolean hasTypeSource() { + return hasTypeSource; + } + + @Override public synchronized SourcePosition getTypeSource() { if (typeSource == null) { typeSource = typeSourceSupp.get(); diff --git a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/vars/TruffleVariable.java b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/vars/TruffleVariable.java index 9b58279..3674c42 100644 --- a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/vars/TruffleVariable.java +++ b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/vars/TruffleVariable.java @@ -21,6 +21,7 @@ package org.netbeans.modules.debugger.jpda.truffle.vars; import org.netbeans.api.debugger.jpda.JPDADebugger; import org.netbeans.api.debugger.jpda.ObjectVariable; +import org.netbeans.modules.debugger.jpda.truffle.LanguageName; import org.netbeans.modules.debugger.jpda.truffle.source.SourcePosition; /** @@ -29,7 +30,9 @@ import org.netbeans.modules.debugger.jpda.truffle.source.SourcePosition; public interface TruffleVariable { String getName(); - + + LanguageName getLanguage(); + String getType(); boolean isReadable(); @@ -40,8 +43,12 @@ public interface TruffleVariable { Object getValue(); + boolean hasValueSource(); + SourcePosition getValueSource(); + boolean hasTypeSource(); + SourcePosition getTypeSource(); boolean isLeaf(); diff --git a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/vars/TruffleVariableImpl.java b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/vars/TruffleVariableImpl.java index f9a45de..3ec8ad4 100644 --- a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/vars/TruffleVariableImpl.java +++ b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/vars/TruffleVariableImpl.java @@ -26,6 +26,7 @@ import org.netbeans.api.debugger.jpda.JPDADebugger; import org.netbeans.api.debugger.jpda.ObjectVariable; import org.netbeans.api.debugger.jpda.Variable; import org.netbeans.modules.debugger.jpda.models.AbstractVariable; +import org.netbeans.modules.debugger.jpda.truffle.LanguageName; import org.netbeans.modules.debugger.jpda.truffle.access.CurrentPCInfo; import org.netbeans.modules.debugger.jpda.truffle.access.TruffleAccess; import org.netbeans.modules.debugger.jpda.truffle.source.SourcePosition; @@ -35,6 +36,7 @@ public class TruffleVariableImpl implements TruffleVariable { private static final String GUEST_OBJECT_TYPE = "org.netbeans.modules.debugger.jpda.backend.truffle.GuestObject"; // NOI18N private static final String FIELD_NAME = "name"; // NOI18N + private static final String FIELD_LANGUAGE = "language"; // NOI18N private static final String FIELD_TYPE = "type"; // NOI18N private static final String FIELD_READABLE = "readable"; // NOI18N private static final String FIELD_WRITABLE = "writable"; // NOI18N @@ -50,29 +52,36 @@ public class TruffleVariableImpl implements TruffleVariable { private final ObjectVariable guestObject; private final String name; + private final LanguageName language; private final String type; private final String displayValue; private final boolean readable; private final boolean writable; private final boolean internal; private final boolean leaf; + private final boolean hasValueSource; + private final boolean hasTypeSource; private SourcePosition valueSource; private SourcePosition typeSource; private TruffleVariableImpl(ObjectVariable guestObject, String name, - String type, String displayValue, + LanguageName language, String type, String displayValue, boolean readable, boolean writable, boolean internal, + boolean hasValueSource, boolean hasTypeSource, boolean leaf) { this.guestObject = guestObject; this.name = name; + this.language = language; this.type = type; this.displayValue = displayValue; this.readable = readable; this.writable = writable; this.internal = internal; + this.hasValueSource = hasValueSource; + this.hasTypeSource = hasTypeSource; this.leaf = leaf; } - + public static TruffleVariableImpl get(Variable var) { if (GUEST_OBJECT_TYPE.equals(var.getType())) { ObjectVariable truffleObj = (ObjectVariable) var; @@ -84,6 +93,12 @@ public class TruffleVariableImpl implements TruffleVariable { } String name = (String) f.createMirrorObject(); + f = truffleObj.getField(FIELD_LANGUAGE); + if (f == null) { + return null; + } + LanguageName language = LanguageName.parse((String) f.createMirrorObject()); + f = truffleObj.getField(FIELD_TYPE); if (f == null) { return null; @@ -120,8 +135,13 @@ public class TruffleVariableImpl implements TruffleVariable { internal = (Boolean) f.createMirrorObject(); } + f = truffleObj.getField(FIELD_VALUE_SOURCE); + boolean hasValueSource = ((ObjectVariable) f).getUniqueID() != 0L; + f = truffleObj.getField(FIELD_TYPE_SOURCE); + boolean hasTypeSource = ((ObjectVariable) f).getUniqueID() != 0L; + boolean leaf = isLeaf(truffleObj); - return new TruffleVariableImpl(truffleObj, name, type, dispVal, readable, writable, internal, leaf); + return new TruffleVariableImpl(truffleObj, name, language, type, dispVal, readable, writable, internal, hasValueSource, hasTypeSource, leaf); } else { return null; } @@ -145,6 +165,11 @@ public class TruffleVariableImpl implements TruffleVariable { } @Override + public LanguageName getLanguage() { + return language; + } + + @Override public String getType() { return type; } @@ -175,6 +200,9 @@ public class TruffleVariableImpl implements TruffleVariable { @Override public ObjectVariable setValue(JPDADebugger debugger, String newExpression) { + if (this.displayValue.equals(newExpression)) { + return null; + } return setValue(debugger, guestObject, newExpression); } @@ -196,6 +224,11 @@ public class TruffleVariableImpl implements TruffleVariable { } @Override + public boolean hasValueSource() { + return hasValueSource; + } + + @Override public synchronized SourcePosition getValueSource() { if (valueSource == null) { Field f = getFieldChecked(FIELD_VALUE_SOURCE, guestObject); @@ -205,6 +238,11 @@ public class TruffleVariableImpl implements TruffleVariable { } @Override + public boolean hasTypeSource() { + return hasTypeSource; + } + + @Override public synchronized SourcePosition getTypeSource() { if (typeSource == null) { Field f = getFieldChecked(FIELD_TYPE_SOURCE, guestObject); diff --git a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/vars/models/TruffleVariablesActionsProviderFilter.java b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/vars/models/TruffleVariablesActionsProviderFilter.java index 0abf393..ab37af7 100644 --- a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/vars/models/TruffleVariablesActionsProviderFilter.java +++ b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/vars/models/TruffleVariablesActionsProviderFilter.java @@ -23,7 +23,9 @@ import java.net.URL; import javax.swing.Action; import javax.swing.SwingUtilities; +import org.netbeans.api.debugger.jpda.JPDADebugger; import org.netbeans.modules.debugger.jpda.EditorContextBridge; +import org.netbeans.modules.debugger.jpda.JPDADebuggerImpl; import org.netbeans.modules.debugger.jpda.truffle.access.TruffleStrataProvider; import org.netbeans.modules.debugger.jpda.truffle.source.SourcePosition; import org.netbeans.modules.debugger.jpda.truffle.vars.TruffleVariable; @@ -37,6 +39,7 @@ import org.netbeans.spi.viewmodel.UnknownTypeException; import org.openide.DialogDisplayer; import org.openide.NotifyDescriptor; import org.openide.util.NbBundle; +import org.openide.util.RequestProcessor; @DebuggerServiceRegistrations({ @DebuggerServiceRegistration(path="netbeans-JPDASession/"+TruffleStrataProvider.TRUFFLE_STRATUM+"/LocalsView", types=NodeActionsProviderFilter.class), @@ -45,9 +48,11 @@ import org.openide.util.NbBundle; @DebuggerServiceRegistration(path="netbeans-JPDASession/"+TruffleStrataProvider.TRUFFLE_STRATUM+"/WatchesView", types=NodeActionsProviderFilter.class), }) public class TruffleVariablesActionsProviderFilter implements NodeActionsProviderFilter { - + + private final RequestProcessor rp; + public TruffleVariablesActionsProviderFilter(ContextProvider contextProvider) { - System.err.println("new TruffleVariablesActionsProviderFilter()"); + this.rp = ((JPDADebuggerImpl) contextProvider.lookupFirst(null, JPDADebugger.class)).getRequestProcessor(); } @NbBundle.Messages("CTL_GoToSource=Go to source") @@ -61,7 +66,7 @@ public class TruffleVariablesActionsProviderFilter implements NodeActionsProvide @Override public void perform (final Object[] nodes) { TruffleVariable var = (TruffleVariable) nodes[0]; - showSource(var.getValueSource()); + rp.post(() -> showSource(var.getValueSource())); } }, Models.MULTISELECTION_TYPE_EXACTLY_ONE @@ -78,7 +83,7 @@ public class TruffleVariablesActionsProviderFilter implements NodeActionsProvide @Override public void perform (final Object[] nodes) { TruffleVariable var = (TruffleVariable) nodes[0]; - showSource(var.getTypeSource()); + rp.post(() -> showSource(var.getTypeSource())); } }, Models.MULTISELECTION_TYPE_EXACTLY_ONE @@ -86,19 +91,18 @@ public class TruffleVariablesActionsProviderFilter implements NodeActionsProvide @Override public void performDefaultAction(NodeActionsProvider original, Object node) throws UnknownTypeException { - boolean shown = false; if (node instanceof TruffleVariable) { TruffleVariable var = (TruffleVariable) node; - SourcePosition source = var.getValueSource(); - if (source == null) { - source = var.getTypeSource(); - } - if (source != null) { - showSource(source); - shown = true; - } - } - if (!shown) { + rp.post(() -> { + SourcePosition source = var.getValueSource(); + if (source == null) { + source = var.getTypeSource(); + } + if (source != null) { + showSource(source); + } + }); + } else { original.performDefaultAction(node); } } @@ -115,23 +119,23 @@ public class TruffleVariablesActionsProviderFilter implements NodeActionsProvide } if (node instanceof TruffleVariable) { TruffleVariable var = (TruffleVariable) node; - SourcePosition valueSource = var.getValueSource(); - SourcePosition typeSource = var.getTypeSource(); - if (valueSource != null || typeSource != null) { + boolean hasValueSource = var.hasValueSource(); + boolean hasTypeSource = var.hasTypeSource(); + if (hasValueSource || hasTypeSource) { int l = actions.length; - if (valueSource != null) { + if (hasValueSource) { l++; } - if (typeSource != null) { + if (hasTypeSource) { l++; } Action[] newActions = new Action[l]; System.arraycopy(actions, 0, newActions, 0, actions.length); l = actions.length; - if (valueSource != null) { + if (hasValueSource) { newActions[l++] = GO_TO_VALUE_SOURCE_ACTION; } - if (typeSource != null) { + if (hasTypeSource) { newActions[l++] = GO_TO_TYPE_SOURCE_ACTION; } actions = newActions; @@ -145,7 +149,7 @@ public class TruffleVariablesActionsProviderFilter implements NodeActionsProvide @NbBundle.Messages({"# {0} - The file path", "MSG_NoSourceFile=Cannot find source file {0}."}) private void showSource(SourcePosition source) { URL url = source.getSource().getUrl(); - int lineNumber = source.getLine(); + int lineNumber = source.getStartLine(); SwingUtilities.invokeLater (() -> { boolean success = EditorContextBridge.getContext().showSource(url.toExternalForm(), lineNumber, null); if (!success) { diff --git a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/vars/models/TruffleVariablesTableModel.java b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/vars/models/TruffleVariablesTableModel.java index 69b2bad..edb8f61 100644 --- a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/vars/models/TruffleVariablesTableModel.java +++ b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/vars/models/TruffleVariablesTableModel.java @@ -19,13 +19,19 @@ package org.netbeans.modules.debugger.jpda.truffle.vars.models; +import java.awt.Color; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; +import javax.swing.JTable; +import javax.swing.UIManager; import org.netbeans.api.debugger.jpda.JPDADebugger; -import org.netbeans.api.debugger.jpda.JPDAWatch; import org.netbeans.api.debugger.jpda.Variable; +import org.netbeans.modules.debugger.jpda.truffle.LanguageName; +import org.netbeans.modules.debugger.jpda.truffle.access.CurrentPCInfo; +import org.netbeans.modules.debugger.jpda.truffle.access.TruffleAccess; import org.netbeans.modules.debugger.jpda.truffle.access.TruffleStrataProvider; +import org.netbeans.modules.debugger.jpda.truffle.frames.TruffleStackFrame; import org.netbeans.modules.debugger.jpda.truffle.vars.TruffleScope; import org.netbeans.modules.debugger.jpda.truffle.vars.TruffleVariable; import org.netbeans.modules.debugger.jpda.truffle.vars.TruffleVariableImpl; @@ -47,10 +53,10 @@ import org.netbeans.spi.viewmodel.TableModelFilter; import org.netbeans.spi.viewmodel.UnknownTypeException; @DebuggerServiceRegistrations({ - @DebuggerServiceRegistration(path="netbeans-JPDASession/"+TruffleStrataProvider.TRUFFLE_STRATUM+"/LocalsView", types = TableModelFilter.class), - @DebuggerServiceRegistration(path="netbeans-JPDASession/"+TruffleStrataProvider.TRUFFLE_STRATUM+"/ResultsView", types = TableModelFilter.class), - @DebuggerServiceRegistration(path="netbeans-JPDASession/"+TruffleStrataProvider.TRUFFLE_STRATUM+"/ToolTipView", types = TableModelFilter.class), - @DebuggerServiceRegistration(path="netbeans-JPDASession/"+TruffleStrataProvider.TRUFFLE_STRATUM+"/WatchesView", types = TableModelFilter.class) + @DebuggerServiceRegistration(path="netbeans-JPDASession/"+TruffleStrataProvider.TRUFFLE_STRATUM+"/LocalsView", types = {TableModelFilter.class, TableHTMLModelFilter.class}), + @DebuggerServiceRegistration(path="netbeans-JPDASession/"+TruffleStrataProvider.TRUFFLE_STRATUM+"/ResultsView", types = {TableModelFilter.class, TableHTMLModelFilter.class}), + @DebuggerServiceRegistration(path="netbeans-JPDASession/"+TruffleStrataProvider.TRUFFLE_STRATUM+"/ToolTipView", types = {TableModelFilter.class, TableHTMLModelFilter.class}), + @DebuggerServiceRegistration(path="netbeans-JPDASession/"+TruffleStrataProvider.TRUFFLE_STRATUM+"/WatchesView", types = {TableModelFilter.class, TableHTMLModelFilter.class}) }) public class TruffleVariablesTableModel implements TableModelFilter, TableHTMLModelFilter { @@ -61,23 +67,22 @@ public class TruffleVariablesTableModel implements TableModelFilter, TableHTMLMo debugger = contextProvider.lookupFirst(null, JPDADebugger.class); } + private static TruffleVariable getTruffleVariable(Object node) { + if (node instanceof Variable) { + return TruffleVariableImpl.get((Variable) node); + } else if (node instanceof TruffleVariable) { + return (TruffleVariable) node; + } else { + return null; + } + } + @Override public Object getValueAt(TableModel original, Object node, String columnID) throws UnknownTypeException { if (node instanceof TruffleScope) { return ""; } - TruffleVariable tv = null; - if (node instanceof JPDAWatch) {// && !isEnabled((JPDAWatch) node)) { - Object orig = original.getValueAt(node, columnID); // Call in any case because of error displaying - if (node instanceof Variable) { - tv = TruffleVariableImpl.get((Variable) node); - } - if (tv == null) { - return orig; - } - } else if (node instanceof TruffleVariable) { - tv = (TruffleVariable) node; - } + TruffleVariable tv = getTruffleVariable(node); if (tv != null) { switch (columnID) { case LOCALS_TYPE_COLUMN_ID: @@ -128,13 +133,34 @@ public class TruffleVariablesTableModel implements TableModelFilter, TableHTMLMo @Override public boolean hasHTMLValueAt(TableHTMLModel original, Object node, String columnID) throws UnknownTypeException { if (node instanceof TruffleVariable) { - return false; + switch (columnID) { + case LOCALS_TYPE_COLUMN_ID: + case WATCH_TYPE_COLUMN_ID: + return true; + } } return original.hasHTMLValueAt(node, columnID); } @Override public String getHTMLValueAt(TableHTMLModel original, Object node, String columnID) throws UnknownTypeException { + switch (columnID) { + case LOCALS_TYPE_COLUMN_ID: + case WATCH_TYPE_COLUMN_ID: + TruffleVariable tv = getTruffleVariable(node); + if (tv != null) { + LanguageName frameLanguage = LanguageName.NONE; + CurrentPCInfo currentPCInfo = TruffleAccess.getCurrentPCInfo(debugger.getCurrentThread()); + if (currentPCInfo != null) { + TruffleStackFrame selectedStackFrame = currentPCInfo.getSelectedStackFrame(); + frameLanguage = selectedStackFrame.getLanguage(); + } + LanguageName valueLanguage = tv.getLanguage(); + if (!LanguageName.NONE.equals(valueLanguage) && !frameLanguage.equals(valueLanguage)) { + return toHTML(valueLanguage.getName(), tv.getType()); + } + } + } return original.getHTMLValueAt(node, columnID); } @@ -148,4 +174,32 @@ public class TruffleVariablesTableModel implements TableModelFilter, TableHTMLMo listeners.remove(l); } + public static String toHTML(String id, String text) { + if (text == null) return null; + StringBuilder sb = new StringBuilder (); + sb.append("<html>"); + Color color = UIManager.getColor("Table.foreground"); + if (color == null) { + color = new JTable().getForeground(); + } + sb.append("<font color=\"#"); + String hexColor = Integer.toHexString ((color.getRGB () & 0xffffff)); + for (int i = hexColor.length(); i < 6; i++) { + sb.append("0"); // Prepend zeros to length of 6 + } + sb.append(hexColor); + sb.append("\">"); + + sb.append("<font color=\"#808080\">["); + sb.append(id); + sb.append("]</font> "); + + text = text.replaceAll("&", "&"); + text = text.replaceAll("<", "<"); + text = text.replaceAll(">", ">"); + sb.append(text); + sb.append("</font>"); + sb.append("</html>"); + return sb.toString (); + } } diff --git a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/vars/models/TruffleVariablesTreeModel.java b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/vars/models/TruffleVariablesTreeModel.java index cf9f119..66c135c 100644 --- a/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/vars/models/TruffleVariablesTreeModel.java +++ b/java/debugger.jpda.truffle/src/org/netbeans/modules/debugger/jpda/truffle/vars/models/TruffleVariablesTreeModel.java @@ -23,7 +23,6 @@ import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import org.netbeans.api.debugger.jpda.JPDADebugger; -import org.netbeans.api.debugger.jpda.JPDAWatch; import org.netbeans.api.debugger.jpda.Variable; import org.netbeans.modules.debugger.jpda.truffle.access.TruffleStrataProvider; import org.netbeans.modules.debugger.jpda.truffle.vars.TruffleScope; @@ -62,7 +61,7 @@ public class TruffleVariablesTreeModel implements TreeModelFilter { @Override public Object[] getChildren(TreeModel original, Object parent, int from, int to) throws UnknownTypeException { - if (parent instanceof JPDAWatch) { + if (parent instanceof Variable) { TruffleVariable tv = TruffleVariableImpl.get((Variable) parent); if (tv != null) { parent = tv; diff --git a/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/DebugSLTest.java b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/DebugSLTest.java index dc3ab84..94e0f43 100644 --- a/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/DebugSLTest.java +++ b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/DebugSLTest.java @@ -130,7 +130,7 @@ public class DebugSLTest extends NbTestCase { assertNotNull("No top frame", topFrame); SourcePosition sourcePosition = topFrame.getSourcePosition(); assertEquals("Bad source", "Meaning of world.sl", sourcePosition.getSource().getName()); - assertEquals("Bad line", lineNo, sourcePosition.getLine()); + assertEquals("Bad line", lineNo, sourcePosition.getStartLine()); assertEquals("Bad method name", methodName, topFrame.getMethodName()); support.doContinue(); @@ -178,7 +178,7 @@ public class DebugSLTest extends NbTestCase { assertNotNull("No top frame", topFrame); SourcePosition sourcePosition = topFrame.getSourcePosition(); assertEquals("Bad source", "TestApp.sl", sourcePosition.getSource().getName()); - assertEquals("Bad line", lb.getLineNumber(), sourcePosition.getLine()); + assertEquals("Bad line", lb.getLineNumber(), sourcePosition.getStartLine()); assertEquals("Bad method name", "main", topFrame.getMethodName()); support.doContinue(); diff --git a/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/testapps/SLApp.java b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/testapps/SLApp.java index 15cabd4..4d1e9f6 100644 --- a/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/testapps/SLApp.java +++ b/java/debugger.jpda.truffle/test/unit/src/org/netbeans/modules/debugger/jpda/truffle/testapps/SLApp.java @@ -44,7 +44,7 @@ public class SLApp { "}\n", "Meaning of world.sl").build(); - Context context = Context.newBuilder().out(os).build(); + Context context = Context.newBuilder().allowAllAccess(true).out(os).build(); Value result = context.eval(src); // LBREAKPOINT assertEquals("Expected result", 42L, result.asLong()); diff --git a/java/debugger.jpda.truffle/truffle-backend/org/netbeans/modules/debugger/jpda/backend/truffle/FrameInfo.java b/java/debugger.jpda.truffle/truffle-backend/org/netbeans/modules/debugger/jpda/backend/truffle/FrameInfo.java index 7e53dea..61c7167 100644 --- a/java/debugger.jpda.truffle/truffle-backend/org/netbeans/modules/debugger/jpda/backend/truffle/FrameInfo.java +++ b/java/debugger.jpda.truffle/truffle-backend/org/netbeans/modules/debugger/jpda/backend/truffle/FrameInfo.java @@ -20,6 +20,7 @@ package org.netbeans.modules.debugger.jpda.backend.truffle; import com.oracle.truffle.api.debug.DebugStackFrame; +import com.oracle.truffle.api.nodes.LanguageInfo; import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.source.SourceSection; import java.lang.reflect.InvocationTargetException; @@ -40,7 +41,7 @@ final class FrameInfo { FrameInfo(DebugStackFrame topStackFrame, Iterable<DebugStackFrame> stackFrames) { SourceSection topSS = topStackFrame.getSourceSection(); - SourcePosition position = JPDATruffleDebugManager.getPosition(topSS); + SourcePosition position = new SourcePosition(topSS); ArrayList<DebugStackFrame> stackFramesArray = new ArrayList<>(); for (DebugStackFrame sf : stackFrames) { if (sf == topStackFrame) { @@ -55,10 +56,13 @@ final class FrameInfo { } frame = topStackFrame; stackTrace = stackFramesArray.toArray(new DebugStackFrame[stackFramesArray.size()]); + LanguageInfo sfLang = topStackFrame.getLanguage(); topFrame = topStackFrame.getName() + "\n" + + ((sfLang != null) ? sfLang.getId() + " " + sfLang.getName() : "") + "\n" + DebuggerVisualizer.getSourceLocation(topSS) + "\n" + position.id + "\n" + position.name + "\n" + position.path + "\n" + - position.uri.toString() + "\n" + position.line + "\n" + isInternal(topStackFrame); + position.uri.toString() + "\n" + position.sourceSection +/* "," + position.startColumn + "," + + position.endLine + "," + position.endColumn +*/ "\n" + isInternal(topStackFrame); topVariables = JPDATruffleAccessor.getVariables(topStackFrame); } diff --git a/java/debugger.jpda.truffle/truffle-backend/org/netbeans/modules/debugger/jpda/backend/truffle/GuestObject.java b/java/debugger.jpda.truffle/truffle-backend/org/netbeans/modules/debugger/jpda/backend/truffle/GuestObject.java index 6d3f6a5..8b159a1 100644 --- a/java/debugger.jpda.truffle/truffle-backend/org/netbeans/modules/debugger/jpda/backend/truffle/GuestObject.java +++ b/java/debugger.jpda.truffle/truffle-backend/org/netbeans/modules/debugger/jpda/backend/truffle/GuestObject.java @@ -21,12 +21,11 @@ package org.netbeans.modules.debugger.jpda.backend.truffle; import com.oracle.truffle.api.debug.DebugStackFrame; import com.oracle.truffle.api.debug.DebugValue; +import com.oracle.truffle.api.nodes.LanguageInfo; import com.oracle.truffle.api.source.SourceSection; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; + import java.util.Collection; import java.util.List; -import java.util.Objects; /** * A guest language object. @@ -37,6 +36,7 @@ public final class GuestObject { final DebugValue value; final String name; + final String language; final String type; final String displayValue; final boolean readable; @@ -50,6 +50,14 @@ public final class GuestObject { final SourcePosition typeSourcePosition; GuestObject(DebugValue value) { + LanguageInfo originalLanguage = value.getOriginalLanguage(); + // Setup the object with a language-specific value + if (originalLanguage != null) { + value = value.asInLanguage(originalLanguage); + this.language = originalLanguage.getId() + " " + originalLanguage.getName(); + } else { + this.language = ""; + } this.value = value; this.name = value.getName(); //System.err.println("new GuestObject("+name+")"); @@ -62,36 +70,34 @@ public final class GuestObject { LangErrors.exception("Value "+name+" .getMetaObject()", ex); } String typeStr = ""; - if (metaObject != null) { - try { - typeStr = metaObject.as(String.class); - } catch (ThreadDeath td) { - throw td; - } catch (Throwable ex) { - LangErrors.exception("Meta object of "+name+" .as(String.class)", ex); + try { + // New in GraalVM 20.1.0 + typeStr = (String) DebugValue.class.getMethod("getMetaSimpleName").invoke(value); + } catch (ReflectiveOperationException | IllegalArgumentException | SecurityException exc) { + if (metaObject != null) { + try { + typeStr = metaObject.as(String.class); + } catch (ThreadDeath td) { + throw td; + } catch (Throwable ex) { + LangErrors.exception("Meta object of "+name+" .as(String.class)", ex); + } } } this.type = typeStr; //this.object = value; String valueStr = null; try { - valueStr = value.as(String.class); + try { + // New in GraalVM 20.1.0 + valueStr = (String) DebugValue.class.getMethod("toDisplayString").invoke(value); + } catch (ReflectiveOperationException | IllegalArgumentException | SecurityException exc) { + valueStr = value.as(String.class); + } } catch (ThreadDeath td) { throw td; } catch (Throwable ex) { - LangErrors.exception("Value "+name+" .as(String.class)", ex); - } - if (valueStr == null) { - // Hack for R: - try { - Method getMethod = DebugValue.class.getDeclaredMethod("get"); - getMethod.setAccessible(true); - Object realValue = getMethod.invoke(value); - valueStr = Objects.toString(realValue); - } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | - NoSuchMethodException | SecurityException ex) { - LangErrors.exception("Value "+name+" get() invocation", ex); - } + LangErrors.exception("Value "+name+" .toDisplayString", ex); } this.displayValue = valueStr; //System.err.println(" have display value "+valueStr); @@ -138,8 +144,8 @@ public final class GuestObject { try { SourceSection sourceLocation = value.getSourceLocation(); //System.err.println("\nSOURCE of "+value.getName()+" is: "+sourceLocation); - if (sourceLocation != null) { - sp = JPDATruffleDebugManager.getPosition(sourceLocation); + if (sourceLocation != null && sourceLocation.isAvailable()) { + sp = new SourcePosition(sourceLocation); } } catch (ThreadDeath td) { throw td; @@ -152,8 +158,8 @@ public final class GuestObject { try { SourceSection sourceLocation = metaObject.getSourceLocation(); //System.err.println("\nSOURCE of metaobject "+metaObject+" is: "+sourceLocation); - if (sourceLocation != null) { - sp = JPDATruffleDebugManager.getPosition(sourceLocation); + if (sourceLocation != null && sourceLocation.isAvailable()) { + sp = new SourcePosition(sourceLocation); } } catch (ThreadDeath td) { throw td; diff --git a/java/debugger.jpda.truffle/truffle-backend/org/netbeans/modules/debugger/jpda/backend/truffle/JPDATruffleAccessor.java b/java/debugger.jpda.truffle/truffle-backend/org/netbeans/modules/debugger/jpda/backend/truffle/JPDATruffleAccessor.java index 26f624a..af6d364 100644 --- a/java/debugger.jpda.truffle/truffle-backend/org/netbeans/modules/debugger/jpda/backend/truffle/JPDATruffleAccessor.java +++ b/java/debugger.jpda.truffle/truffle-backend/org/netbeans/modules/debugger/jpda/backend/truffle/JPDATruffleAccessor.java @@ -26,7 +26,8 @@ import com.oracle.truffle.api.debug.DebugValue; import com.oracle.truffle.api.debug.Debugger; import com.oracle.truffle.api.debug.DebuggerSession; import com.oracle.truffle.api.debug.SuspendedEvent; -//import com.oracle.truffle.api.vm.PolyglotEngine; +import com.oracle.truffle.api.nodes.LanguageInfo; + import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; @@ -111,7 +112,7 @@ public class JPDATruffleAccessor extends Object { } } - static JPDATruffleDebugManager setUpDebugManagerFor(/*Engine*/Object engineObj, boolean doStepInto) { + static JPDATruffleDebugManager setUpDebugManagerFor(/*Engine*/Object engineObj, boolean includeInternal, boolean doStepInto) { trace("setUpDebugManagerFor("+engineObj+", "+doStepInto+")"); Engine engine = (Engine) engineObj; Debugger debugger; @@ -126,13 +127,24 @@ public class JPDATruffleAccessor extends Object { return null; } } - JPDATruffleDebugManager tdm = new JPDATruffleDebugManager(debugger, doStepInto); + JPDATruffleDebugManager tdm = new JPDATruffleDebugManager(debugger, includeInternal, doStepInto); synchronized (debugManagers) { debugManagers.put(debugger, tdm); } return tdm; } + static void setIncludeInternal(boolean includeInternal) { + synchronized (debugManagers) { + for (JPDATruffleDebugManager tdm : debugManagers.values()) { + DebuggerSession debuggerSession = tdm.getDebuggerSession(); + if (debuggerSession != null) { + debuggerSession.setSteppingFilter(JPDATruffleDebugManager.createSteppingFilter(includeInternal)); + } + } + } + } + static int executionHalted(JPDATruffleDebugManager tdm, SourcePosition position, boolean haltedBefore, @@ -200,6 +212,10 @@ public class JPDATruffleAccessor extends Object { } frameInfos.append(sfName); frameInfos.append('\n'); + LanguageInfo sfLang = sf.getLanguage(); + String sfLangId = (sfLang != null) ? sfLang.getId() + " " + sfLang.getName() : ""; + frameInfos.append(sfLangId); + frameInfos.append('\n'); frameInfos.append(DebuggerVisualizer.getSourceLocation(sf.getSourceSection())); frameInfos.append('\n'); /*if (fi.getCallNode() == null) { @@ -210,7 +226,7 @@ public class JPDATruffleAccessor extends Object { System.err.println("frameInfos = "+frameInfos); *//* }*/ - SourcePosition position = JPDATruffleDebugManager.getPosition(sf.getSourceSection()); + SourcePosition position = new SourcePosition(sf.getSourceSection()); frameInfos.append(createPositionIdentificationString(position)); if (includeInternal) { frameInfos.append('\n'); @@ -220,12 +236,6 @@ public class JPDATruffleAccessor extends Object { frameInfos.append("\n\n"); codes[j] = position.code; - /* - TODO Find "this" - Frame f = fi.getFrame(FrameInstance.FrameAccess.READ_ONLY, false); - if (f instanceof VirtualFrame) { - thiss[i] = JSFrameUtil.getThisObj((VirtualFrame) f); - }*/ j++; } if (j < n) { @@ -246,7 +256,7 @@ public class JPDATruffleAccessor extends Object { str.append('\n'); str.append(position.uri.toString()); str.append('\n'); - str.append(position.line); + str.append(position.sourceSection); return str.toString(); } @@ -293,7 +303,8 @@ public class JPDATruffleAccessor extends Object { } Iterable<DebugValue> varsIt = scope.getDeclaredValues(); Iterator<DebugValue> vars = varsIt.iterator(); - if ((args == null || !args.hasNext()) && !vars.hasNext()) { + DebugValue receiver = scope.isFunctionScope() ? scope.getReceiver() : null; + if ((args == null || !args.hasNext()) && !vars.hasNext() && receiver == null) { // An empty scope, skip it scope = scope.getParent(); continue; @@ -314,6 +325,9 @@ public class JPDATruffleAccessor extends Object { while (vars.hasNext()) { variables.add(vars.next()); } + if (receiver != null) { + variables.add(receiver); + } elements.add(variables.size()); if (arguments != null) { for (DebugValue v : arguments) { @@ -377,6 +391,12 @@ public class JPDATruffleAccessor extends Object { while (vars.hasNext()) { variables.add(vars.next()); } + if (scope.isFunctionScope()) { + DebugValue receiver = scope.getReceiver(); + if (receiver != null) { + variables.add(receiver); + } + } elements.add(variables.size()); if (arguments != null) { for (DebugValue v : arguments) { @@ -394,11 +414,12 @@ public class JPDATruffleAccessor extends Object { return elements.toArray(); } - // Store 11 elements: <name>, <type>, <readable>, <writable>, <internal>, <String value>, + // Store 12 elements: <name>, <language>, <type>, <readable>, <writable>, <internal>, <String value>, // <var source>, <VS code>, <type source>, <TS code>, <DebugValue> static void addValueElement(DebugValue value, List<Object> elements) { GuestObject tobj = new GuestObject(value); elements.add(tobj.name); + elements.add(tobj.language); elements.add(tobj.type); elements.add(tobj.readable); elements.add(tobj.writable); diff --git a/java/debugger.jpda.truffle/truffle-backend/org/netbeans/modules/debugger/jpda/backend/truffle/JPDATruffleDebugManager.java b/java/debugger.jpda.truffle/truffle-backend/org/netbeans/modules/debugger/jpda/backend/truffle/JPDATruffleDebugManager.java index 98ecfa7..f3fd297 100644 --- a/java/debugger.jpda.truffle/truffle-backend/org/netbeans/modules/debugger/jpda/backend/truffle/JPDATruffleDebugManager.java +++ b/java/debugger.jpda.truffle/truffle-backend/org/netbeans/modules/debugger/jpda/backend/truffle/JPDATruffleDebugManager.java @@ -26,8 +26,7 @@ import com.oracle.truffle.api.debug.SuspendAnchor; import com.oracle.truffle.api.debug.SuspendedCallback; import com.oracle.truffle.api.debug.SuspendedEvent; import com.oracle.truffle.api.debug.SuspensionFilter; -import com.oracle.truffle.api.source.Source; -import com.oracle.truffle.api.source.SourceSection; + import java.lang.ref.Reference; import java.lang.ref.WeakReference; @@ -41,16 +40,20 @@ class JPDATruffleDebugManager implements SuspendedCallback { private final Reference<DebuggerSession> session; private final ThreadLocal<SuspendedEvent> suspendedEvents = new ThreadLocal<>(); - public JPDATruffleDebugManager(Debugger debugger, boolean doStepInto) { + public JPDATruffleDebugManager(Debugger debugger, boolean includeInternal, boolean doStepInto) { this.debugger = new WeakReference<>(debugger); DebuggerSession debuggerSession = debugger.startSession(this); - debuggerSession.setSteppingFilter(SuspensionFilter.newBuilder().ignoreLanguageContextInitialization(true).build()); + debuggerSession.setSteppingFilter(createSteppingFilter(includeInternal)); if (doStepInto) { debuggerSession.suspendNextExecution(); } this.session = new WeakReference<>(debuggerSession); } - + + static SuspensionFilter createSteppingFilter(boolean includeInternal) { + return SuspensionFilter.newBuilder().ignoreLanguageContextInitialization(true).includeInternal(includeInternal).build(); + } + Debugger getDebugger() { return debugger.get(); } @@ -63,18 +66,6 @@ class JPDATruffleDebugManager implements SuspendedCallback { return suspendedEvents.get(); } - static SourcePosition getPosition(SourceSection sourceSection) { - int line = sourceSection.getStartLine(); - Source source = sourceSection.getSource(); - String name = source.getName(); - String path = source.getPath(); - if (path == null) { - path = name; - } - String code = source.getCharacters().toString(); - return new SourcePosition(source, name, path, line, code); - } - void dispose() { DebuggerSession ds = session.get(); if (ds != null) { @@ -116,7 +107,7 @@ class JPDATruffleDebugManager implements SuspendedCallback { } suspendedEvents.set(event); try { - SourcePosition position = getPosition(event.getSourceSection()); + SourcePosition position = new SourcePosition(event.getSourceSection()); int stepCmd = JPDATruffleAccessor.executionHalted( this, position, event.getSuspendAnchor() == SuspendAnchor.BEFORE, diff --git a/java/debugger.jpda.truffle/truffle-backend/org/netbeans/modules/debugger/jpda/backend/truffle/SourcePosition.java b/java/debugger.jpda.truffle/truffle-backend/org/netbeans/modules/debugger/jpda/backend/truffle/SourcePosition.java index 5552ba6..d4321b0 100644 --- a/java/debugger.jpda.truffle/truffle-backend/org/netbeans/modules/debugger/jpda/backend/truffle/SourcePosition.java +++ b/java/debugger.jpda.truffle/truffle-backend/org/netbeans/modules/debugger/jpda/backend/truffle/SourcePosition.java @@ -20,6 +20,8 @@ package org.netbeans.modules.debugger.jpda.backend.truffle; import com.oracle.truffle.api.source.Source; +import com.oracle.truffle.api.source.SourceSection; + import java.net.URI; import java.util.Map; import java.util.WeakHashMap; @@ -36,16 +38,21 @@ final class SourcePosition { final long id; final String name; final String path; - final int line; + final String sourceSection; final String code; final URI uri; - public SourcePosition(Source source, String name, String path, int line, String code) { + public SourcePosition(SourceSection sourceSection) { + Source source = sourceSection.getSource(); this.id = getId(source); - this.name = name; - this.path = path; - this.line = line; - this.code = code; + this.name = source.getName(); + String sourcePath = source.getPath(); + if (sourcePath == null) { + sourcePath = name; + } + this.path = sourcePath; + this.sourceSection = sourceSection.getStartLine() + "," + sourceSection.getStartColumn() + "," + sourceSection.getEndLine() + "," + sourceSection.getEndColumn(); + this.code = source.getCharacters().toString(); this.uri = source.getURI(); } diff --git a/java/debugger.jpda.truffle/truffle-backend/org/netbeans/modules/debugger/jpda/backend/truffle/TruffleAST.java b/java/debugger.jpda.truffle/truffle-backend/org/netbeans/modules/debugger/jpda/backend/truffle/TruffleAST.java index 997e64f..64131f9 100644 --- a/java/debugger.jpda.truffle/truffle-backend/org/netbeans/modules/debugger/jpda/backend/truffle/TruffleAST.java +++ b/java/debugger.jpda.truffle/truffle-backend/org/netbeans/modules/debugger/jpda/backend/truffle/TruffleAST.java @@ -26,12 +26,13 @@ import com.oracle.truffle.api.frame.Frame; import com.oracle.truffle.api.frame.FrameInstance; import com.oracle.truffle.api.frame.FrameInstanceVisitor; import com.oracle.truffle.api.frame.FrameSlot; +import com.oracle.truffle.api.instrumentation.InstrumentableNode; import com.oracle.truffle.api.instrumentation.StandardTags; +import com.oracle.truffle.api.instrumentation.Tag; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.NodeUtil; import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.source.SourceSection; -import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; @@ -132,23 +133,19 @@ public class TruffleAST { } // TAGS: try { - java.lang.reflect.Method isTaggedWithMethod = Node.class.getDeclaredMethod("isTaggedWith", Class.class); - isTaggedWithMethod.setAccessible(true); StringBuilder tags = new StringBuilder(); - if ((Boolean) isTaggedWithMethod.invoke(node, StandardTags.RootTag.class)) { - tags.append("Root"); - } - if ((Boolean) isTaggedWithMethod.invoke(node, StandardTags.CallTag.class)) { - if (tags.length() > 0) { - tags.append(' '); - } - tags.append("Call"); - } - if ((Boolean) isTaggedWithMethod.invoke(node, StandardTags.StatementTag.class)) { - if (tags.length() > 0) { - tags.append(' '); + if (node instanceof InstrumentableNode) { + InstrumentableNode inode = (InstrumentableNode) node; + for (Class<?> tag : StandardTags.class.getDeclaredClasses()) { + if (Tag.class.isAssignableFrom(tag)) { + if (inode.hasTag(tag.asSubclass(Tag.class))) { + if (tags.length() > 0) { + tags.append(','); + } + tags.append(tag.getSimpleName()); + } + } } - tags.append("Statement"); } nodes.append(tags); } catch (Throwable t) { --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@netbeans.apache.org For additional commands, e-mail: commits-h...@netbeans.apache.org For further information about the NetBeans mailing lists, visit: https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists