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 function_view_element; | 5 library function_view_element; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'observatory_element.dart'; | 8 import 'dart:html'; |
| 9 import 'package:observatory/service.dart'; | 9 import 'package:observatory/models.dart' as M; |
| 10 | 10 import 'package:observatory/src/elements/class_ref.dart'; |
| 11 import 'package:polymer/polymer.dart'; | 11 import 'package:observatory/src/elements/code_ref.dart'; |
| 12 | 12 import 'package:observatory/src/elements/curly_block.dart'; |
| 13 @CustomTag('function-view') | 13 import 'package:observatory/src/elements/field_ref.dart'; |
| 14 class FunctionViewElement extends ObservatoryElement { | 14 import 'package:observatory/src/elements/instance_ref.dart'; |
| 15 @published ServiceFunction function; | 15 import 'package:observatory/src/elements/helpers/any_ref.dart'; |
| 16 import 'package:observatory/src/elements/helpers/rendering_scheduler.dart'; | |
| 17 import 'package:observatory/src/elements/helpers/tag.dart'; | |
| 18 import 'package:observatory/src/elements/nav/bar.dart'; | |
| 19 import 'package:observatory/src/elements/nav/class_menu.dart'; | |
| 20 import 'package:observatory/src/elements/nav/isolate_menu.dart'; | |
| 21 import 'package:observatory/src/elements/nav/library_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/source_inset.dart'; | |
| 29 import 'package:observatory/src/elements/source_link.dart'; | |
| 30 import 'package:observatory/src/elements/view_footer.dart'; | |
| 31 | |
| 32 class FunctionViewElement extends HtmlElement implements Renderable { | |
| 33 static const tag = const Tag<FunctionViewElement>('function-view', | |
| 34 dependencies: const [ | |
| 35 ClassRefElement.tag, | |
| 36 CodeRefElement.tag, | |
| 37 CurlyBlockElement.tag, | |
| 38 FieldRefElement.tag, | |
| 39 InstanceRefElement.tag, | |
| 40 NavBarElement.tag, | |
| 41 NavClassMenuElement.tag, | |
| 42 NavLibraryMenuElement.tag, | |
| 43 NavTopMenuElement.tag, | |
| 44 NavVMMenuElement.tag, | |
| 45 NavIsolateMenuElement.tag, | |
| 46 NavMenuElement.tag, | |
| 47 NavRefreshElement.tag, | |
| 48 NavNotifyElement.tag, | |
| 49 ObjectCommonElement.tag, | |
| 50 SourceLinkElement.tag, | |
| 51 SourceInsetElement.tag, | |
| 52 ViewFooterElement.tag | |
| 53 ]); | |
| 54 | |
| 55 RenderingScheduler<FunctionViewElement> _r; | |
| 56 | |
| 57 Stream<RenderedEvent<FunctionViewElement>> get onRendered => _r.onRendered; | |
| 58 | |
| 59 M.VM _vm; | |
| 60 M.IsolateRef _isolate; | |
| 61 M.EventRepository _events; | |
| 62 M.NotificationRepository _notifications; | |
| 63 M.Function _function; | |
| 64 M.LibraryRef _library; | |
| 65 M.FunctionRepository _functions; | |
| 66 M.ClassRepository _classes; | |
| 67 M.RetainedSizeRepository _retainedSizes; | |
| 68 M.ReachableSizeRepository _reachableSizes; | |
| 69 M.InboundReferencesRepository _references; | |
| 70 M.RetainingPathRepository _retainingPaths; | |
| 71 M.ScriptRepository _scripts; | |
| 72 M.InstanceRepository _instances; | |
| 73 | |
| 74 | |
| 75 M.VMRef get vm => _vm; | |
| 76 M.IsolateRef get isolate => _isolate; | |
| 77 M.NotificationRepository get notifications => _notifications; | |
| 78 M.Function get function => _function; | |
| 79 | |
| 80 factory FunctionViewElement(M.VM vm, M.IsolateRef isolate, M.Function function , | |
| 81 M.EventRepository events, | |
| 82 M.NotificationRepository notifications, | |
| 83 M.FunctionRepository functions, | |
| 84 M.ClassRepository classes, | |
| 85 M.RetainedSizeRepository retainedSizes, | |
| 86 M.ReachableSizeRepository reachableSizes, | |
| 87 M.InboundReferencesRepository references, | |
| 88 M.RetainingPathRepository retainingPaths, | |
| 89 M.ScriptRepository scripts, | |
| 90 M.InstanceRepository instances, | |
| 91 {RenderingQueue queue}) { | |
| 92 assert(vm != null); | |
| 93 assert(isolate != null); | |
| 94 assert(events != null); | |
| 95 assert(notifications != null); | |
| 96 assert(function != null); | |
| 97 assert(functions != null); | |
| 98 assert(classes != null); | |
| 99 assert(retainedSizes != null); | |
| 100 assert(reachableSizes != null); | |
| 101 assert(references != null); | |
| 102 assert(retainingPaths != null); | |
| 103 assert(scripts != null); | |
| 104 assert(instances != null); | |
| 105 FunctionViewElement e = document.createElement(tag.name); | |
| 106 e._r = new RenderingScheduler(e, queue: queue); | |
| 107 e._vm = vm; | |
| 108 e._isolate = isolate; | |
| 109 e._events = events; | |
| 110 e._notifications = notifications; | |
| 111 e._function = function; | |
| 112 e._functions = functions; | |
| 113 e._classes = classes; | |
| 114 e._retainedSizes = retainedSizes; | |
| 115 e._reachableSizes = reachableSizes; | |
| 116 e._references = references; | |
| 117 e._retainingPaths = retainingPaths; | |
| 118 e._scripts = scripts; | |
| 119 e._instances = instances; | |
| 120 if (function.dartOwner is M.LibraryRef) { | |
| 121 e._library = function.dartOwner; | |
| 122 } | |
| 123 return e; | |
| 124 } | |
| 125 | |
| 16 FunctionViewElement.created() : super.created(); | 126 FunctionViewElement.created() : super.created(); |
| 17 | 127 |
| 18 Future refresh() { | 128 @override |
| 19 return function.reload(); | 129 attached() { |
| 130 super.attached(); | |
| 131 _r.enable(); | |
| 132 _refresh(); | |
| 133 } | |
| 134 | |
| 135 @override | |
| 136 detached() { | |
| 137 super.detached(); | |
| 138 _r.disable(notify: true); | |
| 139 children = []; | |
| 140 } | |
| 141 | |
| 142 void render() { | |
| 143 children = [ | |
| 144 new NavBarElement(queue: _r.queue) | |
| 145 ..children = _createMenu(), | |
| 146 new DivElement()..classes = const ['content-centered-big'] | |
| 147 ..children = [ | |
| 148 new HeadingElement.h2()..text = 'Function ${_function.name}', | |
| 149 new HRElement(), | |
| 150 new ObjectCommonElement(_isolate, _function, _retainedSizes, | |
| 151 _reachableSizes, _references, _retainingPaths, | |
| 152 _instances, queue: _r.queue), | |
| 153 new BRElement(), | |
| 154 new DivElement()..classes = ['memberList'] | |
| 155 ..children = _createMembers(), | |
| 156 new HRElement(), | |
| 157 new DivElement() | |
| 158 ..children = _function.location == null ? const [] | |
| 159 : [ | |
| 160 new SourceInsetElement(_isolate, _function.location, _scripts, | |
| 161 _instances, _events, queue: _r.queue) | |
| 162 ], | |
| 163 new ViewFooterElement(queue: _r.queue) | |
| 164 ] | |
| 165 ]; | |
| 166 } | |
| 167 | |
| 168 List<Element> _createMenu() { | |
| 169 final menu = [ | |
| 170 new NavTopMenuElement(queue: _r.queue), | |
| 171 new NavVMMenuElement(_vm, _events, queue: _r.queue), | |
| 172 new NavIsolateMenuElement(_isolate, _events, queue: _r.queue) | |
| 173 ]; | |
| 174 if (_library != null) { | |
| 175 menu.add(new NavLibraryMenuElement(_isolate, _function.dartOwner, | |
| 176 queue: _r.queue)); | |
| 177 } else if (_function.dartOwner is M.ClassRef) { | |
| 178 menu.add( | |
| 179 new NavClassMenuElement(_isolate, _function.dartOwner, queue: _r.queue), | |
|
rmacnak
2016/08/29 23:34:35
stray trailing comma
cbernaschina
2016/08/29 23:36:16
Done.
| |
| 180 ); | |
| 181 } | |
| 182 menu.addAll([ | |
| 183 new NavMenuElement(_function.name, last: true, queue: _r.queue), | |
| 184 new NavRefreshElement(queue: _r.queue) | |
| 185 ..onRefresh.listen((e) { | |
| 186 e.element.disabled = true; | |
| 187 _refresh(); | |
| 188 }), | |
| 189 new NavNotifyElement(_notifications, queue: _r.queue) | |
| 190 ]); | |
| 191 return menu; | |
| 192 } | |
| 193 | |
| 194 List<Element> _createMembers() { | |
| 195 final members = <Element>[ | |
| 196 new DivElement()..classes = ['memberItem'] | |
| 197 ..children = [ | |
| 198 new DivElement()..classes = ['memberName'] | |
| 199 ..text = 'kind', | |
| 200 new DivElement()..classes = ['memberName'] | |
| 201 ..children = [ | |
| 202 new SpanElement() | |
| 203 ..text = '${_function.isStatic ? "static ": ""}' | |
| 204 '${_function.isConst ? "const ": ""}' | |
| 205 '${_functionKindToString(_function.kind)}' | |
| 206 ] | |
| 207 ], | |
| 208 new DivElement()..classes = ['memberItem'] | |
| 209 ..children = [ | |
| 210 new DivElement()..classes = ['memberName'] | |
| 211 ..text = 'owner', | |
| 212 new DivElement()..classes = ['memberName'] | |
| 213 ..children = [ | |
| 214 _function.dartOwner == null | |
| 215 ? (new SpanElement()..text = '...') | |
| 216 : anyRef(_isolate, _function.dartOwner, _instances, | |
| 217 queue: _r.queue) | |
| 218 ] | |
| 219 ] | |
| 220 ]; | |
| 221 if (_function.field != null) { | |
| 222 members.add( | |
| 223 new DivElement()..classes = ['memberItem'] | |
| 224 ..children = [ | |
| 225 new DivElement()..classes = ['memberName'] | |
| 226 ..text = 'script', | |
| 227 new DivElement()..classes = ['memberName'] | |
| 228 ..children = [ | |
| 229 new FieldRefElement(_isolate, _function.field, _instances, | |
| 230 queue: _r.queue) | |
| 231 ] | |
| 232 ] | |
| 233 ); | |
| 234 } | |
| 235 members.add( | |
| 236 new DivElement()..classes = ['memberItem'] | |
| 237 ..children = [ | |
| 238 new DivElement()..classes = ['memberName'] | |
| 239 ..text = 'script', | |
| 240 new DivElement()..classes = ['memberName'] | |
| 241 ..children = [ | |
| 242 new SourceLinkElement(_isolate, _function.location, _scripts, | |
| 243 queue: _r.queue) | |
| 244 ] | |
| 245 ] | |
| 246 ); | |
| 247 if (_function.code != null) { | |
| 248 members.add( | |
| 249 new DivElement()..classes = ['memberItem'] | |
| 250 ..children = [ | |
| 251 new DivElement()..classes = ['memberName'] | |
| 252 ..text = 'current code', | |
| 253 new DivElement()..classes = ['memberName'] | |
| 254 ..children = [ | |
| 255 new CodeRefElement(_isolate, _function.code, queue: _r.queue) | |
| 256 ] | |
| 257 ] | |
| 258 ); | |
| 259 } | |
| 260 if (_function.unoptimizedCode != null) { | |
| 261 members.add( | |
| 262 new DivElement()..classes = ['memberItem'] | |
| 263 ..children = [ | |
| 264 new DivElement()..classes = ['memberName'] | |
| 265 ..text = 'unoptimized code', | |
| 266 new DivElement()..classes = ['memberName'] | |
| 267 ..children = [ | |
| 268 new CodeRefElement(_isolate, _function.unoptimizedCode, | |
| 269 queue: _r.queue), | |
| 270 new SpanElement() | |
| 271 ..title = 'This count is used to determine when a function ' | |
| 272 'will be optimized. It is a combination of call ' | |
| 273 'counts and other factors.' | |
| 274 ..text = ' (usage count: ${function.usageCounter })' | |
| 275 ] | |
| 276 ] | |
| 277 ); | |
| 278 } | |
| 279 members.addAll([ | |
| 280 new DivElement()..classes = ['memberItem'] | |
| 281 ..text = ' ', | |
| 282 new DivElement()..classes = ['memberItem'] | |
| 283 ..children = [ | |
| 284 new DivElement()..classes = ['memberName'] | |
| 285 ..text = 'ic data array', | |
| 286 new DivElement()..classes = ['memberName'] | |
| 287 ..children = [ | |
| 288 new InstanceRefElement(_isolate, _function.icDataArray, | |
| 289 _instances, queue: _r.queue) | |
| 290 ] | |
| 291 ], | |
| 292 new DivElement()..classes = ['memberItem'] | |
| 293 ..children = [ | |
| 294 new DivElement()..classes = ['memberName'] | |
| 295 ..text = 'deoptimizations', | |
| 296 new DivElement()..classes = ['memberName'] | |
| 297 ..text = '${_function.deoptimizations}' | |
| 298 ], | |
| 299 new DivElement()..classes = ['memberItem'] | |
| 300 ..children = [ | |
| 301 new DivElement()..classes = ['memberName'] | |
| 302 ..text = 'optimizable', | |
| 303 new DivElement()..classes = ['memberName'] | |
| 304 ..text = _function.isOptimizable ? 'yes' : 'no' | |
| 305 ], | |
| 306 new DivElement()..classes = ['memberItem'] | |
| 307 ..children = [ | |
| 308 new DivElement()..classes = ['memberName'] | |
| 309 ..text = 'inlinable', | |
| 310 new DivElement()..classes = ['memberName'] | |
| 311 ..text = _function.isInlinable ? 'yes' : 'no' | |
| 312 ], | |
| 313 new DivElement()..classes = ['memberItem'] | |
| 314 ..children = [ | |
| 315 new DivElement()..classes = ['memberName'] | |
| 316 ..text = 'intrinsic', | |
| 317 new DivElement()..classes = ['memberName'] | |
| 318 ..text = _function.hasIntrinsic ? 'yes' : 'no' | |
| 319 ], | |
| 320 new DivElement()..classes = ['memberItem'] | |
| 321 ..children = [ | |
| 322 new DivElement()..classes = ['memberName'] | |
| 323 ..text = 'recognized', | |
| 324 new DivElement()..classes = ['memberName'] | |
| 325 ..text = _function.isRecognized ? 'yes' : 'no' | |
| 326 ], | |
| 327 new DivElement()..classes = ['memberItem'] | |
| 328 ..children = [ | |
| 329 new DivElement()..classes = ['memberName'] | |
| 330 ..text = 'native', | |
| 331 new DivElement()..classes = ['memberName'] | |
| 332 ..text = _function.isNative ? 'yes' : 'no' | |
| 333 ], | |
| 334 new DivElement()..classes = ['memberItem'] | |
| 335 ..children = [ | |
| 336 new DivElement()..classes = ['memberName'] | |
| 337 ..text = 'vm name', | |
| 338 new DivElement()..classes = ['memberName'] | |
| 339 ..text = _function.vmName | |
| 340 ] | |
| 341 ]); | |
| 342 return members; | |
| 343 } | |
| 344 | |
| 345 Future _refresh() async { | |
| 346 _function = await _functions.get(_isolate, _function.id); | |
| 347 if (_function.dartOwner is M.LibraryRef) { | |
| 348 _library = _function.dartOwner; | |
| 349 } else if (_function.dartOwner is M.ClassRef) { | |
| 350 _library = (await _classes.get(_isolate, _function.dartOwner.id)).library; | |
| 351 } | |
| 352 _r.dirty(); | |
| 353 } | |
| 354 | |
| 355 static String _functionKindToString(M.FunctionKind kind) { | |
| 356 switch(kind) { | |
| 357 case M.FunctionKind.regular: | |
| 358 return 'regular'; | |
| 359 case M.FunctionKind.closure: | |
| 360 return 'closure'; | |
| 361 case M.FunctionKind.getter: | |
| 362 return 'getter'; | |
| 363 case M.FunctionKind.setter: | |
| 364 return 'setter'; | |
| 365 case M.FunctionKind.constructor: | |
| 366 return 'constructor'; | |
| 367 case M.FunctionKind.implicitGetter: | |
| 368 return 'implicit getter'; | |
| 369 case M.FunctionKind.implicitSetter: | |
| 370 return 'implicit setter'; | |
| 371 case M.FunctionKind.implicitStaticFinalGetter: | |
| 372 return 'implicit static final getter'; | |
| 373 case M.FunctionKind.irregexpFunction: | |
| 374 return 'irregexp function'; | |
| 375 case M.FunctionKind.staticInitializer: | |
| 376 return 'static initializer'; | |
| 377 case M.FunctionKind.methodExtractor: | |
| 378 return 'method extractor'; | |
| 379 case M.FunctionKind.noSuchMethodDispatcher: | |
| 380 return 'noSuchMethod dispatcher'; | |
| 381 case M.FunctionKind.invokeFieldDispatcher: | |
| 382 return 'invokeField dispatcher'; | |
| 383 case M.FunctionKind.collected: | |
| 384 return 'collected'; | |
| 385 case M.FunctionKind.native: | |
| 386 return 'native'; | |
| 387 case M.FunctionKind.stub: | |
| 388 return 'stub'; | |
| 389 case M.FunctionKind.tag: | |
| 390 return 'tag'; | |
| 391 case M.FunctionKind.signatureFunction: | |
| 392 return 'signature function'; | |
| 393 } | |
| 394 throw new Exception('Unknown Functionkind ($kind)'); | |
| 20 } | 395 } |
| 21 } | 396 } |
| OLD | NEW |