Chromium Code Reviews| 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 (_disassemblyTable == null) { |
| 72 Future refreshTicks() { | 153 _disassemblyTable = new TableElement()..classes = ['table']; |
| 73 var isolate = code.isolate; | 154 _disassemblyTable.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'] |
|
rmacnak
2016/09/01 19:38:09
The headers for the two tables are swapped.
cbernaschina
2016/09/01 20:56:34
Done.
| |
| 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 _disassemblyTableBody = _disassemblyTable.createTBody(); | |
| 169 _disassemblyTableBody.classes = ['monospace']; | |
| 170 } | |
| 171 if (_inlineRangeTable == null) { | |
|
rmacnak
2016/09/01 19:38:09
I'd move creating the inline range table above cre
cbernaschina
2016/09/01 20:56:34
Done.
| |
| 172 _inlineRangeTable = new TableElement()..classes = ['table']; | |
| 173 _inlineRangeTable.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 _inlineRangeTableBody = _inlineRangeTable.createTBody(); | |
| 192 _inlineRangeTableBody.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 cell.children = [ |
| 214 element.ref = content; | 449 anyRef(_isolate, content, _instances, queue: _r.queue) |
| 215 cell.children = [element]; | 450 ]; |
| 216 } else if (content != null) { | 451 } else if (content != null) { |
| 217 String text = '$content'; | 452 String text = '$content'; |
| 218 if (i == kDisassemblyColumnIndex) { | 453 if (i == kDisassemblyColumnIndex) { |
| 219 // Disassembly might be a comment. Reduce indentation, change styling, | 454 // Disassembly might be a comment. Reduce indentation, change styling, |
| 220 // widen to span next column (which should be empty). | 455 // widen to span next column (which should be empty). |
| 221 if (text.startsWith(' ;;')) { | 456 if (text.startsWith(' ;;')) { |
| 222 cell.attributes['colspan'] = '2'; | 457 cell.attributes['colspan'] = '2'; |
| 223 cell.classes.add('code-comment'); | 458 cell.classes.add('code-comment'); |
| 224 text = text.substring(6); | 459 text = text.substring(6); |
| 225 } else { | 460 } else { |
| 226 cell.attributes['colspan'] = '1'; | 461 cell.attributes['colspan'] = '1'; |
| 227 cell.classes.remove('code-comment'); | 462 cell.classes.remove('code-comment'); |
| 228 } | 463 } |
| 229 } | 464 } |
| 230 cell.text = text; | 465 cell.text = text; |
| 231 } | 466 } |
| 232 } | 467 } |
| 233 } | 468 } |
| 234 | 469 |
| 235 void _updateDisassemblyDOMTable() { | 470 void _updateDisassemblyDOMTable() { |
| 236 var tableBody = $['disassemblyTableBody']; | 471 var tableBody = _disassemblyTableBody; |
| 237 assert(tableBody != null); | 472 assert(tableBody != null); |
| 238 // Resize DOM table. | 473 // Resize DOM table. |
| 239 if (tableBody.children.length > disassemblyTable.sortedRows.length) { | 474 if (tableBody.children.length > disassemblyTable.sortedRows.length) { |
| 240 // Shrink the table. | 475 // Shrink the table. |
| 241 var deadRows = | 476 var deadRows = |
| 242 tableBody.children.length - disassemblyTable.sortedRows.length; | 477 tableBody.children.length - disassemblyTable.sortedRows.length; |
| 243 for (var i = 0; i < deadRows; i++) { | 478 for (var i = 0; i < deadRows; i++) { |
| 244 tableBody.children.removeLast(); | 479 tableBody.children.removeLast(); |
| 245 } | 480 } |
| 246 } else if (tableBody.children.length < disassemblyTable.sortedRows.length) { | 481 } else if (tableBody.children.length < disassemblyTable.sortedRows.length) { |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 263 } | 498 } |
| 264 } | 499 } |
| 265 | 500 |
| 266 void _updateDisassembly() { | 501 void _updateDisassembly() { |
| 267 _updateDiasssemblyTable(); | 502 _updateDiasssemblyTable(); |
| 268 _updateDisassemblyDOMTable(); | 503 _updateDisassemblyDOMTable(); |
| 269 } | 504 } |
| 270 | 505 |
| 271 void _updateInlineTable() { | 506 void _updateInlineTable() { |
| 272 inlineTable.clearRows(); | 507 inlineTable.clearRows(); |
| 273 if (code == null) { | 508 S.Code code = _code as S.Code; |
| 274 return; | 509 for (S.CodeInlineInterval interval in code.inlineIntervals) { |
| 275 } | |
| 276 for (CodeInlineInterval interval in code.inlineIntervals) { | |
| 277 var row = [interval, | 510 var row = [interval, |
| 278 formattedInclusiveInterval(interval), | 511 _formattedInclusiveInterval(interval), |
| 279 formattedExclusiveInterval(interval), | 512 _formattedExclusiveInterval(interval), |
| 280 interval.functions]; | 513 interval.functions]; |
| 281 inlineTable.addRow(new SortedTableRow(row)); | 514 inlineTable.addRow(new SortedTableRow(row)); |
| 282 } | 515 } |
| 283 } | 516 } |
| 284 | 517 |
| 285 void _addInlineDOMRow() { | 518 void _addInlineDOMRow() { |
| 286 var tableBody = shadowRoot.querySelector('#inlineRangeTableBody'); | 519 var tableBody = _inlineRangeTableBody; |
| 287 assert(tableBody != null); | 520 assert(tableBody != null); |
| 288 var tr = new TableRowElement(); | 521 var tr = new TableRowElement(); |
| 289 | 522 |
| 290 var cell; | 523 var cell; |
| 291 | 524 |
| 292 // Add new space. | 525 // Add new space. |
| 293 cell = tr.insertCell(-1); | 526 cell = tr.insertCell(-1); |
| 294 cell.classes.add('monospace'); | 527 cell.classes.add('monospace'); |
| 295 cell = tr.insertCell(-1); | 528 cell = tr.insertCell(-1); |
| 296 cell.classes.add('monospace'); | 529 cell.classes.add('monospace'); |
| 297 cell = tr.insertCell(-1); | 530 cell = tr.insertCell(-1); |
| 298 cell.classes.add('monospace'); | 531 cell.classes.add('monospace'); |
| 299 cell = tr.insertCell(-1); | 532 cell = tr.insertCell(-1); |
| 300 | 533 |
| 301 tableBody.children.add(tr); | 534 tableBody.children.add(tr); |
| 302 } | 535 } |
| 303 | 536 |
| 304 void _fillInlineDOMRow(TableRowElement tr, int rowIndex) { | 537 void _fillInlineDOMRow(TableRowElement tr, int rowIndex) { |
| 305 var row = inlineTable.rows[rowIndex]; | 538 var row = inlineTable.rows[rowIndex]; |
| 306 var columns = row.values.length; | 539 var columns = row.values.length; |
| 307 var addressRangeColumn = 0; | 540 var addressRangeColumn = 0; |
| 308 var functionsColumn = columns - 1; | 541 var functionsColumn = columns - 1; |
| 309 | 542 |
| 310 { | 543 { |
| 311 var addressRangeCell = tr.children[addressRangeColumn]; | 544 var addressRangeCell = tr.children[addressRangeColumn]; |
| 312 var interval = row.values[addressRangeColumn]; | 545 var interval = row.values[addressRangeColumn]; |
| 313 var addressRangeString = formattedAddressRange(interval); | 546 var addressRangeString = _formattedAddressRange(interval); |
| 314 var addressRangeElement = new SpanElement(); | 547 var addressRangeElement = new SpanElement(); |
| 315 addressRangeElement.classes.add('monospace'); | 548 addressRangeElement.classes.add('monospace'); |
| 316 addressRangeElement.text = addressRangeString; | 549 addressRangeElement.text = addressRangeString; |
| 317 addressRangeCell.children.clear(); | 550 addressRangeCell.children.clear(); |
| 318 addressRangeCell.children.add(addressRangeElement); | 551 addressRangeCell.children.add(addressRangeElement); |
| 319 } | 552 } |
| 320 | 553 |
| 321 for (var i = addressRangeColumn + 1; i < columns - 1; i++) { | 554 for (var i = addressRangeColumn + 1; i < columns - 1; i++) { |
| 322 var cell = tr.children[i]; | 555 var cell = tr.children[i]; |
| 323 cell.text = row.values[i].toString(); | 556 cell.text = row.values[i].toString(); |
| 324 } | 557 } |
| 325 var functions = row.values[functionsColumn]; | 558 var functions = row.values[functionsColumn]; |
| 326 var functionsCell = tr.children[functionsColumn]; | 559 var functionsCell = tr.children[functionsColumn]; |
| 327 functionsCell.children.clear(); | 560 functionsCell.children.clear(); |
| 328 for (var func in functions) { | 561 for (var func in functions) { |
| 329 var functionRef = new Element.tag('function-ref'); | 562 functionsCell.children.add( |
| 330 functionRef.ref = func; | 563 new FunctionRefElement(_isolate, func, queue: _r.queue)); |
| 331 functionsCell.children.add(functionRef); | |
| 332 var gap = new SpanElement(); | 564 var gap = new SpanElement(); |
| 333 gap.style.minWidth = '1em'; | 565 gap.style.minWidth = '1em'; |
| 334 gap.text = ' '; | 566 gap.text = ' '; |
| 335 functionsCell.children.add(gap); | 567 functionsCell.children.add(gap); |
| 336 } | 568 } |
| 337 } | 569 } |
| 338 | 570 |
| 339 void _updateInlineDOMTable() { | 571 void _updateInlineDOMTable() { |
| 340 var tableBody = shadowRoot.querySelector('#inlineRangeTableBody'); | 572 var tableBody = _inlineRangeTableBody; |
| 341 // Resize DOM table. | 573 // Resize DOM table. |
| 342 if (tableBody.children.length > inlineTable.sortedRows.length) { | 574 if (tableBody.children.length > inlineTable.sortedRows.length) { |
| 343 // Shrink the table. | 575 // Shrink the table. |
| 344 var deadRows = | 576 var deadRows = |
| 345 tableBody.children.length - inlineTable.sortedRows.length; | 577 tableBody.children.length - inlineTable.sortedRows.length; |
| 346 for (var i = 0; i < deadRows; i++) { | 578 for (var i = 0; i < deadRows; i++) { |
| 347 tableBody.children.removeLast(); | 579 tableBody.children.removeLast(); |
| 348 } | 580 } |
| 349 } else if (tableBody.children.length < inlineTable.sortedRows.length) { | 581 } else if (tableBody.children.length < inlineTable.sortedRows.length) { |
| 350 // Grow table. | 582 // Grow table. |
| 351 var newRows = inlineTable.sortedRows.length - tableBody.children.length; | 583 var newRows = inlineTable.sortedRows.length - tableBody.children.length; |
| 352 for (var i = 0; i < newRows; i++) { | 584 for (var i = 0; i < newRows; i++) { |
| 353 _addInlineDOMRow(); | 585 _addInlineDOMRow(); |
| 354 } | 586 } |
| 355 } | 587 } |
| 356 assert(tableBody.children.length == inlineTable.sortedRows.length); | 588 assert(tableBody.children.length == inlineTable.sortedRows.length); |
| 357 // Fill table. | 589 // Fill table. |
| 358 for (var i = 0; i < inlineTable.sortedRows.length; i++) { | 590 for (var i = 0; i < inlineTable.sortedRows.length; i++) { |
| 359 var rowIndex = inlineTable.sortedRows[i]; | 591 var rowIndex = inlineTable.sortedRows[i]; |
| 360 var tr = tableBody.children[i]; | 592 var tr = tableBody.children[i]; |
| 361 _fillInlineDOMRow(tr, rowIndex); | 593 _fillInlineDOMRow(tr, rowIndex); |
| 362 } | 594 } |
| 363 } | 595 } |
| 364 | 596 |
| 365 void _updateInline() { | 597 void _updateInline() { |
| 366 _updateInlineTable(); | 598 _updateInlineTable(); |
| 367 _updateInlineDOMTable(); | 599 _updateInlineDOMTable(); |
| 368 } | 600 } |
| 369 | 601 |
| 370 Element _findJumpTarget(Element target) { | 602 static String _codeKindToString(M.CodeKind kind) { |
| 371 var jumpTarget = target.attributes['data-jump-target']; | 603 switch (kind) { |
| 372 if (jumpTarget == '') { | 604 case M.CodeKind.dart: return 'dart'; |
| 373 return null; | 605 case M.CodeKind.native: return 'native'; |
| 606 case M.CodeKind.stub: return 'stub'; | |
| 607 case M.CodeKind.tag: return 'tag'; | |
| 608 case M.CodeKind.collected: return 'collected'; | |
| 374 } | 609 } |
| 375 var address = int.parse(jumpTarget); | 610 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 } | 611 } |
| 398 } | 612 } |
| OLD | NEW |