| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library code_view_element; | 5 library code_view_element; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:html'; | 8 import 'dart:html'; |
| 9 import 'observatory_element.dart'; | |
| 10 import 'service_ref.dart'; | |
| 11 import 'package:observatory/app.dart'; | |
| 12 import 'package:observatory/service.dart'; | |
| 13 import 'package:observatory/cpu_profile.dart'; | 9 import 'package:observatory/cpu_profile.dart'; |
| 14 import 'package:polymer/polymer.dart'; | 10 import 'package:observatory/service.dart' as S; |
| 11 import 'package:observatory/models.dart' as M; |
| 12 import 'package:observatory/app.dart' |
| 13 show SortedTable, SortedTableColumn, SortedTableRow; |
| 14 import 'package:observatory/src/elements/curly_block.dart'; |
| 15 import 'package:observatory/src/elements/function_ref.dart'; |
| 16 import 'package:observatory/src/elements/helpers/any_ref.dart'; |
| 17 import 'package:observatory/src/elements/helpers/rendering_scheduler.dart'; |
| 18 import 'package:observatory/src/elements/helpers/tag.dart'; |
| 19 import 'package:observatory/src/elements/nav/bar.dart'; |
| 20 import 'package:observatory/src/elements/nav/class_menu.dart'; |
| 21 import 'package:observatory/src/elements/nav/isolate_menu.dart'; |
| 22 import 'package:observatory/src/elements/nav/menu.dart'; |
| 23 import 'package:observatory/src/elements/nav/notify.dart'; |
| 24 import 'package:observatory/src/elements/nav/refresh.dart'; |
| 25 import 'package:observatory/src/elements/nav/top_menu.dart'; |
| 26 import 'package:observatory/src/elements/nav/vm_menu.dart'; |
| 27 import 'package:observatory/src/elements/object_common.dart'; |
| 28 import 'package:observatory/src/elements/objectpool_ref.dart'; |
| 29 import 'package:observatory/utils.dart'; |
| 15 | 30 |
| 16 class DisassemblyTable extends SortedTable { | 31 class DisassemblyTable extends SortedTable { |
| 17 DisassemblyTable(columns) : super(columns); | 32 DisassemblyTable(columns) : super(columns); |
| 18 } | 33 } |
| 19 | 34 |
| 20 class InlineTable extends SortedTable { | 35 class InlineTable extends SortedTable { |
| 21 InlineTable(columns) : super(columns); | 36 InlineTable(columns) : super(columns); |
| 22 } | 37 } |
| 23 | 38 |
| 24 @CustomTag('code-view') | 39 class CodeViewElement extends HtmlElement implements Renderable { |
| 25 class CodeViewElement extends ObservatoryElement { | 40 static const tag = const Tag<CodeViewElement>('code-view', |
| 26 @observable Code code; | 41 dependencies: const [ |
| 27 ProfileCode get profile => code == null ? null : code.profile; | 42 CurlyBlockElement.tag, |
| 43 FunctionRefElement.tag, |
| 44 NavBarElement.tag, |
| 45 NavClassMenuElement.tag, |
| 46 NavTopMenuElement.tag, |
| 47 NavVMMenuElement.tag, |
| 48 NavIsolateMenuElement.tag, |
| 49 NavMenuElement.tag, |
| 50 NavRefreshElement.tag, |
| 51 NavNotifyElement.tag, |
| 52 ObjectCommonElement.tag, |
| 53 ObjectPoolRefElement.tag, |
| 54 ]); |
| 55 |
| 56 RenderingScheduler<CodeViewElement> _r; |
| 57 |
| 58 Stream<RenderedEvent<CodeViewElement>> get onRendered => _r.onRendered; |
| 59 |
| 60 M.VM _vm; |
| 61 M.IsolateRef _isolate; |
| 62 M.EventRepository _events; |
| 63 M.NotificationRepository _notifications; |
| 64 M.Code _code; |
| 65 M.RetainedSizeRepository _retainedSizes; |
| 66 M.ReachableSizeRepository _reachableSizes; |
| 67 M.InboundReferencesRepository _references; |
| 68 M.RetainingPathRepository _retainingPaths; |
| 69 M.InstanceRepository _instances; |
| 28 DisassemblyTable disassemblyTable; | 70 DisassemblyTable disassemblyTable; |
| 29 InlineTable inlineTable; | 71 InlineTable inlineTable; |
| 30 | 72 |
| 31 static const kDisassemblyColumnIndex = 3; | 73 static const kDisassemblyColumnIndex = 3; |
| 32 | 74 |
| 75 |
| 76 M.VMRef get vm => _vm; |
| 77 M.IsolateRef get isolate => _isolate; |
| 78 M.NotificationRepository get notifications => _notifications; |
| 79 M.Code get context => _code; |
| 80 |
| 81 factory CodeViewElement(M.VM vm, M.IsolateRef isolate, M.Code code, |
| 82 M.EventRepository events, |
| 83 M.NotificationRepository notifications, |
| 84 M.RetainedSizeRepository retainedSizes, |
| 85 M.ReachableSizeRepository reachableSizes, |
| 86 M.InboundReferencesRepository references, |
| 87 M.RetainingPathRepository retainingPaths, |
| 88 M.InstanceRepository instances, |
| 89 {RenderingQueue queue}) { |
| 90 assert(vm != null); |
| 91 assert(isolate != null); |
| 92 assert(events != null); |
| 93 assert(notifications != null); |
| 94 assert(code != null); |
| 95 assert(instances != null); |
| 96 assert(retainedSizes != null); |
| 97 assert(reachableSizes != null); |
| 98 assert(references != null); |
| 99 assert(retainingPaths != null); |
| 100 CodeViewElement e = document.createElement(tag.name); |
| 101 e._r = new RenderingScheduler(e, queue: queue); |
| 102 e._vm = vm; |
| 103 e._isolate = isolate; |
| 104 e._events = events; |
| 105 e._notifications = notifications; |
| 106 e._code = code; |
| 107 e._instances = instances; |
| 108 e._retainedSizes = retainedSizes; |
| 109 e._reachableSizes = reachableSizes; |
| 110 e._references = references; |
| 111 e._retainingPaths = retainingPaths; |
| 112 return e; |
| 113 } |
| 114 |
| 33 CodeViewElement.created() : super.created() { | 115 CodeViewElement.created() : super.created() { |
| 34 // Create table models. | |
| 35 var columns = [ | 116 var columns = [ |
| 36 new SortedTableColumn('Address'), | 117 new SortedTableColumn('Address'), |
| 37 new SortedTableColumn('Inclusive'), | 118 new SortedTableColumn('Inclusive'), |
| 38 new SortedTableColumn('Exclusive'), | 119 new SortedTableColumn('Exclusive'), |
| 39 new SortedTableColumn('Disassembly'), | 120 new SortedTableColumn('Disassembly'), |
| 40 new SortedTableColumn('Objects'), | 121 new SortedTableColumn('Objects'), |
| 41 ]; | 122 ]; |
| 42 disassemblyTable = new DisassemblyTable(columns); | 123 disassemblyTable = new DisassemblyTable(columns); |
| 43 columns = [ | 124 columns = [ |
| 44 new SortedTableColumn('Address'), | 125 new SortedTableColumn('Address'), |
| 45 new SortedTableColumn('Inclusive'), | 126 new SortedTableColumn('Inclusive'), |
| 46 new SortedTableColumn('Exclusive'), | 127 new SortedTableColumn('Exclusive'), |
| 47 new SortedTableColumn('Functions'), | 128 new SortedTableColumn('Functions'), |
| 48 ]; | 129 ]; |
| 49 inlineTable = new InlineTable(columns); | 130 inlineTable = new InlineTable(columns); |
| 50 } | 131 } |
| 51 | 132 |
| 52 @override | 133 @override |
| 53 void attached() { | 134 attached() { |
| 54 super.attached(); | 135 super.attached(); |
| 55 } | 136 _r.enable(); |
| 56 | 137 } |
| 57 void codeChanged(oldValue) { | 138 |
| 58 if (code == null) { | 139 @override |
| 59 return; | 140 detached() { |
| 60 } | 141 super.detached(); |
| 61 code.load().then((Code c) { | 142 _r.disable(notify: true); |
| 62 c.loadScript(); | 143 children = []; |
| 63 _updateDisassembly(); | 144 } |
| 64 _updateInline(); | 145 |
| 65 }); | 146 TableElement _disassemblyTable; |
| 66 } | 147 TableElement _inlineRangeTable; |
| 67 | 148 Element _disassemblyTableBody; |
| 68 Future refresh() { | 149 Element _inlineRangeTableBody; |
| 69 return code.reload(); | 150 |
| 70 } | 151 void render() { |
| 71 | 152 if (_inlineRangeTable == null) { |
| 72 Future refreshTicks() { | 153 _inlineRangeTable = new TableElement()..classes = ['table']; |
| 73 var isolate = code.isolate; | 154 _inlineRangeTable.createTHead() |
| 74 return isolate.invokeRpc('_getCpuProfile', { 'tags': 'None' }) | 155 .children = [ |
| 75 .then((ServiceMap response) { | 156 new TableRowElement() |
| 76 var cpuProfile = new CpuProfile(); | 157 ..children = [ |
| 77 cpuProfile.load(isolate, response); | 158 document.createElement('th')..classes = ['address'] |
| 78 _updateDisassembly(); | 159 ..text = 'Address Range', |
| 79 _updateInline(); | 160 document.createElement('th')..classes = ['tick'] |
| 80 }); | 161 ..text = 'Inclusive', |
| 81 } | 162 document.createElement('th')..classes = ['tick'] |
| 82 | 163 ..text = 'Exclusive', |
| 83 String formattedAddress(CodeInstruction instruction) { | 164 document.createElement('th') |
| 165 ..text = 'Functions', |
| 166 ] |
| 167 ]; |
| 168 _inlineRangeTableBody = _inlineRangeTable.createTBody(); |
| 169 _inlineRangeTableBody.classes = ['monospace']; |
| 170 } |
| 171 if (_disassemblyTable == null) { |
| 172 _disassemblyTable = new TableElement()..classes = ['table']; |
| 173 _disassemblyTable.createTHead() |
| 174 .children = [ |
| 175 new TableRowElement() |
| 176 ..children = [ |
| 177 document.createElement('th')..classes = ['address'] |
| 178 ..text = 'Address Range', |
| 179 document.createElement('th')..classes = ['tick'] |
| 180 ..title = 'Ticks with PC on the stack' |
| 181 ..text = 'Inclusive', |
| 182 document.createElement('th')..classes = ['tick'] |
| 183 ..title = 'Ticks with PC at top of stack' |
| 184 ..text = 'Exclusive', |
| 185 document.createElement('th')..classes = ['disassembly'] |
| 186 ..text = 'Disassembly', |
| 187 document.createElement('th')..classes = ['object'] |
| 188 ..text = 'Object', |
| 189 ] |
| 190 ]; |
| 191 _disassemblyTableBody = _disassemblyTable.createTBody(); |
| 192 _disassemblyTableBody.classes = ['monospace']; |
| 193 } |
| 194 final inlinedFunctions = _code.inlinedFunctions.toList(); |
| 195 final S.Code code = _code as S.Code; |
| 196 children = [ |
| 197 new NavBarElement(queue: _r.queue) |
| 198 ..children = [ |
| 199 new NavTopMenuElement(queue: _r.queue), |
| 200 new NavVMMenuElement(_vm, _events, queue: _r.queue), |
| 201 new NavIsolateMenuElement(_isolate, _events, queue: _r.queue), |
| 202 new NavMenuElement(_code.name, last: true, queue: _r.queue), |
| 203 new NavRefreshElement(queue: _r.queue) |
| 204 ..onRefresh.listen((e) async { |
| 205 e.element.disabled = true; |
| 206 _refresh(); |
| 207 }), |
| 208 new NavRefreshElement(label: 'refresh ticks', queue: _r.queue) |
| 209 ..onRefresh.listen((e) async { |
| 210 e.element.disabled = true; |
| 211 _refreshTicks(); |
| 212 }), |
| 213 new NavNotifyElement(_notifications, queue: _r.queue) |
| 214 ], |
| 215 new DivElement()..classes = ['content-centered-big'] |
| 216 ..children = [ |
| 217 new HeadingElement.h1() |
| 218 ..text = (M.isDartCode(_code.kind) && _code.isOptimized) |
| 219 ? 'Optimized code for ${_code.name}' |
| 220 : 'Code for ${_code.name}', |
| 221 new HRElement(), |
| 222 new ObjectCommonElement(_isolate, _code, _retainedSizes, |
| 223 _reachableSizes, _references, _retainingPaths, |
| 224 _instances, queue: _r.queue), |
| 225 new BRElement(), |
| 226 new DivElement()..classes = ['memberList'] |
| 227 ..children = [ |
| 228 new DivElement()..classes = ['memberItem'] |
| 229 ..children = [ |
| 230 new DivElement()..classes = ['memberName'] |
| 231 ..text = 'Kind', |
| 232 new DivElement()..classes = ['memberValue'] |
| 233 ..text = _codeKindToString(_code.kind) |
| 234 ], |
| 235 new DivElement()..classes = ['memberItem'] |
| 236 ..children = M.isDartCode(_code.kind) |
| 237 ? const [] |
| 238 : [ |
| 239 new DivElement()..classes = ['memberName'] |
| 240 ..text = 'Optimized', |
| 241 new DivElement()..classes = ['memberValue'] |
| 242 ..text = _code.isOptimized ? 'Yes' : 'No' |
| 243 ], |
| 244 new DivElement()..classes = ['memberItem'] |
| 245 ..children = [ |
| 246 new DivElement()..classes = ['memberName'] |
| 247 ..text = 'Function', |
| 248 new DivElement()..classes = ['memberValue'] |
| 249 ..children = [ |
| 250 new FunctionRefElement(_isolate, _code.function, |
| 251 queue: _r.queue) |
| 252 ] |
| 253 ], |
| 254 new DivElement()..classes = ['memberItem'] |
| 255 ..children = code.profile == null |
| 256 ? const [] |
| 257 : [ |
| 258 new DivElement()..classes = ['memberName'] |
| 259 ..text = 'Inclusive', |
| 260 new DivElement()..classes = ['memberValue'] |
| 261 ..text = '${code.profile.formattedInclusiveTicks}' |
| 262 ], |
| 263 new DivElement()..classes = ['memberItem'] |
| 264 ..children = code.profile == null |
| 265 ? const [] |
| 266 : [ |
| 267 new DivElement()..classes = ['memberName'] |
| 268 ..text = 'Exclusive', |
| 269 new DivElement()..classes = ['memberValue'] |
| 270 ..text = '${code.profile.formattedExclusiveTicks}' |
| 271 ], |
| 272 new DivElement()..classes = ['memberItem'] |
| 273 ..children = [ |
| 274 new DivElement()..classes = ['memberName'] |
| 275 ..text = 'Object pool', |
| 276 new DivElement()..classes = ['memberValue'] |
| 277 ..children = [ |
| 278 new ObjectPoolRefElement(_isolate, _code.objectPool, |
| 279 queue: _r.queue) |
| 280 ] |
| 281 ], |
| 282 new DivElement()..classes = ['memberItem'] |
| 283 ..children = inlinedFunctions.isNotEmpty |
| 284 ? const [] |
| 285 : [ |
| 286 new DivElement()..classes = ['memberName'] |
| 287 ..text = 'inlined functions (${inlinedFunctions.length})', |
| 288 new DivElement()..classes = ['memberValue'] |
| 289 ..children = [ |
| 290 new CurlyBlockElement( |
| 291 expanded: inlinedFunctions.length < 8, |
| 292 queue: _r.queue) |
| 293 ..children = inlinedFunctions.map((f) => |
| 294 new FunctionRefElement(_isolate, f, queue: _r.queue) |
| 295 ).toList() |
| 296 ] |
| 297 ] |
| 298 ], |
| 299 new HRElement(), |
| 300 _inlineRangeTable, |
| 301 new HRElement(), |
| 302 _disassemblyTable |
| 303 ], |
| 304 ]; |
| 305 _updateDisassembly(); |
| 306 _updateInline(); |
| 307 } |
| 308 |
| 309 Future _refresh() async { |
| 310 S.Code code = _code as S.Code; |
| 311 await code.reload(); |
| 312 _r.dirty(); |
| 313 } |
| 314 |
| 315 Future _refreshTicks() async { |
| 316 S.Code code = _code as S.Code; |
| 317 final isolate = code.isolate; |
| 318 S.ServiceMap response = await isolate.invokeRpc('_getCpuProfile', |
| 319 { 'tags': 'None' }); |
| 320 final cpuProfile = new CpuProfile(); |
| 321 await cpuProfile.load(isolate, response); |
| 322 _r.dirty(); |
| 323 } |
| 324 |
| 325 String _formattedAddress(S.CodeInstruction instruction) { |
| 84 if (instruction.address == 0) { | 326 if (instruction.address == 0) { |
| 85 return ''; | 327 return ''; |
| 86 } | 328 } |
| 87 return '0x${instruction.address.toRadixString(16)}'; | 329 return '0x${instruction.address.toRadixString(16)}'; |
| 88 } | 330 } |
| 89 | 331 |
| 90 String formattedAddressRange(CodeInlineInterval interval) { | 332 String _formattedAddressRange(S.CodeInlineInterval interval) { |
| 91 String start = interval.start.toRadixString(16); | 333 String start = interval.start.toRadixString(16); |
| 92 String end = interval.end.toRadixString(16); | 334 String end = interval.end.toRadixString(16); |
| 93 return '[0x$start, 0x$end)'; | 335 return '[0x$start, 0x$end)'; |
| 94 } | 336 } |
| 95 | 337 |
| 96 String formattedInclusiveInterval(CodeInlineInterval interval) { | 338 String _formattedInclusiveInterval(S.CodeInlineInterval interval) { |
| 97 if (code == null) { | 339 S.Code code = _code as S.Code; |
| 98 return ''; | |
| 99 } | |
| 100 if (code.profile == null) { | 340 if (code.profile == null) { |
| 101 return ''; | 341 return ''; |
| 102 } | 342 } |
| 103 var intervalTick = code.profile.intervalTicks[interval.start]; | 343 var intervalTick = code.profile.intervalTicks[interval.start]; |
| 104 if (intervalTick == null) { | 344 if (intervalTick == null) { |
| 105 return ''; | 345 return ''; |
| 106 } | 346 } |
| 107 // Don't show inclusive ticks if they are the same as exclusive ticks. | 347 // Don't show inclusive ticks if they are the same as exclusive ticks. |
| 108 if (intervalTick.inclusiveTicks == intervalTick.exclusiveTicks) { | 348 if (intervalTick.inclusiveTicks == intervalTick.exclusiveTicks) { |
| 109 return ''; | 349 return ''; |
| 110 } | 350 } |
| 111 var pcent = Utils.formatPercent(intervalTick.inclusiveTicks, | 351 var pcent = Utils.formatPercent(intervalTick.inclusiveTicks, |
| 112 code.profile.profile.sampleCount); | 352 code.profile.profile.sampleCount); |
| 113 return '$pcent (${intervalTick.inclusiveTicks})'; | 353 return '$pcent (${intervalTick.inclusiveTicks})'; |
| 114 } | 354 } |
| 115 | 355 |
| 116 String formattedExclusiveInterval(CodeInlineInterval interval) { | 356 String _formattedExclusiveInterval(S.CodeInlineInterval interval) { |
| 117 if (code == null) { | 357 S.Code code = _code as S.Code; |
| 118 return ''; | |
| 119 } | |
| 120 if (code.profile == null) { | 358 if (code.profile == null) { |
| 121 return ''; | 359 return ''; |
| 122 } | 360 } |
| 123 var intervalTick = code.profile.intervalTicks[interval.start]; | 361 var intervalTick = code.profile.intervalTicks[interval.start]; |
| 124 if (intervalTick == null) { | 362 if (intervalTick == null) { |
| 125 return ''; | 363 return ''; |
| 126 } | 364 } |
| 127 var pcent = Utils.formatPercent(intervalTick.exclusiveTicks, | 365 var pcent = Utils.formatPercent(intervalTick.exclusiveTicks, |
| 128 code.profile.profile.sampleCount); | 366 code.profile.profile.sampleCount); |
| 129 return '$pcent (${intervalTick.exclusiveTicks})'; | 367 return '$pcent (${intervalTick.exclusiveTicks})'; |
| 130 } | 368 } |
| 131 | 369 |
| 132 | 370 |
| 133 String formattedInclusive(CodeInstruction instruction) { | 371 String _formattedInclusive(S.CodeInstruction instruction) { |
| 134 if (code == null) { | 372 S.Code code = _code as S.Code; |
| 135 return ''; | |
| 136 } | |
| 137 if (code.profile == null) { | 373 if (code.profile == null) { |
| 138 return ''; | 374 return ''; |
| 139 } | 375 } |
| 140 var tick = code.profile.addressTicks[instruction.address]; | 376 var tick = code.profile.addressTicks[instruction.address]; |
| 141 if (tick == null) { | 377 if (tick == null) { |
| 142 return ''; | 378 return ''; |
| 143 } | 379 } |
| 144 // Don't show inclusive ticks if they are the same as exclusive ticks. | 380 // Don't show inclusive ticks if they are the same as exclusive ticks. |
| 145 if (tick.inclusiveTicks == tick.exclusiveTicks) { | 381 if (tick.inclusiveTicks == tick.exclusiveTicks) { |
| 146 return ''; | 382 return ''; |
| 147 } | 383 } |
| 148 var pcent = Utils.formatPercent(tick.inclusiveTicks, | 384 var pcent = Utils.formatPercent(tick.inclusiveTicks, |
| 149 code.profile.profile.sampleCount); | 385 code.profile.profile.sampleCount); |
| 150 return '$pcent (${tick.inclusiveTicks})'; | 386 return '$pcent (${tick.inclusiveTicks})'; |
| 151 } | 387 } |
| 152 | 388 |
| 153 String formattedExclusive(CodeInstruction instruction) { | 389 String _formattedExclusive(S.CodeInstruction instruction) { |
| 154 if (code == null) { | 390 S.Code code = _code as S.Code; |
| 155 return ''; | |
| 156 } | |
| 157 if (code.profile == null) { | 391 if (code.profile == null) { |
| 158 return ''; | 392 return ''; |
| 159 } | 393 } |
| 160 var tick = code.profile.addressTicks[instruction.address]; | 394 var tick = code.profile.addressTicks[instruction.address]; |
| 161 if (tick == null) { | 395 if (tick == null) { |
| 162 return ''; | 396 return ''; |
| 163 } | 397 } |
| 164 var pcent = Utils.formatPercent(tick.exclusiveTicks, | 398 var pcent = Utils.formatPercent(tick.exclusiveTicks, |
| 165 code.profile.profile.sampleCount); | 399 code.profile.profile.sampleCount); |
| 166 return '$pcent (${tick.exclusiveTicks})'; | 400 return '$pcent (${tick.exclusiveTicks})'; |
| 167 } | 401 } |
| 168 | 402 |
| 169 void _updateDiasssemblyTable() { | 403 void _updateDiasssemblyTable() { |
| 404 S.Code code = _code as S.Code; |
| 170 disassemblyTable.clearRows(); | 405 disassemblyTable.clearRows(); |
| 171 if (code == null) { | 406 if (code == null) { |
| 172 return; | 407 return; |
| 173 } | 408 } |
| 174 for (CodeInstruction instruction in code.instructions) { | 409 for (S.CodeInstruction instruction in code.instructions) { |
| 175 var row = [formattedAddress(instruction), | 410 var row = [_formattedAddress(instruction), |
| 176 formattedInclusive(instruction), | 411 _formattedInclusive(instruction), |
| 177 formattedExclusive(instruction), | 412 _formattedExclusive(instruction), |
| 178 instruction.human, | 413 instruction.human, |
| 179 instruction.object]; | 414 instruction.object]; |
| 180 disassemblyTable.addRow(new SortedTableRow(row)); | 415 disassemblyTable.addRow(new SortedTableRow(row)); |
| 181 } | 416 } |
| 182 } | 417 } |
| 183 | 418 |
| 184 void _addDisassemblyDOMRow() { | 419 void _addDisassemblyDOMRow() { |
| 185 var tableBody = $['disassemblyTableBody']; | 420 var tableBody = _disassemblyTableBody; |
| 186 assert(tableBody != null); | 421 assert(tableBody != null); |
| 187 var tr = new TableRowElement(); | 422 var tr = new TableRowElement(); |
| 188 | 423 |
| 189 var cell; | 424 var cell; |
| 190 | 425 |
| 191 // Add new space. | 426 // Add new space. |
| 192 cell = tr.insertCell(-1); | 427 cell = tr.insertCell(-1); |
| 193 cell.classes.add('monospace'); | 428 cell.classes.add('monospace'); |
| 194 cell = tr.insertCell(-1); | 429 cell = tr.insertCell(-1); |
| 195 cell.classes.add('monospace'); | 430 cell.classes.add('monospace'); |
| 196 cell = tr.insertCell(-1); | 431 cell = tr.insertCell(-1); |
| 197 cell.classes.add('monospace'); | 432 cell.classes.add('monospace'); |
| 198 cell = tr.insertCell(-1); | 433 cell = tr.insertCell(-1); |
| 199 cell.classes.add('monospace'); | 434 cell.classes.add('monospace'); |
| 200 cell = tr.insertCell(-1); | 435 cell = tr.insertCell(-1); |
| 201 cell.classes.add('monospace'); | 436 cell.classes.add('monospace'); |
| 202 | 437 |
| 203 tableBody.children.add(tr); | 438 tableBody.children.add(tr); |
| 204 } | 439 } |
| 205 | 440 |
| 206 void _fillDisassemblyDOMRow(TableRowElement tr, int rowIndex) { | 441 void _fillDisassemblyDOMRow(TableRowElement tr, int rowIndex) { |
| 207 final row = disassemblyTable.rows[rowIndex]; | 442 final row = disassemblyTable.rows[rowIndex]; |
| 208 final n = row.values.length; | 443 final n = row.values.length; |
| 209 for (var i = 0; i < n; i++) { | 444 for (var i = 0; i < n; i++) { |
| 210 final cell = tr.children[i]; | 445 final cell = tr.children[i]; |
| 211 final content = row.values[i]; | 446 final content = row.values[i]; |
| 212 if (content is ServiceObject) { | 447 if (content is S.HeapObject) { |
| 213 ServiceRefElement element = new Element.tag('any-service-ref'); | 448 print(content.runtimeType); |
| 214 element.ref = content; | 449 cell.children = [ |
| 215 cell.children = [element]; | 450 anyRef(_isolate, content, _instances, queue: _r.queue) |
| 451 ]; |
| 216 } else if (content != null) { | 452 } else if (content != null) { |
| 217 String text = '$content'; | 453 String text = '$content'; |
| 218 if (i == kDisassemblyColumnIndex) { | 454 if (i == kDisassemblyColumnIndex) { |
| 219 // Disassembly might be a comment. Reduce indentation, change styling, | 455 // Disassembly might be a comment. Reduce indentation, change styling, |
| 220 // widen to span next column (which should be empty). | 456 // widen to span next column (which should be empty). |
| 221 if (text.startsWith(' ;;')) { | 457 if (text.startsWith(' ;;')) { |
| 222 cell.attributes['colspan'] = '2'; | 458 cell.attributes['colspan'] = '2'; |
| 223 cell.classes.add('code-comment'); | 459 cell.classes.add('code-comment'); |
| 224 text = text.substring(6); | 460 text = text.substring(6); |
| 225 } else { | 461 } else { |
| 226 cell.attributes['colspan'] = '1'; | 462 cell.attributes['colspan'] = '1'; |
| 227 cell.classes.remove('code-comment'); | 463 cell.classes.remove('code-comment'); |
| 228 } | 464 } |
| 229 } | 465 } |
| 230 cell.text = text; | 466 cell.text = text; |
| 231 } | 467 } |
| 232 } | 468 } |
| 233 } | 469 } |
| 234 | 470 |
| 235 void _updateDisassemblyDOMTable() { | 471 void _updateDisassemblyDOMTable() { |
| 236 var tableBody = $['disassemblyTableBody']; | 472 var tableBody = _disassemblyTableBody; |
| 237 assert(tableBody != null); | 473 assert(tableBody != null); |
| 238 // Resize DOM table. | 474 // Resize DOM table. |
| 239 if (tableBody.children.length > disassemblyTable.sortedRows.length) { | 475 if (tableBody.children.length > disassemblyTable.sortedRows.length) { |
| 240 // Shrink the table. | 476 // Shrink the table. |
| 241 var deadRows = | 477 var deadRows = |
| 242 tableBody.children.length - disassemblyTable.sortedRows.length; | 478 tableBody.children.length - disassemblyTable.sortedRows.length; |
| 243 for (var i = 0; i < deadRows; i++) { | 479 for (var i = 0; i < deadRows; i++) { |
| 244 tableBody.children.removeLast(); | 480 tableBody.children.removeLast(); |
| 245 } | 481 } |
| 246 } else if (tableBody.children.length < disassemblyTable.sortedRows.length) { | 482 } else if (tableBody.children.length < disassemblyTable.sortedRows.length) { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 263 } | 499 } |
| 264 } | 500 } |
| 265 | 501 |
| 266 void _updateDisassembly() { | 502 void _updateDisassembly() { |
| 267 _updateDiasssemblyTable(); | 503 _updateDiasssemblyTable(); |
| 268 _updateDisassemblyDOMTable(); | 504 _updateDisassemblyDOMTable(); |
| 269 } | 505 } |
| 270 | 506 |
| 271 void _updateInlineTable() { | 507 void _updateInlineTable() { |
| 272 inlineTable.clearRows(); | 508 inlineTable.clearRows(); |
| 273 if (code == null) { | 509 S.Code code = _code as S.Code; |
| 274 return; | 510 for (S.CodeInlineInterval interval in code.inlineIntervals) { |
| 275 } | |
| 276 for (CodeInlineInterval interval in code.inlineIntervals) { | |
| 277 var row = [interval, | 511 var row = [interval, |
| 278 formattedInclusiveInterval(interval), | 512 _formattedInclusiveInterval(interval), |
| 279 formattedExclusiveInterval(interval), | 513 _formattedExclusiveInterval(interval), |
| 280 interval.functions]; | 514 interval.functions]; |
| 281 inlineTable.addRow(new SortedTableRow(row)); | 515 inlineTable.addRow(new SortedTableRow(row)); |
| 282 } | 516 } |
| 283 } | 517 } |
| 284 | 518 |
| 285 void _addInlineDOMRow() { | 519 void _addInlineDOMRow() { |
| 286 var tableBody = shadowRoot.querySelector('#inlineRangeTableBody'); | 520 var tableBody = _inlineRangeTableBody; |
| 287 assert(tableBody != null); | 521 assert(tableBody != null); |
| 288 var tr = new TableRowElement(); | 522 var tr = new TableRowElement(); |
| 289 | 523 |
| 290 var cell; | 524 var cell; |
| 291 | 525 |
| 292 // Add new space. | 526 // Add new space. |
| 293 cell = tr.insertCell(-1); | 527 cell = tr.insertCell(-1); |
| 294 cell.classes.add('monospace'); | 528 cell.classes.add('monospace'); |
| 295 cell = tr.insertCell(-1); | 529 cell = tr.insertCell(-1); |
| 296 cell.classes.add('monospace'); | 530 cell.classes.add('monospace'); |
| 297 cell = tr.insertCell(-1); | 531 cell = tr.insertCell(-1); |
| 298 cell.classes.add('monospace'); | 532 cell.classes.add('monospace'); |
| 299 cell = tr.insertCell(-1); | 533 cell = tr.insertCell(-1); |
| 300 | 534 |
| 301 tableBody.children.add(tr); | 535 tableBody.children.add(tr); |
| 302 } | 536 } |
| 303 | 537 |
| 304 void _fillInlineDOMRow(TableRowElement tr, int rowIndex) { | 538 void _fillInlineDOMRow(TableRowElement tr, int rowIndex) { |
| 305 var row = inlineTable.rows[rowIndex]; | 539 var row = inlineTable.rows[rowIndex]; |
| 306 var columns = row.values.length; | 540 var columns = row.values.length; |
| 307 var addressRangeColumn = 0; | 541 var addressRangeColumn = 0; |
| 308 var functionsColumn = columns - 1; | 542 var functionsColumn = columns - 1; |
| 309 | 543 |
| 310 { | 544 { |
| 311 var addressRangeCell = tr.children[addressRangeColumn]; | 545 var addressRangeCell = tr.children[addressRangeColumn]; |
| 312 var interval = row.values[addressRangeColumn]; | 546 var interval = row.values[addressRangeColumn]; |
| 313 var addressRangeString = formattedAddressRange(interval); | 547 var addressRangeString = _formattedAddressRange(interval); |
| 314 var addressRangeElement = new SpanElement(); | 548 var addressRangeElement = new SpanElement(); |
| 315 addressRangeElement.classes.add('monospace'); | 549 addressRangeElement.classes.add('monospace'); |
| 316 addressRangeElement.text = addressRangeString; | 550 addressRangeElement.text = addressRangeString; |
| 317 addressRangeCell.children.clear(); | 551 addressRangeCell.children.clear(); |
| 318 addressRangeCell.children.add(addressRangeElement); | 552 addressRangeCell.children.add(addressRangeElement); |
| 319 } | 553 } |
| 320 | 554 |
| 321 for (var i = addressRangeColumn + 1; i < columns - 1; i++) { | 555 for (var i = addressRangeColumn + 1; i < columns - 1; i++) { |
| 322 var cell = tr.children[i]; | 556 var cell = tr.children[i]; |
| 323 cell.text = row.values[i].toString(); | 557 cell.text = row.values[i].toString(); |
| 324 } | 558 } |
| 325 var functions = row.values[functionsColumn]; | 559 var functions = row.values[functionsColumn]; |
| 326 var functionsCell = tr.children[functionsColumn]; | 560 var functionsCell = tr.children[functionsColumn]; |
| 327 functionsCell.children.clear(); | 561 functionsCell.children.clear(); |
| 328 for (var func in functions) { | 562 for (var func in functions) { |
| 329 var functionRef = new Element.tag('function-ref'); | 563 functionsCell.children.add( |
| 330 functionRef.ref = func; | 564 new FunctionRefElement(_isolate, func, queue: _r.queue)); |
| 331 functionsCell.children.add(functionRef); | |
| 332 var gap = new SpanElement(); | 565 var gap = new SpanElement(); |
| 333 gap.style.minWidth = '1em'; | 566 gap.style.minWidth = '1em'; |
| 334 gap.text = ' '; | 567 gap.text = ' '; |
| 335 functionsCell.children.add(gap); | 568 functionsCell.children.add(gap); |
| 336 } | 569 } |
| 337 } | 570 } |
| 338 | 571 |
| 339 void _updateInlineDOMTable() { | 572 void _updateInlineDOMTable() { |
| 340 var tableBody = shadowRoot.querySelector('#inlineRangeTableBody'); | 573 var tableBody = _inlineRangeTableBody; |
| 341 // Resize DOM table. | 574 // Resize DOM table. |
| 342 if (tableBody.children.length > inlineTable.sortedRows.length) { | 575 if (tableBody.children.length > inlineTable.sortedRows.length) { |
| 343 // Shrink the table. | 576 // Shrink the table. |
| 344 var deadRows = | 577 var deadRows = |
| 345 tableBody.children.length - inlineTable.sortedRows.length; | 578 tableBody.children.length - inlineTable.sortedRows.length; |
| 346 for (var i = 0; i < deadRows; i++) { | 579 for (var i = 0; i < deadRows; i++) { |
| 347 tableBody.children.removeLast(); | 580 tableBody.children.removeLast(); |
| 348 } | 581 } |
| 349 } else if (tableBody.children.length < inlineTable.sortedRows.length) { | 582 } else if (tableBody.children.length < inlineTable.sortedRows.length) { |
| 350 // Grow table. | 583 // Grow table. |
| 351 var newRows = inlineTable.sortedRows.length - tableBody.children.length; | 584 var newRows = inlineTable.sortedRows.length - tableBody.children.length; |
| 352 for (var i = 0; i < newRows; i++) { | 585 for (var i = 0; i < newRows; i++) { |
| 353 _addInlineDOMRow(); | 586 _addInlineDOMRow(); |
| 354 } | 587 } |
| 355 } | 588 } |
| 356 assert(tableBody.children.length == inlineTable.sortedRows.length); | 589 assert(tableBody.children.length == inlineTable.sortedRows.length); |
| 357 // Fill table. | 590 // Fill table. |
| 358 for (var i = 0; i < inlineTable.sortedRows.length; i++) { | 591 for (var i = 0; i < inlineTable.sortedRows.length; i++) { |
| 359 var rowIndex = inlineTable.sortedRows[i]; | 592 var rowIndex = inlineTable.sortedRows[i]; |
| 360 var tr = tableBody.children[i]; | 593 var tr = tableBody.children[i]; |
| 361 _fillInlineDOMRow(tr, rowIndex); | 594 _fillInlineDOMRow(tr, rowIndex); |
| 362 } | 595 } |
| 363 } | 596 } |
| 364 | 597 |
| 365 void _updateInline() { | 598 void _updateInline() { |
| 366 _updateInlineTable(); | 599 _updateInlineTable(); |
| 367 _updateInlineDOMTable(); | 600 _updateInlineDOMTable(); |
| 368 } | 601 } |
| 369 | 602 |
| 370 Element _findJumpTarget(Element target) { | 603 static String _codeKindToString(M.CodeKind kind) { |
| 371 var jumpTarget = target.attributes['data-jump-target']; | 604 switch (kind) { |
| 372 if (jumpTarget == '') { | 605 case M.CodeKind.dart: return 'dart'; |
| 373 return null; | 606 case M.CodeKind.native: return 'native'; |
| 607 case M.CodeKind.stub: return 'stub'; |
| 608 case M.CodeKind.tag: return 'tag'; |
| 609 case M.CodeKind.collected: return 'collected'; |
| 374 } | 610 } |
| 375 var address = int.parse(jumpTarget); | 611 throw new Exception('Unkown CodeKind ($kind)'); |
| 376 var node = shadowRoot.querySelector('#addr-$address'); | |
| 377 if (node == null) { | |
| 378 return null; | |
| 379 } | |
| 380 return node; | |
| 381 } | |
| 382 | |
| 383 void mouseOver(Event e, var detail, Node target) { | |
| 384 var jt = _findJumpTarget(target); | |
| 385 if (jt == null) { | |
| 386 return; | |
| 387 } | |
| 388 jt.classes.add('highlight'); | |
| 389 } | |
| 390 | |
| 391 void mouseOut(Event e, var detail, Node target) { | |
| 392 var jt = _findJumpTarget(target); | |
| 393 if (jt == null) { | |
| 394 return; | |
| 395 } | |
| 396 jt.classes.remove('highlight'); | |
| 397 } | 612 } |
| 398 } | 613 } |
| OLD | NEW |