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 @reflectable String get link => "$id"; | |
156 | |
157 @observable String version = 'unknown'; | |
158 @observable String architecture = 'unknown'; | |
159 @observable double uptime = 0.0; | |
160 | |
132 void _initOnce() { | 161 void _initOnce() { |
133 assert(_isolates == null); | 162 assert(_isolates == null); |
134 _isolates = new IsolateList(this); | 163 _isolates = new IsolateList(this); |
164 name = "vm"; | |
165 vmName = "vm"; | |
135 } | 166 } |
136 | 167 |
137 VM() { | 168 VM() : super(null, "vm", "VM") { |
138 _initOnce(); | 169 _initOnce(); |
139 } | 170 } |
140 | 171 |
141 /// Get [id] as an [ObservableMap] from the service directly. | 172 static final RegExp _currentIsolateMatcher = new RegExp(r'isolates/\d+'); |
173 static final RegExp _currentObjectMatcher = new RegExp(r'isolates/\d+(/|$)'); | |
174 | |
175 String _parseObjectId(String id) { | |
176 Match m = _currentObjectMatcher.matchAsPrefix(id); | |
177 if (m == null) { | |
178 return null; | |
179 } | |
180 return m.input.substring(m.end); | |
181 } | |
182 | |
183 String _parseIsolateId(String id) { | |
184 Match m = _currentIsolateMatcher.matchAsPrefix(id); | |
185 if (m == null) { | |
186 print("NO MATCH"); | |
Cutch
2014/03/20 18:25:56
Logger.root.warning ?
turnidge
2014/03/20 19:08:02
Actually this happens legitimately on the /vm page
| |
187 return ''; | |
188 } | |
189 return id.substring(0, m.end); | |
190 } | |
191 | |
192 Future<ServiceObject> _getDirect(String id) { | |
193 return vm.getAsMap(id).then((ObservableMap m) { | |
194 return _upgradeToServiceObject(vm, null, m); | |
195 }); | |
196 } | |
197 | |
198 Future<ServiceObject> get(String id) { | |
199 if (id.startsWith('isolates/')) { | |
200 String isolateId = _parseIsolateId(id); | |
201 if (isolateId == '') { | |
202 return reload(); | |
203 } else { | |
204 Isolate isolate = _isolates.getIsolate(isolateId); | |
205 if (isolate == null) { | |
206 // TODO(turnidge): Isolate not found error. | |
207 return reload(); | |
208 } else { | |
209 String objectId = _parseObjectId(id); | |
210 if (objectId == null) { | |
211 return isolate.reload(); | |
212 } else { | |
213 return isolate.get(objectId); | |
214 } | |
215 } | |
216 } | |
217 } else if (id == 'vm') { | |
218 return reload(); | |
219 } else { | |
220 return _getDirect(id); | |
221 } | |
222 } | |
223 | |
224 /// Gets [id] as an [ObservableMap] from the service directly. | |
142 Future<ObservableMap> getAsMap(String id) { | 225 Future<ObservableMap> getAsMap(String id) { |
143 return getString(id).then((response) { | 226 return getString(id).then((response) { |
144 try { | 227 try { |
145 var map = JSON.decode(response); | 228 var map = JSON.decode(response); |
146 Logger.root.info('Decoded $id'); | 229 Logger.root.info('Decoded $id'); |
147 return toObservable(map); | 230 return toObservable(map); |
148 } catch (e, st) { | 231 } catch (e, st) { |
149 return toObservable({ | 232 return toObservable({ |
150 'type': 'Error', | 233 'type': 'Error', |
151 'id': '', | 234 'id': '', |
152 'kind': 'DecodeError', | 235 'kind': 'DecodeError', |
153 'message': '$e', | 236 'message': '$e', |
154 }); | 237 }); |
155 } | 238 } |
156 }).catchError((error) { | 239 }).catchError((error) { |
157 return toObservable({ | 240 return toObservable({ |
158 'type': 'Error', | 241 'type': 'Error', |
159 'id': '', | 242 'id': '', |
160 'kind': 'LastResort', | 243 'kind': 'LastResort', |
161 'message': '$error' | 244 'message': '$error' |
162 }); | 245 }); |
163 }); | 246 }); |
164 } | 247 } |
165 | 248 |
166 /// Get [id] as a [String] from the service directly. See [getAsMap]. | 249 /// Get [id] as a [String] from the service directly. See [getAsMap]. |
167 Future<String> getString(String id); | 250 Future<String> getString(String id); |
251 | |
252 void _update(ObservableMap map) { | |
253 print("$map"); | |
Cutch
2014/03/20 18:25:56
remove?
turnidge
2014/03/20 19:08:02
Done.
| |
254 _ref = false; | |
255 version = map['version']; | |
256 architecture = map['architecture']; | |
257 uptime = map['uptime']; | |
258 _isolates.updateIsolates(map['isolates']); | |
259 } | |
168 } | 260 } |
169 | 261 |
170 /// State for a running isolate. | 262 /// State for a running isolate. |
171 class Isolate extends ServiceObject { | 263 class Isolate extends ServiceObject { |
172 final VM vm; | |
173 String get link => _id; | 264 String get link => _id; |
174 String get hashLink => '#/$_id'; | 265 String get hashLink => '#/$_id'; |
175 | 266 |
267 @observable bool pausedOnStart = false; | |
268 @observable bool pausedOnExit = false; | |
269 @observable bool running = false; | |
270 @observable bool idle = false; | |
271 | |
176 ScriptCache _scripts; | 272 ScriptCache _scripts; |
177 /// Script cache. | 273 /// Script cache. |
178 ScriptCache get scripts => _scripts; | 274 ScriptCache get scripts => _scripts; |
179 CodeCache _codes; | 275 CodeCache _codes; |
180 /// Code cache. | 276 /// Code cache. |
181 CodeCache get codes => _codes; | 277 CodeCache get codes => _codes; |
182 /// Class cache. | 278 /// Class cache. |
183 ClassCache _classes; | 279 ClassCache _classes; |
184 ClassCache get classes => _classes; | 280 ClassCache get classes => _classes; |
185 /// Function cache. | 281 /// Function cache. |
186 FunctionCache _functions; | 282 FunctionCache _functions; |
187 FunctionCache get functions => _functions; | 283 FunctionCache get functions => _functions; |
188 | 284 |
189 void _initOnce() { | 285 void _initOnce() { |
190 // Only called once. | 286 // Only called once. |
191 assert(_isolate == null); | 287 assert(_scripts == null); |
192 _isolate = this; | |
193 _scripts = new ScriptCache(this); | 288 _scripts = new ScriptCache(this); |
194 _codes = new CodeCache(this); | 289 _codes = new CodeCache(this); |
195 _classes = new ClassCache(this); | 290 _classes = new ClassCache(this); |
196 _functions = new FunctionCache(this); | 291 _functions = new FunctionCache(this); |
197 } | 292 } |
198 | 293 |
199 Isolate.fromId(this.vm, String id) : super(null, id, '@Isolate') { | 294 Isolate.fromId(VM vm, String id) : super(vm, id, '@Isolate') { |
200 _initOnce(); | 295 _initOnce(); |
201 } | 296 } |
202 | 297 |
203 Isolate.fromMap(this.vm, Map map) : super.fromMap(null, map) { | 298 Isolate.fromMap(VM vm, Map map) : super.fromMap(vm, map) { |
204 _initOnce(); | 299 _initOnce(); |
205 } | 300 } |
206 | 301 |
207 /// Creates a link to [id] relative to [this]. | 302 /// Creates a link to [id] relative to [this]. |
208 @reflectable String relativeLink(String id) => '${this.id}/$id'; | 303 @reflectable String relativeLink(String id) => '${this.id}/$id'; |
209 /// Creates a relative link to [id] with a '#/' prefix. | 304 /// Creates a relative link to [id] with a '#/' prefix. |
210 @reflectable String relativeHashLink(String id) => '#/${relativeLink(id)}'; | 305 @reflectable String relativeHashLink(String id) => '#/${relativeLink(id)}'; |
211 | 306 |
212 Future<ScriptCache> refreshCoverage() { | 307 Future<ScriptCache> refreshCoverage() { |
213 return get('coverage').then(_scripts._processCoverage); | 308 return get('coverage').then(_scripts._processCoverage); |
214 } | 309 } |
215 | 310 |
216 void processProfile(ServiceMap profile) { | 311 void processProfile(ServiceMap profile) { |
217 assert(profile.serviceType == 'Profile'); | 312 assert(profile.serviceType == 'Profile'); |
218 var codeTable = new List<Code>(); | 313 var codeTable = new List<Code>(); |
219 var codeRegions = profile['codes']; | 314 var codeRegions = profile['codes']; |
220 for (var codeRegion in codeRegions) { | 315 for (var codeRegion in codeRegions) { |
221 Code code = codeRegion['code']; | 316 Code code = codeRegion['code']; |
222 assert(code != null); | 317 assert(code != null); |
223 codeTable.add(code); | 318 codeTable.add(code); |
224 } | 319 } |
225 _codes._resetProfileData(); | 320 _codes._resetProfileData(); |
226 _codes._updateProfileData(profile, codeTable); | 321 _codes._updateProfileData(profile, codeTable); |
227 var exclusiveTrie = profile['exclusive_trie']; | 322 var exclusiveTrie = profile['exclusive_trie']; |
228 if (exclusiveTrie != null) { | 323 if (exclusiveTrie != null) { |
229 profileTrieRoot = _processProfileTrie(exclusiveTrie, codeTable); | 324 profileTrieRoot = _processProfileTrie(exclusiveTrie, codeTable); |
230 } | 325 } |
231 } | 326 } |
232 | 327 |
233 Future<ServiceObject> getDirect(String serviceId) { | 328 Future<ServiceObject> _getDirect(String serviceId) { |
234 return vm.getAsMap(relativeLink(serviceId)).then((ObservableMap m) { | 329 return vm.getAsMap(relativeLink(serviceId)).then((ObservableMap m) { |
235 return _upgradeToServiceObject(vm, this, m); | 330 return _upgradeToServiceObject(vm, this, m); |
236 }); | 331 }); |
237 } | 332 } |
238 | 333 |
239 /// Requests [serviceId] from [this]. Completes to a [ServiceObject]. | 334 /// Requests [serviceId] from [this]. Completes to a [ServiceObject]. |
240 /// Can return pre-existing, cached, [ServiceObject]s. | 335 /// Can return pre-existing, cached, [ServiceObject]s. |
241 Future<ServiceObject> get(String serviceId) { | 336 Future<ServiceObject> get(String serviceId) { |
242 if (serviceId == '') { | 337 if (serviceId == '') { |
243 return reload(); | 338 return reload(); |
244 } | 339 } |
245 if (_scripts.cachesId(serviceId)) { | 340 if (_scripts.cachesId(serviceId)) { |
246 return _scripts.get(serviceId); | 341 return _scripts.get(serviceId); |
247 } | 342 } |
248 if (_codes.cachesId(serviceId)) { | 343 if (_codes.cachesId(serviceId)) { |
249 return _codes.get(serviceId); | 344 return _codes.get(serviceId); |
250 } | 345 } |
251 if (_classes.cachesId(serviceId)) { | 346 if (_classes.cachesId(serviceId)) { |
252 return _classes.get(serviceId); | 347 return _classes.get(serviceId); |
253 } | 348 } |
254 if (_functions.cachesId(serviceId)) { | 349 if (_functions.cachesId(serviceId)) { |
255 return _functions.get(serviceId); | 350 return _functions.get(serviceId); |
256 } | 351 } |
257 return getDirect(serviceId); | 352 return _getDirect(serviceId); |
258 } | 353 } |
259 | 354 |
260 @observable ServiceMap rootLib; | 355 @observable ServiceMap rootLib; |
261 @observable ObservableMap topFrame; | 356 @observable ObservableMap topFrame; |
262 | 357 |
263 @observable String name; | 358 @observable String name; |
264 @observable String vmName; | 359 @observable String vmName; |
265 @observable Map entry; | 360 @observable Map entry; |
266 | 361 |
267 @observable final Map<String, double> timers = | 362 @observable final Map<String, double> timers = |
268 toObservable(new Map<String, double>()); | 363 toObservable(new Map<String, double>()); |
269 | 364 |
270 @observable int newHeapUsed = 0; | 365 @observable int newHeapUsed = 0; |
271 @observable int oldHeapUsed = 0; | 366 @observable int oldHeapUsed = 0; |
272 @observable int newHeapCapacity = 0; | 367 @observable int newHeapCapacity = 0; |
273 @observable int oldHeapCapacity = 0; | 368 @observable int oldHeapCapacity = 0; |
274 | 369 |
275 @observable String fileAndLine; | 370 @observable String fileAndLine; |
276 | 371 |
277 void _update(ObservableMap map) { | 372 void _update(ObservableMap map) { |
278 upgradeCollection(map, vm, this); | 373 upgradeCollection(map, vm, this); |
374 mainPort = map['mainPort']; | |
375 name = map['name']; | |
376 if (ServiceObject.isRefType(map['type'])) { | |
377 return; | |
378 } | |
279 _ref = false; | 379 _ref = false; |
280 if (map['rootLib'] == null || | 380 if (map['rootLib'] == null || |
281 map['timers'] == null || | 381 map['timers'] == null || |
282 map['heap'] == null) { | 382 map['heap'] == null) { |
283 Logger.root.severe("Malformed 'Isolate' response: $map"); | 383 Logger.root.severe("Malformed 'Isolate' response: $map"); |
284 return; | 384 return; |
285 } | 385 } |
286 rootLib = map['rootLib']; | 386 rootLib = map['rootLib']; |
287 vmName = map['name']; | 387 vmName = map['name']; |
288 if (map['entry'] != null) { | 388 if (map['entry'] != null) { |
289 entry = map['entry']; | 389 entry = map['entry']; |
290 name = entry['name']; | |
291 } else { | |
292 // fred | |
293 name = 'root'; | |
294 } | 390 } |
295 if (map['topFrame'] != null) { | 391 if (map['topFrame'] != null) { |
296 topFrame = map['topFrame']; | 392 topFrame = map['topFrame']; |
297 } else { | 393 } else { |
298 topFrame = null ; | 394 topFrame = null ; |
299 } | 395 } |
300 | 396 |
301 var timerMap = {}; | 397 var timerMap = {}; |
302 map['timers'].forEach((timer) { | 398 map['timers'].forEach((timer) { |
303 timerMap[timer['name']] = timer['time']; | 399 timerMap[timer['name']] = timer['time']; |
304 }); | 400 }); |
305 timers['total'] = timerMap['time_total_runtime']; | 401 timers['total'] = timerMap['time_total_runtime']; |
306 timers['compile'] = timerMap['time_compilation']; | 402 timers['compile'] = timerMap['time_compilation']; |
307 timers['gc'] = 0.0; // TODO(turnidge): Export this from VM. | 403 timers['gc'] = 0.0; // TODO(turnidge): Export this from VM. |
308 timers['init'] = (timerMap['time_script_loading'] + | 404 timers['init'] = (timerMap['time_script_loading'] + |
309 timerMap['time_creating_snapshot'] + | 405 timerMap['time_creating_snapshot'] + |
310 timerMap['time_isolate_initialization'] + | 406 timerMap['time_isolate_initialization'] + |
311 timerMap['time_bootstrap']); | 407 timerMap['time_bootstrap']); |
312 timers['dart'] = timerMap['time_dart_execution']; | 408 timers['dart'] = timerMap['time_dart_execution']; |
313 | 409 |
314 newHeapUsed = map['heap']['usedNew']; | 410 newHeapUsed = map['heap']['usedNew']; |
315 oldHeapUsed = map['heap']['usedOld']; | 411 oldHeapUsed = map['heap']['usedOld']; |
316 newHeapCapacity = map['heap']['capacityNew']; | 412 newHeapCapacity = map['heap']['capacityNew']; |
317 oldHeapCapacity = map['heap']['capacityOld']; | 413 oldHeapCapacity = map['heap']['capacityOld']; |
414 | |
415 // Isolate status | |
416 pausedOnStart = map['pausedOnStart']; | |
417 pausedOnExit = map['pausedOnExit']; | |
418 running = map['topFrame'] != null; | |
419 idle = !pausedOnStart && !pausedOnExit && !running; | |
318 } | 420 } |
319 | 421 |
320 @reflectable CodeTrieNode profileTrieRoot; | 422 @reflectable CodeTrieNode profileTrieRoot; |
321 // The profile trie is serialized as a list of integers. Each node | 423 // 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 | 424 // is recreated by consuming some portion of the list. The format is as |
323 // follows: | 425 // follows: |
324 // [0] index into codeTable of code object. | 426 // [0] index into codeTable of code object. |
325 // [1] tick count (number of times this stack frame occured). | 427 // [1] tick count (number of times this stack frame occured). |
326 // [2] child node count | 428 // [2] child node count |
327 // Reading the trie is done by recursively reading the tree depth-first | 429 // 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++) { | 459 for (var i = 0; i < children; i++) { |
358 var child = _readTrieNode(codeTable); | 460 var child = _readTrieNode(codeTable); |
359 node.children.add(child); | 461 node.children.add(child); |
360 node.summedChildCount += child.count; | 462 node.summedChildCount += child.count; |
361 } | 463 } |
362 return node; | 464 return node; |
363 } | 465 } |
364 } | 466 } |
365 | 467 |
366 // TODO(johnmccutchan): Make this into an IsolateCache. | 468 // TODO(johnmccutchan): Make this into an IsolateCache. |
367 class IsolateList extends ServiceObject { | 469 class IsolateList { |
368 final VM _vm; | 470 final VM _vm; |
369 VM get vm => _vm; | |
370 @observable final isolates = new ObservableMap<String, Isolate>(); | 471 @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 | 472 |
380 Future<ServiceObject> reload() { | 473 IsolateList(this._vm); |
381 return vm.getAsMap(id).then(update); | |
382 } | |
383 | 474 |
384 void _update(ObservableMap map) { | 475 void updateIsolates(List<Map> members) { |
385 _updateIsolates(map['members']); | |
386 } | |
387 | |
388 void _updateIsolates(List<Map> members) { | |
389 // Find dead isolates. | 476 // Find dead isolates. |
390 var deadIsolates = []; | 477 var deadIsolates = []; |
391 isolates.forEach((k, v) { | 478 isolates.forEach((k, v) { |
392 if (!_foundIsolateInMembers(k, members)) { | 479 if (!_foundIsolateInMembers(k, members)) { |
393 deadIsolates.add(k); | 480 deadIsolates.add(k); |
394 } | 481 } |
395 }); | 482 }); |
396 // Remove them. | 483 // Remove them. |
397 deadIsolates.forEach((id) { | 484 deadIsolates.forEach((id) { |
398 isolates.remove(id); | 485 isolates.remove(id); |
399 Logger.root.info('Isolate \'$id\' has gone away.'); | 486 Logger.root.info('Isolate \'$id\' has gone away.'); |
400 }); | 487 }); |
401 | 488 |
402 // Add new isolates. | 489 // Add new isolates. |
403 members.forEach((map) { | 490 members.forEach((map) { |
404 var id = map['id']; | 491 var id = map['id']; |
405 var isolate = isolates[id]; | 492 var isolate = isolates[id]; |
406 if (isolate == null) { | 493 if (isolate == null) { |
407 isolate = new Isolate.fromMap(vm, map); | 494 isolate = new Isolate.fromMap(_vm, map); |
408 Logger.root.info('Created ServiceObject for \'${isolate.id}\' with ' | 495 Logger.root.info('Created ServiceObject for \'${isolate.id}\' with ' |
409 'type \'${isolate.serviceType}\''); | 496 'type \'${isolate.serviceType}\''); |
410 isolates[id] = isolate; | 497 isolates[id] = isolate; |
411 } | 498 } |
412 }); | 499 }); |
413 | 500 |
414 // After updating the isolate list, refresh each isolate. | 501 // After updating the isolate list, refresh each isolate. |
415 _refreshIsolates(); | 502 _refreshIsolates(); |
416 } | 503 } |
417 | 504 |
418 void _refreshIsolates() { | 505 void _refreshIsolates() { |
419 // This is technically asynchronous but we don't need to wait for | 506 // This is technically asynchronous but we don't need to wait for |
420 // the result. | 507 // the result. |
421 isolates.forEach((k, Isolate isolate) { | 508 isolates.forEach((k, Isolate isolate) { |
422 isolate.reload(); | 509 isolate.reload(); |
423 }); | 510 }); |
424 } | 511 } |
425 | 512 |
426 Isolate getIsolate(String id) { | 513 Isolate getIsolate(String id) { |
427 assert(id.startsWith('isolates/')); | 514 assert(id.startsWith('isolates/')); |
428 var isolate = isolates[id]; | 515 var isolate = isolates[id]; |
429 if (isolate != null) { | 516 if (isolate != null) { |
430 return isolate; | 517 return isolate; |
431 } | 518 } |
432 isolate = new Isolate.fromId(vm, id); | 519 isolate = new Isolate.fromId(_vm, id); |
433 isolates[id] = isolate; | 520 isolates[id] = isolate; |
434 isolate.load(); | 521 isolate.load(); |
435 return isolate; | 522 return isolate; |
436 } | 523 } |
437 | 524 |
438 Isolate getIsolateFromMap(ObservableMap m) { | 525 Isolate getIsolateFromMap(ObservableMap m) { |
439 assert(ServiceObject.isServiceMap(m)); | 526 assert(ServiceObject.isServiceMap(m)); |
440 String id = m['id']; | 527 String id = m['id']; |
441 assert(id.startsWith('isolates/')); | 528 assert(id.startsWith('isolates/')); |
442 var isolate = isolates[id]; | 529 var isolate = isolates[id]; |
443 if (isolate != null) { | 530 if (isolate != null) { |
444 isolate.update(m); | 531 isolate.update(m); |
445 return isolate; | 532 return isolate; |
446 } | 533 } |
447 isolate = new Isolate.fromMap(vm, m); | 534 isolate = new Isolate.fromMap(_vm, m); |
448 isolates[id] = isolate; | 535 isolates[id] = isolate; |
449 isolate.load(); | 536 isolate.load(); |
450 return isolate; | 537 return isolate; |
451 } | 538 } |
452 | 539 |
453 static bool _foundIsolateInMembers(String id, List<Map> members) { | 540 static bool _foundIsolateInMembers(String id, List<Map> members) { |
454 return members.any((E) => E['id'] == id); | 541 return members.any((E) => E['id'] == id); |
455 } | 542 } |
456 } | 543 } |
457 | 544 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
502 void notifyChange(ChangeRecord record) => _map.notifyChange(record); | 589 void notifyChange(ChangeRecord record) => _map.notifyChange(record); |
503 notifyPropertyChange(Symbol field, Object oldValue, Object newValue) => | 590 notifyPropertyChange(Symbol field, Object oldValue, Object newValue) => |
504 _map.notifyPropertyChange(field, oldValue, newValue); | 591 _map.notifyPropertyChange(field, oldValue, newValue); |
505 void observed() => _map.observed(); | 592 void observed() => _map.observed(); |
506 void unobserved() => _map.unobserved(); | 593 void unobserved() => _map.unobserved(); |
507 Stream<List<ChangeRecord>> get changes => _map.changes; | 594 Stream<List<ChangeRecord>> get changes => _map.changes; |
508 bool get hasObservers => _map.hasObservers; | 595 bool get hasObservers => _map.hasObservers; |
509 } | 596 } |
510 | 597 |
511 class ServiceError extends ServiceObject { | 598 class ServiceError extends ServiceObject { |
512 ServiceError.fromMap(Isolate isolate, Map m) : super.fromMap(isolate, m); | 599 ServiceError.fromMap(ServiceObject owner, Map m) : super.fromMap(owner, m); |
513 | 600 |
514 @observable String kind; | 601 @observable String kind; |
515 @observable String message; | 602 @observable String message; |
516 | 603 |
517 void _update(ObservableMap map) { | 604 void _update(ObservableMap map) { |
518 kind = map['kind']; | 605 kind = map['kind']; |
519 message = map['message']; | 606 message = map['message']; |
520 name = 'ServiceError $kind'; | 607 name = 'ServiceError $kind'; |
521 vmName = name; | 608 vmName = name; |
522 } | 609 } |
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
859 | 946 |
860 int _callCount(List<CodeCallCount> calls, Code code) { | 947 int _callCount(List<CodeCallCount> calls, Code code) { |
861 for (CodeCallCount caller in calls) { | 948 for (CodeCallCount caller in calls) { |
862 if (caller.code == code) { | 949 if (caller.code == code) { |
863 return caller.count; | 950 return caller.count; |
864 } | 951 } |
865 } | 952 } |
866 return 0; | 953 return 0; |
867 } | 954 } |
868 } | 955 } |
OLD | NEW |