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 |