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] represents a persistent object within the vm. | 7 /// A [ServiceObject] represents a persistent object within the vm. |
8 abstract class ServiceObject extends Observable { | 8 abstract class ServiceObject extends Observable { |
9 static int LexicalSortName(ServiceObject o1, ServiceObject o2) { | 9 static int LexicalSortName(ServiceObject o1, ServiceObject o2) { |
10 return o1.name.compareTo(o2.name); | 10 return o1.name.compareTo(o2.name); |
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
336 // TODO(johnmccutchan): Ensure that isolates do not end up in _cache. | 336 // TODO(johnmccutchan): Ensure that isolates do not end up in _cache. |
337 Map<String,ServiceObject> _cache = new Map<String,ServiceObject>(); | 337 Map<String,ServiceObject> _cache = new Map<String,ServiceObject>(); |
338 final ObservableMap<String,Isolate> _isolateCache = | 338 final ObservableMap<String,Isolate> _isolateCache = |
339 new ObservableMap<String,Isolate>(); | 339 new ObservableMap<String,Isolate>(); |
340 | 340 |
341 @reflectable Iterable<Isolate> get isolates => _isolateCache.values; | 341 @reflectable Iterable<Isolate> get isolates => _isolateCache.values; |
342 | 342 |
343 @observable String version = 'unknown'; | 343 @observable String version = 'unknown'; |
344 @observable String targetCPU; | 344 @observable String targetCPU; |
345 @observable int architectureBits; | 345 @observable int architectureBits; |
346 @observable double uptime = 0.0; | |
347 @observable bool assertsEnabled = false; | 346 @observable bool assertsEnabled = false; |
348 @observable bool typeChecksEnabled = false; | 347 @observable bool typeChecksEnabled = false; |
349 @observable String pid = ''; | 348 @observable String pid = ''; |
350 @observable DateTime lastUpdate; | 349 @observable DateTime startTime; |
350 @observable DateTime refreshTime; | |
351 @observable Duration get upTime => | |
352 (new DateTime.now().difference(startTime)); | |
351 | 353 |
352 VM() : super._empty(null) { | 354 VM() : super._empty(null) { |
353 name = 'vm'; | 355 name = 'vm'; |
354 vmName = 'vm'; | 356 vmName = 'vm'; |
355 _cache['vm'] = this; | 357 _cache['vm'] = this; |
356 update(toObservable({'id':'vm', 'type':'@VM'})); | 358 update(toObservable({'id':'vm', 'type':'@VM'})); |
357 } | 359 } |
358 | 360 |
359 final StreamController<ServiceException> exceptions = | 361 final StreamController<ServiceException> exceptions = |
360 new StreamController.broadcast(); | 362 new StreamController.broadcast(); |
361 final StreamController<ServiceError> errors = | 363 final StreamController<ServiceError> errors = |
362 new StreamController.broadcast(); | 364 new StreamController.broadcast(); |
363 final StreamController<ServiceEvent> events = | 365 final StreamController<ServiceEvent> events = |
364 new StreamController.broadcast(); | 366 new StreamController.broadcast(); |
365 | 367 |
366 bool _isIsolateLifecycleEvent(String eventType) { | |
367 return _isIsolateExitEvent(eventType) || | |
368 _isIsolateStartEvent(eventType); | |
369 } | |
370 | |
371 bool _isIsolateExitEvent(String eventType) { | |
372 return (eventType == ServiceEvent.kIsolateExit); | |
373 } | |
374 | |
375 bool _isIsolateStartEvent(String eventType) { | |
376 return (eventType == ServiceEvent.kIsolateStart); | |
377 } | |
378 | |
379 void postServiceEvent(String response, ByteData data) { | 368 void postServiceEvent(String response, ByteData data) { |
380 var map; | 369 var map; |
381 try { | 370 try { |
382 map = _parseJSON(response); | 371 map = _parseJSON(response); |
383 assert(!map.containsKey('_data')); | 372 assert(!map.containsKey('_data')); |
384 if (data != null) { | 373 if (data != null) { |
385 map['_data'] = data; | 374 map['_data'] = data; |
386 } | 375 } |
387 } catch (e, st) { | 376 } catch (e, st) { |
388 Logger.root.severe('Ignoring malformed event response: ${response}'); | 377 Logger.root.severe('Ignoring malformed event response: ${response}'); |
389 return; | 378 return; |
390 } | 379 } |
391 if (map['type'] != 'ServiceEvent') { | 380 if (map['type'] != 'ServiceEvent') { |
392 Logger.root.severe( | 381 Logger.root.severe( |
393 "Expected 'ServiceEvent' but found '${map['type']}'"); | 382 "Expected 'ServiceEvent' but found '${map['type']}'"); |
394 return; | 383 return; |
395 } | 384 } |
396 | 385 |
397 var eventType = map['eventType']; | 386 var eventIsolate = map['isolate']; |
398 | 387 if (eventIsolate == null) { |
399 if (_isIsolateLifecycleEvent(eventType)) { | 388 var event = new ServiceObject._fromMap(vm, map); |
400 String isolateId = map['isolate']['id']; | 389 events.add(event); |
401 var event; | 390 } else { |
402 if (_isIsolateStartEvent(eventType)) { | 391 // getFromMap creates the Isolate if it hasn't been seen already. |
403 _onIsolateStart(map['isolate']); | 392 var isolate = getFromMap(map['isolate']); |
404 // By constructing the event *after* adding the isolate to the | 393 var event = new ServiceObject._fromMap(isolate, map); |
405 // isolate cache, the call to getFromMap will use the cached Isolate. | 394 if (event.eventType == ServiceEvent.kIsolateExit) { |
406 event = new ServiceObject._fromMap(this, map); | 395 _removeIsolate(isolate.id); |
407 } else { | |
408 assert(_isIsolateExitEvent(eventType)); | |
409 // By constructing the event *before* removing the isolate from the | |
410 // isolate cache, the call to getFromMap will use the cached Isolate. | |
411 event = new ServiceObject._fromMap(this, map); | |
412 _onIsolateExit(isolateId); | |
413 } | 396 } |
414 assert(event != null); | 397 isolate._onEvent(event); |
415 events.add(event); | 398 events.add(event); |
416 return; | |
417 } | 399 } |
418 | |
419 // Extract the owning isolate from the event itself. | |
420 String owningIsolateId = map['isolate']['id']; | |
421 getIsolate(owningIsolateId).then((owningIsolate) { | |
422 if (owningIsolate == null) { | |
423 // TODO(koda): Do we care about GC events in VM isolate? | |
424 Logger.root.severe('Ignoring event with unknown isolate id: ' | |
425 '$owningIsolateId'); | |
426 return; | |
427 } | |
428 var event = new ServiceObject._fromMap(owningIsolate, map); | |
429 owningIsolate._onEvent(event); | |
430 events.add(event); | |
431 }); | |
432 } | 400 } |
433 | 401 |
434 Isolate _onIsolateStart(Map isolateMap) { | 402 void _removeIsolate(String isolateId) { |
435 var isolateId = isolateMap['id']; | |
436 assert(!_isolateCache.containsKey(isolateId)); | |
437 Isolate isolate = new ServiceObject._fromMap(this, isolateMap); | |
438 _isolateCache[isolateId] = isolate; | |
439 notifyPropertyChange(#isolates, true, false); | |
440 // Eagerly load the isolate. | |
441 isolate.load().catchError((e) { | |
442 Logger.root.info('Eagerly loading an isolate failed: $e'); | |
443 }); | |
444 return isolate; | |
445 } | |
446 | |
447 void _onIsolateExit(String isolateId) { | |
448 assert(_isolateCache.containsKey(isolateId)); | 403 assert(_isolateCache.containsKey(isolateId)); |
449 _isolateCache.remove(isolateId); | 404 _isolateCache.remove(isolateId); |
450 notifyPropertyChange(#isolates, true, false); | 405 notifyPropertyChange(#isolates, true, false); |
451 } | 406 } |
452 | 407 |
453 void _updateIsolatesFromList(List isolateList) { | 408 void _updateIsolates(List newIsolates) { |
454 var shutdownIsolates = <String>[]; | 409 // Build a set of new isolates. |
455 var createdIsolates = <Map>[]; | 410 var newIsolateSet = new Set(); |
456 var isolateStillExists = <String, bool>{}; | 411 newIsolates.forEach((iso) => newIsolateSet.add(iso.id)); |
457 | 412 |
458 // Start with the assumption that all isolates are gone. | 413 // Remove any old isolates which no longer exist. |
459 for (var isolateId in _isolateCache.keys) { | 414 List toRemove = []; |
460 isolateStillExists[isolateId] = false; | 415 _isolateCache.forEach((id, _) { |
461 } | 416 if (!newIsolateSet.contains(id)) { |
462 | 417 toRemove.add(id); |
463 // Find created isolates and mark existing isolates as living. | |
464 for (var isolateMap in isolateList) { | |
465 var isolateId = isolateMap['id']; | |
466 if (!_isolateCache.containsKey(isolateId)) { | |
467 createdIsolates.add(isolateMap); | |
468 } else { | |
469 isolateStillExists[isolateId] = true; | |
470 } | |
471 } | |
472 | |
473 // Find shutdown isolates. | |
474 isolateStillExists.forEach((isolateId, exists) { | |
475 if (!exists) { | |
476 shutdownIsolates.add(isolateId); | |
477 } | 418 } |
478 }); | 419 }); |
479 | 420 toRemove.forEach((id) => _removeIsolate(id)); |
480 // Process shutdown. | 421 notifyPropertyChange(#isolates, true, false); |
481 for (var isolateId in shutdownIsolates) { | |
482 _onIsolateExit(isolateId); | |
483 } | |
484 | |
485 // Process creation. | |
486 for (var isolateMap in createdIsolates) { | |
487 _onIsolateStart(isolateMap); | |
488 } | |
489 } | 422 } |
490 | 423 |
491 static final String _isolateIdPrefix = 'isolates/'; | 424 static final String _isolateIdPrefix = 'isolates/'; |
492 | 425 |
493 ServiceObject getFromMap(ObservableMap map) { | 426 ServiceObject getFromMap(ObservableMap map) { |
494 if (map == null) { | 427 if (map == null) { |
495 return null; | 428 return null; |
496 } | 429 } |
497 String id = map['id']; | 430 String id = map['id']; |
498 if (!id.startsWith(_isolateIdPrefix)) { | 431 if (!id.startsWith(_isolateIdPrefix)) { |
499 // Currently the VM only supports upgrading Isolate ServiceObjects. | 432 // Currently the VM only supports upgrading Isolate ServiceObjects. |
500 throw new UnimplementedError(); | 433 throw new UnimplementedError(); |
501 } | 434 } |
502 | 435 |
503 // Check cache. | 436 // Check cache. |
504 var isolate = _isolateCache[id]; | 437 var isolate = _isolateCache[id]; |
505 if (isolate == null) { | 438 if (isolate == null) { |
506 // We should never see an unknown isolate here. | 439 // Add new isolate to the cache. |
507 throw new UnimplementedError(); | 440 isolate = new ServiceObject._fromMap(this, map); |
508 } | 441 _isolateCache[id] = isolate; |
509 var mapIsRef = _hasRef(map['type']); | 442 notifyPropertyChange(#isolates, true, false); |
510 if (!mapIsRef) { | 443 |
444 // Eagerly load the isolate. | |
445 isolate.load().catchError((e, stack) { | |
446 Logger.root.info('Eagerly loading an isolate failed: $e\n$stack'); | |
447 }); | |
448 } else { | |
511 isolate.update(map); | 449 isolate.update(map); |
512 } | 450 } |
513 return isolate; | 451 return isolate; |
514 } | 452 } |
515 | 453 |
516 // Note that this function does not reload the isolate if it found | 454 // Note that this function does not reload the isolate if it found |
517 // in the cache. | 455 // in the cache. |
518 Future<ServiceObject> getIsolate(String isolateId) { | 456 Future<ServiceObject> getIsolate(String isolateId) { |
519 if (!loaded) { | 457 if (!loaded) { |
520 // Trigger a VM load, then get the isolate. | 458 // Trigger a VM load, then get the isolate. |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
613 void disconnect(); | 551 void disconnect(); |
614 /// Completes when the VM first connects. | 552 /// Completes when the VM first connects. |
615 Future get onConnect; | 553 Future get onConnect; |
616 /// Completes when the VM disconnects or there was an error connecting. | 554 /// Completes when the VM disconnects or there was an error connecting. |
617 Future get onDisconnect; | 555 Future get onDisconnect; |
618 | 556 |
619 void _update(ObservableMap map, bool mapIsRef) { | 557 void _update(ObservableMap map, bool mapIsRef) { |
620 if (mapIsRef) { | 558 if (mapIsRef) { |
621 return; | 559 return; |
622 } | 560 } |
561 // Note that upgrading the collection creates any isolates in the | |
562 // isolate list which are new. | |
563 _upgradeCollection(map, vm); | |
564 | |
623 _loaded = true; | 565 _loaded = true; |
624 version = map['version']; | 566 version = map['version']; |
625 targetCPU = map['targetCPU']; | 567 targetCPU = map['targetCPU']; |
626 architectureBits = map['architectureBits']; | 568 architectureBits = map['architectureBits']; |
627 uptime = map['uptime']; | 569 var startTimeMillis = map['startTime']; |
628 var dateInMillis = int.parse(map['date']); | 570 startTime = new DateTime.fromMillisecondsSinceEpoch(startTimeMillis); |
629 lastUpdate = new DateTime.fromMillisecondsSinceEpoch(dateInMillis); | 571 var refreshTimeMillis = map['refreshTime']; |
572 refreshTime = new DateTime.fromMillisecondsSinceEpoch(refreshTimeMillis); | |
573 notifyPropertyChange(#upTime, 0, 1); | |
630 assertsEnabled = map['assertsEnabled']; | 574 assertsEnabled = map['assertsEnabled']; |
631 pid = map['pid']; | 575 pid = map['pid']; |
632 typeChecksEnabled = map['typeChecksEnabled']; | 576 typeChecksEnabled = map['typeChecksEnabled']; |
633 _updateIsolatesFromList(map['isolates']); | 577 _updateIsolates(map['isolates']); |
Cutch
2015/03/18 20:05:48
s/_updateIsolates/_removeDeadIsolates
turnidge
2015/03/26 17:46:58
Done.
| |
634 } | 578 } |
635 | 579 |
636 // Reload all isolates. | 580 // Reload all isolates. |
637 Future reloadIsolates() { | 581 Future reloadIsolates() { |
638 var reloads = []; | 582 var reloads = []; |
639 for (var isolate in isolates) { | 583 for (var isolate in isolates) { |
640 var reload = isolate.reload().catchError((e) { | 584 var reload = isolate.reload().catchError((e) { |
641 Logger.root.info('Bulk reloading of isolates failed: $e'); | 585 Logger.root.info('Bulk reloading of isolates failed: $e'); |
642 }); | 586 }); |
643 reloads.add(reload); | 587 reloads.add(reload); |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
769 return result; | 713 return result; |
770 } | 714 } |
771 | 715 |
772 | 716 |
773 } | 717 } |
774 | 718 |
775 /// State for a running isolate. | 719 /// State for a running isolate. |
776 class Isolate extends ServiceObjectOwner with Coverage { | 720 class Isolate extends ServiceObjectOwner with Coverage { |
777 @reflectable VM get vm => owner; | 721 @reflectable VM get vm => owner; |
778 @reflectable Isolate get isolate => this; | 722 @reflectable Isolate get isolate => this; |
723 @observable int number; | |
724 @observable DateTime startTime; | |
725 @observable Duration get upTime => | |
726 (new DateTime.now().difference(startTime)); | |
727 | |
779 @observable ObservableMap counters = new ObservableMap(); | 728 @observable ObservableMap counters = new ObservableMap(); |
780 | 729 |
781 @observable ServiceEvent pauseEvent = null; | |
782 | |
783 void _updateRunState() { | 730 void _updateRunState() { |
784 topFrame = (pauseEvent != null ? pauseEvent.topFrame : null); | 731 topFrame = (pauseEvent != null ? pauseEvent.topFrame : null); |
785 paused = (pauseEvent != null && | 732 paused = (pauseEvent != null && |
786 pauseEvent.eventType != ServiceEvent.kResume); | 733 pauseEvent.eventType != ServiceEvent.kResume); |
787 running = (!paused && topFrame != null); | 734 running = (!paused && topFrame != null); |
788 idle = (!paused && topFrame == null); | 735 idle = (!paused && topFrame == null); |
789 notifyPropertyChange(#topFrame, 0, 1); | 736 notifyPropertyChange(#topFrame, 0, 1); |
790 notifyPropertyChange(#paused, 0, 1); | 737 notifyPropertyChange(#paused, 0, 1); |
791 notifyPropertyChange(#running, 0, 1); | 738 notifyPropertyChange(#running, 0, 1); |
792 notifyPropertyChange(#idle, 0, 1); | 739 notifyPropertyChange(#idle, 0, 1); |
793 } | 740 } |
794 | 741 |
742 @observable ServiceEvent pauseEvent = null; | |
795 @observable bool paused = false; | 743 @observable bool paused = false; |
796 @observable bool running = false; | 744 @observable bool running = false; |
797 @observable bool idle = false; | 745 @observable bool idle = false; |
798 @observable bool loading = true; | 746 @observable bool loading = true; |
799 | 747 |
800 @observable bool ioEnabled = false; | 748 @observable bool ioEnabled = false; |
801 | 749 |
802 Map<String,ServiceObject> _cache = new Map<String,ServiceObject>(); | 750 Map<String,ServiceObject> _cache = new Map<String,ServiceObject>(); |
803 final TagProfile tagProfile = new TagProfile(20); | 751 final TagProfile tagProfile = new TagProfile(20); |
804 | 752 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
852 } | 800 } |
853 } | 801 } |
854 assert(objectClass != null); | 802 assert(objectClass != null); |
855 return new Future.value(objectClass); | 803 return new Future.value(objectClass); |
856 } | 804 } |
857 | 805 |
858 ServiceObject getFromMap(ObservableMap map) { | 806 ServiceObject getFromMap(ObservableMap map) { |
859 if (map == null) { | 807 if (map == null) { |
860 return null; | 808 return null; |
861 } | 809 } |
810 var mapType = _stripRef(map['type']); | |
811 if (mapType == 'Isolate') { | |
812 // There are sometimes isolate refs in ServiceEvents. | |
813 return vm.getFromMap(map); | |
814 } | |
862 String mapId = map['id']; | 815 String mapId = map['id']; |
863 var obj = (mapId != null) ? _cache[mapId] : null; | 816 var obj = (mapId != null) ? _cache[mapId] : null; |
864 if (obj != null) { | 817 if (obj != null) { |
865 var mapIsRef = _hasRef(map['type']); | 818 obj.update(map); |
866 if (!mapIsRef) { | |
867 obj.update(map); | |
868 } | |
869 return obj; | 819 return obj; |
870 } | 820 } |
871 // Build the object from the map directly. | 821 // Build the object from the map directly. |
872 obj = new ServiceObject._fromMap(this, map); | 822 obj = new ServiceObject._fromMap(this, map); |
873 if ((obj != null) && obj.canCache) { | 823 if ((obj != null) && obj.canCache) { |
874 _cache[mapId] = obj; | 824 _cache[mapId] = obj; |
875 } | 825 } |
876 return obj; | 826 return obj; |
877 } | 827 } |
878 | 828 |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
945 | 895 |
946 void updateHeapsFromMap(ObservableMap map) { | 896 void updateHeapsFromMap(ObservableMap map) { |
947 newSpace.update(map['new']); | 897 newSpace.update(map['new']); |
948 oldSpace.update(map['old']); | 898 oldSpace.update(map['old']); |
949 } | 899 } |
950 | 900 |
951 void _update(ObservableMap map, bool mapIsRef) { | 901 void _update(ObservableMap map, bool mapIsRef) { |
952 mainPort = map['mainPort']; | 902 mainPort = map['mainPort']; |
953 name = map['name']; | 903 name = map['name']; |
954 vmName = map['name']; | 904 vmName = map['name']; |
905 number = int.parse(map['number'], onError:(_) => null); | |
955 if (mapIsRef) { | 906 if (mapIsRef) { |
956 return; | 907 return; |
957 } | 908 } |
958 _loaded = true; | 909 _loaded = true; |
959 loading = false; | 910 loading = false; |
960 | 911 |
961 _upgradeCollection(map, isolate); | 912 _upgradeCollection(map, isolate); |
962 if (map['rootLib'] == null || | 913 if (map['rootLib'] == null || |
963 map['timers'] == null || | 914 map['timers'] == null || |
964 map['heaps'] == null) { | 915 map['heaps'] == null) { |
965 Logger.root.severe("Malformed 'Isolate' response: $map"); | 916 Logger.root.severe("Malformed 'Isolate' response: $map"); |
966 return; | 917 return; |
967 } | 918 } |
968 rootLib = map['rootLib']; | 919 rootLib = map['rootLib']; |
969 if (map['entry'] != null) { | 920 if (map['entry'] != null) { |
970 entry = map['entry']; | 921 entry = map['entry']; |
971 } | 922 } |
972 | 923 var startTimeInMillis = map['startTime']; |
924 startTime = new DateTime.fromMillisecondsSinceEpoch(startTimeInMillis); | |
925 notifyPropertyChange(#upTime, 0, 1); | |
973 var countersMap = map['tagCounters']; | 926 var countersMap = map['tagCounters']; |
974 if (countersMap != null) { | 927 if (countersMap != null) { |
975 var names = countersMap['names']; | 928 var names = countersMap['names']; |
976 var counts = countersMap['counters']; | 929 var counts = countersMap['counters']; |
977 assert(names.length == counts.length); | 930 assert(names.length == counts.length); |
978 var sum = 0; | 931 var sum = 0; |
979 for (var i = 0; i < counts.length; i++) { | 932 for (var i = 0; i < counts.length; i++) { |
980 sum += counts[i]; | 933 sum += counts[i]; |
981 } | 934 } |
982 // TODO: Why does this not work without this? | 935 // TODO: Why does this not work without this? |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1030 (ObservableMap map) { | 983 (ObservableMap map) { |
1031 var seconds = new DateTime.now().millisecondsSinceEpoch / 1000.0; | 984 var seconds = new DateTime.now().millisecondsSinceEpoch / 1000.0; |
1032 tagProfile._processTagProfile(seconds, map); | 985 tagProfile._processTagProfile(seconds, map); |
1033 return tagProfile; | 986 return tagProfile; |
1034 }); | 987 }); |
1035 } | 988 } |
1036 | 989 |
1037 ObservableMap<int, Breakpoint> breakpoints = new ObservableMap(); | 990 ObservableMap<int, Breakpoint> breakpoints = new ObservableMap(); |
1038 | 991 |
1039 void _updateBreakpoints(List newBpts) { | 992 void _updateBreakpoints(List newBpts) { |
1040 // Build a map of new breakpoints. | 993 // Build a set of new breakpoints. |
1041 var newBptMap = {}; | 994 var newBptSet = new Set(); |
1042 newBpts.forEach((bpt) => (newBptMap[bpt.number] = bpt)); | 995 newBpts.forEach((bpt) => newBptSet.add(bpt.number)); |
1043 | 996 |
1044 // Remove any old breakpoints which no longer exist. | 997 // Remove any old breakpoints which no longer exist. |
1045 List toRemove = []; | 998 List toRemove = []; |
1046 breakpoints.forEach((key, _) { | 999 breakpoints.forEach((key, _) { |
1047 if (!newBptMap.containsKey(key)) { | 1000 if (!newBptSet.contains(key)) { |
1048 toRemove.add(key); | 1001 toRemove.add(key); |
1049 } | 1002 } |
1050 }); | 1003 }); |
1051 toRemove.forEach((key) => breakpoints.remove(key)); | 1004 toRemove.forEach((key) => breakpoints.remove(key)); |
1052 | 1005 |
1053 // Add all new breakpoints. | 1006 // Add all new breakpoints. |
1054 breakpoints.addAll(newBptMap); | 1007 newBpts.forEach((bpt) => (breakpoints[bpt.number] = bpt)); |
1055 } | 1008 } |
1056 | 1009 |
1057 void _addBreakpoint(Breakpoint bpt) { | 1010 void _addBreakpoint(Breakpoint bpt) { |
1058 breakpoints[bpt.number] = bpt; | 1011 breakpoints[bpt.number] = bpt; |
1059 } | 1012 } |
1060 | 1013 |
1061 void _removeBreakpoint(Breakpoint bpt) { | 1014 void _removeBreakpoint(Breakpoint bpt) { |
1062 breakpoints.remove(bpt.number); | 1015 breakpoints.remove(bpt.number); |
1063 bpt.remove(); | 1016 bpt.remove(); |
1064 } | 1017 } |
1065 | 1018 |
1066 void _onEvent(ServiceEvent event) { | 1019 void _onEvent(ServiceEvent event) { |
1067 assert(event.eventType != ServiceEvent.kIsolateStart && | |
1068 event.eventType != ServiceEvent.kIsolateExit); | |
1069 switch(event.eventType) { | 1020 switch(event.eventType) { |
1021 case ServiceEvent.kIsolateStart: | |
1022 case ServiceEvent.kIsolateExit: | |
1023 // Handled elsewhere. | |
1024 break; | |
1025 | |
1070 case ServiceEvent.kBreakpointAdded: | 1026 case ServiceEvent.kBreakpointAdded: |
1071 _addBreakpoint(event.breakpoint); | 1027 _addBreakpoint(event.breakpoint); |
1072 break; | 1028 break; |
1073 | 1029 |
1030 case ServiceEvent.kIsolateUpdate: | |
1074 case ServiceEvent.kBreakpointResolved: | 1031 case ServiceEvent.kBreakpointResolved: |
1075 // Update occurs as side-effect of caching. | 1032 // Update occurs as side-effect of caching. |
1076 break; | 1033 break; |
1077 | 1034 |
1078 case ServiceEvent.kBreakpointRemoved: | 1035 case ServiceEvent.kBreakpointRemoved: |
1079 _removeBreakpoint(event.breakpoint); | 1036 _removeBreakpoint(event.breakpoint); |
1080 break; | 1037 break; |
1081 | 1038 |
1082 case ServiceEvent.kPauseStart: | 1039 case ServiceEvent.kPauseStart: |
1083 case ServiceEvent.kPauseExit: | 1040 case ServiceEvent.kPauseExit: |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1134 return invokeRpc('removeBreakpoint', | 1091 return invokeRpc('removeBreakpoint', |
1135 { 'breakpointId': bpt.id }); | 1092 { 'breakpointId': bpt.id }); |
1136 } | 1093 } |
1137 | 1094 |
1138 Future pause() { | 1095 Future pause() { |
1139 return invokeRpc('pause', {}).then((result) { | 1096 return invokeRpc('pause', {}).then((result) { |
1140 if (result is DartError) { | 1097 if (result is DartError) { |
1141 // TODO(turnidge): Handle this more gracefully. | 1098 // TODO(turnidge): Handle this more gracefully. |
1142 Logger.root.severe(result.message); | 1099 Logger.root.severe(result.message); |
1143 } | 1100 } |
1101 return result; | |
1144 }); | 1102 }); |
1145 } | 1103 } |
1146 | 1104 |
1147 Future resume() { | 1105 Future resume() { |
1148 return invokeRpc('resume', {}).then((result) { | 1106 return invokeRpc('resume', {}).then((result) { |
1149 if (result is DartError) { | 1107 if (result is DartError) { |
1150 // TODO(turnidge): Handle this more gracefully. | 1108 // TODO(turnidge): Handle this more gracefully. |
1151 Logger.root.severe(result.message); | 1109 Logger.root.severe(result.message); |
1152 } | 1110 } |
1111 return result; | |
1153 }); | 1112 }); |
1154 } | 1113 } |
1155 | 1114 |
1156 Future stepInto() { | 1115 Future stepInto() { |
1157 return invokeRpc('resume', {'step': 'into'}).then((result) { | 1116 return invokeRpc('resume', {'step': 'into'}).then((result) { |
1158 if (result is DartError) { | 1117 if (result is DartError) { |
1159 // TODO(turnidge): Handle this more gracefully. | 1118 // TODO(turnidge): Handle this more gracefully. |
1160 Logger.root.severe(result.message); | 1119 Logger.root.severe(result.message); |
1161 } | 1120 } |
1121 return result; | |
1162 }); | 1122 }); |
1163 } | 1123 } |
1164 | 1124 |
1165 Future stepOver() { | 1125 Future stepOver() { |
1166 return invokeRpc('resume', {'step': 'over'}).then((result) { | 1126 return invokeRpc('resume', {'step': 'over'}).then((result) { |
1167 if (result is DartError) { | 1127 if (result is DartError) { |
1168 // TODO(turnidge): Handle this more gracefully. | 1128 // TODO(turnidge): Handle this more gracefully. |
1169 Logger.root.severe(result.message); | 1129 Logger.root.severe(result.message); |
1170 } | 1130 } |
1131 return result; | |
1171 }); | 1132 }); |
1172 } | 1133 } |
1173 | 1134 |
1174 Future stepOut() { | 1135 Future stepOut() { |
1175 return invokeRpc('resume', {'step': 'out'}).then((result) { | 1136 return invokeRpc('resume', {'step': 'out'}).then((result) { |
1176 if (result is DartError) { | 1137 if (result is DartError) { |
1177 // TODO(turnidge): Handle this more gracefully. | 1138 // TODO(turnidge): Handle this more gracefully. |
1178 Logger.root.severe(result.message); | 1139 Logger.root.severe(result.message); |
1179 } | 1140 } |
1141 return result; | |
1180 }); | 1142 }); |
1181 } | 1143 } |
1182 | 1144 |
1145 Future setName(String newName) { | |
1146 Map params = { | |
1147 'name': newName, | |
1148 }; | |
1149 return invokeRpc('setName', params); | |
1150 } | |
1151 | |
1183 Future<ServiceMap> getStack() { | 1152 Future<ServiceMap> getStack() { |
1184 return invokeRpc('getStack', {}).then((result) { | 1153 return invokeRpc('getStack', {}).then((result) { |
1185 if (result is DartError) { | 1154 if (result is DartError) { |
1186 // TODO(turnidge): Handle this more gracefully. | 1155 // TODO(turnidge): Handle this more gracefully. |
1187 Logger.root.severe(result.message); | 1156 Logger.root.severe(result.message); |
1188 } | 1157 } |
1189 return result; | 1158 return result; |
1190 }); | 1159 }); |
1191 } | 1160 } |
1192 | 1161 |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1415 } | 1384 } |
1416 | 1385 |
1417 String toString() => 'ServiceException($message)'; | 1386 String toString() => 'ServiceException($message)'; |
1418 } | 1387 } |
1419 | 1388 |
1420 /// A [ServiceEvent] is an asynchronous event notification from the vm. | 1389 /// A [ServiceEvent] is an asynchronous event notification from the vm. |
1421 class ServiceEvent extends ServiceObject { | 1390 class ServiceEvent extends ServiceObject { |
1422 /// The possible 'eventType' values. | 1391 /// The possible 'eventType' values. |
1423 static const kIsolateStart = 'IsolateStart'; | 1392 static const kIsolateStart = 'IsolateStart'; |
1424 static const kIsolateExit = 'IsolateExit'; | 1393 static const kIsolateExit = 'IsolateExit'; |
1394 static const kIsolateUpdate = 'IsolateUpdate'; | |
1425 static const kPauseStart = 'PauseStart'; | 1395 static const kPauseStart = 'PauseStart'; |
1426 static const kPauseExit = 'PauseExit'; | 1396 static const kPauseExit = 'PauseExit'; |
1427 static const kPauseBreakpoint = 'PauseBreakpoint'; | 1397 static const kPauseBreakpoint = 'PauseBreakpoint'; |
1428 static const kPauseInterrupted = 'PauseInterrupted'; | 1398 static const kPauseInterrupted = 'PauseInterrupted'; |
1429 static const kPauseException = 'PauseException'; | 1399 static const kPauseException = 'PauseException'; |
1430 static const kResume = 'Resume'; | 1400 static const kResume = 'Resume'; |
1431 static const kBreakpointAdded = 'BreakpointAdded'; | 1401 static const kBreakpointAdded = 'BreakpointAdded'; |
1432 static const kBreakpointResolved = 'BreakpointResolved'; | 1402 static const kBreakpointResolved = 'BreakpointResolved'; |
1433 static const kBreakpointRemoved = 'BreakpointRemoved'; | 1403 static const kBreakpointRemoved = 'BreakpointRemoved'; |
1434 static const kGraph = '_Graph'; | 1404 static const kGraph = '_Graph'; |
1435 static const kGC = 'GC'; | 1405 static const kGC = 'GC'; |
1436 static const kVMDisconnected = 'VMDisconnected'; | 1406 static const kVMDisconnected = 'VMDisconnected'; |
1437 | 1407 |
1438 ServiceEvent._empty(ServiceObjectOwner owner) : super._empty(owner); | 1408 ServiceEvent._empty(ServiceObjectOwner owner) : super._empty(owner); |
1439 | 1409 |
1440 ServiceEvent.vmDisconencted() : super._empty(null) { | 1410 ServiceEvent.vmDisconencted() : super._empty(null) { |
1441 eventType = kVMDisconnected; | 1411 eventType = kVMDisconnected; |
1442 } | 1412 } |
1443 | 1413 |
1444 @observable String eventType; | 1414 @observable String eventType; |
1445 @observable Breakpoint breakpoint; | 1415 @observable Breakpoint breakpoint; |
1446 @observable ServiceMap topFrame; | 1416 @observable ServiceMap topFrame; |
1447 @observable ServiceMap exception; | 1417 @observable ServiceMap exception; |
1448 @observable ByteData data; | 1418 @observable ByteData data; |
1449 @observable int count; | 1419 @observable int count; |
1450 | 1420 |
1451 void _update(ObservableMap map, bool mapIsRef) { | 1421 void _update(ObservableMap map, bool mapIsRef) { |
1452 _loaded = true; | 1422 _loaded = true; |
1453 _upgradeCollection(map, owner); | 1423 _upgradeCollection(map, owner); |
1424 assert(map['isolate'] == null || owner == map['isolate']); | |
1454 eventType = map['eventType']; | 1425 eventType = map['eventType']; |
1455 name = 'ServiceEvent $eventType'; | 1426 name = 'ServiceEvent $eventType'; |
1456 vmName = name; | 1427 vmName = name; |
1457 if (map['breakpoint'] != null) { | 1428 if (map['breakpoint'] != null) { |
1458 breakpoint = map['breakpoint']; | 1429 breakpoint = map['breakpoint']; |
1459 } | 1430 } |
1460 if (map['topFrame'] != null) { | 1431 if (map['topFrame'] != null) { |
1461 topFrame = map['topFrame']; | 1432 topFrame = map['topFrame']; |
1462 } | 1433 } |
1463 if (map['exception'] != null) { | 1434 if (map['exception'] != null) { |
(...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1857 case 'kIrregexpFunction': return kIrregexpFunction; | 1828 case 'kIrregexpFunction': return kIrregexpFunction; |
1858 case 'kStaticInitializer': return kStaticInitializer; | 1829 case 'kStaticInitializer': return kStaticInitializer; |
1859 case 'kMethodExtractor': return kMethodExtractor; | 1830 case 'kMethodExtractor': return kMethodExtractor; |
1860 case 'kNoSuchMethodDispatcher': return kNoSuchMethodDispatcher; | 1831 case 'kNoSuchMethodDispatcher': return kNoSuchMethodDispatcher; |
1861 case 'kInvokeFieldDispatcher': return kInvokeFieldDispatcher; | 1832 case 'kInvokeFieldDispatcher': return kInvokeFieldDispatcher; |
1862 case 'Collected': return kCollected; | 1833 case 'Collected': return kCollected; |
1863 case 'Native': return kNative; | 1834 case 'Native': return kNative; |
1864 case 'Stub': return kStub; | 1835 case 'Stub': return kStub; |
1865 case 'Tag': return kTag; | 1836 case 'Tag': return kTag; |
1866 } | 1837 } |
1867 print('did not understand $value'); | 1838 Logger.root.severe('Unrecognized function kind: $value'); |
1868 throw new FallThroughError(); | 1839 throw new FallThroughError(); |
1869 } | 1840 } |
1870 | 1841 |
1871 static FunctionKind kRegularFunction = new FunctionKind._internal('function'); | 1842 static FunctionKind kRegularFunction = new FunctionKind._internal('function'); |
1872 static FunctionKind kClosureFunction = new FunctionKind._internal('closure fun ction'); | 1843 static FunctionKind kClosureFunction = new FunctionKind._internal('closure fun ction'); |
1873 static FunctionKind kGetterFunction = new FunctionKind._internal('getter funct ion'); | 1844 static FunctionKind kGetterFunction = new FunctionKind._internal('getter funct ion'); |
1874 static FunctionKind kSetterFunction = new FunctionKind._internal('setter funct ion'); | 1845 static FunctionKind kSetterFunction = new FunctionKind._internal('setter funct ion'); |
1875 static FunctionKind kConstructor = new FunctionKind._internal('constructor'); | 1846 static FunctionKind kConstructor = new FunctionKind._internal('constructor'); |
1876 static FunctionKind kImplicitGetterFunction = new FunctionKind._internal('impl icit getter function'); | 1847 static FunctionKind kImplicitGetterFunction = new FunctionKind._internal('impl icit getter function'); |
1877 static FunctionKind kImplicitSetterFunction = new FunctionKind._internal('impl icit setter function'); | 1848 static FunctionKind kImplicitSetterFunction = new FunctionKind._internal('impl icit setter function'); |
(...skipping 545 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2423 return Native; | 2394 return Native; |
2424 } else if (s == 'Dart') { | 2395 } else if (s == 'Dart') { |
2425 return Dart; | 2396 return Dart; |
2426 } else if (s == 'Collected') { | 2397 } else if (s == 'Collected') { |
2427 return Collected; | 2398 return Collected; |
2428 } else if (s == 'Tag') { | 2399 } else if (s == 'Tag') { |
2429 return Tag; | 2400 return Tag; |
2430 } else if (s == 'Stub') { | 2401 } else if (s == 'Stub') { |
2431 return Stub; | 2402 return Stub; |
2432 } | 2403 } |
2433 print('do not understand code kind $s'); | 2404 Logger.root.severe('Unrecognized code kind: $s'); |
2434 throw new FallThroughError(); | 2405 throw new FallThroughError(); |
2435 } | 2406 } |
2436 static const Collected = const CodeKind._internal('Collected'); | 2407 static const Collected = const CodeKind._internal('Collected'); |
2437 static const Dart = const CodeKind._internal('Dart'); | 2408 static const Dart = const CodeKind._internal('Dart'); |
2438 static const Native = const CodeKind._internal('Native'); | 2409 static const Native = const CodeKind._internal('Native'); |
2439 static const Stub = const CodeKind._internal('Stub'); | 2410 static const Stub = const CodeKind._internal('Stub'); |
2440 static const Tag = const CodeKind._internal('Tag'); | 2411 static const Tag = const CodeKind._internal('Tag'); |
2441 } | 2412 } |
2442 | 2413 |
2443 class CodeInlineInterval { | 2414 class CodeInlineInterval { |
(...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2897 var v = list[i]; | 2868 var v = list[i]; |
2898 if ((v is ObservableMap) && _isServiceMap(v)) { | 2869 if ((v is ObservableMap) && _isServiceMap(v)) { |
2899 list[i] = owner.getFromMap(v); | 2870 list[i] = owner.getFromMap(v); |
2900 } else if (v is ObservableList) { | 2871 } else if (v is ObservableList) { |
2901 _upgradeObservableList(v, owner); | 2872 _upgradeObservableList(v, owner); |
2902 } else if (v is ObservableMap) { | 2873 } else if (v is ObservableMap) { |
2903 _upgradeObservableMap(v, owner); | 2874 _upgradeObservableMap(v, owner); |
2904 } | 2875 } |
2905 } | 2876 } |
2906 } | 2877 } |
OLD | NEW |