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