Chromium Code Reviews| Index: runtime/observatory/lib/src/elements/function_view.dart |
| diff --git a/runtime/observatory/lib/src/elements/function_view.dart b/runtime/observatory/lib/src/elements/function_view.dart |
| index 58f206b40bfb9030d14058fb1b8b5dba967ebcc8..d0d08668cc2aa7441b4af3e8b851196ac40e6a9c 100644 |
| --- a/runtime/observatory/lib/src/elements/function_view.dart |
| +++ b/runtime/observatory/lib/src/elements/function_view.dart |
| @@ -5,17 +5,392 @@ |
| library function_view_element; |
| import 'dart:async'; |
| -import 'observatory_element.dart'; |
| -import 'package:observatory/service.dart'; |
| +import 'dart:html'; |
| +import 'package:observatory/models.dart' as M; |
| +import 'package:observatory/src/elements/class_ref.dart'; |
| +import 'package:observatory/src/elements/code_ref.dart'; |
| +import 'package:observatory/src/elements/curly_block.dart'; |
| +import 'package:observatory/src/elements/field_ref.dart'; |
| +import 'package:observatory/src/elements/instance_ref.dart'; |
| +import 'package:observatory/src/elements/helpers/any_ref.dart'; |
| +import 'package:observatory/src/elements/helpers/rendering_scheduler.dart'; |
| +import 'package:observatory/src/elements/helpers/tag.dart'; |
| +import 'package:observatory/src/elements/nav/bar.dart'; |
| +import 'package:observatory/src/elements/nav/class_menu.dart'; |
| +import 'package:observatory/src/elements/nav/isolate_menu.dart'; |
| +import 'package:observatory/src/elements/nav/library_menu.dart'; |
| +import 'package:observatory/src/elements/nav/menu.dart'; |
| +import 'package:observatory/src/elements/nav/notify.dart'; |
| +import 'package:observatory/src/elements/nav/refresh.dart'; |
| +import 'package:observatory/src/elements/nav/top_menu.dart'; |
| +import 'package:observatory/src/elements/nav/vm_menu.dart'; |
| +import 'package:observatory/src/elements/object_common.dart'; |
| +import 'package:observatory/src/elements/source_inset.dart'; |
| +import 'package:observatory/src/elements/source_link.dart'; |
| +import 'package:observatory/src/elements/view_footer.dart'; |
| -import 'package:polymer/polymer.dart'; |
| +class FunctionViewElement extends HtmlElement implements Renderable { |
| + static const tag = const Tag<FunctionViewElement>('function-view', |
| + dependencies: const [ |
| + ClassRefElement.tag, |
| + CodeRefElement.tag, |
| + CurlyBlockElement.tag, |
| + FieldRefElement.tag, |
| + InstanceRefElement.tag, |
| + NavBarElement.tag, |
| + NavClassMenuElement.tag, |
| + NavLibraryMenuElement.tag, |
| + NavTopMenuElement.tag, |
| + NavVMMenuElement.tag, |
| + NavIsolateMenuElement.tag, |
| + NavMenuElement.tag, |
| + NavRefreshElement.tag, |
| + NavNotifyElement.tag, |
| + ObjectCommonElement.tag, |
| + SourceLinkElement.tag, |
| + SourceInsetElement.tag, |
| + ViewFooterElement.tag |
| + ]); |
| + |
| + RenderingScheduler<FunctionViewElement> _r; |
| + |
| + Stream<RenderedEvent<FunctionViewElement>> get onRendered => _r.onRendered; |
| + |
| + M.VM _vm; |
| + M.IsolateRef _isolate; |
| + M.EventRepository _events; |
| + M.NotificationRepository _notifications; |
| + M.Function _function; |
| + M.LibraryRef _library; |
| + M.FunctionRepository _functions; |
| + M.ClassRepository _classes; |
| + M.RetainedSizeRepository _retainedSizes; |
| + M.ReachableSizeRepository _reachableSizes; |
| + M.InboundReferencesRepository _references; |
| + M.RetainingPathRepository _retainingPaths; |
| + M.ScriptRepository _scripts; |
| + M.InstanceRepository _instances; |
| + |
| + |
| + M.VMRef get vm => _vm; |
| + M.IsolateRef get isolate => _isolate; |
| + M.NotificationRepository get notifications => _notifications; |
| + M.Function get function => _function; |
| + |
| + factory FunctionViewElement(M.VM vm, M.IsolateRef isolate, M.Function function, |
| + M.EventRepository events, |
| + M.NotificationRepository notifications, |
| + M.FunctionRepository functions, |
| + M.ClassRepository classes, |
| + M.RetainedSizeRepository retainedSizes, |
| + M.ReachableSizeRepository reachableSizes, |
| + M.InboundReferencesRepository references, |
| + M.RetainingPathRepository retainingPaths, |
| + M.ScriptRepository scripts, |
| + M.InstanceRepository instances, |
| + {RenderingQueue queue}) { |
| + assert(vm != null); |
| + assert(isolate != null); |
| + assert(events != null); |
| + assert(notifications != null); |
| + assert(function != null); |
| + assert(functions != null); |
| + assert(classes != null); |
| + assert(retainedSizes != null); |
| + assert(reachableSizes != null); |
| + assert(references != null); |
| + assert(retainingPaths != null); |
| + assert(scripts != null); |
| + assert(instances != null); |
| + FunctionViewElement e = document.createElement(tag.name); |
| + e._r = new RenderingScheduler(e, queue: queue); |
| + e._vm = vm; |
| + e._isolate = isolate; |
| + e._events = events; |
| + e._notifications = notifications; |
| + e._function = function; |
| + e._functions = functions; |
| + e._classes = classes; |
| + e._retainedSizes = retainedSizes; |
| + e._reachableSizes = reachableSizes; |
| + e._references = references; |
| + e._retainingPaths = retainingPaths; |
| + e._scripts = scripts; |
| + e._instances = instances; |
| + if (function.dartOwner is M.LibraryRef) { |
| + e._library = function.dartOwner; |
| + } |
| + return e; |
| + } |
| -@CustomTag('function-view') |
| -class FunctionViewElement extends ObservatoryElement { |
| - @published ServiceFunction function; |
| FunctionViewElement.created() : super.created(); |
| - Future refresh() { |
| - return function.reload(); |
| + @override |
| + attached() { |
| + super.attached(); |
| + _r.enable(); |
| + _refresh(); |
| + } |
| + |
| + @override |
| + detached() { |
| + super.detached(); |
| + _r.disable(notify: true); |
| + children = []; |
| + } |
| + |
| + void render() { |
| + children = [ |
| + new NavBarElement(queue: _r.queue) |
| + ..children = _createMenu(), |
| + new DivElement()..classes = const ['content-centered-big'] |
| + ..children = [ |
| + new HeadingElement.h2()..text = 'Function ${_function.name}', |
| + new HRElement(), |
| + new ObjectCommonElement(_isolate, _function, _retainedSizes, |
| + _reachableSizes, _references, _retainingPaths, |
| + _instances, queue: _r.queue), |
| + new BRElement(), |
| + new DivElement()..classes = ['memberList'] |
| + ..children = _createMembers(), |
| + new HRElement(), |
| + new DivElement() |
| + ..children = _function.location == null ? const [] |
| + : [ |
| + new SourceInsetElement(_isolate, _function.location, _scripts, |
| + _instances, _events, queue: _r.queue) |
| + ], |
| + new ViewFooterElement(queue: _r.queue) |
| + ] |
| + ]; |
| + } |
| + |
| + List<Element> _createMenu() { |
| + final menu = [ |
| + new NavTopMenuElement(queue: _r.queue), |
| + new NavVMMenuElement(_vm, _events, queue: _r.queue), |
| + new NavIsolateMenuElement(_isolate, _events, queue: _r.queue) |
| + ]; |
| + if (_library != null) { |
| + menu.add(new NavLibraryMenuElement(_isolate, _function.dartOwner, |
| + queue: _r.queue)); |
| + } else if (_function.dartOwner is M.ClassRef) { |
| + menu.add( |
| + 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.
|
| + ); |
| + } |
| + menu.addAll([ |
| + new NavMenuElement(_function.name, last: true, queue: _r.queue), |
| + new NavRefreshElement(queue: _r.queue) |
| + ..onRefresh.listen((e) { |
| + e.element.disabled = true; |
| + _refresh(); |
| + }), |
| + new NavNotifyElement(_notifications, queue: _r.queue) |
| + ]); |
| + return menu; |
| + } |
| + |
| + List<Element> _createMembers() { |
| + final members = <Element>[ |
| + new DivElement()..classes = ['memberItem'] |
| + ..children = [ |
| + new DivElement()..classes = ['memberName'] |
| + ..text = 'kind', |
| + new DivElement()..classes = ['memberName'] |
| + ..children = [ |
| + new SpanElement() |
| + ..text = '${_function.isStatic ? "static ": ""}' |
| + '${_function.isConst ? "const ": ""}' |
| + '${_functionKindToString(_function.kind)}' |
| + ] |
| + ], |
| + new DivElement()..classes = ['memberItem'] |
| + ..children = [ |
| + new DivElement()..classes = ['memberName'] |
| + ..text = 'owner', |
| + new DivElement()..classes = ['memberName'] |
| + ..children = [ |
| + _function.dartOwner == null |
| + ? (new SpanElement()..text = '...') |
| + : anyRef(_isolate, _function.dartOwner, _instances, |
| + queue: _r.queue) |
| + ] |
| + ] |
| + ]; |
| + if (_function.field != null) { |
| + members.add( |
| + new DivElement()..classes = ['memberItem'] |
| + ..children = [ |
| + new DivElement()..classes = ['memberName'] |
| + ..text = 'script', |
| + new DivElement()..classes = ['memberName'] |
| + ..children = [ |
| + new FieldRefElement(_isolate, _function.field, _instances, |
| + queue: _r.queue) |
| + ] |
| + ] |
| + ); |
| + } |
| + members.add( |
| + new DivElement()..classes = ['memberItem'] |
| + ..children = [ |
| + new DivElement()..classes = ['memberName'] |
| + ..text = 'script', |
| + new DivElement()..classes = ['memberName'] |
| + ..children = [ |
| + new SourceLinkElement(_isolate, _function.location, _scripts, |
| + queue: _r.queue) |
| + ] |
| + ] |
| + ); |
| + if (_function.code != null) { |
| + members.add( |
| + new DivElement()..classes = ['memberItem'] |
| + ..children = [ |
| + new DivElement()..classes = ['memberName'] |
| + ..text = 'current code', |
| + new DivElement()..classes = ['memberName'] |
| + ..children = [ |
| + new CodeRefElement(_isolate, _function.code, queue: _r.queue) |
| + ] |
| + ] |
| + ); |
| + } |
| + if (_function.unoptimizedCode != null) { |
| + members.add( |
| + new DivElement()..classes = ['memberItem'] |
| + ..children = [ |
| + new DivElement()..classes = ['memberName'] |
| + ..text = 'unoptimized code', |
| + new DivElement()..classes = ['memberName'] |
| + ..children = [ |
| + new CodeRefElement(_isolate, _function.unoptimizedCode, |
| + queue: _r.queue), |
| + new SpanElement() |
| + ..title = 'This count is used to determine when a function ' |
| + 'will be optimized. It is a combination of call ' |
| + 'counts and other factors.' |
| + ..text = ' (usage count: ${function.usageCounter })' |
| + ] |
| + ] |
| + ); |
| + } |
| + members.addAll([ |
| + new DivElement()..classes = ['memberItem'] |
| + ..text = ' ', |
| + new DivElement()..classes = ['memberItem'] |
| + ..children = [ |
| + new DivElement()..classes = ['memberName'] |
| + ..text = 'ic data array', |
| + new DivElement()..classes = ['memberName'] |
| + ..children = [ |
| + new InstanceRefElement(_isolate, _function.icDataArray, |
| + _instances, queue: _r.queue) |
| + ] |
| + ], |
| + new DivElement()..classes = ['memberItem'] |
| + ..children = [ |
| + new DivElement()..classes = ['memberName'] |
| + ..text = 'deoptimizations', |
| + new DivElement()..classes = ['memberName'] |
| + ..text = '${_function.deoptimizations}' |
| + ], |
| + new DivElement()..classes = ['memberItem'] |
| + ..children = [ |
| + new DivElement()..classes = ['memberName'] |
| + ..text = 'optimizable', |
| + new DivElement()..classes = ['memberName'] |
| + ..text = _function.isOptimizable ? 'yes' : 'no' |
| + ], |
| + new DivElement()..classes = ['memberItem'] |
| + ..children = [ |
| + new DivElement()..classes = ['memberName'] |
| + ..text = 'inlinable', |
| + new DivElement()..classes = ['memberName'] |
| + ..text = _function.isInlinable ? 'yes' : 'no' |
| + ], |
| + new DivElement()..classes = ['memberItem'] |
| + ..children = [ |
| + new DivElement()..classes = ['memberName'] |
| + ..text = 'intrinsic', |
| + new DivElement()..classes = ['memberName'] |
| + ..text = _function.hasIntrinsic ? 'yes' : 'no' |
| + ], |
| + new DivElement()..classes = ['memberItem'] |
| + ..children = [ |
| + new DivElement()..classes = ['memberName'] |
| + ..text = 'recognized', |
| + new DivElement()..classes = ['memberName'] |
| + ..text = _function.isRecognized ? 'yes' : 'no' |
| + ], |
| + new DivElement()..classes = ['memberItem'] |
| + ..children = [ |
| + new DivElement()..classes = ['memberName'] |
| + ..text = 'native', |
| + new DivElement()..classes = ['memberName'] |
| + ..text = _function.isNative ? 'yes' : 'no' |
| + ], |
| + new DivElement()..classes = ['memberItem'] |
| + ..children = [ |
| + new DivElement()..classes = ['memberName'] |
| + ..text = 'vm name', |
| + new DivElement()..classes = ['memberName'] |
| + ..text = _function.vmName |
| + ] |
| + ]); |
| + return members; |
| + } |
| + |
| + Future _refresh() async { |
| + _function = await _functions.get(_isolate, _function.id); |
| + if (_function.dartOwner is M.LibraryRef) { |
| + _library = _function.dartOwner; |
| + } else if (_function.dartOwner is M.ClassRef) { |
| + _library = (await _classes.get(_isolate, _function.dartOwner.id)).library; |
| + } |
| + _r.dirty(); |
| + } |
| + |
| + static String _functionKindToString(M.FunctionKind kind) { |
| + switch(kind) { |
| + case M.FunctionKind.regular: |
| + return 'regular'; |
| + case M.FunctionKind.closure: |
| + return 'closure'; |
| + case M.FunctionKind.getter: |
| + return 'getter'; |
| + case M.FunctionKind.setter: |
| + return 'setter'; |
| + case M.FunctionKind.constructor: |
| + return 'constructor'; |
| + case M.FunctionKind.implicitGetter: |
| + return 'implicit getter'; |
| + case M.FunctionKind.implicitSetter: |
| + return 'implicit setter'; |
| + case M.FunctionKind.implicitStaticFinalGetter: |
| + return 'implicit static final getter'; |
| + case M.FunctionKind.irregexpFunction: |
| + return 'irregexp function'; |
| + case M.FunctionKind.staticInitializer: |
| + return 'static initializer'; |
| + case M.FunctionKind.methodExtractor: |
| + return 'method extractor'; |
| + case M.FunctionKind.noSuchMethodDispatcher: |
| + return 'noSuchMethod dispatcher'; |
| + case M.FunctionKind.invokeFieldDispatcher: |
| + return 'invokeField dispatcher'; |
| + case M.FunctionKind.collected: |
| + return 'collected'; |
| + case M.FunctionKind.native: |
| + return 'native'; |
| + case M.FunctionKind.stub: |
| + return 'stub'; |
| + case M.FunctionKind.tag: |
| + return 'tag'; |
| + case M.FunctionKind.signatureFunction: |
| + return 'signature function'; |
| + } |
| + throw new Exception('Unknown Functionkind ($kind)'); |
| } |
| } |