Index: runtime/observatory/lib/src/elements/code_view.dart |
diff --git a/runtime/observatory/lib/src/elements/code_view.dart b/runtime/observatory/lib/src/elements/code_view.dart |
index f44af1f597e39e5f86135788ebe83ce218cefdf2..1c5ccbddf81320c23f4cb0c1b7029a593cce9733 100644 |
--- a/runtime/observatory/lib/src/elements/code_view.dart |
+++ b/runtime/observatory/lib/src/elements/code_view.dart |
@@ -6,13 +6,30 @@ library code_view_element; |
import 'dart:html'; |
import 'observatory_element.dart'; |
+import 'package:observatory/app.dart'; |
import 'package:observatory/service.dart'; |
+import 'package:observatory/cpu_profile.dart'; |
import 'package:polymer/polymer.dart'; |
+class DisassemblyTable extends SortedTable { |
+ DisassemblyTable(columns) : super(columns); |
+} |
+ |
@CustomTag('code-view') |
class CodeViewElement extends ObservatoryElement { |
@published Code code; |
- CodeViewElement.created() : super.created(); |
+ @observable DisassemblyTable disassemblyTable; |
+ |
+ CodeViewElement.created() : super.created() { |
+ // Create table model. |
+ var columns = [ |
+ new SortedTableColumn('Inclusive'), |
+ new SortedTableColumn('Exclusive'), |
+ new SortedTableColumn('Address'), |
+ new SortedTableColumn('Disassembly'), |
+ ]; |
+ disassemblyTable = new DisassemblyTable(columns); |
+ } |
@override |
void attached() { |
@@ -23,12 +40,143 @@ class CodeViewElement extends ObservatoryElement { |
code.load().then((Code c) { |
c.loadScript(); |
}); |
+ _updateDisassembly(); |
} |
void refresh(var done) { |
code.reload().whenComplete(done); |
} |
+ void refreshTicks(var done) { |
+ var isolate = code.isolate; |
+ isolate.invokeRpc('getCpuProfile', { 'tags': 'None' }) |
+ .then((ServiceMap response) { |
+ new CpuProfile()..load(isolate, response); |
rmacnak
2015/02/19 23:49:53
No need to cascade.
Cutch
2015/02/20 01:49:56
Done.
|
+ _updateDisassembly(); |
+ }).whenComplete(done); |
+ } |
+ |
+ String formattedAddress(CodeInstruction instruction) { |
+ if (instruction.address == 0) { |
+ return ''; |
+ } |
+ return '0x${instruction.address.toRadixString(16)}'; |
+ } |
+ |
+ String formattedInclusive(CodeInstruction instruction) { |
+ if (code == null) { |
+ return ''; |
+ } |
+ if (code.profile == null) { |
+ return ''; |
+ } |
+ var tick = code.profile.addressTicks[instruction.address]; |
+ if (tick == null) { |
+ return ''; |
+ } |
+ // Don't show inclusive ticks if they are the same as exclusive ticks. |
+ if (tick.inclusiveTicks == tick.exclusiveTicks) { |
+ return ''; |
+ } |
+ var pcent = Utils.formatPercent(tick.inclusiveTicks, |
+ code.profile.profile.sampleCount); |
+ return '$pcent (${tick.inclusiveTicks})'; |
+ } |
+ |
+ String formattedExclusive(CodeInstruction instruction) { |
+ if (code == null) { |
+ return ''; |
+ } |
+ if (code.profile == null) { |
+ return ''; |
+ } |
+ var tick = code.profile.addressTicks[instruction.address]; |
+ if (tick == null) { |
+ return ''; |
+ } |
+ var pcent = Utils.formatPercent(tick.exclusiveTicks, |
+ code.profile.profile.sampleCount); |
+ return '$pcent (${tick.exclusiveTicks})'; |
+ } |
+ |
+ void _updateTable() { |
+ disassemblyTable.clearRows(); |
+ if (code == null) { |
+ return; |
+ } |
+ for (CodeInstruction instruction in code.instructions) { |
+ var row = [formattedInclusive(instruction), |
+ formattedExclusive(instruction), |
+ formattedAddress(instruction), |
+ instruction.human]; |
+ disassemblyTable.addRow(new SortedTableRow(row)); |
+ } |
+ } |
+ |
+ void _addDOMRow() { |
+ var tableBody = $['disassemblyTableBody']; |
+ assert(tableBody != null); |
+ var tr = new TableRowElement(); |
+ |
+ var cell; |
+ |
+ // Add new space. |
+ cell = tr.insertCell(-1); |
+ cell.classes.add('monospace'); |
+ cell = tr.insertCell(-1); |
+ cell.classes.add('monospace'); |
+ cell = tr.insertCell(-1); |
+ cell.classes.add('monospace'); |
+ cell = tr.insertCell(-1); |
+ cell.classes.add('monospace'); |
+ |
+ tableBody.children.add(tr); |
+ } |
+ |
+ void _fillDOMRow(TableRowElement tr, int rowIndex) { |
+ var row = disassemblyTable.rows[rowIndex]; |
+ for (var i = 0; i < row.values.length; i++) { |
+ var cell = tr.children[i]; |
+ cell.title = row.values[i].toString(); |
rmacnak
2015/02/19 23:49:53
Why set the tooltip if it is the same?
Cutch
2015/02/20 01:49:56
Acknowledged.
|
+ cell.text = row.values[i].toString(); |
+ } |
+ } |
+ |
+ void _updateDOMTable() { |
+ var tableBody = $['disassemblyTableBody']; |
+ assert(tableBody != null); |
+ // Resize DOM table. |
+ if (tableBody.children.length > disassemblyTable.sortedRows.length) { |
+ // Shrink the table. |
+ var deadRows = |
+ tableBody.children.length - disassemblyTable.sortedRows.length; |
+ for (var i = 0; i < deadRows; i++) { |
+ tableBody.children.removeLast(); |
+ } |
+ } else if (tableBody.children.length < disassemblyTable.sortedRows.length) { |
+ // Grow table. |
+ var newRows = |
+ disassemblyTable.sortedRows.length - tableBody.children.length; |
+ for (var i = 0; i < newRows; i++) { |
+ _addDOMRow(); |
+ } |
+ } |
+ |
+ assert(tableBody.children.length == disassemblyTable.sortedRows.length); |
+ // Fill table. |
+ for (var i = 0; i < disassemblyTable.sortedRows.length; i++) { |
+ var rowIndex = disassemblyTable.sortedRows[i]; |
+ var tr = tableBody.children[i]; |
+ _fillDOMRow(tr, rowIndex); |
+ } |
+ } |
+ |
+ void _updateDisassembly() { |
+ notifyPropertyChange(#code, true, false); |
+ _updateTable(); |
+ _updateDOMTable(); |
+ } |
+ |
Element _findJumpTarget(Element target) { |
var jumpTarget = target.attributes['data-jump-target']; |
if (jumpTarget == '') { |