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) |
| 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 |