Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(935)

Unified Diff: runtime/observatory/lib/src/service/object.dart

Issue 839543002: Revert "Build Observatory with runtime" (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/observatory/lib/src/elements/vm_view.html ('k') | runtime/observatory/lib/tracer.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/observatory/lib/src/service/object.dart
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
deleted file mode 100644
index 3c8f3b7ede9659e4026edc6dd616895f914a3578..0000000000000000000000000000000000000000
--- a/runtime/observatory/lib/src/service/object.dart
+++ /dev/null
@@ -1,2744 +0,0 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of service;
-
-/// A [ServiceObject] is an object known to the VM service and is tied
-/// to an owning [Isolate].
-abstract class ServiceObject extends Observable {
- static int LexicalSortName(ServiceObject o1, ServiceObject o2) {
- return o1.name.compareTo(o2.name);
- }
-
- List removeDuplicatesAndSortLexical(List<ServiceObject> list) {
- return list.toSet().toList()..sort(LexicalSortName);
- }
-
- /// The owner of this [ServiceObject]. This can be an [Isolate], a
- /// [VM], or null.
- @reflectable ServiceObjectOwner get owner => _owner;
- ServiceObjectOwner _owner;
-
- /// The [VM] which owns this [ServiceObject].
- @reflectable VM get vm => _owner.vm;
-
- /// The [Isolate] which owns this [ServiceObject]. May be null.
- @reflectable Isolate get isolate => _owner.isolate;
-
- /// The id of this object.
- @reflectable String get id => _id;
- String _id;
-
- /// The user-level type of this object.
- @reflectable String get type => _type;
- String _type;
-
- /// The vm type of this object.
- @reflectable String get vmType => _vmType;
- String _vmType;
-
- static bool _isInstanceType(String type) {
- switch (type) {
- case 'BoundedType':
- case 'Instance':
- case 'List':
- case 'String':
- case 'Type':
- case 'TypeParameter':
- case 'TypeRef':
- case 'bool':
- case 'double':
- case 'int':
- case 'null':
- return true;
- default:
- return false;
- }
- }
-
- static bool _isTypeType(String type) {
- switch (type) {
- case 'BoundedType':
- case 'Type':
- case 'TypeParameter':
- case 'TypeRef':
- return true;
- default:
- return false;
- }
- }
-
- bool get isAbstractType => _isTypeType(type);
- bool get isBool => type == 'bool';
- bool get isContext => type == 'Context';
- bool get isDouble => type == 'double';
- bool get isError => type == 'Error';
- bool get isInstance => _isInstanceType(type);
- bool get isInt => type == 'int';
- bool get isList => type == 'List';
- bool get isNull => type == 'null';
- bool get isSentinel => type == 'Sentinel';
- bool get isString => type == 'String';
-
- // Kinds of Instance.
- bool get isMirrorReference => vmType == 'MirrorReference';
- bool get isWeakProperty => vmType == 'WeakProperty';
- bool get isClosure => false;
- bool get isPlainInstance {
- return (type == 'Instance' &&
- !isMirrorReference && !isWeakProperty && !isClosure);
- }
-
- /// The complete service url of this object.
- @reflectable String get link => _owner.relativeLink(_id);
-
- /// Has this object been fully loaded?
- bool get loaded => _loaded;
- bool _loaded = false;
- // TODO(turnidge): Make loaded observable and get rid of loading
- // from Isolate.
-
- /// Is this object cacheable? That is, is it impossible for the [id]
- /// of this object to change?
- bool get canCache => false;
-
- /// Is this object immutable after it is [loaded]?
- bool get immutable => false;
-
- @observable String name;
- @observable String vmName;
-
- /// Creates an empty [ServiceObject].
- ServiceObject._empty(this._owner);
-
- /// Creates a [ServiceObject] initialized from [map].
- factory ServiceObject._fromMap(ServiceObjectOwner owner,
- ObservableMap map) {
- if (map == null) {
- return null;
- }
- if (!_isServiceMap(map)) {
- Logger.root.severe('Malformed service object: $map');
- }
- assert(_isServiceMap(map));
- var type = _stripRef(map['type']);
- var vmType = map['_vmType'] != null ? _stripRef(map['_vmType']) : type;
- var obj = null;
- assert(type != 'VM');
- switch (type) {
- case 'Class':
- obj = new Class._empty(owner);
- break;
- case 'Code':
- obj = new Code._empty(owner);
- break;
- case 'Context':
- obj = new Context._empty(owner);
- break;
- case 'Counter':
- obj = new ServiceMetric._empty(owner);
- break;
- case 'Error':
- obj = new DartError._empty(owner);
- break;
- case 'Field':
- obj = new Field._empty(owner);
- break;
- case 'Function':
- obj = new ServiceFunction._empty(owner);
- break;
- case 'Gauge':
- obj = new ServiceMetric._empty(owner);
- break;
- case 'Isolate':
- obj = new Isolate._empty(owner.vm);
- break;
- case 'Library':
- obj = new Library._empty(owner);
- break;
- case 'Object':
- switch (vmType) {
- case 'PcDescriptors':
- obj = new PcDescriptors._empty(owner);
- break;
- case 'LocalVarDescriptors':
- obj = new LocalVarDescriptors._empty(owner);
- break;
- case 'TokenStream':
- obj = new TokenStream._empty(owner);
- break;
- }
- break;
- case 'ServiceError':
- obj = new ServiceError._empty(owner);
- break;
- case 'ServiceEvent':
- obj = new ServiceEvent._empty(owner);
- break;
- case 'ServiceException':
- obj = new ServiceException._empty(owner);
- break;
- case 'Script':
- obj = new Script._empty(owner);
- break;
- case 'Socket':
- obj = new Socket._empty(owner);
- break;
- default:
- if (_isInstanceType(type) ||
- type == 'Sentinel') { // TODO(rmacnak): Separate this out.
- obj = new Instance._empty(owner);
- }
- break;
- }
- if (obj == null) {
- obj = new ServiceMap._empty(owner);
- }
- obj.update(map);
- return obj;
- }
-
- /// If [this] was created from a reference, load the full object
- /// from the service by calling [reload]. Else, return [this].
- Future<ServiceObject> load() {
- if (loaded) {
- return new Future.value(this);
- }
- // Call reload which will fill in the entire object.
- return reload();
- }
-
- Future<ServiceObject> _inProgressReload;
-
- /// Reload [this]. Returns a future which completes to [this] or
- /// a [ServiceError].
- Future<ServiceObject> reload() {
- if (id == '') {
- // Errors don't have ids.
- assert(type == 'Error');
- return new Future.value(this);
- }
- if (loaded && immutable) {
- return new Future.value(this);
- }
- if (_inProgressReload == null) {
- _inProgressReload = vm.getAsMap(link).then((ObservableMap map) {
- var mapType = _stripRef(map['type']);
- if (mapType != _type) {
- // If the type changes, return a new object instead of
- // updating the existing one.
- //
- // TODO(turnidge): Check for vmType changing as well?
- assert(mapType == 'Error' || mapType == 'Sentinel');
- return new ServiceObject._fromMap(owner, map);
- }
- update(map);
- return this;
- }).whenComplete(() {
- // This reload is complete.
- _inProgressReload = null;
- });
- }
- return _inProgressReload;
- }
-
- /// Update [this] using [map] as a source. [map] can be a reference.
- void update(ObservableMap map) {
- assert(_isServiceMap(map));
-
- // Don't allow the type to change on an object update.
- // TODO(turnidge): Make this a ServiceError?
- var mapIsRef = _hasRef(map['type']);
- var mapType = _stripRef(map['type']);
- assert(_type == null || _type == mapType);
-
- if (_id != null && _id != map['id']) {
- // It is only safe to change an id when the object isn't cacheable.
- assert(!canCache);
- }
- _id = map['id'];
-
- _type = mapType;
-
- // When the response specifies a specific vmType, use it.
- // Otherwise the vmType of the response is the same as the 'user'
- // type.
- if (map.containsKey('_vmType')) {
- _vmType = _stripRef(map['_vmType']);
- } else {
- _vmType = _type;
- }
-
- _update(map, mapIsRef);
- }
-
- // Updates internal state from [map]. [map] can be a reference.
- void _update(ObservableMap map, bool mapIsRef);
-
- String relativeLink(String id) {
- assert(id != null);
- return "${link}/${id}";
- }
-}
-
-abstract class Coverage {
- // Following getters and functions will be provided by [ServiceObject].
- ServiceObjectOwner get owner;
- String get type;
- VM get vm;
- String relativeLink(String id);
-
- /// Default handler for coverage data.
- void processCoverageData(List coverageData) {
- coverageData.forEach((scriptCoverage) {
- assert(scriptCoverage['script'] != null);
- scriptCoverage['script']._processHits(scriptCoverage['hits']);
- });
- }
-
- Future refreshCoverage() {
- return vm.getAsMap(relativeLink('coverage')).then((ObservableMap map) {
- var coverageOwner = (type == 'Isolate') ? this : owner;
- var coverage = new ServiceObject._fromMap(coverageOwner, map);
- assert(coverage.type == 'CodeCoverage');
- var coverageList = coverage['coverage'];
- assert(coverageList != null);
- processCoverageData(coverageList);
- });
- }
-}
-
-abstract class ServiceObjectOwner extends ServiceObject {
- /// Creates an empty [ServiceObjectOwner].
- ServiceObjectOwner._empty(ServiceObjectOwner owner) : super._empty(owner);
-
- /// Builds a [ServiceObject] corresponding to the [id] from [map].
- /// The result may come from the cache. The result will not necessarily
- /// be [loaded].
- ServiceObject getFromMap(ObservableMap map);
-
- /// Creates a link to [id] relative to [this].
- String relativeLink(String id);
-}
-
-/// State for a VM being inspected.
-abstract class VM extends ServiceObjectOwner {
- @reflectable VM get vm => this;
- @reflectable Isolate get isolate => null;
-
- @reflectable Iterable<Isolate> get isolates => _isolateCache.values;
-
- @reflectable String get link => '$id';
- @reflectable String relativeLink(String id) => '$id';
-
- @observable String version = 'unknown';
- @observable String targetCPU;
- @observable int architectureBits;
- @observable double uptime = 0.0;
- @observable bool assertsEnabled = false;
- @observable bool typeChecksEnabled = false;
- @observable String pid = '';
- @observable DateTime lastUpdate;
-
- VM() : super._empty(null) {
- name = 'vm';
- vmName = 'vm';
- _cache['vm'] = this;
- update(toObservable({'id':'vm', 'type':'@VM'}));
- }
-
- final StreamController<ServiceException> exceptions =
- new StreamController.broadcast();
- final StreamController<ServiceError> errors =
- new StreamController.broadcast();
- final StreamController<ServiceEvent> events =
- new StreamController.broadcast();
-
- void postEventMessage(String eventMessage, [dynamic data]) {
- var map;
- try {
- map = _parseJSON(eventMessage);
- assert(!map.containsKey('_data'));
- if (data != null) {
- map['_data'] = data;
- }
- } catch (e, st) {
- Logger.root.severe('Ignoring malformed event message: ${eventMessage}');
- return;
- }
- if (map['type'] != 'ServiceEvent') {
- Logger.root.severe(
- "Expected 'ServiceEvent' but found '${map['type']}'");
- return;
- }
-
- // Extract the owning isolate from the event itself.
- String owningIsolateId = map['isolate']['id'];
- _getIsolate(owningIsolateId).then((owningIsolate) {
- if (owningIsolate == null) {
- // TODO(koda): Do we care about GC events in VM isolate?
- Logger.root.severe(
- 'Ignoring event with unknown isolate id: $owningIsolateId');
- } else {
- var event = new ServiceObject._fromMap(owningIsolate, map);
- events.add(event);
- }
- });
- }
-
- static final RegExp _currentIsolateMatcher = new RegExp(r'isolates/\d+');
- static final RegExp _currentObjectMatcher = new RegExp(r'isolates/\d+/');
- static final String _isolatesPrefix = 'isolates/';
-
- String _parseObjectId(String id) {
- Match m = _currentObjectMatcher.matchAsPrefix(id);
- if (m == null) {
- return null;
- }
- return m.input.substring(m.end);
- }
-
- String _parseIsolateId(String id) {
- Match m = _currentIsolateMatcher.matchAsPrefix(id);
- if (m == null) {
- return '';
- }
- return id.substring(0, m.end);
- }
-
- Map<String,ServiceObject> _cache = new Map<String,ServiceObject>();
- Map<String,Isolate> _isolateCache = new Map<String,Isolate>();
-
- ServiceObject getFromMap(ObservableMap map) {
- throw new UnimplementedError();
- }
-
- Future<ServiceObject> _getIsolate(String isolateId) {
- if (isolateId == '') {
- return new Future.value(null);
- }
- Isolate isolate = _isolateCache[isolateId];
- if (isolate != null) {
- return new Future.value(isolate);
- }
- // The isolate is not in the cache. Reload the vm and see if the
- // requested isolate is found.
- return reload().then((result) {
- if (result is! VM) {
- return null;
- }
- assert(result == this);
- return _isolateCache[isolateId];
- });
- }
-
- Future<ServiceObject> get(String id) {
- assert(id.startsWith('/') == false);
- // Isolates are handled specially, since they can cache sub-objects.
- if (id.startsWith(_isolatesPrefix)) {
- String isolateId = _parseIsolateId(id);
- String objectId = _parseObjectId(id);
- return _getIsolate(isolateId).then((isolate) {
- if (isolate == null) {
- // The isolate does not exist. Return the VM object instead.
- //
- // TODO(turnidge): Generate a service error?
- return this;
- }
- if (objectId == null) {
- return isolate.reload();
- } else {
- return isolate.get(objectId);
- }
- });
- }
-
- var obj = _cache[id];
- if (obj != null) {
- return obj.reload();
- }
-
- // Cache miss. Get the object from the vm directly.
- return getAsMap(id).then((ObservableMap map) {
- var obj = new ServiceObject._fromMap(this, map);
- if (obj.canCache) {
- _cache.putIfAbsent(id, () => obj);
- }
- return obj;
- });
- }
-
- dynamic _reviver(dynamic key, dynamic value) {
- return value;
- }
-
- ObservableMap _parseJSON(String response) {
- var map;
- try {
- var decoder = new JsonDecoder(_reviver);
- map = decoder.convert(response);
- } catch (e, st) {
- return null;
- }
- return toObservable(map);
- }
-
- Future<ObservableMap> _processMap(ObservableMap map) {
- // Verify that the top level response is a service map.
- if (!_isServiceMap(map)) {
- return new Future.error(
- new ServiceObject._fromMap(this, toObservable({
- 'type': 'ServiceException',
- 'id': '',
- 'kind': 'FormatException',
- 'response': map,
- 'message': 'Top level service responses must be service maps.',
- })));
- }
- // Preemptively capture ServiceError and ServiceExceptions.
- if (map['type'] == 'ServiceError') {
- return new Future.error(new ServiceObject._fromMap(this, map));
- } else if (map['type'] == 'ServiceException') {
- return new Future.error(new ServiceObject._fromMap(this, map));
- }
- // map is now guaranteed to be a non-error/exception ServiceObject.
- return new Future.value(map);
- }
-
- Future<ObservableMap> _decodeError(e) {
- return new Future.error(new ServiceObject._fromMap(this, toObservable({
- 'type': 'ServiceException',
- 'id': '',
- 'kind': 'DecodeException',
- 'response':
- 'This is likely a result of a known V8 bug. Although the '
- 'the bug has been fixed the fix may not be in your Chrome'
- ' version. For more information see dartbug.com/18385. '
- 'Observatory is still functioning and you should try your'
- ' action again.',
- 'message': 'Could not decode JSON: $e',
- })));
- }
-
- /// Gets [id] as an [ObservableMap] from the service directly. If
- /// an error occurs, the future is completed as an error with a
- /// ServiceError or ServiceException. Therefore any chained then() calls
- /// will only receive a map encoding a valid ServiceObject.
- Future<ObservableMap> getAsMap(String id) {
- return getString(id).then((response) {
- var map = _parseJSON(response);
- if (Tracer.current != null) {
- Tracer.current.trace("Received response for ${id}", map:map);
- }
- return _processMap(map);
- }).catchError((error) {
- // ServiceError, forward to VM's ServiceError stream.
- errors.add(error);
- return new Future.error(error);
- }, test: (e) => e is ServiceError).catchError((exception) {
- // ServiceException, forward to VM's ServiceException stream.
- exceptions.add(exception);
- return new Future.error(exception);
- }, test: (e) => e is ServiceException);
- }
-
- /// Get [id] as a [String] from the service directly. See [getAsMap].
- Future<String> getString(String id);
- /// Force the VM to disconnect.
- void disconnect();
- /// Completes when the VM first connects.
- Future get onConnect;
- /// Completes when the VM disconnects or there was an error connecting.
- Future get onDisconnect;
-
- void _update(ObservableMap map, bool mapIsRef) {
- if (mapIsRef) {
- return;
- }
- _loaded = true;
- version = map['version'];
- targetCPU = map['targetCPU'];
- architectureBits = map['architectureBits'];
- uptime = map['uptime'];
- var dateInMillis = int.parse(map['date']);
- lastUpdate = new DateTime.fromMillisecondsSinceEpoch(dateInMillis);
- assertsEnabled = map['assertsEnabled'];
- pid = map['pid'];
- typeChecksEnabled = map['typeChecksEnabled'];
- _updateIsolates(map['isolates']);
- }
-
- void _updateIsolates(List newIsolates) {
- var oldIsolateCache = _isolateCache;
- var newIsolateCache = new Map<String,Isolate>();
- for (var isolateMap in newIsolates) {
- var isolateId = isolateMap['id'];
- var isolate = oldIsolateCache[isolateId];
- if (isolate != null) {
- newIsolateCache[isolateId] = isolate;
- } else {
- isolate = new ServiceObject._fromMap(this, isolateMap);
- newIsolateCache[isolateId] = isolate;
- Logger.root.info('New isolate \'${isolate.id}\'');
- }
- }
- // Update the individual isolates asynchronously.
- newIsolateCache.forEach((isolateId, isolate) {
- isolate.reload();
- });
-
- _isolateCache = newIsolateCache;
- }
-}
-
-/// Snapshot in time of tag counters.
-class TagProfileSnapshot {
- final double seconds;
- final List<int> counters;
- int get sum => _sum;
- int _sum = 0;
- TagProfileSnapshot(this.seconds, int countersLength)
- : counters = new List<int>(countersLength);
-
- /// Set [counters] and update [sum].
- void set(List<int> counters) {
- this.counters.setAll(0, counters);
- for (var i = 0; i < this.counters.length; i++) {
- _sum += this.counters[i];
- }
- }
-
- /// Set [counters] with the delta from [counters] to [old_counters]
- /// and update [sum].
- void delta(List<int> counters, List<int> old_counters) {
- for (var i = 0; i < this.counters.length; i++) {
- this.counters[i] = counters[i] - old_counters[i];
- _sum += this.counters[i];
- }
- }
-
- /// Update [counters] with new maximum values seen in [counters].
- void max(List<int> counters) {
- for (var i = 0; i < counters.length; i++) {
- var c = counters[i];
- this.counters[i] = this.counters[i] > c ? this.counters[i] : c;
- }
- }
-
- /// Zero [counters].
- void zero() {
- for (var i = 0; i < counters.length; i++) {
- counters[i] = 0;
- }
- }
-}
-
-class TagProfile {
- final List<String> names = new List<String>();
- final List<TagProfileSnapshot> snapshots = new List<TagProfileSnapshot>();
- double get updatedAtSeconds => _seconds;
- double _seconds;
- TagProfileSnapshot _maxSnapshot;
- int _historySize;
- int _countersLength = 0;
-
- TagProfile(this._historySize);
-
- void _processTagProfile(double seconds, ObservableMap tagProfile) {
- _seconds = seconds;
- var counters = tagProfile['counters'];
- if (names.length == 0) {
- // Initialization.
- names.addAll(tagProfile['names']);
- _countersLength = tagProfile['counters'].length;
- for (var i = 0; i < _historySize; i++) {
- var snapshot = new TagProfileSnapshot(0.0, _countersLength);
- snapshot.zero();
- snapshots.add(snapshot);
- }
- // The counters monotonically grow, keep track of the maximum value.
- _maxSnapshot = new TagProfileSnapshot(0.0, _countersLength);
- _maxSnapshot.set(counters);
- return;
- }
- var snapshot = new TagProfileSnapshot(seconds, _countersLength);
- // We snapshot the delta from the current counters to the maximum counter
- // values.
- snapshot.delta(counters, _maxSnapshot.counters);
- _maxSnapshot.max(counters);
- snapshots.add(snapshot);
- // Only keep _historySize snapshots.
- if (snapshots.length > _historySize) {
- snapshots.removeAt(0);
- }
- }
-}
-
-class HeapSpace extends Observable {
- @observable int used = 0;
- @observable int capacity = 0;
- @observable int external = 0;
- @observable int collections = 0;
- @observable double totalCollectionTimeInSeconds = 0.0;
- @observable double averageCollectionPeriodInMillis = 0.0;
-
- void update(Map heapMap) {
- used = heapMap['used'];
- capacity = heapMap['capacity'];
- external = heapMap['external'];
- collections = heapMap['collections'];
- totalCollectionTimeInSeconds = heapMap['time'];
- averageCollectionPeriodInMillis = heapMap['avgCollectionPeriodMillis'];
- }
-}
-
-/// State for a running isolate.
-class Isolate extends ServiceObjectOwner with Coverage {
- @reflectable VM get vm => owner;
- @reflectable Isolate get isolate => this;
- @observable ObservableMap counters = new ObservableMap();
-
- String get link => '/${_id}';
-
- @observable ServiceEvent pauseEvent = null;
- bool get _isPaused => pauseEvent != null;
-
- @observable bool running = false;
- @observable bool idle = false;
- @observable bool loading = true;
- @observable bool ioEnabled = false;
-
- Map<String,ServiceObject> _cache = new Map<String,ServiceObject>();
- final TagProfile tagProfile = new TagProfile(20);
-
- Isolate._empty(ServiceObjectOwner owner) : super._empty(owner) {
- assert(owner is VM);
- }
-
- /// Creates a link to [id] relative to [this].
- @reflectable String relativeLink(String id) => '/${this.id}/$id';
-
- static const TAG_ROOT_ID = 'code/tag-0';
-
- /// Returns the Code object for the root tag.
- Code tagRoot() {
- // TODO(turnidge): Use get() here instead?
- return _cache[TAG_ROOT_ID];
- }
-
- void processProfile(ServiceMap profile) {
- assert(profile.type == 'Profile');
- var codeTable = new List<Code>();
- var codeRegions = profile['codes'];
- for (var codeRegion in codeRegions) {
- Code code = codeRegion['code'];
- assert(code != null);
- codeTable.add(code);
- }
- _resetProfileData();
- _updateProfileData(profile, codeTable);
- var exclusiveTrie = profile['exclusive_trie'];
- if (exclusiveTrie != null) {
- profileTrieRoot = _processProfileTrie(exclusiveTrie, codeTable);
- }
- }
-
- void _resetProfileData() {
- _cache.values.forEach((value) {
- if (value is Code) {
- Code code = value;
- code.resetProfileData();
- }
- });
- }
-
- void _updateProfileData(ServiceMap profile, List<Code> codeTable) {
- var codeRegions = profile['codes'];
- var sampleCount = profile['samples'];
- for (var codeRegion in codeRegions) {
- Code code = codeRegion['code'];
- code.updateProfileData(codeRegion, codeTable, sampleCount);
- }
- }
-
- /// Fetches and builds the class hierarchy for this isolate. Returns the
- /// Object class object.
- Future<Class> getClassHierarchy() {
- return get('classes').then(_loadClasses).then(_buildClassHierarchy);
- }
-
- /// Given the class list, loads each class.
- Future<List<Class>> _loadClasses(ServiceMap classList) {
- assert(classList.type == 'ClassList');
- var futureClasses = [];
- for (var cls in classList['members']) {
- // Skip over non-class classes.
- if (cls is Class) {
- futureClasses.add(cls.load());
- }
- }
- return Future.wait(futureClasses);
- }
-
- /// Builds the class hierarchy and returns the Object class.
- Future<Class> _buildClassHierarchy(List<Class> classes) {
- rootClasses.clear();
- objectClass = null;
- for (var cls in classes) {
- if (cls.superclass == null) {
- rootClasses.add(cls);
- }
- if ((cls.vmName == 'Object') && (cls.isPatch == false)) {
- objectClass = cls;
- }
- }
- assert(objectClass != null);
- return new Future.value(objectClass);
- }
-
- ServiceObject getFromMap(ObservableMap map) {
- if (map == null) {
- return null;
- }
- String id = map['id'];
- var obj = _cache[id];
- if (obj != null) {
- // Consider calling update when map is not a reference.
- return obj;
- }
- // Build the object from the map directly.
- obj = new ServiceObject._fromMap(this, map);
- if (obj != null && obj.canCache) {
- _cache[id] = obj;
- }
- return obj;
- }
-
- Future<ServiceObject> get(String id) {
- // Do not allow null ids or empty ids.
- assert(id != null && id != '');
- var obj = _cache[id];
- if (obj != null) {
- return obj.reload();
- }
- // Cache miss. Get the object from the vm directly.
- return vm.getAsMap(relativeLink(id)).then((ObservableMap map) {
- var obj = new ServiceObject._fromMap(this, map);
- if (obj.canCache) {
- _cache.putIfAbsent(id, () => obj);
- }
- return obj;
- });
- }
-
- @observable Class objectClass;
- @observable final rootClasses = new ObservableList<Class>();
-
- @observable Library rootLib;
- @observable ObservableList<Library> libraries =
- new ObservableList<Library>();
- @observable ObservableMap topFrame;
-
- @observable String name;
- @observable String vmName;
- @observable String mainPort;
- @observable ServiceFunction entry;
-
- @observable final Map<String, double> timers =
- toObservable(new Map<String, double>());
-
- final HeapSpace newSpace = new HeapSpace();
- final HeapSpace oldSpace = new HeapSpace();
-
- @observable String fileAndLine;
-
- @observable DartError error;
-
- void updateHeapsFromMap(ObservableMap map) {
- newSpace.update(map['new']);
- oldSpace.update(map['old']);
- }
-
- void _update(ObservableMap map, bool mapIsRef) {
- mainPort = map['mainPort'];
- name = map['name'];
- vmName = map['name'];
- if (mapIsRef) {
- return;
- }
- _loaded = true;
- loading = false;
-
- reloadBreakpoints();
- _upgradeCollection(map, isolate);
- if (map['rootLib'] == null ||
- map['timers'] == null ||
- map['heaps'] == null) {
- Logger.root.severe("Malformed 'Isolate' response: $map");
- return;
- }
- rootLib = map['rootLib'];
- if (map['entry'] != null) {
- entry = map['entry'];
- }
- if (map['topFrame'] != null) {
- topFrame = map['topFrame'];
- } else {
- topFrame = null ;
- }
-
- var countersMap = map['tagCounters'];
- if (countersMap != null) {
- var names = countersMap['names'];
- var counts = countersMap['counters'];
- assert(names.length == counts.length);
- var sum = 0;
- for (var i = 0; i < counts.length; i++) {
- sum += counts[i];
- }
- // TODO: Why does this not work without this?
- counters = toObservable({});
- if (sum == 0) {
- for (var i = 0; i < names.length; i++) {
- counters[names[i]] = '0.0%';
- }
- } else {
- for (var i = 0; i < names.length; i++) {
- counters[names[i]] =
- (counts[i] / sum * 100.0).toStringAsFixed(2) + '%';
- }
- }
- }
- var timerMap = {};
- map['timers'].forEach((timer) {
- timerMap[timer['name']] = timer['time'];
- });
- timers['total'] = timerMap['time_total_runtime'];
- timers['compile'] = timerMap['time_compilation'];
- timers['gc'] = 0.0; // TODO(turnidge): Export this from VM.
- timers['init'] = (timerMap['time_script_loading'] +
- timerMap['time_creating_snapshot'] +
- timerMap['time_isolate_initialization'] +
- timerMap['time_bootstrap']);
- timers['dart'] = timerMap['time_dart_execution'];
-
- updateHeapsFromMap(map['heaps']);
-
- List features = map['features'];
- if (features != null) {
- for (var feature in features) {
- if (feature == 'io') {
- ioEnabled = true;
- }
- }
- }
- // Isolate status
- pauseEvent = map['pauseEvent'];
- running = (!_isPaused && map['topFrame'] != null);
- idle = (!_isPaused && map['topFrame'] == null);
- error = map['error'];
-
- libraries.clear();
- libraries.addAll(map['libraries']);
- libraries.sort(ServiceObject.LexicalSortName);
- }
-
- Future<TagProfile> updateTagProfile() {
- return vm.getAsMap(relativeLink('profile/tag')).then((ObservableMap m) {
- var seconds = new DateTime.now().millisecondsSinceEpoch / 1000.0;
- tagProfile._processTagProfile(seconds, m);
- return tagProfile;
- });
- }
-
- @reflectable CodeTrieNode profileTrieRoot;
- // The profile trie is serialized as a list of integers. Each node
- // is recreated by consuming some portion of the list. The format is as
- // follows:
- // [0] index into codeTable of code object.
- // [1] tick count (number of times this stack frame occured).
- // [2] child node count
- // Reading the trie is done by recursively reading the tree depth-first
- // pre-order.
- CodeTrieNode _processProfileTrie(List<int> data, List<Code> codeTable) {
- // Setup state shared across calls to _readTrieNode.
- _trieDataCursor = 0;
- _trieData = data;
- if (_trieData == null) {
- return null;
- }
- if (_trieData.length < 3) {
- // Not enough integers for 1 node.
- return null;
- }
- // Read the tree, returns the root node.
- return _readTrieNode(codeTable);
- }
- int _trieDataCursor;
- List<int> _trieData;
- CodeTrieNode _readTrieNode(List<Code> codeTable) {
- // Read index into code table.
- var index = _trieData[_trieDataCursor++];
- // Lookup code object.
- var code = codeTable[index];
- // Frame counter.
- var count = _trieData[_trieDataCursor++];
- // Create node.
- var node = new CodeTrieNode(code, count);
- // Number of children.
- var children = _trieData[_trieDataCursor++];
- // Recursively read child nodes.
- for (var i = 0; i < children; i++) {
- var child = _readTrieNode(codeTable);
- node.children.add(child);
- node.summedChildCount += child.count;
- }
- return node;
- }
-
- ServiceMap breakpoints;
-
- void _removeBreakpoint(ServiceMap bpt) {
- var script = bpt['location']['script'];
- var tokenPos = bpt['location']['tokenPos'];
- assert(tokenPos != null);
- if (script.loaded) {
- var line = script.tokenToLine(tokenPos);
- assert(line != null);
- assert(script.lines[line - 1].bpt == bpt);
- script.lines[line - 1].bpt = null;
- }
- }
-
- void _addBreakpoint(ServiceMap bpt) {
- var script = bpt['location']['script'];
- var tokenPos = bpt['location']['tokenPos'];
- assert(tokenPos != null);
- if (script.loaded) {
- var line = script.tokenToLine(tokenPos);
- assert(line != null);
- assert(script.lines[line - 1].bpt == null);
- script.lines[line - 1].bpt = bpt;
- } else {
- // Load the script and then plop in the breakpoint.
- script.load().then((_) {
- _addBreakpoint(bpt);
- });
- }
- }
-
- void _updateBreakpoints(ServiceMap newBreakpoints) {
- // Remove all of the old breakpoints from the Script lines.
- if (breakpoints != null) {
- for (var bpt in breakpoints['breakpoints']) {
- _removeBreakpoint(bpt);
- }
- }
- // Add all of the new breakpoints to the Script lines.
- for (var bpt in newBreakpoints['breakpoints']) {
- _addBreakpoint(bpt);
- }
- breakpoints = newBreakpoints;
- }
-
- Future<ServiceObject> _inProgressReloadBpts;
-
- Future reloadBreakpoints() {
- // TODO(turnidge): Can reusing the Future here ever cause us to
- // get stale breakpoints?
- if (_inProgressReloadBpts == null) {
- _inProgressReloadBpts =
- get('debug/breakpoints').then((newBpts) {
- _updateBreakpoints(newBpts);
- }).whenComplete(() {
- _inProgressReloadBpts = null;
- });
- }
- return _inProgressReloadBpts;
- }
-
- Future<ServiceObject> setBreakpoint(Script script, int line) {
- return get(script.id + "/setBreakpoint?line=${line}").then((result) {
- if (result is DartError) {
- // Unable to set a breakpoint at desired line.
- script.lines[line - 1].possibleBpt = false;
- }
- return reloadBreakpoints();
- });
- }
-
- Future clearBreakpoint(ServiceMap bpt) {
- return get('${bpt.id}/clear').then((result) {
- if (result is DartError) {
- // TODO(turnidge): Handle this more gracefully.
- Logger.root.severe(result.message);
- }
- if (pauseEvent != null &&
- pauseEvent.breakpoint != null &&
- (pauseEvent.breakpoint['id'] == bpt['id'])) {
- return isolate.reload();
- } else {
- return reloadBreakpoints();
- }
- });
- }
-
- Future pause() {
- return get("debug/pause").then((result) {
- if (result is DartError) {
- // TODO(turnidge): Handle this more gracefully.
- Logger.root.severe(result.message);
- }
- return isolate.reload();
- });
- }
-
- Future resume() {
- return get("debug/resume").then((result) {
- if (result is DartError) {
- // TODO(turnidge): Handle this more gracefully.
- Logger.root.severe(result.message);
- }
- return isolate.reload();
- });
- }
-
- Future stepInto() {
- return get("debug/resume?step=into").then((result) {
- if (result is DartError) {
- // TODO(turnidge): Handle this more gracefully.
- Logger.root.severe(result.message);
- }
- return isolate.reload();
- });
- }
-
- Future stepOver() {
- return get("debug/resume?step=over").then((result) {
- if (result is DartError) {
- // TODO(turnidge): Handle this more gracefully.
- Logger.root.severe(result.message);
- }
- return isolate.reload();
- });
- }
-
- Future stepOut() {
- return get("debug/resume?step=out").then((result) {
- if (result is DartError) {
- // TODO(turnidge): Handle this more gracefully.
- Logger.root.severe(result.message);
- }
- return isolate.reload();
- });
- }
-
- final ObservableMap<String, ServiceMetric> dartMetrics =
- new ObservableMap<String, ServiceMetric>();
-
- final ObservableMap<String, ServiceMetric> vmMetrics =
- new ObservableMap<String, ServiceMetric>();
-
- Future<ObservableMap<String, ServiceMetric>> _refreshMetrics(
- String id,
- ObservableMap<String, ServiceMetric> metricsMap) {
- return get(id).then((result) {
- if (result is DartError) {
- // TODO(turnidge): Handle this more gracefully.
- Logger.root.severe(result.message);
- return null;
- }
- // Clear metrics map.
- metricsMap.clear();
- // Repopulate metrics map.
- var members = result['members'];
- for (var metric in members) {
- metricsMap[metric.id] = metric;
- }
- return metricsMap;
- });
- }
-
- Future<ObservableMap<String, ServiceMetric>> refreshDartMetrics() {
- return _refreshMetrics('metrics', dartMetrics);
- }
-
- Future<ObservableMap<String, ServiceMetric>> refreshVMMetrics() {
- return _refreshMetrics('metrics/vm', vmMetrics);
- }
-
- Future refreshMetrics() {
- return refreshDartMetrics().then((_) => refreshVMMetrics());
- }
-
- String toString() => "Isolate($_id)";
-}
-
-/// A [ServiceObject] which implements [ObservableMap].
-class ServiceMap extends ServiceObject implements ObservableMap {
- final ObservableMap _map = new ObservableMap();
- static String objectIdRingPrefix = 'objects/';
-
- bool get canCache {
- return (_type == 'Class' ||
- _type == 'Function' ||
- _type == 'Field') &&
- !_id.startsWith(objectIdRingPrefix);
- }
- bool get immutable => false;
-
- ServiceMap._empty(ServiceObjectOwner owner) : super._empty(owner);
-
- void _upgradeValues() {
- assert(owner != null);
- _upgradeCollection(_map, owner);
- }
-
- void _update(ObservableMap map, bool mapIsRef) {
- _loaded = !mapIsRef;
-
- // TODO(turnidge): Currently _map.clear() prevents us from
- // upgrading an already upgraded submap. Is clearing really the
- // right thing to do here?
- _map.clear();
- _map.addAll(map);
-
- name = _map['name'];
- vmName = (_map.containsKey('vmName') ? _map['vmName'] : name);
- _upgradeValues();
- }
-
- // Forward Map interface calls.
- void addAll(Map other) => _map.addAll(other);
- void clear() => _map.clear();
- bool containsValue(v) => _map.containsValue(v);
- bool containsKey(k) => _map.containsKey(k);
- void forEach(Function f) => _map.forEach(f);
- putIfAbsent(key, Function ifAbsent) => _map.putIfAbsent(key, ifAbsent);
- void remove(key) => _map.remove(key);
- operator [](k) => _map[k];
- operator []=(k, v) => _map[k] = v;
- bool get isEmpty => _map.isEmpty;
- bool get isNotEmpty => _map.isNotEmpty;
- Iterable get keys => _map.keys;
- Iterable get values => _map.values;
- int get length => _map.length;
-
- // Forward ChangeNotifier interface calls.
- bool deliverChanges() => _map.deliverChanges();
- void notifyChange(ChangeRecord record) => _map.notifyChange(record);
- notifyPropertyChange(Symbol field, Object oldValue, Object newValue) =>
- _map.notifyPropertyChange(field, oldValue, newValue);
- void observed() => _map.observed();
- void unobserved() => _map.unobserved();
- Stream<List<ChangeRecord>> get changes => _map.changes;
- bool get hasObservers => _map.hasObservers;
-
- String toString() => "ServiceMap($_map)";
-}
-
-/// A [DartError] is peered to a Dart Error object.
-class DartError extends ServiceObject {
- DartError._empty(ServiceObject owner) : super._empty(owner);
-
- @observable String kind;
- @observable String message;
- @observable Instance exception;
- @observable Instance stacktrace;
-
- void _update(ObservableMap map, bool mapIsRef) {
- kind = map['kind'];
- message = map['message'];
- exception = new ServiceObject._fromMap(owner, map['exception']);
- stacktrace = new ServiceObject._fromMap(owner, map['stacktrace']);
- name = 'DartError $kind';
- vmName = name;
- }
-
- String toString() => 'DartError($message)';
-}
-
-/// A [ServiceError] is an error that was triggered in the service
-/// server or client. Errors are prorammer mistakes that could have
-/// been prevented, for example, requesting a non-existant path over the
-/// service.
-class ServiceError extends ServiceObject {
- ServiceError._empty(ServiceObjectOwner owner) : super._empty(owner);
-
- @observable String kind;
- @observable String message;
-
- void _update(ObservableMap map, bool mapIsRef) {
- _loaded = true;
- kind = map['kind'];
- message = map['message'];
- name = 'ServiceError $kind';
- vmName = name;
- }
-
- String toString() => 'ServiceError($message)';
-}
-
-/// A [ServiceException] is an exception that was triggered in the service
-/// server or client. Exceptions are events that should be handled,
-/// for example, an isolate went away or the connection to the VM was lost.
-class ServiceException extends ServiceObject {
- ServiceException._empty(ServiceObject owner) : super._empty(owner);
-
- @observable String kind;
- @observable String message;
- @observable dynamic response;
-
- void _update(ObservableMap map, bool mapIsRef) {
- kind = map['kind'];
- message = map['message'];
- response = map['response'];
- name = 'ServiceException $kind';
- vmName = name;
- }
-
- String toString() => 'ServiceException($message)';
-}
-
-/// A [ServiceEvent] is an asynchronous event notification from the vm.
-class ServiceEvent extends ServiceObject {
- ServiceEvent._empty(ServiceObjectOwner owner) : super._empty(owner);
-
- ServiceEvent.vmDisconencted() : super._empty(null) {
- eventType = 'VMDisconnected';
- }
-
- @observable String eventType;
- @observable ServiceMap breakpoint;
- @observable ServiceMap exception;
- @observable ByteData data;
- @observable int count;
-
- void _update(ObservableMap map, bool mapIsRef) {
- _loaded = true;
- _upgradeCollection(map, owner);
- eventType = map['eventType'];
- name = 'ServiceEvent $eventType';
- vmName = name;
- if (map['breakpoint'] != null) {
- breakpoint = map['breakpoint'];
- }
- if (map['exception'] != null) {
- exception = map['exception'];
- }
- if (map['_data'] != null) {
- data = map['_data'];
- }
- if (map['count'] != null) {
- count = map['count'];
- }
- }
-
- String toString() {
- return 'ServiceEvent of type $eventType with '
- '${data == null ? 0 : data.lengthInBytes} bytes of binary data';
- }
-}
-
-class Library extends ServiceObject with Coverage {
- @observable String url;
- @reflectable final imports = new ObservableList<Library>();
- @reflectable final scripts = new ObservableList<Script>();
- @reflectable final classes = new ObservableList<Class>();
- @reflectable final variables = new ObservableList<Field>();
- @reflectable final functions = new ObservableList<ServiceFunction>();
-
- bool get canCache => true;
- bool get immutable => false;
-
- Library._empty(ServiceObjectOwner owner) : super._empty(owner);
-
- void _update(ObservableMap map, bool mapIsRef) {
- url = map['url'];
- var shortUrl = url;
- if (url.startsWith('file://') ||
- url.startsWith('http://')) {
- shortUrl = url.substring(url.lastIndexOf('/') + 1);
- }
- name = map['name'];
- if (name.isEmpty) {
- // When there is no name for a library, use the shortUrl.
- name = shortUrl;
- }
- vmName = (map.containsKey('vmName') ? map['vmName'] : name);
- if (mapIsRef) {
- return;
- }
- _loaded = true;
- _upgradeCollection(map, isolate);
- imports.clear();
- imports.addAll(removeDuplicatesAndSortLexical(map['imports']));
- scripts.clear();
- scripts.addAll(removeDuplicatesAndSortLexical(map['scripts']));
- classes.clear();
- classes.addAll(map['classes']);
- classes.sort(ServiceObject.LexicalSortName);
- variables.clear();
- variables.addAll(map['variables']);
- variables.sort(ServiceObject.LexicalSortName);
- functions.clear();
- functions.addAll(map['functions']);
- functions.sort(ServiceObject.LexicalSortName);
- }
-
- String toString() => "Library($url)";
-}
-
-class AllocationCount extends Observable {
- @observable int instances = 0;
- @observable int bytes = 0;
-
- void reset() {
- instances = 0;
- bytes = 0;
- }
-
- bool get empty => (instances == 0) && (bytes == 0);
-}
-
-class Allocations {
- // Indexes into VM provided array. (see vm/class_table.h).
- static const ALLOCATED_BEFORE_GC = 0;
- static const ALLOCATED_BEFORE_GC_SIZE = 1;
- static const LIVE_AFTER_GC = 2;
- static const LIVE_AFTER_GC_SIZE = 3;
- static const ALLOCATED_SINCE_GC = 4;
- static const ALLOCATED_SINCE_GC_SIZE = 5;
- static const ACCUMULATED = 6;
- static const ACCUMULATED_SIZE = 7;
-
- final AllocationCount accumulated = new AllocationCount();
- final AllocationCount current = new AllocationCount();
-
- void update(List stats) {
- accumulated.instances = stats[ACCUMULATED];
- accumulated.bytes = stats[ACCUMULATED_SIZE];
- current.instances = stats[LIVE_AFTER_GC] + stats[ALLOCATED_SINCE_GC];
- current.bytes = stats[LIVE_AFTER_GC_SIZE] + stats[ALLOCATED_SINCE_GC_SIZE];
- }
-
- bool get empty => accumulated.empty && current.empty;
-}
-
-class Class extends ServiceObject with Coverage {
- @observable Library library;
- @observable Script script;
-
- @observable bool isAbstract;
- @observable bool isConst;
- @observable bool isFinalized;
- @observable bool isPatch;
- @observable bool isImplemented;
-
- @observable int tokenPos;
- @observable int endTokenPos;
-
- @observable ServiceMap error;
- @observable int vmCid;
-
- final Allocations newSpace = new Allocations();
- final Allocations oldSpace = new Allocations();
- final AllocationCount promotedByLastNewGC = new AllocationCount();
-
- bool get hasNoAllocations => newSpace.empty && oldSpace.empty;
-
- @reflectable final fields = new ObservableList<Field>();
- @reflectable final functions = new ObservableList<ServiceFunction>();
-
- @observable Class superclass;
- @reflectable final interfaces = new ObservableList<Class>();
- @reflectable final subclasses = new ObservableList<Class>();
-
- bool get canCache => true;
- bool get immutable => false;
-
- Class._empty(ServiceObjectOwner owner) : super._empty(owner);
-
- void _update(ObservableMap map, bool mapIsRef) {
- name = map['name'];
- vmName = (map.containsKey('vmName') ? map['vmName'] : name);
- var idPrefix = "classes/";
- assert(id.startsWith(idPrefix));
- vmCid = int.parse(id.substring(idPrefix.length));
-
- if (mapIsRef) {
- return;
- }
-
- // We are fully loaded.
- _loaded = true;
-
- // Extract full properties.
- _upgradeCollection(map, isolate);
-
- // Some builtin classes aren't associated with a library.
- if (map['library'] is Library) {
- library = map['library'];
- } else {
- library = null;
- }
-
- script = map['script'];
-
- isAbstract = map['abstract'];
- isConst = map['const'];
- isFinalized = map['finalized'];
- isPatch = map['patch'];
- isImplemented = map['implemented'];
-
- tokenPos = map['tokenPos'];
- endTokenPos = map['endTokenPos'];
-
- subclasses.clear();
- subclasses.addAll(map['subclasses']);
- subclasses.sort(ServiceObject.LexicalSortName);
-
- fields.clear();
- fields.addAll(map['fields']);
- fields.sort(ServiceObject.LexicalSortName);
-
- functions.clear();
- functions.addAll(map['functions']);
- functions.sort(ServiceObject.LexicalSortName);
-
- superclass = map['super'];
- // Work-around Object not tracking its subclasses in the VM.
- if (superclass != null && superclass.name == "Object") {
- superclass._addSubclass(this);
- }
- error = map['error'];
-
- var allocationStats = map['allocationStats'];
- if (allocationStats != null) {
- newSpace.update(allocationStats['new']);
- oldSpace.update(allocationStats['old']);
- promotedByLastNewGC.instances = allocationStats['promotedInstances'];
- promotedByLastNewGC.bytes = allocationStats['promotedBytes'];
- }
- }
-
- void _addSubclass(Class subclass) {
- if (subclasses.contains(subclass)) {
- return;
- }
- subclasses.add(subclass);
- subclasses.sort(ServiceObject.LexicalSortName);
- }
-
- Future<ServiceObject> get(String command) {
- return isolate.get(id + "/$command");
- }
-
- String toString() => 'Class($vmName)';
-}
-
-class Instance extends ServiceObject {
- @observable Class clazz;
- @observable int size;
- @observable String valueAsString; // If primitive.
- @observable bool valueAsStringIsTruncated;
- @observable ServiceFunction closureFunc; // If a closure.
- @observable Context closureCtxt; // If a closure.
- @observable String name; // If a Type.
- @observable int length; // If a List.
-
- @observable var typeClass;
- @observable var fields;
- @observable var nativeFields;
- @observable var elements;
- @observable var userName;
- @observable var referent; // If a MirrorReference.
- @observable Instance key; // If a WeakProperty.
- @observable Instance value; // If a WeakProperty.
-
- bool get isClosure => closureFunc != null;
-
- Instance._empty(ServiceObjectOwner owner) : super._empty(owner);
-
- void _update(ObservableMap map, bool mapIsRef) {
- // Extract full properties.
- _upgradeCollection(map, isolate);
-
- clazz = map['class'];
- size = map['size'];
- valueAsString = map['valueAsString'];
- // Coerce absence to false.
- valueAsStringIsTruncated = map['valueAsStringIsTruncated'] == true;
- closureFunc = map['closureFunc'];
- closureCtxt = map['closureCtxt'];
- name = map['name'];
- length = map['length'];
-
- if (mapIsRef) {
- return;
- }
-
- nativeFields = map['nativeFields'];
- fields = map['fields'];
- elements = map['elements'];
- typeClass = map['type_class'];
- userName = map['user_name'];
- referent = map['referent'];
- key = map['key'];
- value = map['value'];
-
- // We are fully loaded.
- _loaded = true;
- }
-
- String get shortName => valueAsString != null ? valueAsString : 'a ${clazz.name}';
-
- String toString() => 'Instance($shortName)';
-}
-
-
-class Context extends ServiceObject {
- @observable Class clazz;
- @observable int size;
-
- @observable var parentContext;
- @observable int length;
- @observable var variables;
-
- Context._empty(ServiceObjectOwner owner) : super._empty(owner);
-
- void _update(ObservableMap map, bool mapIsRef) {
- // Extract full properties.
- _upgradeCollection(map, isolate);
-
- size = map['size'];
- length = map['length'];
- parentContext = map['parent'];
-
- if (mapIsRef) {
- return;
- }
-
- clazz = map['class'];
- variables = map['variables'];
-
- // We are fully loaded.
- _loaded = true;
- }
-
- String toString() => 'Context($length)';
-}
-
-
-// TODO(koda): Sync this with VM.
-class FunctionKind {
- final String _strValue;
- FunctionKind._internal(this._strValue);
- toString() => _strValue;
- bool isFake() => [kCollected, kNative, kTag, kReused].contains(this);
-
- static FunctionKind fromJSON(String value) {
- switch(value) {
- case 'kRegularFunction': return kRegularFunction;
- case 'kClosureFunction': return kClosureFunction;
- case 'kGetterFunction': return kGetterFunction;
- case 'kSetterFunction': return kSetterFunction;
- case 'kConstructor': return kConstructor;
- case 'kImplicitGetter': return kImplicitGetterFunction;
- case 'kImplicitSetter': return kImplicitSetterFunction;
- case 'kStaticInitializer': return kStaticInitializer;
- case 'kMethodExtractor': return kMethodExtractor;
- case 'kNoSuchMethodDispatcher': return kNoSuchMethodDispatcher;
- case 'kInvokeFieldDispatcher': return kInvokeFieldDispatcher;
- case 'Collected': return kCollected;
- case 'Native': return kNative;
- case 'Tag': return kTag;
- case 'Reused': return kReused;
- }
- return kUNKNOWN;
- }
-
- static FunctionKind kRegularFunction = new FunctionKind._internal('function');
- static FunctionKind kClosureFunction = new FunctionKind._internal('closure function');
- static FunctionKind kGetterFunction = new FunctionKind._internal('getter function');
- static FunctionKind kSetterFunction = new FunctionKind._internal('setter function');
- static FunctionKind kConstructor = new FunctionKind._internal('constructor');
- static FunctionKind kImplicitGetterFunction = new FunctionKind._internal('implicit getter function');
- static FunctionKind kImplicitSetterFunction = new FunctionKind._internal('implicit setter function');
- static FunctionKind kStaticInitializer = new FunctionKind._internal('static initializer');
- static FunctionKind kMethodExtractor = new FunctionKind._internal('method extractor');
- static FunctionKind kNoSuchMethodDispatcher = new FunctionKind._internal('noSuchMethod dispatcher');
- static FunctionKind kInvokeFieldDispatcher = new FunctionKind._internal('invoke field dispatcher');
- static FunctionKind kCollected = new FunctionKind._internal('Collected');
- static FunctionKind kNative = new FunctionKind._internal('Native');
- static FunctionKind kTag = new FunctionKind._internal('Tag');
- static FunctionKind kReused = new FunctionKind._internal('Reused');
- static FunctionKind kUNKNOWN = new FunctionKind._internal('UNKNOWN');
-}
-
-class ServiceFunction extends ServiceObject with Coverage {
- @observable Class owningClass;
- @observable Library owningLibrary;
- @observable bool isStatic;
- @observable bool isConst;
- @observable ServiceFunction parent;
- @observable Script script;
- @observable int tokenPos;
- @observable int endTokenPos;
- @observable Code code;
- @observable Code unoptimizedCode;
- @observable bool isOptimizable;
- @observable bool isInlinable;
- @observable FunctionKind kind;
- @observable int deoptimizations;
- @observable String qualifiedName;
- @observable int usageCounter;
- @observable bool isDart;
-
- ServiceFunction._empty(ServiceObject owner) : super._empty(owner);
-
- void _update(ObservableMap map, bool mapIsRef) {
- name = map['name'];
- vmName = (map.containsKey('vmName') ? map['vmName'] : name);
-
- _upgradeCollection(map, isolate);
-
- owningClass = map.containsKey('owningClass') ? map['owningClass'] : null;
- owningLibrary = map.containsKey('owningLibrary') ? map['owningLibrary'] : null;
- kind = FunctionKind.fromJSON(map['kind']);
- isDart = !kind.isFake();
-
- if (mapIsRef) { return; }
-
- isStatic = map['static'];
- isConst = map['const'];
- parent = map['parent'];
- script = map['script'];
- tokenPos = map['tokenPos'];
- endTokenPos = map['endTokenPos'];
- code = _convertNull(map['code']);
- unoptimizedCode = _convertNull(map['unoptimizedCode']);
- isOptimizable = map['optimizable'];
- isInlinable = map['inlinable'];
- deoptimizations = map['deoptimizations'];
- usageCounter = map['usageCounter'];
-
- if (parent == null) {
- qualifiedName = (owningClass != null) ?
- "${owningClass.name}.${name}" :
- name;
- } else {
- qualifiedName = "${parent.qualifiedName}.${name}";
- }
-
- }
-}
-
-
-class Field extends ServiceObject {
- @observable var /* Library or Class */ owner;
- @observable Instance declaredType;
- @observable bool isStatic;
- @observable bool isFinal;
- @observable bool isConst;
- @observable Instance value;
- @observable String name;
- @observable String vmName;
-
- @observable bool guardNullable;
- @observable String guardClass;
- @observable String guardLength;
- @observable Script script;
- @observable int tokenPos;
-
- Field._empty(ServiceObjectOwner owner) : super._empty(owner);
-
- void _update(ObservableMap map, bool mapIsRef) {
- // Extract full properties.
- _upgradeCollection(map, isolate);
-
- name = map['name'];
- vmName = (map.containsKey('vmName') ? map['vmName'] : name);
- owner = map['owner'];
- declaredType = map['declaredType'];
- isStatic = map['static'];
- isFinal = map['final'];
- isConst = map['const'];
- value = map['value'];
-
- if (mapIsRef) {
- return;
- }
-
- guardNullable = map['guardNullable'];
- guardClass = map['guardClass'];
- guardLength = map['guardLength'];
- script = map['script'];
- tokenPos = map['tokenPos'];
-
- _loaded = true;
- }
-
- String toString() => 'Field(${owner.name}.$name)';
-}
-
-
-class ScriptLine extends Observable {
- final Script script;
- final int line;
- final String text;
- @observable int hits;
- @observable ServiceMap bpt;
- @observable bool possibleBpt = true;
-
- static bool _isTrivialToken(String token) {
- if (token == 'else') {
- return true;
- }
- for (var c in token.split('')) {
- switch (c) {
- case '{':
- case '}':
- case '(':
- case ')':
- case ';':
- break;
- default:
- return false;
- }
- }
- return true;
- }
-
- static bool _isTrivialLine(String text) {
- var wsTokens = text.split(new RegExp(r"(\s)+"));
- for (var wsToken in wsTokens) {
- var tokens = wsToken.split(new RegExp(r"(\b)"));
- for (var token in tokens) {
- if (!_isTrivialToken(token)) {
- return false;
- }
- }
- }
- return true;
- }
-
- ScriptLine(this.script, this.line, this.text) {
- possibleBpt = !_isTrivialLine(text);
-
- // TODO(turnidge): This is not so efficient. Consider improving.
- for (var bpt in this.script.isolate.breakpoints['breakpoints']) {
- var bptScript = bpt['location']['script'];
- var bptTokenPos = bpt['location']['tokenPos'];
- if (bptScript == this.script &&
- bptScript.tokenToLine(bptTokenPos) == line) {
- this.bpt = bpt;
- }
- }
- }
-}
-
-class Script extends ServiceObject with Coverage {
- final lines = new ObservableList<ScriptLine>();
- final _hits = new Map<int, int>();
- @observable String kind;
- @observable int firstTokenPos;
- @observable int lastTokenPos;
- @observable Library owningLibrary;
- bool get canCache => true;
- bool get immutable => true;
-
- String _shortUrl;
- String _url;
-
- Script._empty(ServiceObjectOwner owner) : super._empty(owner);
-
- ScriptLine getLine(int line) {
- assert(line >= 1);
- return lines[line - 1];
- }
-
- /// This function maps a token position to a line number.
- int tokenToLine(int token) => _tokenToLine[token];
- Map _tokenToLine = {};
-
- /// This function maps a token position to a column number.
- int tokenToCol(int token) => _tokenToCol[token];
- Map _tokenToCol = {};
-
- void _update(ObservableMap map, bool mapIsRef) {
- _upgradeCollection(map, isolate);
- kind = map['kind'];
- _url = map['name'];
- _shortUrl = _url.substring(_url.lastIndexOf('/') + 1);
- name = _shortUrl;
- vmName = _url;
- if (mapIsRef) {
- return;
- }
- _processSource(map['source']);
- _parseTokenPosTable(map['tokenPosTable']);
- owningLibrary = map['owningLibrary'];
- }
-
- void _parseTokenPosTable(List<List<int>> table) {
- if (table == null) {
- return;
- }
- _tokenToLine.clear();
- _tokenToCol.clear();
- firstTokenPos = null;
- lastTokenPos = null;
- var lineSet = new Set();
-
- for (var line in table) {
- // Each entry begins with a line number...
- var lineNumber = line[0];
- lineSet.add(lineNumber);
- for (var pos = 1; pos < line.length; pos += 2) {
- // ...and is followed by (token offset, col number) pairs.
- var tokenOffset = line[pos];
- var colNumber = line[pos+1];
- if (firstTokenPos == null) {
- // Mark first token position.
- firstTokenPos = tokenOffset;
- lastTokenPos = tokenOffset;
- } else {
- // Keep track of max and min token positions.
- firstTokenPos = (firstTokenPos <= tokenOffset) ?
- firstTokenPos : tokenOffset;
- lastTokenPos = (lastTokenPos >= tokenOffset) ?
- lastTokenPos : tokenOffset;
- }
- _tokenToLine[tokenOffset] = lineNumber;
- _tokenToCol[tokenOffset] = colNumber;
- }
- }
-
- for (var line in lines) {
- // Remove possible breakpoints on lines with no tokens.
- if (!lineSet.contains(line.line)) {
- line.possibleBpt = false;
- }
- }
- }
-
- void _processHits(List scriptHits) {
- // Update hits table.
- for (var i = 0; i < scriptHits.length; i += 2) {
- var line = scriptHits[i];
- var hit = scriptHits[i + 1]; // hit status.
- assert(line >= 1); // Lines start at 1.
- var oldHits = _hits[line];
- if (oldHits != null) {
- hit += oldHits;
- }
- _hits[line] = hit;
- }
- _applyHitsToLines();
- }
-
- void _processSource(String source) {
- // Preemptyively mark that this is not loaded.
- _loaded = false;
- if (source == null) {
- return;
- }
- var sourceLines = source.split('\n');
- if (sourceLines.length == 0) {
- return;
- }
- // We have the source to the script. This is now loaded.
- _loaded = true;
- lines.clear();
- Logger.root.info('Adding ${sourceLines.length} source lines for ${_url}');
- for (var i = 0; i < sourceLines.length; i++) {
- lines.add(new ScriptLine(this, i + 1, sourceLines[i]));
- }
- _applyHitsToLines();
- }
-
- void _applyHitsToLines() {
- for (var line in lines) {
- var hits = _hits[line.line];
- line.hits = hits;
- }
- }
-}
-
-class CodeTick {
- final int address;
- final int exclusiveTicks;
- final int inclusiveTicks;
- CodeTick(this.address, this.exclusiveTicks, this.inclusiveTicks);
-}
-
-class PcDescriptor extends Observable {
- final int address;
- @reflectable final int deoptId;
- @reflectable final int tokenPos;
- @reflectable final int tryIndex;
- @reflectable final String kind;
- @observable Script script;
- @observable String formattedLine;
- PcDescriptor(this.address, this.deoptId, this.tokenPos, this.tryIndex,
- this.kind);
-
- @reflectable String formattedDeoptId() {
- if (deoptId == -1) {
- return 'N/A';
- }
- return deoptId.toString();
- }
-
- @reflectable String formattedTokenPos() {
- if (tokenPos == -1) {
- return '';
- }
- return tokenPos.toString();
- }
-
- void processScript(Script script) {
- this.script = null;
- if (tokenPos == -1) {
- return;
- }
- var line = script.tokenToLine(tokenPos);
- if (line == null) {
- return;
- }
- this.script = script;
- var scriptLine = script.getLine(line);
- formattedLine = scriptLine.text;
- }
-}
-
-class PcDescriptors extends ServiceObject {
- @observable Class clazz;
- @observable int size;
- bool get canCache => false;
- bool get immutable => true;
- @reflectable final List<PcDescriptor> descriptors =
- new ObservableList<PcDescriptor>();
-
- PcDescriptors._empty(ServiceObjectOwner owner) : super._empty(owner) {
- print('created PcDescriptors.');
- }
-
- void _update(ObservableMap m, bool mapIsRef) {
- if (mapIsRef) {
- return;
- }
- _upgradeCollection(m, isolate);
- clazz = m['class'];
- size = m['size'];
- descriptors.clear();
- for (var descriptor in m['members']) {
- var address = int.parse(descriptor['pc'], radix:16);
- var deoptId = descriptor['deoptId'];
- var tokenPos = descriptor['tokenPos'];
- var tryIndex = descriptor['tryIndex'];
- var kind = descriptor['kind'].trim();
- descriptors.add(
- new PcDescriptor(address, deoptId, tokenPos, tryIndex, kind));
- }
- }
-}
-
-class LocalVarDescriptor extends Observable {
- @reflectable final String name;
- @reflectable final int index;
- @reflectable final int beginPos;
- @reflectable final int endPos;
- @reflectable final int scopeId;
- @reflectable final String kind;
-
- LocalVarDescriptor(this.name, this.index, this.beginPos, this.endPos,
- this.scopeId, this.kind);
-}
-
-class LocalVarDescriptors extends ServiceObject {
- @observable Class clazz;
- @observable int size;
- bool get canCache => false;
- bool get immutable => true;
- @reflectable final List<LocalVarDescriptor> descriptors =
- new ObservableList<LocalVarDescriptor>();
- LocalVarDescriptors._empty(ServiceObjectOwner owner) : super._empty(owner);
-
- void _update(ObservableMap m, bool mapIsRef) {
- if (mapIsRef) {
- return;
- }
- _upgradeCollection(m, isolate);
- clazz = m['class'];
- size = m['size'];
- descriptors.clear();
- for (var descriptor in m['members']) {
- var name = descriptor['name'];
- var index = descriptor['index'];
- var beginPos = descriptor['beginPos'];
- var endPos = descriptor['endPos'];
- var scopeId = descriptor['scopeId'];
- var kind = descriptor['kind'].trim();
- descriptors.add(
- new LocalVarDescriptor(name, index, beginPos, endPos, scopeId, kind));
- }
- }
-}
-
-class TokenStream extends ServiceObject {
- @observable Class clazz;
- @observable int size;
- bool get canCache => false;
- bool get immutable => true;
-
- @observable String privateKey;
-
- TokenStream._empty(ServiceObjectOwner owner) : super._empty(owner);
-
- void _update(ObservableMap m, bool mapIsRef) {
- if (mapIsRef) {
- return;
- }
- _upgradeCollection(m, isolate);
- clazz = m['class'];
- size = m['size'];
- privateKey = m['privateKey'];
- }
-}
-
-class CodeInstruction extends Observable {
- @observable final int address;
- @observable final String machine;
- @observable final String human;
- @observable CodeInstruction jumpTarget;
- @reflectable List<PcDescriptor> descriptors =
- new ObservableList<PcDescriptor>();
-
- static String formatPercent(num a, num total) {
- var percent = 100.0 * (a / total);
- return '${percent.toStringAsFixed(2)}%';
- }
-
- CodeInstruction(this.address, this.machine, this.human);
-
- @reflectable bool get isComment => address == 0;
- @reflectable bool get hasDescriptors => descriptors.length > 0;
-
- @reflectable String formattedAddress() {
- if (address == 0) {
- return '';
- }
- return '0x${address.toRadixString(16)}';
- }
-
- @reflectable String formattedInclusive(Code code) {
- if (code == null) {
- return '';
- }
- var tick = code.addressTicks[address];
- if (tick == null) {
- return '';
- }
- // Don't show inclusive ticks if they are the same as exclusive ticks.
- if (tick.inclusiveTicks == tick.exclusiveTicks) {
- return '';
- }
- var pcent = formatPercent(tick.inclusiveTicks, code.totalSamplesInProfile);
- return '$pcent (${tick.inclusiveTicks})';
- }
-
- @reflectable String formattedExclusive(Code code) {
- if (code == null) {
- return '';
- }
- var tick = code.addressTicks[address];
- if (tick == null) {
- return '';
- }
- var pcent = formatPercent(tick.exclusiveTicks, code.totalSamplesInProfile);
- return '$pcent (${tick.exclusiveTicks})';
- }
-
- bool _isJumpInstruction() {
- return human.startsWith('j');
- }
-
- int _getJumpAddress() {
- assert(_isJumpInstruction());
- var chunks = human.split(' ');
- if (chunks.length != 2) {
- // We expect jump instructions to be of the form 'j.. address'.
- return 0;
- }
- var address = chunks[1];
- if (address.startsWith('0x')) {
- // Chop off the 0x.
- address = address.substring(2);
- }
- try {
- return int.parse(address, radix:16);
- } catch (_) {
- return 0;
- }
- }
-
- void _resolveJumpTarget(List<CodeInstruction> instructions) {
- if (!_isJumpInstruction()) {
- return;
- }
- int address = _getJumpAddress();
- if (address == 0) {
- // Could not determine jump address.
- Logger.root.severe('Could not determine jump address for $human');
- return;
- }
- for (var i = 0; i < instructions.length; i++) {
- var instruction = instructions[i];
- if (instruction.address == address) {
- jumpTarget = instruction;
- return;
- }
- }
- Logger.root.severe(
- 'Could not find instruction at ${address.toRadixString(16)}');
- }
-}
-
-class CodeKind {
- final _value;
- const CodeKind._internal(this._value);
- String toString() => '$_value';
-
- static CodeKind fromString(String s) {
- if (s == 'Native') {
- return Native;
- } else if (s == 'Dart') {
- return Dart;
- } else if (s == 'Collected') {
- return Collected;
- } else if (s == 'Reused') {
- return Reused;
- } else if (s == 'Tag') {
- return Tag;
- }
- Logger.root.warning('Unknown code kind $s');
- throw new FallThroughError();
- }
- static const Native = const CodeKind._internal('Native');
- static const Dart = const CodeKind._internal('Dart');
- static const Collected = const CodeKind._internal('Collected');
- static const Reused = const CodeKind._internal('Reused');
- static const Tag = const CodeKind._internal('Tag');
-}
-
-class CodeCallCount {
- final Code code;
- final int count;
- CodeCallCount(this.code, this.count);
-}
-
-class CodeTrieNode {
- final Code code;
- final int count;
- final children = new List<CodeTrieNode>();
- int summedChildCount = 0;
- CodeTrieNode(this.code, this.count);
-}
-
-class Code extends ServiceObject {
- @observable CodeKind kind;
- @observable int totalSamplesInProfile = 0;
- @reflectable int exclusiveTicks = 0;
- @reflectable int inclusiveTicks = 0;
- @reflectable int startAddress = 0;
- @reflectable int endAddress = 0;
- @reflectable final callers = new List<CodeCallCount>();
- @reflectable final callees = new List<CodeCallCount>();
- @reflectable final instructions = new ObservableList<CodeInstruction>();
- @reflectable final addressTicks = new ObservableMap<int, CodeTick>();
- @observable String formattedInclusiveTicks = '';
- @observable String formattedExclusiveTicks = '';
- @observable Instance objectPool;
- @observable ServiceFunction function;
- @observable Script script;
- @observable bool isOptimized = false;
-
- bool get canCache => true;
- bool get immutable => true;
-
- Code._empty(ServiceObjectOwner owner) : super._empty(owner);
-
- // Reset all data associated with a profile.
- void resetProfileData() {
- totalSamplesInProfile = 0;
- exclusiveTicks = 0;
- inclusiveTicks = 0;
- formattedInclusiveTicks = '';
- formattedExclusiveTicks = '';
- callers.clear();
- callees.clear();
- addressTicks.clear();
- }
-
- void _updateDescriptors(Script script) {
- this.script = script;
- for (var instruction in instructions) {
- for (var descriptor in instruction.descriptors) {
- descriptor.processScript(script);
- }
- }
- }
-
- void loadScript() {
- if (script != null) {
- // Already done.
- return;
- }
- if (kind != CodeKind.Dart){
- return;
- }
- if (function == null) {
- return;
- }
- if (function.script == null) {
- // Attempt to load the function.
- function.load().then((func) {
- var script = function.script;
- if (script == null) {
- // Function doesn't have an associated script.
- return;
- }
- // Load the script and then update descriptors.
- script.load().then(_updateDescriptors);
- });
- return;
- }
- // Load the script and then update descriptors.
- function.script.load().then(_updateDescriptors);
- }
-
- /// Reload [this]. Returns a future which completes to [this] or
- /// a [ServiceError].
- Future<ServiceObject> reload() {
- assert(kind != null);
- if (kind == CodeKind.Dart) {
- // We only reload Dart code.
- return super.reload();
- }
- return new Future.value(this);
- }
-
- void _resolveCalls(List<CodeCallCount> calls, List data, List<Code> codes) {
- // Assert that this has been cleared.
- assert(calls.length == 0);
- // Resolve.
- for (var i = 0; i < data.length; i += 2) {
- var index = int.parse(data[i]);
- var count = int.parse(data[i + 1]);
- assert(index >= 0);
- assert(index < codes.length);
- calls.add(new CodeCallCount(codes[index], count));
- }
- // Sort to descending count order.
- calls.sort((a, b) => b.count - a.count);
- }
-
-
- static String formatPercent(num a, num total) {
- var percent = 100.0 * (a / total);
- return '${percent.toStringAsFixed(2)}%';
- }
-
- void updateProfileData(Map profileData,
- List<Code> codeTable,
- int sampleCount) {
- // Assert we have a CodeRegion entry.
- assert(profileData['type'] == 'CodeRegion');
- // Assert we are handed profile data for this code object.
- assert(profileData['code'] == this);
- totalSamplesInProfile = sampleCount;
- inclusiveTicks = int.parse(profileData['inclusive_ticks']);
- exclusiveTicks = int.parse(profileData['exclusive_ticks']);
- _resolveCalls(callers, profileData['callers'], codeTable);
- _resolveCalls(callees, profileData['callees'], codeTable);
- var ticks = profileData['ticks'];
- if (ticks != null) {
- _processTicks(ticks);
- }
- formattedInclusiveTicks =
- '${formatPercent(inclusiveTicks, totalSamplesInProfile)} '
- '($inclusiveTicks)';
- formattedExclusiveTicks =
- '${formatPercent(exclusiveTicks, totalSamplesInProfile)} '
- '($exclusiveTicks)';
- }
-
- void _update(ObservableMap m, bool mapIsRef) {
- name = m['name'];
- vmName = (m.containsKey('vmName') ? m['vmName'] : name);
- isOptimized = m['optimized'] != null ? m['optimized'] : false;
- kind = CodeKind.fromString(m['kind']);
- startAddress = int.parse(m['start'], radix:16);
- endAddress = int.parse(m['end'], radix:16);
- function = isolate.getFromMap(m['function']);
- objectPool = isolate.getFromMap(m['objectPool']);
- var disassembly = m['disassembly'];
- if (disassembly != null) {
- _processDisassembly(disassembly);
- }
- var descriptors = m['descriptors'];
- if (descriptors != null) {
- descriptors = descriptors['members'];
- _processDescriptors(descriptors);
- }
- // We are loaded if we have instructions or are not Dart code.
- _loaded = (instructions.length != 0) || (kind != CodeKind.Dart);
- hasDisassembly = (instructions.length != 0) && (kind == CodeKind.Dart);
- }
-
- @observable bool hasDisassembly = false;
-
- void _processDisassembly(List<String> disassembly){
- assert(disassembly != null);
- instructions.clear();
- assert((disassembly.length % 3) == 0);
- for (var i = 0; i < disassembly.length; i += 3) {
- var address = 0; // Assume code comment.
- var machine = disassembly[i + 1];
- var human = disassembly[i + 2];
- if (disassembly[i] != '') {
- // Not a code comment, extract address.
- address = int.parse(disassembly[i]);
- }
- var instruction = new CodeInstruction(address, machine, human);
- instructions.add(instruction);
- }
- for (var instruction in instructions) {
- instruction._resolveJumpTarget(instructions);
- }
- }
-
- void _processDescriptor(Map d) {
- var address = int.parse(d['pc'], radix:16);
- var deoptId = d['deoptId'];
- var tokenPos = d['tokenPos'];
- var tryIndex = d['tryIndex'];
- var kind = d['kind'].trim();
- for (var instruction in instructions) {
- if (instruction.address == address) {
- instruction.descriptors.add(new PcDescriptor(address,
- deoptId,
- tokenPos,
- tryIndex,
- kind));
- return;
- }
- }
- Logger.root.warning(
- 'Could not find instruction with pc descriptor address: $address');
- }
-
- void _processDescriptors(List<Map> descriptors) {
- for (Map descriptor in descriptors) {
- _processDescriptor(descriptor);
- }
- }
-
- void _processTicks(List<String> profileTicks) {
- assert(profileTicks != null);
- assert((profileTicks.length % 3) == 0);
- for (var i = 0; i < profileTicks.length; i += 3) {
- var address = int.parse(profileTicks[i], radix:16);
- var exclusive = int.parse(profileTicks[i + 1]);
- var inclusive = int.parse(profileTicks[i + 2]);
- var tick = new CodeTick(address, exclusive, inclusive);
- addressTicks[address] = tick;
- }
- }
-
- /// Returns true if [address] is contained inside [this].
- bool contains(int address) {
- return (address >= startAddress) && (address < endAddress);
- }
-
- /// Sum all caller counts.
- int sumCallersCount() => _sumCallCount(callers);
- /// Specific caller count.
- int callersCount(Code code) => _callCount(callers, code);
- /// Sum of callees count.
- int sumCalleesCount() => _sumCallCount(callees);
- /// Specific callee count.
- int calleesCount(Code code) => _callCount(callees, code);
-
- int _sumCallCount(List<CodeCallCount> calls) {
- var sum = 0;
- for (CodeCallCount caller in calls) {
- sum += caller.count;
- }
- return sum;
- }
-
- int _callCount(List<CodeCallCount> calls, Code code) {
- for (CodeCallCount caller in calls) {
- if (caller.code == code) {
- return caller.count;
- }
- }
- return 0;
- }
-
- @reflectable bool get isDartCode => kind == CodeKind.Dart;
-}
-
-
-class SocketKind {
- final _value;
- const SocketKind._internal(this._value);
- String toString() => '$_value';
-
- static SocketKind fromString(String s) {
- if (s == 'Listening') {
- return Listening;
- } else if (s == 'Normal') {
- return Normal;
- } else if (s == 'Pipe') {
- return Pipe;
- } else if (s == 'Internal') {
- return Internal;
- }
- Logger.root.warning('Unknown socket kind $s');
- throw new FallThroughError();
- }
- static const Listening = const SocketKind._internal('Listening');
- static const Normal = const SocketKind._internal('Normal');
- static const Pipe = const SocketKind._internal('Pipe');
- static const Internal = const SocketKind._internal('Internal');
-}
-
-/// A snapshot of statistics associated with a [Socket].
-class SocketStats {
- @reflectable final int bytesRead;
- @reflectable final int bytesWritten;
- @reflectable final int readCalls;
- @reflectable final int writeCalls;
- @reflectable final int available;
-
- SocketStats(this.bytesRead, this.bytesWritten,
- this.readCalls, this.writeCalls,
- this.available);
-}
-
-/// A peer to a Socket in dart:io. Sockets can represent network sockets or
-/// OS pipes. Each socket is owned by another ServceObject, for example,
-/// a process or an HTTP server.
-class Socket extends ServiceObject {
- Socket._empty(ServiceObjectOwner owner) : super._empty(owner);
-
- bool get canCache => true;
-
- ServiceObject socketOwner;
-
- @reflectable bool get isPipe => (kind == SocketKind.Pipe);
-
- @observable SocketStats latest;
- @observable SocketStats previous;
-
- @observable SocketKind kind;
-
- @observable String protocol = '';
-
- @observable bool readClosed = false;
- @observable bool writeClosed = false;
- @observable bool closing = false;
-
- /// Listening for connections.
- @observable bool listening = false;
-
- @observable int fd;
-
- @observable String localAddress;
- @observable int localPort;
- @observable String remoteAddress;
- @observable int remotePort;
-
- // Updates internal state from [map]. [map] can be a reference.
- void _update(ObservableMap map, bool mapIsRef) {
- name = map['name'];
- vmName = map['name'];
-
- kind = SocketKind.fromString(map['kind']);
-
- if (mapIsRef) {
- return;
- }
-
- _loaded = true;
-
- _upgradeCollection(map, isolate);
-
- readClosed = map['readClosed'];
- writeClosed = map['writeClosed'];
- closing = map['closing'];
- listening = map['listening'];
-
- protocol = map['protocol'];
-
- localAddress = map['localAddress'];
- localPort = map['localPort'];
- remoteAddress = map['remoteAddress'];
- remotePort = map['remotePort'];
-
- fd = map['fd'];
- socketOwner = map['owner'];
- }
-}
-
-class MetricSample {
- final double value;
- final DateTime time;
- MetricSample(this.value) : time = new DateTime.now();
-}
-
-class ServiceMetric extends ServiceObject {
- ServiceMetric._empty(ServiceObjectOwner owner) : super._empty(owner) {
- }
-
- bool get canCache => true;
- bool get immutable => false;
-
- @observable bool recording = false;
- MetricPoller poller;
-
- final ObservableList<MetricSample> samples =
- new ObservableList<MetricSample>();
- int _sampleBufferSize = 100;
- int get sampleBufferSize => _sampleBufferSize;
- set sampleBufferSize(int size) {
- _sampleBufferSize = size;
- _removeOld();
- }
-
- void addSample(MetricSample sample) {
- samples.add(sample);
- _removeOld();
- }
-
- void _removeOld() {
- // TODO(johnmccutchan): If this becomes hot, consider using a circular
- // buffer.
- if (samples.length > _sampleBufferSize) {
- int count = samples.length - _sampleBufferSize;
- samples.removeRange(0, count);
- }
- }
-
- @observable String description;
- @observable double value = 0.0;
- // Only a guage has a non-null min and max.
- @observable double min;
- @observable double max;
-
- bool get isGauge => (min != null) && (max != null);
-
- void _update(ObservableMap map, bool mapIsRef) {
- name = map['name'];
- description = map['description'];
- vmName = map['name'];
- value = map['value'];
- min = map['min'];
- max = map['max'];
- }
-
- String toString() => "ServiceMetric($_id)";
-}
-
-class MetricPoller {
- // Metrics to be polled.
- final List<ServiceMetric> metrics = new List<ServiceMetric>();
- final Duration pollPeriod;
- Timer _pollTimer;
-
- MetricPoller(int milliseconds) :
- pollPeriod = new Duration(milliseconds: milliseconds) {
- start();
- }
-
- void start() {
- _pollTimer = new Timer.periodic(pollPeriod, _onPoll);
- }
-
- void cancel() {
- if (_pollTimer != null) {
- _pollTimer.cancel();
- }
- _pollTimer = null;
- }
-
- void _onPoll(_) {
- // Reload metrics and add a sample to each.
- for (var metric in metrics) {
- metric.reload().then((m) {
- m.addSample(new MetricSample(m.value));
- });
- }
- }
-}
-
-// Convert any ServiceMaps representing a null instance into an actual null.
-_convertNull(obj) {
- if (obj.isNull) {
- return null;
- }
- return obj;
-}
-
-// Returns true if [map] is a service map. i.e. it has the following keys:
-// 'id' and a 'type'.
-bool _isServiceMap(ObservableMap m) {
- return (m != null) && (m['id'] != null) && (m['type'] != null);
-}
-
-bool _hasRef(String type) => type.startsWith('@');
-String _stripRef(String type) => (_hasRef(type) ? type.substring(1) : type);
-
-/// Recursively upgrades all [ServiceObject]s inside [collection] which must
-/// be an [ObservableMap] or an [ObservableList]. Upgraded elements will be
-/// associated with [vm] and [isolate].
-void _upgradeCollection(collection, ServiceObjectOwner owner) {
- if (collection is ServiceMap) {
- return;
- }
- if (collection is ObservableMap) {
- _upgradeObservableMap(collection, owner);
- } else if (collection is ObservableList) {
- _upgradeObservableList(collection, owner);
- }
-}
-
-void _upgradeObservableMap(ObservableMap map, ServiceObjectOwner owner) {
- map.forEach((k, v) {
- if ((v is ObservableMap) && _isServiceMap(v)) {
- map[k] = owner.getFromMap(v);
- } else if (v is ObservableList) {
- _upgradeObservableList(v, owner);
- } else if (v is ObservableMap) {
- _upgradeObservableMap(v, owner);
- }
- });
-}
-
-void _upgradeObservableList(ObservableList list, ServiceObjectOwner owner) {
- for (var i = 0; i < list.length; i++) {
- var v = list[i];
- if ((v is ObservableMap) && _isServiceMap(v)) {
- list[i] = owner.getFromMap(v);
- } else if (v is ObservableList) {
- _upgradeObservableList(v, owner);
- } else if (v is ObservableMap) {
- _upgradeObservableMap(v, owner);
- }
- }
-}
« no previous file with comments | « runtime/observatory/lib/src/elements/vm_view.html ('k') | runtime/observatory/lib/tracer.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698