Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(378)

Unified Diff: pkg/dartino_compiler/lib/src/debug_service_protocol.dart

Issue 2060283002: Inspect local variables and fields from service protocol. (Closed) Base URL: git@github.com:dartino/sdk.git@master
Patch Set: Address review Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/dartino_compiler/lib/src/debug_service_protocol.dart
diff --git a/pkg/dartino_compiler/lib/src/debug_service_protocol.dart b/pkg/dartino_compiler/lib/src/debug_service_protocol.dart
index c21df67cc9e8f4c913bc81f548c29eddb31339ba..148bde39a3d6e507f63e5d2cde275a0b8994fa29 100644
--- a/pkg/dartino_compiler/lib/src/debug_service_protocol.dart
+++ b/pkg/dartino_compiler/lib/src/debug_service_protocol.dart
@@ -6,7 +6,6 @@
/// Processes are mapped to isolates.
// TODO(sigurdm): Handle processes better.
// TODO(sigurdm): Find a way to represent fibers.
-// TODO(sigurdm): Represent remote values.
// TODO(sigurdm): Use https://pub.dartlang.org/packages/json_rpc_2 for serving.
import "dart:async" show Future;
@@ -20,7 +19,15 @@ import 'hub/session_manager.dart' show SessionState;
import 'guess_configuration.dart' show dartinoVersion;
import '../debug_state.dart'
- show BackTrace, BackTraceFrame, Breakpoint, RemoteObject;
+ show
+ BackTrace,
+ BackTraceFrame,
+ Breakpoint,
+ RemoteArray,
+ RemoteErrorObject,
+ RemoteInstance,
+ RemoteObject,
+ RemoteValue;
import '../vm_context.dart' show DartinoVmContext, DebugListener;
@@ -31,10 +38,20 @@ import 'debug_info.dart' show DebugInfo, ScopeInfo, SourceLocation;
import 'dartino_compiler_implementation.dart'
show DartinoCompilerImplementation;
-
-import 'codegen_visitor.dart' show LocalValue;
+import 'element_utils.dart';
import '../program_info.dart' show Configuration;
+import '../vm_commands.dart'
+ show
+ Array,
+ Boolean,
+ ClassValue,
+ DartValue,
+ Double,
+ Instance,
+ Integer,
+ NullValue,
+ StringValue;
import 'package:collection/collection.dart' show binarySearch;
@@ -44,8 +61,10 @@ import 'package:compiler/src/io/source_file.dart' show SourceFile;
import 'package:compiler/src/elements/visitor.dart' show BaseElementVisitor;
import 'package:compiler/src/elements/elements.dart'
show
+ ClassElement,
CompilationUnitElement,
Element,
+ FieldElement,
FunctionElement,
LibraryElement,
MemberElement,
@@ -53,43 +72,6 @@ import 'package:compiler/src/elements/elements.dart'
const bool logging = const bool.fromEnvironment("dartino-log-debug-server");
-//TODO(danrubel): Verify const map values
-const Map<String, dynamic> dartCoreLibRefDesc = const <String, dynamic>{
- "type": "@Library",
- "id": "libraries/dart:core",
- "fixedId": true,
- "name": "dart:core",
- "uri": "dart:core",
-};
-
-//TODO(danrubel): Verify correct id
-const String nullId = "objects/Null";
-
-//TODO(danrubel): Verify const map values
-const Map<String, dynamic> nullClassRefDesc = const <String, dynamic>{
- "type": "@Class",
- "id": "classes/NullClass",
- "name": "NullClass",
-};
-
-//TODO(danrubel): Verify const map values
-const Map<String, dynamic> nullRefDesc = const <String, dynamic>{
- "type": "@Null",
- "id": nullId,
- "kind": "Null",
- "class": nullClassRefDesc,
- "valueAsString": "null",
-};
-
-//TODO(danrubel): Verify const map values
-const Map<String, dynamic> nullDesc = const <String, dynamic>{
- "type": "Null",
- "id": nullId,
- "kind": "Null",
- "class": nullClassRefDesc,
- "valueAsString": "null",
-};
-
class DebugServer {
Future<int> serveSingleShot(SessionState state,
{int port: 0, Uri snapshotLocation}) async {
@@ -145,15 +127,18 @@ class DebugConnection implements DebugListener {
Map<String, CompilationUnitElement> scripts =
new Map<String, CompilationUnitElement>();
- Map frameDesc(BackTraceFrame frame, int index) {
+ Future<Map> frameDesc(BackTraceFrame frame, int index) async {
List<Map> vars = new List<Map>();
for (ScopeInfo current = frame.scopeInfo();
current != ScopeInfo.sentinel;
current = current.previous) {
+ RemoteValue remoteValue =
+ await vmContext.processLocal(index, current.local.slot);
vars.add({
"type": "BoundVariable",
"name": current.name,
- "value": valueDesc(current.lookup(current.name))
+ "value": instanceRef(
+ remoteValue.value, "objects/$index.${current.local.slot}"),
});
}
return {
@@ -338,10 +323,136 @@ class DebugConnection implements DebugListener {
};
}
- Map valueDesc(LocalValue lookup) {
- //TODO(danrubel): Translate local value into description?
- // Need to return an @InstanceRef or Sentinel
- return nullRefDesc;
+ Map classRef(ClassElement classElement) {
+ if (classElement == null) {
+ return {"type": "@Class", "id": "unknown", "name": "unknown class"};
+ }
+ String symbolicName =
+ "${classElement.library.canonicalUri}.${classElement.name}";
+ return {
+ "type": "@Class",
+ "id": "classes/$symbolicName",
+ "name": "${classElement.name}",
+ };
+ }
+
+ Map instanceRef(DartValue value, String id) {
+ int classId;
+ Element classElement;
+ String stringValue;
+ String kind;
+ int length;
+ String name;
+ if (value is Instance) {
+ kind = "PlainInstance";
+ classId = value.classId;
+ } else if (value is Integer) {
+ kind = "Int";
+ classElement = vmContext.compiler.compiler.backend.intImplementation;
+ stringValue = "${value.value}";
+ } else if (value is StringValue) {
+ kind = "String";
+ classElement = vmContext.compiler.compiler.backend.stringImplementation;
+ stringValue = value.value;
+ } else if (value is Boolean) {
+ kind = "Bool";
+ classElement = vmContext.compiler.compiler.backend.boolImplementation;
+ stringValue = "${value.value}";
+ } else if (value is Double) {
+ kind = "Double";
+ classElement = vmContext.compiler.compiler.backend.doubleImplementation;
+ stringValue = "${value.value}";
+ } else if (value is ClassValue) {
+ kind = "Type";
+ Element element =
+ vmContext.dartinoSystem.classesById[value.classId].element;
+ classElement = vmContext.compiler.compiler.backend.typeImplementation;
+ name = "${element}";
+ } else if (value is NullValue) {
+ kind = "Null";
+ classElement = vmContext.compiler.compiler.backend.nullImplementation;
+ stringValue = "null";
+ } else if (value is Array) {
+ kind = "List";
+ classElement = vmContext.compiler.compiler.backend.listImplementation;
+ length = value.length;
+ } else {
+ throw "Unexpected remote value $value";
+ }
+ Map classReference = classRef(
+ classElement ?? vmContext.dartinoSystem.classesById[classId]?.element);
+ Map result = {
+ "type": "@Instance",
+ "id": id,
+ "kind": kind,
+ "class": classReference,
+ };
+ if (stringValue != null) {
+ result["valueAsString"] = stringValue;
+ }
+ if (length != null) {
+ result["length"] = length;
+ }
+ if (name != null) {
+ result["name"] = name;
+ }
+ return result;
+ }
+
+ Map instanceDesc(RemoteObject remoteObject, String id) {
+ // TODO(sigurdm): Allow inspecting any frame.
+ assert(remoteObject is! RemoteErrorObject);
+ if (remoteObject is RemoteInstance) {
+ int classId = remoteObject.instance.classId;
+ Element classElement =
+ vmContext.dartinoSystem.classesById[classId].element;
+ List<FieldElement> fieldElements = computeFields(classElement);
+ assert(fieldElements.length == remoteObject.fields.length);
+ List fields = new List();
+ for (int i = 0; i < fieldElements.length; i++) {
+ FieldElement fieldElement = fieldElements[i];
+ fields.add({
+ "type": "BoundField",
+ "decl": {
+ "type": "@Field",
+ "name": fieldElement.name,
+ "owner": classRef(fieldElement.contextClass),
+ "declaredType": null, // TODO(sigurdm): fill this in.
+ "const": fieldElement.isConst,
+ "final": fieldElement.isFinal,
+ "static": fieldElement.isStatic,
+ },
+ "value": instanceRef(remoteObject.fields[i], "$id.$i"),
+ });
+ }
+ return <String, dynamic>{
+ "type": "Instance",
+ "id": id,
+ "kind": "PlainInstance",
+ "class": classRef(classElement),
+ "fields": fields,
+ };
+ } else if (remoteObject is RemoteArray) {
+ // TODO(sigurdm): Handle large arrays. (Issue #536).
+ List elements = new List();
+ for (int i = 0; i < remoteObject.array.length; i++) {
+ elements.add(instanceRef(remoteObject.values[i], "$id.$i"));
+ }
+ return <String, dynamic>{
+ "type": "Instance",
+ "id": id,
+ "kind": "List",
+ "class":
+ classRef(vmContext.compiler.compiler.backend.listImplementation),
+ "elements": elements,
+ };
+ } else if (remoteObject is RemoteValue) {
+ Map instance = instanceRef(remoteObject.value, id);
+ instance["type"] = "Instance";
+ return instance;
+ } else {
+ throw "Unexpected remote object kind";
+ }
}
initialize(DartinoCompilerImplementation compiler) {
@@ -504,13 +615,15 @@ class DebugConnection implements DebugListener {
int.parse(id.substring(slashIndex + 1))]));
break;
case "objects":
- if (id == nullId) {
- sendResult(nullDesc);
- } else {
- //TODO(danrubel): Need to return an Instance description
- // or Sentinel for the given @InstanceRef
- throw 'Unknown object: $id';
- }
+ String path = id.substring(slashIndex + 1);
+ List<int> dotted = path.split(".").map(int.parse).toList();
+ int localFrame = dotted.first;
+ int localSlot = dotted[1];
+ List<int> fieldAccesses = dotted.skip(2).toList();
+ RemoteObject remoteObject = await vmContext.processLocalStructure(
+ localFrame, localSlot,
+ fieldAccesses: fieldAccesses);
+ sendResult(instanceDesc(remoteObject, id));
break;
default:
throw "Unsupported object type $id";
@@ -525,7 +638,7 @@ class DebugConnection implements DebugListener {
List frames = [];
int index = 0;
for (BackTraceFrame frame in backTrace.frames) {
- frames.add(frameDesc(frame, index));
+ frames.add(await frameDesc(frame, index));
index++;
}
@@ -710,7 +823,7 @@ class DebugConnection implements DebugListener {
@override
pauseBreakpoint(
- int processId, BackTraceFrame topFrame, Breakpoint breakpoint) {
+ int processId, BackTraceFrame topFrame, Breakpoint breakpoint) async {
//TODO(danrubel): are there any other breakpoints
// at which we are currently paused for a PauseBreakpoint event?
List<Breakpoint> pauseBreakpoints = <Breakpoint>[];
@@ -720,7 +833,7 @@ class DebugConnection implements DebugListener {
"kind": "PauseBreakpoint",
"isolate": isolateRef(processId),
"timestamp": new DateTime.now().millisecondsSinceEpoch,
- "topFrame": frameDesc(topFrame, 0),
+ "topFrame": await frameDesc(topFrame, 0),
"atAsyncSuspension": false,
"breakpoint": breakpointDesc(breakpoint),
"pauseBreakpoints":
@@ -731,13 +844,14 @@ class DebugConnection implements DebugListener {
}
@override
- pauseException(int processId, BackTraceFrame topFrame, RemoteObject thrown) {
+ pauseException(
+ int processId, BackTraceFrame topFrame, RemoteObject thrown) async {
Map event = {
"type": "Event",
"kind": "PauseException",
"isolate": isolateRef(processId),
"timestamp": new DateTime.now().millisecondsSinceEpoch,
- "topFrame": frameDesc(topFrame, 0),
+ "topFrame": await frameDesc(topFrame, 0),
"atAsyncSuspension": false,
// TODO(sigurdm): pass thrown as an instance.
};
@@ -750,13 +864,13 @@ class DebugConnection implements DebugListener {
}
@override
- pauseInterrupted(int processId, BackTraceFrame topFrame) {
+ pauseInterrupted(int processId, BackTraceFrame topFrame) async {
Map event = {
"type": "Event",
"kind": "PauseInterrupted",
"isolate": isolateRef(processId),
"timestamp": new DateTime.now().millisecondsSinceEpoch,
- "topFrame": frameDesc(topFrame, 0),
+ "topFrame": await frameDesc(topFrame, 0),
"atAsyncSuspension": false,
};
lastPauseEvent = event;
@@ -808,7 +922,7 @@ class DebugConnection implements DebugListener {
}
@override
- resume(int processId) {
+ resume(int processId) async {
Map event = {
"type": "Event",
"kind": "Resume",
@@ -817,7 +931,7 @@ class DebugConnection implements DebugListener {
};
BackTraceFrame topFrame = vmContext.debugState.topFrame;
if (topFrame != null) {
- event["topFrame"] = frameDesc(vmContext.debugState.topFrame, 0);
+ event["topFrame"] = await frameDesc(vmContext.debugState.topFrame, 0);
}
lastPauseEvent = event;
streamNotify("Debug", event);
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698