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 /// The owner of this [ServiceObject]. This can be an [Isolate], a | 10 /// The owner of this [ServiceObject]. This can be an [Isolate], a |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
95 assert(serviceType == 'Error'); | 95 assert(serviceType == 'Error'); |
96 return new Future.value(this); | 96 return new Future.value(this); |
97 } | 97 } |
98 return vm.getAsMap(link).then(update); | 98 return vm.getAsMap(link).then(update); |
99 } | 99 } |
100 | 100 |
101 /// 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. |
102 ServiceObject update(ObservableMap m) { | 102 ServiceObject update(ObservableMap m) { |
103 // Assert that m is a service map. | 103 // Assert that m is a service map. |
104 assert(ServiceObject.isServiceMap(m)); | 104 assert(ServiceObject.isServiceMap(m)); |
105 if ((m['type'] == 'Error') && (_serviceType != 'Error')) { | |
106 // Got an unexpected error. Don't update the object. | |
107 return _upgradeToServiceObject(vm, isolate, m); | |
108 } | |
109 // TODO(johnmccutchan): Should we allow for a ServiceObject's id | 105 // TODO(johnmccutchan): Should we allow for a ServiceObject's id |
110 // or type to change? | 106 // or type to change? |
111 _id = m['id']; | 107 _id = m['id']; |
112 _serviceType = stripRef(m['type']); | 108 _serviceType = stripRef(m['type']); |
113 _update(m); | 109 _update(m); |
114 return this; | 110 return this; |
115 } | 111 } |
116 | 112 |
117 // update internal state from [map]. [map] can be a reference. | 113 // update internal state from [map]. [map] can be a reference. |
118 void _update(ObservableMap map); | 114 void _update(ObservableMap map); |
119 | 115 |
120 void _created() { | 116 void _created() { |
121 var refNotice = _ref ? ' Created from reference.' : ''; | |
122 Logger.root.info('Created ServiceObject for \'${_id}\' with type ' | |
123 '\'${_serviceType}\'.' + refNotice); | |
124 } | 117 } |
turnidge
2014/03/24 20:22:13
Maybe just drop _created() entirely.
Cutch
2014/03/25 14:39:06
Done.
| |
125 | 118 |
126 // ------------------------------------------------------ | 119 // ------------------------------------------------------ |
127 | 120 |
128 /// Returns true if [map] is a service map. i.e. it has the following keys: | 121 /// Returns true if [map] is a service map. i.e. it has the following keys: |
129 /// 'id' and a 'type'. | 122 /// 'id' and a 'type'. |
130 static bool isServiceMap(ObservableMap m) { | 123 static bool isServiceMap(ObservableMap m) { |
131 return (m != null) && (m['id'] != null) && (m['type'] != null); | 124 return (m != null) && (m['id'] != null) && (m['type'] != null); |
132 } | 125 } |
133 | 126 |
134 /// Returns true if [type] is a reference type. i.e. it begins with an | 127 /// Returns true if [type] is a reference type. i.e. it begins with an |
(...skipping 29 matching lines...) Expand all Loading... | |
164 assert(_isolates == null); | 157 assert(_isolates == null); |
165 _isolates = new IsolateList(this); | 158 _isolates = new IsolateList(this); |
166 name = "vm"; | 159 name = "vm"; |
167 vmName = "vm"; | 160 vmName = "vm"; |
168 } | 161 } |
169 | 162 |
170 VM() : super(null, "vm", "VM") { | 163 VM() : super(null, "vm", "VM") { |
171 _initOnce(); | 164 _initOnce(); |
172 } | 165 } |
173 | 166 |
167 final StreamController<ServiceException> exceptions = | |
168 new StreamController.broadcast(); | |
169 final StreamController<ServiceError> errors = | |
170 new StreamController.broadcast(); | |
171 | |
174 static final RegExp _currentIsolateMatcher = new RegExp(r'isolates/\d+'); | 172 static final RegExp _currentIsolateMatcher = new RegExp(r'isolates/\d+'); |
175 static final RegExp _currentObjectMatcher = new RegExp(r'isolates/\d+(/|$)'); | 173 static final RegExp _currentObjectMatcher = new RegExp(r'isolates/\d+(/|$)'); |
176 | 174 |
177 String _parseObjectId(String id) { | 175 String _parseObjectId(String id) { |
178 Match m = _currentObjectMatcher.matchAsPrefix(id); | 176 Match m = _currentObjectMatcher.matchAsPrefix(id); |
179 if (m == null) { | 177 if (m == null) { |
180 return null; | 178 return null; |
181 } | 179 } |
182 return m.input.substring(m.end); | 180 return m.input.substring(m.end); |
183 } | 181 } |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
215 } | 213 } |
216 } | 214 } |
217 } | 215 } |
218 } else if (id == 'vm') { | 216 } else if (id == 'vm') { |
219 return reload(); | 217 return reload(); |
220 } else { | 218 } else { |
221 return getDirect(id); | 219 return getDirect(id); |
222 } | 220 } |
223 } | 221 } |
224 | 222 |
225 /// Gets [id] as an [ObservableMap] from the service directly. | 223 /// Gets [id] as an [ObservableMap] from the service directly. If |
224 /// an error occurs, the future is completed as an error with a | |
225 /// ServiceError or ServiceException. Therefore the chained then() | |
226 /// execution path will always receive a map encoding a ServiceObject. | |
226 Future<ObservableMap> getAsMap(String id) { | 227 Future<ObservableMap> getAsMap(String id) { |
227 return getString(id).then((response) { | 228 return getString(id).then((response) { |
228 try { | 229 try { |
229 var map = JSON.decode(response); | 230 var map = toObservable(JSON.decode(response)); |
230 Logger.root.info('Decoded $id'); | 231 if (!ServiceObject.isServiceMap(map)) { |
231 Logger.root.info('Response $response'); | 232 return new Future.error( |
232 return toObservable(map); | 233 new ServiceException.fromMap(this, toObservable({ |
234 'type': 'ServiceException', | |
235 'id': '', | |
236 'kind': 'FormatException', | |
237 'response': map, | |
238 'message': 'Top level service responses must be service maps.', | |
239 }))); | |
240 } | |
241 // Preemptively capture ServiceError and ServiceExceptions. | |
242 if (map['type'] == 'ServiceError') { | |
243 return new Future.error(new ServiceError.fromMap(this, map)); | |
244 } else if (map['type'] == 'ServiceException') { | |
245 return new Future.error(new ServiceException.fromMap(this, map)); | |
246 } | |
247 // map is now guaranteed to be a non-error/exception ServiceObject. | |
248 return map; | |
233 } catch (e, st) { | 249 } catch (e, st) { |
234 return toObservable({ | 250 print(e); |
235 'type': 'Error', | 251 print(st); |
252 return new Future.error( | |
253 new ServiceException.fromMap(this, toObservable({ | |
254 'type': 'ServiceException', | |
236 'id': '', | 255 'id': '', |
237 'kind': 'DecodeError', | 256 'kind': 'DecodeException', |
238 'message': '$e', | 257 'response': response, |
239 }); | 258 'message': 'Could not decode JSON: $e', |
259 }))); | |
240 } | 260 } |
241 }).catchError((error) { | 261 }).catchError((error) { |
242 return toObservable({ | 262 // ServiceError. |
243 'type': 'Error', | 263 errors.add(error); |
244 'id': '', | 264 return new Future.error(error); |
245 'kind': 'LastResort', | 265 }, test: (e) => e is ServiceError).catchError((exception) { |
turnidge
2014/03/24 20:22:13
I hadn't seen the "test" stuff before. Wacky!
| |
246 'message': '$error' | 266 // ServiceException. |
247 }); | 267 exceptions.add(exception); |
248 }); | 268 return new Future.error(exception); |
269 }, test: (e) => e is ServiceException); | |
249 } | 270 } |
250 | 271 |
251 /// Get [id] as a [String] from the service directly. See [getAsMap]. | 272 /// Get [id] as a [String] from the service directly. See [getAsMap]. |
252 Future<String> getString(String id); | 273 Future<String> getString(String id); |
253 | 274 |
254 void _update(ObservableMap map) { | 275 void _update(ObservableMap map) { |
255 _ref = false; | 276 _ref = false; |
256 version = map['version']; | 277 version = map['version']; |
257 architecture = map['architecture']; | 278 architecture = map['architecture']; |
258 uptime = map['uptime']; | 279 uptime = map['uptime']; |
259 _isolates.updateIsolates(map['isolates']); | 280 _isolates.updateIsolates(map['isolates']); |
260 allIsolates.clear(); | 281 allIsolates.clear(); |
261 allIsolates.addAll(_isolates.isolates.values); | 282 allIsolates.addAll(_isolates.isolates.values); |
262 } | 283 } |
263 } | 284 } |
264 | 285 |
286 class TagProfileSnapshot { | |
287 final double seconds; | |
288 final List<int> counters; | |
289 int get sum => _sum; | |
290 int _sum = 0; | |
291 TagProfileSnapshot(this.seconds, int countersLength) | |
292 : counters = new List<int>(countersLength); | |
293 | |
294 /// Set [counters] and update [sum]. | |
295 void set(List<int> counters) { | |
296 this.counters.setAll(0, counters); | |
297 for (var i = 0; i < this.counters.length; i++) { | |
298 _sum += this.counters[i]; | |
299 } | |
300 } | |
301 | |
302 /// Set [counters] with the delta from [counters] to [old_counters] | |
303 /// and update [sum]. | |
304 void delta(List<int> counters, List<int> old_counters) { | |
305 for (var i = 0; i < this.counters.length; i++) { | |
306 this.counters[i] = counters[i] - old_counters[i]; | |
307 _sum += this.counters[i]; | |
308 } | |
309 } | |
310 | |
311 /// Update [counters] with new maximum values seen in [counters]. | |
312 void max(List<int> counters) { | |
313 for (var i = 0; i < counters.length; i++) { | |
314 var c = counters[i]; | |
315 this.counters[i] = this.counters[i] > c ? this.counters[i] : c; | |
316 } | |
317 } | |
318 | |
319 /// Zero [counters]. | |
320 void zero() { | |
321 for (var i = 0; i < counters.length; i++) { | |
322 counters[i] = 0; | |
323 } | |
324 } | |
325 } | |
326 | |
327 class TagProfile { | |
328 final List<String> names = new List<String>(); | |
329 final List<TagProfileSnapshot> snapshots = new List<TagProfileSnapshot>(); | |
330 double get updatedAtSeconds => _seconds; | |
331 double _seconds; | |
332 TagProfileSnapshot _maxSnapshot; | |
333 int _historySize; | |
334 int _countersLength = 0; | |
335 | |
336 TagProfile(this._historySize); | |
337 | |
338 void _processTagProfile(double seconds, ObservableMap tagProfile) { | |
339 _seconds = seconds; | |
340 var counters = tagProfile['counters']; | |
341 if (names.length == 0) { | |
342 // Initialization. | |
343 names.addAll(tagProfile['names']); | |
344 _countersLength = tagProfile['counters'].length; | |
345 for (var i = 0; i < _historySize; i++) { | |
346 var snapshot = new TagProfileSnapshot(0.0, _countersLength); | |
347 snapshot.zero(); | |
348 snapshots.add(snapshot); | |
349 } | |
350 // The counters monotonically grow, keep track of the maximum value. | |
351 _maxSnapshot = new TagProfileSnapshot(0.0, _countersLength); | |
352 _maxSnapshot.set(counters); | |
353 return; | |
354 } | |
355 var snapshot = new TagProfileSnapshot(seconds, _countersLength); | |
356 // We snapshot the delta from the current counters to the maximum counter | |
357 // values. | |
358 snapshot.delta(counters, _maxSnapshot.counters); | |
359 _maxSnapshot.max(counters); | |
360 snapshots.add(snapshot); | |
361 // Only keep _historySize snapshots. | |
362 if (snapshots.length > _historySize) { | |
363 snapshots.removeAt(0); | |
364 } | |
365 } | |
366 } | |
turnidge
2014/03/24 20:22:13
What do you think of us moving the profilng helper
Cutch
2014/03/25 14:39:06
sgtm.
| |
367 | |
265 /// State for a running isolate. | 368 /// State for a running isolate. |
266 class Isolate extends ServiceObject { | 369 class Isolate extends ServiceObject { |
370 final TagProfile tagProfile = new TagProfile(20); | |
371 | |
267 String get link => _id; | 372 String get link => _id; |
268 String get hashLink => '#/$_id'; | 373 String get hashLink => '#/$_id'; |
269 | 374 |
270 @observable bool pausedOnStart = false; | 375 @observable bool pausedOnStart = false; |
271 @observable bool pausedOnExit = false; | 376 @observable bool pausedOnExit = false; |
272 @observable bool running = false; | 377 @observable bool running = false; |
273 @observable bool idle = false; | 378 @observable bool idle = false; |
274 | 379 |
275 ScriptCache _scripts; | 380 ScriptCache _scripts; |
276 /// Script cache. | 381 /// Script cache. |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
365 @observable final Map<String, double> timers = | 470 @observable final Map<String, double> timers = |
366 toObservable(new Map<String, double>()); | 471 toObservable(new Map<String, double>()); |
367 | 472 |
368 @observable int newHeapUsed = 0; | 473 @observable int newHeapUsed = 0; |
369 @observable int oldHeapUsed = 0; | 474 @observable int oldHeapUsed = 0; |
370 @observable int newHeapCapacity = 0; | 475 @observable int newHeapCapacity = 0; |
371 @observable int oldHeapCapacity = 0; | 476 @observable int oldHeapCapacity = 0; |
372 | 477 |
373 @observable String fileAndLine; | 478 @observable String fileAndLine; |
374 | 479 |
480 @observable DartError stickyError; | |
481 | |
375 void _update(ObservableMap map) { | 482 void _update(ObservableMap map) { |
376 upgradeCollection(map, vm, this); | 483 upgradeCollection(map, vm, this); |
377 mainPort = map['mainPort']; | 484 mainPort = map['mainPort']; |
378 name = map['name']; | 485 name = map['name']; |
379 if (ServiceObject.isRefType(map['type'])) { | 486 if (ServiceObject.isRefType(map['type'])) { |
380 return; | 487 return; |
381 } | 488 } |
382 _ref = false; | 489 _ref = false; |
383 if (map['rootLib'] == null || | 490 if (map['rootLib'] == null || |
384 map['timers'] == null || | 491 map['timers'] == null || |
(...skipping 28 matching lines...) Expand all Loading... | |
413 newHeapUsed = map['heap']['usedNew']; | 520 newHeapUsed = map['heap']['usedNew']; |
414 oldHeapUsed = map['heap']['usedOld']; | 521 oldHeapUsed = map['heap']['usedOld']; |
415 newHeapCapacity = map['heap']['capacityNew']; | 522 newHeapCapacity = map['heap']['capacityNew']; |
416 oldHeapCapacity = map['heap']['capacityOld']; | 523 oldHeapCapacity = map['heap']['capacityOld']; |
417 | 524 |
418 // Isolate status | 525 // Isolate status |
419 pausedOnStart = map['pausedOnStart']; | 526 pausedOnStart = map['pausedOnStart']; |
420 pausedOnExit = map['pausedOnExit']; | 527 pausedOnExit = map['pausedOnExit']; |
421 running = map['topFrame'] != null; | 528 running = map['topFrame'] != null; |
422 idle = !pausedOnStart && !pausedOnExit && !running; | 529 idle = !pausedOnStart && !pausedOnExit && !running; |
530 stickyError = map['stickyError']; | |
531 } | |
532 | |
533 Future<TagProfile> updateTagProfile() { | |
534 return vm.getAsMap(relativeLink('profile/tag')).then((ObservableMap m) { | |
535 var seconds = new DateTime.now().millisecondsSinceEpoch / 1000.0; | |
536 tagProfile._processTagProfile(seconds, m); | |
537 return tagProfile; | |
538 }); | |
423 } | 539 } |
424 | 540 |
425 @reflectable CodeTrieNode profileTrieRoot; | 541 @reflectable CodeTrieNode profileTrieRoot; |
426 // The profile trie is serialized as a list of integers. Each node | 542 // The profile trie is serialized as a list of integers. Each node |
427 // is recreated by consuming some portion of the list. The format is as | 543 // is recreated by consuming some portion of the list. The format is as |
428 // follows: | 544 // follows: |
429 // [0] index into codeTable of code object. | 545 // [0] index into codeTable of code object. |
430 // [1] tick count (number of times this stack frame occured). | 546 // [1] tick count (number of times this stack frame occured). |
431 // [2] child node count | 547 // [2] child node count |
432 // Reading the trie is done by recursively reading the tree depth-first | 548 // Reading the trie is done by recursively reading the tree depth-first |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
467 return node; | 583 return node; |
468 } | 584 } |
469 } | 585 } |
470 | 586 |
471 // TODO(johnmccutchan): Make this into an IsolateCache. | 587 // TODO(johnmccutchan): Make this into an IsolateCache. |
472 class IsolateList { | 588 class IsolateList { |
473 final VM _vm; | 589 final VM _vm; |
474 final isolates = new ObservableMap<String, Isolate>(); | 590 final isolates = new ObservableMap<String, Isolate>(); |
475 | 591 |
476 IsolateList(this._vm); | 592 IsolateList(this._vm); |
477 | 593 |
478 void updateIsolates(List<Map> members) { | 594 void updateIsolates(List<Map> members) { |
479 // Find dead isolates. | 595 // Find dead isolates. |
480 var deadIsolates = []; | 596 var deadIsolates = []; |
481 isolates.forEach((k, v) { | 597 isolates.forEach((k, v) { |
482 if (!_foundIsolateInMembers(k, members)) { | 598 if (!_foundIsolateInMembers(k, members)) { |
483 deadIsolates.add(k); | 599 deadIsolates.add(k); |
484 } | 600 } |
485 }); | 601 }); |
486 // Remove them. | 602 // Remove them. |
487 deadIsolates.forEach((id) { | 603 deadIsolates.forEach((id) { |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
538 isolates[id] = isolate; | 654 isolates[id] = isolate; |
539 isolate.load(); | 655 isolate.load(); |
540 return isolate; | 656 return isolate; |
541 } | 657 } |
542 | 658 |
543 static bool _foundIsolateInMembers(String id, List<Map> members) { | 659 static bool _foundIsolateInMembers(String id, List<Map> members) { |
544 return members.any((E) => E['id'] == id); | 660 return members.any((E) => E['id'] == id); |
545 } | 661 } |
546 } | 662 } |
547 | 663 |
548 | |
549 /// A [ServiceObject] which implements [ObservableMap]. | 664 /// A [ServiceObject] which implements [ObservableMap]. |
550 class ServiceMap extends ServiceObject implements ObservableMap { | 665 class ServiceMap extends ServiceObject implements ObservableMap { |
551 final ObservableMap _map = new ObservableMap(); | 666 final ObservableMap _map = new ObservableMap(); |
552 ServiceMap(Isolate isolate, String id, String serviceType) : | 667 ServiceMap(Isolate isolate, String id, String serviceType) : |
553 super(isolate, id, serviceType) { | 668 super(isolate, id, serviceType) { |
554 } | 669 } |
555 | 670 |
556 ServiceMap.fromMap(Isolate isolate, ObservableMap m) : | 671 ServiceMap.fromMap(Isolate isolate, ObservableMap m) : |
557 super.fromMap(isolate, m); | 672 super.fromMap(isolate, m); |
558 | 673 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
591 bool deliverChanges() => _map.deliverChanges(); | 706 bool deliverChanges() => _map.deliverChanges(); |
592 void notifyChange(ChangeRecord record) => _map.notifyChange(record); | 707 void notifyChange(ChangeRecord record) => _map.notifyChange(record); |
593 notifyPropertyChange(Symbol field, Object oldValue, Object newValue) => | 708 notifyPropertyChange(Symbol field, Object oldValue, Object newValue) => |
594 _map.notifyPropertyChange(field, oldValue, newValue); | 709 _map.notifyPropertyChange(field, oldValue, newValue); |
595 void observed() => _map.observed(); | 710 void observed() => _map.observed(); |
596 void unobserved() => _map.unobserved(); | 711 void unobserved() => _map.unobserved(); |
597 Stream<List<ChangeRecord>> get changes => _map.changes; | 712 Stream<List<ChangeRecord>> get changes => _map.changes; |
598 bool get hasObservers => _map.hasObservers; | 713 bool get hasObservers => _map.hasObservers; |
599 } | 714 } |
600 | 715 |
601 class ServiceError extends ServiceObject { | 716 /// A [DartError] is peered to a Dart Error object. |
602 ServiceError.fromMap(ServiceObject owner, Map m) : super.fromMap(owner, m); | 717 class DartError extends ServiceObject { |
718 DartError.fromMap(ServiceObject owner, Map m) : super.fromMap(owner, m); | |
603 | 719 |
604 @observable String kind; | 720 @observable String kind; |
605 @observable String message; | 721 @observable String message; |
722 @observable ServiceMap exception; | |
723 @observable ServiceMap stacktrace; | |
724 | |
725 void _update(ObservableMap map) { | |
726 kind = map['kind']; | |
727 message = map['message']; | |
728 if (map['exception'] != null) { | |
729 exception = new ServiceMap.fromMap(owner, map['exception']); | |
730 } else { | |
731 exception = null; | |
732 } | |
733 if (map['stacktrace'] != null) { | |
734 stacktrace = new ServiceMap.fromMap(owner, map['stacktrace']); | |
735 } else { | |
736 stacktrace = null; | |
737 } | |
738 name = 'DartError $kind'; | |
739 vmName = name; | |
740 } | |
741 | |
742 // TODO: stackTrace? | |
turnidge
2014/03/24 20:22:13
Delete this TODO?
Cutch
2014/03/25 14:39:06
Done.
| |
743 } | |
744 | |
745 /// A [ServiceError] is an error that was triggered in the service | |
746 /// server or client. Errors are prorammer mistakes that could have | |
747 /// been prevented, for example, requesting a non-existant path over the | |
748 /// service. | |
749 class ServiceError extends ServiceObject { | |
750 ServiceError.fromMap(ServiceObject owner, Map m) | |
751 : super.fromMap(owner, m); | |
752 | |
753 @observable String kind; | |
754 @observable String message; | |
606 | 755 |
607 void _update(ObservableMap map) { | 756 void _update(ObservableMap map) { |
608 kind = map['kind']; | 757 kind = map['kind']; |
609 message = map['message']; | 758 message = map['message']; |
610 name = 'ServiceError $kind'; | 759 name = 'ServiceError $kind'; |
611 vmName = name; | 760 vmName = name; |
612 } | 761 } |
762 } | |
613 | 763 |
614 // TODO: stackTrace? | 764 /// A [ServiceException] is an exception that was triggered in the service |
765 /// server or client. Exceptions are events that should be handled, | |
766 /// for example, an isolate went away or the connection to the VM was lost. | |
767 class ServiceException extends ServiceObject { | |
768 ServiceException.fromMap(ServiceObject owner, Map m) | |
769 : super.fromMap(owner, m); | |
770 | |
771 @observable String kind; | |
772 @observable String message; | |
773 @observable dynamic response; | |
774 | |
775 void _update(ObservableMap map) { | |
776 kind = map['kind']; | |
777 message = map['message']; | |
778 response = map['response']; | |
779 name = 'ServiceException $kind'; | |
780 vmName = name; | |
781 } | |
615 } | 782 } |
616 | 783 |
617 class ScriptLine { | 784 class ScriptLine { |
618 @reflectable final int line; | 785 @reflectable final int line; |
619 @reflectable final String text; | 786 @reflectable final String text; |
620 ScriptLine(this.line, this.text); | 787 ScriptLine(this.line, this.text); |
621 } | 788 } |
622 | 789 |
623 class Script extends ServiceObject { | 790 class Script extends ServiceObject { |
624 @reflectable final lines = new ObservableList<ScriptLine>(); | 791 @reflectable final lines = new ObservableList<ScriptLine>(); |
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
877 void _update(ObservableMap m) { | 1044 void _update(ObservableMap m) { |
878 assert(ServiceObject.isServiceMap(m)); | 1045 assert(ServiceObject.isServiceMap(m)); |
879 assert(m['id'] == _id); | 1046 assert(m['id'] == _id); |
880 assert(ServiceObject.stripRef(m['type']) == _serviceType); | 1047 assert(ServiceObject.stripRef(m['type']) == _serviceType); |
881 name = m['user_name']; | 1048 name = m['user_name']; |
882 vmName = m['name']; | 1049 vmName = m['name']; |
883 kind = CodeKind.fromString(m['kind']); | 1050 kind = CodeKind.fromString(m['kind']); |
884 startAddress = int.parse(m['start'], radix:16); | 1051 startAddress = int.parse(m['start'], radix:16); |
885 endAddress = int.parse(m['end'], radix:16); | 1052 endAddress = int.parse(m['end'], radix:16); |
886 function = _upgradeToServiceObject(vm, isolate, m['function']); | 1053 function = _upgradeToServiceObject(vm, isolate, m['function']); |
887 objectPool = _upgradeToServiceObject(vm, isolate, m['object_pool']); | 1054 if (m['object_pool'] != null) { |
1055 objectPool = _upgradeToServiceObject(vm, isolate, m['object_pool']); | |
1056 } else { | |
1057 objectPool = null; | |
1058 } | |
888 var disassembly = m['disassembly']; | 1059 var disassembly = m['disassembly']; |
889 if (disassembly != null) { | 1060 if (disassembly != null) { |
890 _processDisassembly(disassembly); | 1061 _processDisassembly(disassembly); |
891 } | 1062 } |
892 // We are a reference if we don't have instructions and are Dart code. | 1063 // We are a reference if we don't have instructions and are Dart code. |
893 _ref = (instructions.length == 0) && (kind == CodeKind.Dart); | 1064 _ref = (instructions.length == 0) && (kind == CodeKind.Dart); |
894 hasDisassembly = (instructions.length != 0) && (kind == CodeKind.Dart); | 1065 hasDisassembly = (instructions.length != 0) && (kind == CodeKind.Dart); |
895 } | 1066 } |
896 | 1067 |
897 @observable bool hasDisassembly = false; | 1068 @observable bool hasDisassembly = false; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
949 | 1120 |
950 int _callCount(List<CodeCallCount> calls, Code code) { | 1121 int _callCount(List<CodeCallCount> calls, Code code) { |
951 for (CodeCallCount caller in calls) { | 1122 for (CodeCallCount caller in calls) { |
952 if (caller.code == code) { | 1123 if (caller.code == code) { |
953 return caller.count; | 1124 return caller.count; |
954 } | 1125 } |
955 } | 1126 } |
956 return 0; | 1127 return 0; |
957 } | 1128 } |
958 } | 1129 } |
OLD | NEW |