Chromium Code Reviews| 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 == '') { |