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

Unified Diff: runtime/bin/vmservice/client/lib/src/service/object.dart

Issue 251043003: Observatory Display PC descriptors with disassembling (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 8 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
Index: runtime/bin/vmservice/client/lib/src/service/object.dart
diff --git a/runtime/bin/vmservice/client/lib/src/service/object.dart b/runtime/bin/vmservice/client/lib/src/service/object.dart
index 71345774be2eef47a59fe0338866cb7bb84044da..6ec387df6e1641027d29e5b32a0af32f2330e521 100644
--- a/runtime/bin/vmservice/client/lib/src/service/object.dart
+++ b/runtime/bin/vmservice/client/lib/src/service/object.dart
@@ -864,6 +864,11 @@ class Script extends ServiceObject {
Script._empty(ServiceObjectOwner owner) : super._empty(owner);
+ ScriptLine getLine(int line) {
+ assert(line >= 1);
+ return lines[line - 1];
+ }
+
/// This function maps a token position to a line number.
int tokenToLine(int token) => _tokenToLine[token];
Map _tokenToLine;
@@ -952,10 +957,52 @@ class CodeTick {
}
+class PcDescriptor extends Observable {
+ final int address;
+ @reflectable final int deoptId;
+ @reflectable final int tokenPos;
+ @reflectable final int tryIndex;
+ @reflectable final String kind;
+ @observable Script script;
+ @observable String formattedLine;
+ PcDescriptor(this.address, this.deoptId, this.tokenPos, this.tryIndex,
+ this.kind);
+
+ @reflectable String formattedDeoptId() {
+ if (deoptId == -1) {
+ return 'N/A';
+ }
+ return deoptId.toString();
+ }
+
+ @reflectable String formattedTokenPos() {
+ if (tokenPos == -1) {
+ return '';
+ }
+ return tokenPos.toString();
+ }
+
+ void processScript(Script script) {
+ this.script = null;
+ if (tokenPos == -1) {
+ return;
+ }
+ var line = script.tokenToLine(tokenPos);
+ if (line == null) {
+ return;
+ }
+ this.script = script;
+ var scriptLine = script.getLine(line);
+ formattedLine = scriptLine.text;
+ }
+}
+
class CodeInstruction extends Observable {
@observable final int address;
@observable final String machine;
@observable final String human;
+ @observable CodeInstruction jumpTarget;
+ @observable PcDescriptor descriptor;
turnidge 2014/04/28 17:41:49 from offline: support multiple descriptors.
Cutch 2014/04/28 22:48:00 Done.
static String formatPercent(num a, num total) {
var percent = 100.0 * (a / total);
@@ -964,6 +1011,9 @@ class CodeInstruction extends Observable {
CodeInstruction(this.address, this.machine, this.human);
+ @reflectable bool get isComment => address == 0;
+ @reflectable bool get hasDescriptor => descriptor != null;
+
@reflectable String formattedAddress() {
if (address == 0) {
return '';
@@ -998,6 +1048,49 @@ class CodeInstruction extends Observable {
var pcent = formatPercent(tick.exclusiveTicks, code.totalSamplesInProfile);
return '$pcent (${tick.exclusiveTicks})';
}
+
+ bool _isJumpInstruction() {
+ return human.startsWith('j');
+ }
+
+ int _getJumpAddress() {
+ assert(_isJumpInstruction());
+ var chunks = human.split(' ');
+ if (chunks.length != 2) {
+ // We expect jump instructions to be of the form 'j.. address'.
+ return 0;
+ }
+ var address = chunks[1];
+ if (address.startsWith('0x')) {
+ // Chop off the 0x.
+ address = address.substring(2);
+ }
+ try {
+ return int.parse(address, radix:16);
+ } catch (_) {
+ return 0;
+ }
+ }
+
+ void _resolveJumpTarget(List<CodeInstruction> instructions) {
+ if (!_isJumpInstruction()) {
+ return;
+ }
+ int address = _getJumpAddress();
+ if (address == 0) {
+ // Could not determine jump address.
+ print('Could not determine jump address for $human');
+ return;
+ }
+ for (var i = 0; i < instructions.length; i++) {
+ var instruction = instructions[i];
+ if (instruction.address == address) {
+ jumpTarget = instruction;
+ return;
+ }
+ }
+ print('Could not find instruction at ${address.toRadixString(16)}');
+ }
}
class CodeKind {
@@ -1056,6 +1149,7 @@ class Code extends ServiceObject {
@observable String formattedExclusiveTicks = '';
@observable ServiceMap objectPool;
@observable ServiceMap function;
+ @observable Script script;
String name;
String vmName;
@@ -1076,6 +1170,43 @@ class Code extends ServiceObject {
addressTicks.clear();
}
+ void _updateDescriptors(Script script) {
+ this.script = script;
+ for (var instruction in instructions) {
+ if (instruction.descriptor != null) {
+ instruction.descriptor.processScript(script);
+ }
+ }
+ }
+
+ void loadScript() {
+ if (script != null) {
+ // Already done.
+ return;
+ }
+ if (kind != CodeKind.Dart){
+ return;
+ }
+ if (function == null) {
+ return;
+ }
+ if (function['script'] == null) {
+ // Attempt to load the function.
+ function.load().then((func) {
+ var script = function['script'];
+ if (script == null) {
+ // Function doesn't have an associated script.
+ return;
+ }
+ // Load the script and then update descriptors.
+ script.load().then(_updateDescriptors);
+ });
+ return;
+ }
+ // Load the script and then update descriptors.
+ function['script'].load().then(_updateDescriptors);
+ }
+
/// Reload [this]. Returns a future which completes to [this] or
/// a [ServiceError].
Future<ServiceObject> reload() {
@@ -1144,6 +1275,11 @@ class Code extends ServiceObject {
if (disassembly != null) {
_processDisassembly(disassembly);
}
+ var descriptors = m['descriptors'];
+ if (descriptors != null) {
+ descriptors = descriptors['members'];
+ _processDescriptors(descriptors);
+ }
// We are loaded if we have instructions or are not Dart code.
_loaded = (instructions.length != 0) || (kind != CodeKind.Dart);
hasDisassembly = (instructions.length != 0) && (kind == CodeKind.Dart);
@@ -1166,6 +1302,35 @@ class Code extends ServiceObject {
var instruction = new CodeInstruction(address, machine, human);
instructions.add(instruction);
}
+ for (var instruction in instructions) {
+ instruction._resolveJumpTarget(instructions);
+ }
+ }
+
+ void _processDescriptor(Map d) {
+ var address = int.parse(d['pc'], radix:16);
+ var deoptId = d['deoptId'];
+ var tokenPos = d['tokenPos'];
+ var tryIndex = d['tryIndex'];
+ var kind = d['kind'].trim();
+ for (var instruction in instructions) {
+ if (instruction.address == address) {
+ instruction.descriptor = new PcDescriptor(address,
+ deoptId,
+ tokenPos,
+ tryIndex,
+ kind);
+ return;
+ }
+ }
+ Logger.root.warning(
+ 'Could not find instruction with pc descriptor address: $address');
+ }
+
+ void _processDescriptors(List<Map> descriptors) {
+ for (Map descriptor in descriptors) {
+ _processDescriptor(descriptor);
+ }
}
void _processTicks(List<String> profileTicks) {
« no previous file with comments | « runtime/bin/vmservice/client/lib/src/elements/vm_view.html ('k') | runtime/bin/vmservice/client/notdotdot.sh » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698