| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of service; | 5 part of service; |
| 6 | 6 |
| 7 /// A [ServiceObject] is an object known to the VM service and is tied | 7 /// A [ServiceObject] is an object known to the VM service and is tied |
| 8 /// to an owning [Isolate]. | 8 /// to an owning [Isolate]. |
| 9 abstract class ServiceObject extends Observable { | 9 abstract class ServiceObject extends Observable { |
| 10 Isolate _isolate; | 10 /// The owner of this [ServiceObject]. This can be an [Isolate], a |
| 11 /// [VM], or null. |
| 12 @reflectable ServiceObject get owner => _owner; |
| 13 ServiceObject _owner; |
| 11 | 14 |
| 12 /// Owning isolate. | 15 /// The [VM] which owns this [ServiceObject]. |
| 13 @reflectable Isolate get isolate => _isolate; | 16 @reflectable VM get vm { |
| 17 if (owner == null) { |
| 18 assert(this is VM); |
| 19 return this; |
| 20 } else if (owner is VM) { |
| 21 return owner; |
| 22 } else { |
| 23 assert(owner.owner is VM); |
| 24 return owner.owner; |
| 25 } |
| 26 } |
| 14 | 27 |
| 15 /// Owning vm. | 28 /// The [Isolate] which owns this [ServiceObject]. May be null. |
| 16 @reflectable VM get vm => _isolate.vm; | 29 @reflectable Isolate get isolate { |
| 30 if (owner == null) { |
| 31 return null; |
| 32 } else if (this is Isolate) { |
| 33 return this; |
| 34 } else { |
| 35 assert(owner is Isolate); |
| 36 return owner; |
| 37 } |
| 38 } |
| 39 |
| 40 /// The id of this object. |
| 41 @reflectable String get id => _id; |
| 42 String _id; |
| 43 |
| 44 /// The service type of this object. |
| 45 @reflectable String get serviceType => _serviceType; |
| 46 String _serviceType; |
| 17 | 47 |
| 18 /// The complete service url of this object. | 48 /// The complete service url of this object. |
| 19 @reflectable String get link => isolate.relativeLink(_id); | 49 @reflectable String get link => isolate.relativeLink(_id); |
| 20 | 50 |
| 21 /// The complete service url of this object with a '#/' prefix. | 51 /// The complete service url of this object with a '#/' prefix. |
| 22 @reflectable String get hashLink => isolate.relativeHashLink(_id); | 52 @reflectable String get hashLink => '#/${link}'; |
| 23 set hashLink(var o) { /* silence polymer */ } | 53 set hashLink(var o) { /* silence polymer */ } |
| 24 | 54 |
| 25 String _id; | 55 /// Returns true if [this] has only been partially initialized via |
| 26 /// The id of this object. | 56 /// a reference. See [load]. |
| 27 @reflectable String get id => _id; | 57 bool isRef() => _ref; |
| 28 | |
| 29 String _serviceType; | |
| 30 /// The service type of this object. | |
| 31 @reflectable String get serviceType => _serviceType; | |
| 32 | |
| 33 bool _ref; | 58 bool _ref; |
| 34 | 59 |
| 35 @observable String name; | 60 @observable String name; |
| 36 @observable String vmName; | 61 @observable String vmName; |
| 62 @observable String mainPort; |
| 37 | 63 |
| 38 ServiceObject(this._isolate, this._id, this._serviceType) { | 64 ServiceObject(this._owner, this._id, this._serviceType) { |
| 39 _ref = isRefType(_serviceType); | 65 _ref = isRefType(_serviceType); |
| 40 _serviceType = stripRef(_serviceType); | 66 _serviceType = stripRef(_serviceType); |
| 41 _created(); | 67 _created(); |
| 42 } | 68 } |
| 43 | 69 |
| 44 ServiceObject.fromMap(this._isolate, ObservableMap m) { | 70 ServiceObject.fromMap(this._owner, ObservableMap map) { |
| 45 assert(isServiceMap(m)); | 71 assert(isServiceMap(map)); |
| 46 _id = m['id']; | 72 _id = map['id']; |
| 47 _ref = isRefType(m['type']); | 73 _ref = isRefType(map['type']); |
| 48 _serviceType = stripRef(m['type']); | 74 _serviceType = stripRef(map['type']); |
| 75 update(map); |
| 49 _created(); | 76 _created(); |
| 50 update(m); | |
| 51 } | 77 } |
| 52 | 78 |
| 53 /// If [this] was created from a reference, load the full object | 79 /// If [this] was created from a reference, load the full object |
| 54 /// from the service by calling [reload]. Else, return [this]. | 80 /// from the service by calling [reload]. Else, return [this]. |
| 55 Future<ServiceObject> load() { | 81 Future<ServiceObject> load() { |
| 56 if (!_ref) { | 82 if (!_ref) { |
| 57 // Not a reference. | 83 // Not a reference. |
| 58 return new Future.value(this); | 84 return new Future.value(this); |
| 59 } | 85 } |
| 60 // Call reload which will fill in the entire object. | 86 // Call reload which will fill in the entire object. |
| 61 return reload(); | 87 return reload(); |
| 62 } | 88 } |
| 63 | 89 |
| 64 /// Reload [this]. Returns a future which completes to [this] or | 90 /// Reload [this]. Returns a future which completes to [this] or |
| 65 /// a [ServiceError]. | 91 /// a [ServiceError]. |
| 66 Future<ServiceObject> reload() { | 92 Future<ServiceObject> reload() { |
| 67 assert(isolate != null); | |
| 68 if (id == '') { | 93 if (id == '') { |
| 69 // Errors don't have ids. | 94 // Errors don't have ids. |
| 70 assert(serviceType == 'Error'); | 95 assert(serviceType == 'Error'); |
| 71 return new Future.value(this); | 96 return new Future.value(this); |
| 72 } | 97 } |
| 73 return isolate.vm.getAsMap(link).then(update); | 98 return vm.getAsMap(link).then(update); |
| 74 } | 99 } |
| 75 | 100 |
| 76 /// Update [this] using [m] as a source. [m] can be a reference. | 101 /// Update [this] using [m] as a source. [m] can be a reference. |
| 77 ServiceObject update(ObservableMap m) { | 102 ServiceObject update(ObservableMap m) { |
| 78 // Assert that m is a service map. | 103 // Assert that m is a service map. |
| 79 assert(ServiceObject.isServiceMap(m)); | 104 assert(ServiceObject.isServiceMap(m)); |
| 80 if ((m['type'] == 'Error') && (_serviceType != 'Error')) { | 105 if ((m['type'] == 'Error') && (_serviceType != 'Error')) { |
| 81 // Got an unexpected error. Don't update the object. | 106 // Got an unexpected error. Don't update the object. |
| 82 return _upgradeToServiceObject(vm, isolate, m); | 107 return _upgradeToServiceObject(vm, isolate, m); |
| 83 } | 108 } |
| 84 // TODO(johnmccutchan): Should we allow for a ServiceObject's id | 109 // TODO(johnmccutchan): Should we allow for a ServiceObject's id |
| 85 // or type to change? | 110 // or type to change? |
| 86 _id = m['id']; | 111 _id = m['id']; |
| 87 _serviceType = stripRef(m['type']); | 112 _serviceType = stripRef(m['type']); |
| 88 _update(m); | 113 _update(m); |
| 89 return this; | 114 return this; |
| 90 } | 115 } |
| 91 | 116 |
| 92 // update internal state from [map]. [map] can be a reference. | 117 // update internal state from [map]. [map] can be a reference. |
| 93 void _update(ObservableMap map); | 118 void _update(ObservableMap map); |
| 94 | 119 |
| 95 /// Returns true if [this] has only been partially initialized via | |
| 96 /// a reference. See [load]. | |
| 97 bool isRef() => _ref; | |
| 98 | |
| 99 void _created() { | 120 void _created() { |
| 100 var refNotice = _ref ? ' Created from reference.' : ''; | 121 var refNotice = _ref ? ' Created from reference.' : ''; |
| 101 Logger.root.info('Created ServiceObject for \'${_id}\' with type ' | 122 Logger.root.info('Created ServiceObject for \'${_id}\' with type ' |
| 102 '\'${_serviceType}\'.' + refNotice); | 123 '\'${_serviceType}\'.' + refNotice); |
| 103 } | 124 } |
| 104 | 125 |
| 126 // ------------------------------------------------------ |
| 127 |
| 105 /// Returns true if [map] is a service map. i.e. it has the following keys: | 128 /// Returns true if [map] is a service map. i.e. it has the following keys: |
| 106 /// 'id' and a 'type'. | 129 /// 'id' and a 'type'. |
| 107 static bool isServiceMap(ObservableMap m) { | 130 static bool isServiceMap(ObservableMap m) { |
| 108 return (m != null) && (m['id'] != null) && (m['type'] != null); | 131 return (m != null) && (m['id'] != null) && (m['type'] != null); |
| 109 } | 132 } |
| 110 | 133 |
| 111 /// Returns true if [type] is a reference type. i.e. it begins with an | 134 /// Returns true if [type] is a reference type. i.e. it begins with an |
| 112 /// '@' character. | 135 /// '@' character. |
| 113 static bool isRefType(String type) { | 136 static bool isRefType(String type) { |
| 114 return type.startsWith('@'); | 137 return type.startsWith('@'); |
| 115 } | 138 } |
| 116 | 139 |
| 117 /// Returns the unreffed version of [type]. | 140 /// Returns the unreffed version of [type]. |
| 118 static String stripRef(String type) { | 141 static String stripRef(String type) { |
| 119 if (!isRefType(type)) { | 142 if (!isRefType(type)) { |
| 120 return type; | 143 return type; |
| 121 } | 144 } |
| 122 // Strip off the '@' character. | 145 // Strip off the '@' character. |
| 123 return type.substring(1); | 146 return type.substring(1); |
| 124 } | 147 } |
| 125 } | 148 } |
| 126 | 149 |
| 127 /// State for a VM being inspected. | 150 /// State for a VM being inspected. |
| 128 abstract class VM extends Observable { | 151 abstract class VM extends ServiceObject { |
| 129 @reflectable IsolateList _isolates; | 152 @reflectable IsolateList _isolates; |
| 130 @reflectable IsolateList get isolates => _isolates; | 153 @reflectable IsolateList get isolates => _isolates; |
| 131 | 154 |
| 155 @observable List<Isolate> allIsolates = toObservable([]); |
| 156 |
| 157 @reflectable String get link => "$id"; |
| 158 |
| 159 @observable String version = 'unknown'; |
| 160 @observable String architecture = 'unknown'; |
| 161 @observable double uptime = 0.0; |
| 162 |
| 132 void _initOnce() { | 163 void _initOnce() { |
| 133 assert(_isolates == null); | 164 assert(_isolates == null); |
| 134 _isolates = new IsolateList(this); | 165 _isolates = new IsolateList(this); |
| 166 name = "vm"; |
| 167 vmName = "vm"; |
| 135 } | 168 } |
| 136 | 169 |
| 137 VM() { | 170 VM() : super(null, "vm", "VM") { |
| 138 _initOnce(); | 171 _initOnce(); |
| 139 } | 172 } |
| 140 | 173 |
| 141 /// Get [id] as an [ObservableMap] from the service directly. | 174 static final RegExp _currentIsolateMatcher = new RegExp(r'isolates/\d+'); |
| 175 static final RegExp _currentObjectMatcher = new RegExp(r'isolates/\d+(/|$)'); |
| 176 |
| 177 String _parseObjectId(String id) { |
| 178 Match m = _currentObjectMatcher.matchAsPrefix(id); |
| 179 if (m == null) { |
| 180 return null; |
| 181 } |
| 182 return m.input.substring(m.end); |
| 183 } |
| 184 |
| 185 String _parseIsolateId(String id) { |
| 186 Match m = _currentIsolateMatcher.matchAsPrefix(id); |
| 187 if (m == null) { |
| 188 return ''; |
| 189 } |
| 190 return id.substring(0, m.end); |
| 191 } |
| 192 |
| 193 Future<ServiceObject> getDirect(String id) { |
| 194 return vm.getAsMap(id).then((ObservableMap m) { |
| 195 return _upgradeToServiceObject(vm, null, m); |
| 196 }); |
| 197 } |
| 198 |
| 199 Future<ServiceObject> get(String id) { |
| 200 if (id.startsWith('isolates/')) { |
| 201 String isolateId = _parseIsolateId(id); |
| 202 if (isolateId == '') { |
| 203 return reload(); |
| 204 } else { |
| 205 Isolate isolate = _isolates.getIsolate(isolateId); |
| 206 if (isolate == null) { |
| 207 // TODO(turnidge): Isolate not found error. |
| 208 return reload(); |
| 209 } else { |
| 210 String objectId = _parseObjectId(id); |
| 211 if (objectId == null) { |
| 212 return isolate.reload(); |
| 213 } else { |
| 214 return isolate.get(objectId); |
| 215 } |
| 216 } |
| 217 } |
| 218 } else if (id == 'vm') { |
| 219 return reload(); |
| 220 } else { |
| 221 return getDirect(id); |
| 222 } |
| 223 } |
| 224 |
| 225 /// Gets [id] as an [ObservableMap] from the service directly. |
| 142 Future<ObservableMap> getAsMap(String id) { | 226 Future<ObservableMap> getAsMap(String id) { |
| 143 return getString(id).then((response) { | 227 return getString(id).then((response) { |
| 144 try { | 228 try { |
| 145 var map = JSON.decode(response); | 229 var map = JSON.decode(response); |
| 146 Logger.root.info('Decoded $id'); | 230 Logger.root.info('Decoded $id'); |
| 231 Logger.root.info('Response $response'); |
| 147 return toObservable(map); | 232 return toObservable(map); |
| 148 } catch (e, st) { | 233 } catch (e, st) { |
| 149 return toObservable({ | 234 return toObservable({ |
| 150 'type': 'Error', | 235 'type': 'Error', |
| 151 'id': '', | 236 'id': '', |
| 152 'kind': 'DecodeError', | 237 'kind': 'DecodeError', |
| 153 'message': '$e', | 238 'message': '$e', |
| 154 }); | 239 }); |
| 155 } | 240 } |
| 156 }).catchError((error) { | 241 }).catchError((error) { |
| 157 return toObservable({ | 242 return toObservable({ |
| 158 'type': 'Error', | 243 'type': 'Error', |
| 159 'id': '', | 244 'id': '', |
| 160 'kind': 'LastResort', | 245 'kind': 'LastResort', |
| 161 'message': '$error' | 246 'message': '$error' |
| 162 }); | 247 }); |
| 163 }); | 248 }); |
| 164 } | 249 } |
| 165 | 250 |
| 166 /// Get [id] as a [String] from the service directly. See [getAsMap]. | 251 /// Get [id] as a [String] from the service directly. See [getAsMap]. |
| 167 Future<String> getString(String id); | 252 Future<String> getString(String id); |
| 253 |
| 254 void _update(ObservableMap map) { |
| 255 _ref = false; |
| 256 version = map['version']; |
| 257 architecture = map['architecture']; |
| 258 uptime = map['uptime']; |
| 259 _isolates.updateIsolates(map['isolates']); |
| 260 allIsolates.clear(); |
| 261 allIsolates.addAll(_isolates.isolates.values); |
| 262 } |
| 168 } | 263 } |
| 169 | 264 |
| 170 /// State for a running isolate. | 265 /// State for a running isolate. |
| 171 class Isolate extends ServiceObject { | 266 class Isolate extends ServiceObject { |
| 172 final VM vm; | |
| 173 String get link => _id; | 267 String get link => _id; |
| 174 String get hashLink => '#/$_id'; | 268 String get hashLink => '#/$_id'; |
| 175 | 269 |
| 270 @observable bool pausedOnStart = false; |
| 271 @observable bool pausedOnExit = false; |
| 272 @observable bool running = false; |
| 273 @observable bool idle = false; |
| 274 |
| 176 ScriptCache _scripts; | 275 ScriptCache _scripts; |
| 177 /// Script cache. | 276 /// Script cache. |
| 178 ScriptCache get scripts => _scripts; | 277 ScriptCache get scripts => _scripts; |
| 179 CodeCache _codes; | 278 CodeCache _codes; |
| 180 /// Code cache. | 279 /// Code cache. |
| 181 CodeCache get codes => _codes; | 280 CodeCache get codes => _codes; |
| 182 /// Class cache. | 281 /// Class cache. |
| 183 ClassCache _classes; | 282 ClassCache _classes; |
| 184 ClassCache get classes => _classes; | 283 ClassCache get classes => _classes; |
| 185 /// Function cache. | 284 /// Function cache. |
| 186 FunctionCache _functions; | 285 FunctionCache _functions; |
| 187 FunctionCache get functions => _functions; | 286 FunctionCache get functions => _functions; |
| 188 | 287 |
| 189 void _initOnce() { | 288 void _initOnce() { |
| 190 // Only called once. | 289 // Only called once. |
| 191 assert(_isolate == null); | 290 assert(_scripts == null); |
| 192 _isolate = this; | |
| 193 _scripts = new ScriptCache(this); | 291 _scripts = new ScriptCache(this); |
| 194 _codes = new CodeCache(this); | 292 _codes = new CodeCache(this); |
| 195 _classes = new ClassCache(this); | 293 _classes = new ClassCache(this); |
| 196 _functions = new FunctionCache(this); | 294 _functions = new FunctionCache(this); |
| 197 } | 295 } |
| 198 | 296 |
| 199 Isolate.fromId(this.vm, String id) : super(null, id, '@Isolate') { | 297 Isolate.fromId(VM vm, String id) : super(vm, id, '@Isolate') { |
| 200 _initOnce(); | 298 _initOnce(); |
| 201 } | 299 } |
| 202 | 300 |
| 203 Isolate.fromMap(this.vm, Map map) : super.fromMap(null, map) { | 301 Isolate.fromMap(VM vm, Map map) : super.fromMap(vm, map) { |
| 204 _initOnce(); | 302 _initOnce(); |
| 205 } | 303 } |
| 206 | 304 |
| 207 /// Creates a link to [id] relative to [this]. | 305 /// Creates a link to [id] relative to [this]. |
| 208 @reflectable String relativeLink(String id) => '${this.id}/$id'; | 306 @reflectable String relativeLink(String id) => '${this.id}/$id'; |
| 209 /// Creates a relative link to [id] with a '#/' prefix. | 307 /// Creates a relative link to [id] with a '#/' prefix. |
| 210 @reflectable String relativeHashLink(String id) => '#/${relativeLink(id)}'; | 308 @reflectable String relativeHashLink(String id) => '#/${relativeLink(id)}'; |
| 211 | 309 |
| 212 Future<ScriptCache> refreshCoverage() { | 310 Future<ScriptCache> refreshCoverage() { |
| 213 return get('coverage').then(_scripts._processCoverage); | 311 return get('coverage').then(_scripts._processCoverage); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 269 | 367 |
| 270 @observable int newHeapUsed = 0; | 368 @observable int newHeapUsed = 0; |
| 271 @observable int oldHeapUsed = 0; | 369 @observable int oldHeapUsed = 0; |
| 272 @observable int newHeapCapacity = 0; | 370 @observable int newHeapCapacity = 0; |
| 273 @observable int oldHeapCapacity = 0; | 371 @observable int oldHeapCapacity = 0; |
| 274 | 372 |
| 275 @observable String fileAndLine; | 373 @observable String fileAndLine; |
| 276 | 374 |
| 277 void _update(ObservableMap map) { | 375 void _update(ObservableMap map) { |
| 278 upgradeCollection(map, vm, this); | 376 upgradeCollection(map, vm, this); |
| 377 mainPort = map['mainPort']; |
| 378 name = map['name']; |
| 379 if (ServiceObject.isRefType(map['type'])) { |
| 380 return; |
| 381 } |
| 279 _ref = false; | 382 _ref = false; |
| 280 if (map['rootLib'] == null || | 383 if (map['rootLib'] == null || |
| 281 map['timers'] == null || | 384 map['timers'] == null || |
| 282 map['heap'] == null) { | 385 map['heap'] == null) { |
| 283 Logger.root.severe("Malformed 'Isolate' response: $map"); | 386 Logger.root.severe("Malformed 'Isolate' response: $map"); |
| 284 return; | 387 return; |
| 285 } | 388 } |
| 286 rootLib = map['rootLib']; | 389 rootLib = map['rootLib']; |
| 287 vmName = map['name']; | 390 vmName = map['name']; |
| 288 if (map['entry'] != null) { | 391 if (map['entry'] != null) { |
| 289 entry = map['entry']; | 392 entry = map['entry']; |
| 290 name = entry['name']; | |
| 291 } else { | |
| 292 // fred | |
| 293 name = 'root'; | |
| 294 } | 393 } |
| 295 if (map['topFrame'] != null) { | 394 if (map['topFrame'] != null) { |
| 296 topFrame = map['topFrame']; | 395 topFrame = map['topFrame']; |
| 297 } else { | 396 } else { |
| 298 topFrame = null ; | 397 topFrame = null ; |
| 299 } | 398 } |
| 300 | 399 |
| 301 var timerMap = {}; | 400 var timerMap = {}; |
| 302 map['timers'].forEach((timer) { | 401 map['timers'].forEach((timer) { |
| 303 timerMap[timer['name']] = timer['time']; | 402 timerMap[timer['name']] = timer['time']; |
| 304 }); | 403 }); |
| 305 timers['total'] = timerMap['time_total_runtime']; | 404 timers['total'] = timerMap['time_total_runtime']; |
| 306 timers['compile'] = timerMap['time_compilation']; | 405 timers['compile'] = timerMap['time_compilation']; |
| 307 timers['gc'] = 0.0; // TODO(turnidge): Export this from VM. | 406 timers['gc'] = 0.0; // TODO(turnidge): Export this from VM. |
| 308 timers['init'] = (timerMap['time_script_loading'] + | 407 timers['init'] = (timerMap['time_script_loading'] + |
| 309 timerMap['time_creating_snapshot'] + | 408 timerMap['time_creating_snapshot'] + |
| 310 timerMap['time_isolate_initialization'] + | 409 timerMap['time_isolate_initialization'] + |
| 311 timerMap['time_bootstrap']); | 410 timerMap['time_bootstrap']); |
| 312 timers['dart'] = timerMap['time_dart_execution']; | 411 timers['dart'] = timerMap['time_dart_execution']; |
| 313 | 412 |
| 314 newHeapUsed = map['heap']['usedNew']; | 413 newHeapUsed = map['heap']['usedNew']; |
| 315 oldHeapUsed = map['heap']['usedOld']; | 414 oldHeapUsed = map['heap']['usedOld']; |
| 316 newHeapCapacity = map['heap']['capacityNew']; | 415 newHeapCapacity = map['heap']['capacityNew']; |
| 317 oldHeapCapacity = map['heap']['capacityOld']; | 416 oldHeapCapacity = map['heap']['capacityOld']; |
| 417 |
| 418 // Isolate status |
| 419 pausedOnStart = map['pausedOnStart']; |
| 420 pausedOnExit = map['pausedOnExit']; |
| 421 running = map['topFrame'] != null; |
| 422 idle = !pausedOnStart && !pausedOnExit && !running; |
| 318 } | 423 } |
| 319 | 424 |
| 320 @reflectable CodeTrieNode profileTrieRoot; | 425 @reflectable CodeTrieNode profileTrieRoot; |
| 321 // The profile trie is serialized as a list of integers. Each node | 426 // The profile trie is serialized as a list of integers. Each node |
| 322 // is recreated by consuming some portion of the list. The format is as | 427 // is recreated by consuming some portion of the list. The format is as |
| 323 // follows: | 428 // follows: |
| 324 // [0] index into codeTable of code object. | 429 // [0] index into codeTable of code object. |
| 325 // [1] tick count (number of times this stack frame occured). | 430 // [1] tick count (number of times this stack frame occured). |
| 326 // [2] child node count | 431 // [2] child node count |
| 327 // Reading the trie is done by recursively reading the tree depth-first | 432 // Reading the trie is done by recursively reading the tree depth-first |
| (...skipping 29 matching lines...) Expand all Loading... |
| 357 for (var i = 0; i < children; i++) { | 462 for (var i = 0; i < children; i++) { |
| 358 var child = _readTrieNode(codeTable); | 463 var child = _readTrieNode(codeTable); |
| 359 node.children.add(child); | 464 node.children.add(child); |
| 360 node.summedChildCount += child.count; | 465 node.summedChildCount += child.count; |
| 361 } | 466 } |
| 362 return node; | 467 return node; |
| 363 } | 468 } |
| 364 } | 469 } |
| 365 | 470 |
| 366 // TODO(johnmccutchan): Make this into an IsolateCache. | 471 // TODO(johnmccutchan): Make this into an IsolateCache. |
| 367 class IsolateList extends ServiceObject { | 472 class IsolateList { |
| 368 final VM _vm; | 473 final VM _vm; |
| 369 VM get vm => _vm; | 474 final isolates = new ObservableMap<String, Isolate>(); |
| 370 @observable final isolates = new ObservableMap<String, Isolate>(); | |
| 371 IsolateList(this._vm) : super(null, 'isolates', 'IsolateList') { | |
| 372 name = 'IsolateList'; | |
| 373 vmName = name; | |
| 374 } | |
| 375 IsolateList.fromMap(this._vm, Map m) : super.fromMap(null, m) { | |
| 376 name = 'IsolateList'; | |
| 377 vmName = name; | |
| 378 } | |
| 379 | 475 |
| 380 Future<ServiceObject> reload() { | 476 IsolateList(this._vm); |
| 381 return vm.getAsMap(id).then(update); | 477 |
| 382 } | 478 void updateIsolates(List<Map> members) { |
| 383 | |
| 384 void _update(ObservableMap map) { | |
| 385 _updateIsolates(map['members']); | |
| 386 } | |
| 387 | |
| 388 void _updateIsolates(List<Map> members) { | |
| 389 // Find dead isolates. | 479 // Find dead isolates. |
| 390 var deadIsolates = []; | 480 var deadIsolates = []; |
| 391 isolates.forEach((k, v) { | 481 isolates.forEach((k, v) { |
| 392 if (!_foundIsolateInMembers(k, members)) { | 482 if (!_foundIsolateInMembers(k, members)) { |
| 393 deadIsolates.add(k); | 483 deadIsolates.add(k); |
| 394 } | 484 } |
| 395 }); | 485 }); |
| 396 // Remove them. | 486 // Remove them. |
| 397 deadIsolates.forEach((id) { | 487 deadIsolates.forEach((id) { |
| 398 isolates.remove(id); | 488 isolates.remove(id); |
| 399 Logger.root.info('Isolate \'$id\' has gone away.'); | 489 Logger.root.info('Isolate \'$id\' has gone away.'); |
| 400 }); | 490 }); |
| 401 | 491 |
| 402 // Add new isolates. | 492 // Add new isolates. |
| 403 members.forEach((map) { | 493 members.forEach((map) { |
| 404 var id = map['id']; | 494 var id = map['id']; |
| 405 var isolate = isolates[id]; | 495 var isolate = isolates[id]; |
| 406 if (isolate == null) { | 496 if (isolate == null) { |
| 407 isolate = new Isolate.fromMap(vm, map); | 497 isolate = new Isolate.fromMap(_vm, map); |
| 408 Logger.root.info('Created ServiceObject for \'${isolate.id}\' with ' | 498 Logger.root.info('Created ServiceObject for \'${isolate.id}\' with ' |
| 409 'type \'${isolate.serviceType}\''); | 499 'type \'${isolate.serviceType}\''); |
| 410 isolates[id] = isolate; | 500 isolates[id] = isolate; |
| 411 } | 501 } |
| 412 }); | 502 }); |
| 413 | 503 |
| 414 // After updating the isolate list, refresh each isolate. | 504 // After updating the isolate list, refresh each isolate. |
| 415 _refreshIsolates(); | 505 _refreshIsolates(); |
| 416 } | 506 } |
| 417 | 507 |
| 418 void _refreshIsolates() { | 508 void _refreshIsolates() { |
| 419 // This is technically asynchronous but we don't need to wait for | 509 // This is technically asynchronous but we don't need to wait for |
| 420 // the result. | 510 // the result. |
| 421 isolates.forEach((k, Isolate isolate) { | 511 isolates.forEach((k, Isolate isolate) { |
| 422 isolate.reload(); | 512 isolate.reload(); |
| 423 }); | 513 }); |
| 424 } | 514 } |
| 425 | 515 |
| 426 Isolate getIsolate(String id) { | 516 Isolate getIsolate(String id) { |
| 427 assert(id.startsWith('isolates/')); | 517 assert(id.startsWith('isolates/')); |
| 428 var isolate = isolates[id]; | 518 var isolate = isolates[id]; |
| 429 if (isolate != null) { | 519 if (isolate != null) { |
| 430 return isolate; | 520 return isolate; |
| 431 } | 521 } |
| 432 isolate = new Isolate.fromId(vm, id); | 522 isolate = new Isolate.fromId(_vm, id); |
| 433 isolates[id] = isolate; | 523 isolates[id] = isolate; |
| 434 isolate.load(); | 524 isolate.load(); |
| 435 return isolate; | 525 return isolate; |
| 436 } | 526 } |
| 437 | 527 |
| 438 Isolate getIsolateFromMap(ObservableMap m) { | 528 Isolate getIsolateFromMap(ObservableMap m) { |
| 439 assert(ServiceObject.isServiceMap(m)); | 529 assert(ServiceObject.isServiceMap(m)); |
| 440 String id = m['id']; | 530 String id = m['id']; |
| 441 assert(id.startsWith('isolates/')); | 531 assert(id.startsWith('isolates/')); |
| 442 var isolate = isolates[id]; | 532 var isolate = isolates[id]; |
| 443 if (isolate != null) { | 533 if (isolate != null) { |
| 444 isolate.update(m); | 534 isolate.update(m); |
| 445 return isolate; | 535 return isolate; |
| 446 } | 536 } |
| 447 isolate = new Isolate.fromMap(vm, m); | 537 isolate = new Isolate.fromMap(_vm, m); |
| 448 isolates[id] = isolate; | 538 isolates[id] = isolate; |
| 449 isolate.load(); | 539 isolate.load(); |
| 450 return isolate; | 540 return isolate; |
| 451 } | 541 } |
| 452 | 542 |
| 453 static bool _foundIsolateInMembers(String id, List<Map> members) { | 543 static bool _foundIsolateInMembers(String id, List<Map> members) { |
| 454 return members.any((E) => E['id'] == id); | 544 return members.any((E) => E['id'] == id); |
| 455 } | 545 } |
| 456 } | 546 } |
| 457 | 547 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 502 void notifyChange(ChangeRecord record) => _map.notifyChange(record); | 592 void notifyChange(ChangeRecord record) => _map.notifyChange(record); |
| 503 notifyPropertyChange(Symbol field, Object oldValue, Object newValue) => | 593 notifyPropertyChange(Symbol field, Object oldValue, Object newValue) => |
| 504 _map.notifyPropertyChange(field, oldValue, newValue); | 594 _map.notifyPropertyChange(field, oldValue, newValue); |
| 505 void observed() => _map.observed(); | 595 void observed() => _map.observed(); |
| 506 void unobserved() => _map.unobserved(); | 596 void unobserved() => _map.unobserved(); |
| 507 Stream<List<ChangeRecord>> get changes => _map.changes; | 597 Stream<List<ChangeRecord>> get changes => _map.changes; |
| 508 bool get hasObservers => _map.hasObservers; | 598 bool get hasObservers => _map.hasObservers; |
| 509 } | 599 } |
| 510 | 600 |
| 511 class ServiceError extends ServiceObject { | 601 class ServiceError extends ServiceObject { |
| 512 ServiceError.fromMap(Isolate isolate, Map m) : super.fromMap(isolate, m); | 602 ServiceError.fromMap(ServiceObject owner, Map m) : super.fromMap(owner, m); |
| 513 | 603 |
| 514 @observable String kind; | 604 @observable String kind; |
| 515 @observable String message; | 605 @observable String message; |
| 516 | 606 |
| 517 void _update(ObservableMap map) { | 607 void _update(ObservableMap map) { |
| 518 kind = map['kind']; | 608 kind = map['kind']; |
| 519 message = map['message']; | 609 message = map['message']; |
| 520 name = 'ServiceError $kind'; | 610 name = 'ServiceError $kind'; |
| 521 vmName = name; | 611 vmName = name; |
| 522 } | 612 } |
| (...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 859 | 949 |
| 860 int _callCount(List<CodeCallCount> calls, Code code) { | 950 int _callCount(List<CodeCallCount> calls, Code code) { |
| 861 for (CodeCallCount caller in calls) { | 951 for (CodeCallCount caller in calls) { |
| 862 if (caller.code == code) { | 952 if (caller.code == code) { |
| 863 return caller.count; | 953 return caller.count; |
| 864 } | 954 } |
| 865 } | 955 } |
| 866 return 0; | 956 return 0; |
| 867 } | 957 } |
| 868 } | 958 } |
| OLD | NEW |