| 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 static int LexicalSortName(ServiceObject o1, ServiceObject o2) { | 10 static int LexicalSortName(ServiceObject o1, ServiceObject o2) { |
| (...skipping 679 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 690 collections = heapMap['collections']; | 690 collections = heapMap['collections']; |
| 691 totalCollectionTimeInSeconds = heapMap['time']; | 691 totalCollectionTimeInSeconds = heapMap['time']; |
| 692 averageCollectionPeriodInMillis = heapMap['avgCollectionPeriodMillis']; | 692 averageCollectionPeriodInMillis = heapMap['avgCollectionPeriodMillis']; |
| 693 } | 693 } |
| 694 } | 694 } |
| 695 | 695 |
| 696 class HeapSnapshot { | 696 class HeapSnapshot { |
| 697 final ObjectGraph graph; | 697 final ObjectGraph graph; |
| 698 final DateTime timeStamp; | 698 final DateTime timeStamp; |
| 699 final Isolate isolate; | 699 final Isolate isolate; |
| 700 | 700 |
| 701 HeapSnapshot(this.isolate, ByteData data) : | 701 HeapSnapshot(this.isolate, ByteData data) : |
| 702 graph = new ObjectGraph(new ReadStream(data)), | 702 graph = new ObjectGraph(new ReadStream(data)), |
| 703 timeStamp = new DateTime.now() { | 703 timeStamp = new DateTime.now() { |
| 704 } | 704 } |
| 705 | 705 |
| 706 List<Future<ServiceObject>> getMostRetained({int classId, int limit}) { | 706 List<Future<ServiceObject>> getMostRetained({int classId, int limit}) { |
| 707 var result = []; | 707 var result = []; |
| 708 for (var v in graph.getMostRetained(classId: classId, limit: limit)) { | 708 for (var v in graph.getMostRetained(classId: classId, limit: limit)) { |
| 709 var address = v.addressForWordSize(isolate.vm.architectureBits ~/ 8); | 709 var address = v.addressForWordSize(isolate.vm.architectureBits ~/ 8); |
| 710 result.add(isolate.get( | 710 result.add(isolate.get( |
| 711 'address/${address.toRadixString(16)}?ref=true').then((obj) { | 711 'address/${address.toRadixString(16)}?ref=true').then((obj) { |
| 712 obj.retainedSize = v.retainedSize; | 712 obj.retainedSize = v.retainedSize; |
| 713 return new Future(() => obj); | 713 return new Future(() => obj); |
| 714 })); | 714 })); |
| 715 } | 715 } |
| 716 return result; | 716 return result; |
| 717 } | 717 } |
| 718 | 718 |
| 719 | 719 |
| 720 } | 720 } |
| 721 | 721 |
| 722 /// State for a running isolate. | 722 /// State for a running isolate. |
| 723 class Isolate extends ServiceObjectOwner with Coverage { | 723 class Isolate extends ServiceObjectOwner with Coverage { |
| 724 @reflectable VM get vm => owner; | 724 @reflectable VM get vm => owner; |
| 725 @reflectable Isolate get isolate => this; | 725 @reflectable Isolate get isolate => this; |
| 726 @observable ObservableMap counters = new ObservableMap(); | 726 @observable ObservableMap counters = new ObservableMap(); |
| 727 | 727 |
| 728 String get link => '/${_id}'; | 728 String get link => '/${_id}'; |
| 729 | 729 |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 875 toObservable(new Map<String, double>()); | 875 toObservable(new Map<String, double>()); |
| 876 | 876 |
| 877 final HeapSpace newSpace = new HeapSpace(); | 877 final HeapSpace newSpace = new HeapSpace(); |
| 878 final HeapSpace oldSpace = new HeapSpace(); | 878 final HeapSpace oldSpace = new HeapSpace(); |
| 879 | 879 |
| 880 @observable String fileAndLine; | 880 @observable String fileAndLine; |
| 881 | 881 |
| 882 @observable DartError error; | 882 @observable DartError error; |
| 883 @observable HeapSnapshot latestSnapshot; | 883 @observable HeapSnapshot latestSnapshot; |
| 884 Completer<HeapSnapshot> _snapshotFetch; | 884 Completer<HeapSnapshot> _snapshotFetch; |
| 885 | 885 |
| 886 void loadHeapSnapshot(ServiceEvent event) { | 886 void loadHeapSnapshot(ServiceEvent event) { |
| 887 latestSnapshot = new HeapSnapshot(this, event.data); | 887 latestSnapshot = new HeapSnapshot(this, event.data); |
| 888 _snapshotFetch.complete(latestSnapshot); | 888 _snapshotFetch.complete(latestSnapshot); |
| 889 } | 889 } |
| 890 | 890 |
| 891 Future<HeapSnapshot> fetchHeapSnapshot() { | 891 Future<HeapSnapshot> fetchHeapSnapshot() { |
| 892 if (_snapshotFetch == null || _snapshotFetch.isCompleted) { | 892 if (_snapshotFetch == null || _snapshotFetch.isCompleted) { |
| 893 get('graph'); | 893 get('graph'); |
| 894 _snapshotFetch = new Completer<HeapSnapshot>(); | 894 _snapshotFetch = new Completer<HeapSnapshot>(); |
| 895 } | 895 } |
| 896 return _snapshotFetch.future; | 896 return _snapshotFetch.future; |
| 897 } | 897 } |
| 898 | 898 |
| 899 void updateHeapsFromMap(ObservableMap map) { | 899 void updateHeapsFromMap(ObservableMap map) { |
| 900 newSpace.update(map['new']); | 900 newSpace.update(map['new']); |
| (...skipping 1118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2019 } | 2019 } |
| 2020 | 2020 |
| 2021 class CodeTick { | 2021 class CodeTick { |
| 2022 final int address; | 2022 final int address; |
| 2023 final int exclusiveTicks; | 2023 final int exclusiveTicks; |
| 2024 final int inclusiveTicks; | 2024 final int inclusiveTicks; |
| 2025 CodeTick(this.address, this.exclusiveTicks, this.inclusiveTicks); | 2025 CodeTick(this.address, this.exclusiveTicks, this.inclusiveTicks); |
| 2026 } | 2026 } |
| 2027 | 2027 |
| 2028 class PcDescriptor extends Observable { | 2028 class PcDescriptor extends Observable { |
| 2029 final int address; | 2029 final int pcOffset; |
| 2030 @reflectable final int deoptId; | 2030 @reflectable final int deoptId; |
| 2031 @reflectable final int tokenPos; | 2031 @reflectable final int tokenPos; |
| 2032 @reflectable final int tryIndex; | 2032 @reflectable final int tryIndex; |
| 2033 @reflectable final String kind; | 2033 @reflectable final String kind; |
| 2034 @observable Script script; | 2034 @observable Script script; |
| 2035 @observable String formattedLine; | 2035 @observable String formattedLine; |
| 2036 PcDescriptor(this.address, this.deoptId, this.tokenPos, this.tryIndex, | 2036 PcDescriptor(this.pcOffset, this.deoptId, this.tokenPos, this.tryIndex, |
| 2037 this.kind); | 2037 this.kind); |
| 2038 | 2038 |
| 2039 @reflectable String formattedDeoptId() { | 2039 @reflectable String formattedDeoptId() { |
| 2040 if (deoptId == -1) { | 2040 if (deoptId == -1) { |
| 2041 return 'N/A'; | 2041 return 'N/A'; |
| 2042 } | 2042 } |
| 2043 return deoptId.toString(); | 2043 return deoptId.toString(); |
| 2044 } | 2044 } |
| 2045 | 2045 |
| 2046 @reflectable String formattedTokenPos() { | 2046 @reflectable String formattedTokenPos() { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2067 | 2067 |
| 2068 class PcDescriptors extends ServiceObject { | 2068 class PcDescriptors extends ServiceObject { |
| 2069 @observable Class clazz; | 2069 @observable Class clazz; |
| 2070 @observable int size; | 2070 @observable int size; |
| 2071 bool get canCache => false; | 2071 bool get canCache => false; |
| 2072 bool get immutable => true; | 2072 bool get immutable => true; |
| 2073 @reflectable final List<PcDescriptor> descriptors = | 2073 @reflectable final List<PcDescriptor> descriptors = |
| 2074 new ObservableList<PcDescriptor>(); | 2074 new ObservableList<PcDescriptor>(); |
| 2075 | 2075 |
| 2076 PcDescriptors._empty(ServiceObjectOwner owner) : super._empty(owner) { | 2076 PcDescriptors._empty(ServiceObjectOwner owner) : super._empty(owner) { |
| 2077 print('created PcDescriptors.'); | |
| 2078 } | 2077 } |
| 2079 | 2078 |
| 2080 void _update(ObservableMap m, bool mapIsRef) { | 2079 void _update(ObservableMap m, bool mapIsRef) { |
| 2081 if (mapIsRef) { | 2080 if (mapIsRef) { |
| 2082 return; | 2081 return; |
| 2083 } | 2082 } |
| 2084 _upgradeCollection(m, isolate); | 2083 _upgradeCollection(m, isolate); |
| 2085 clazz = m['class']; | 2084 clazz = m['class']; |
| 2086 size = m['size']; | 2085 size = m['size']; |
| 2087 descriptors.clear(); | 2086 descriptors.clear(); |
| 2088 for (var descriptor in m['members']) { | 2087 for (var descriptor in m['members']) { |
| 2089 var address = int.parse(descriptor['pc'], radix:16); | 2088 var pcOffset = int.parse(descriptor['pcOffset'], radix:16); |
| 2090 var deoptId = descriptor['deoptId']; | 2089 var deoptId = descriptor['deoptId']; |
| 2091 var tokenPos = descriptor['tokenPos']; | 2090 var tokenPos = descriptor['tokenPos']; |
| 2092 var tryIndex = descriptor['tryIndex']; | 2091 var tryIndex = descriptor['tryIndex']; |
| 2093 var kind = descriptor['kind'].trim(); | 2092 var kind = descriptor['kind'].trim(); |
| 2094 descriptors.add( | 2093 descriptors.add( |
| 2095 new PcDescriptor(address, deoptId, tokenPos, tryIndex, kind)); | 2094 new PcDescriptor(pcOffset, deoptId, tokenPos, tryIndex, kind)); |
| 2096 } | 2095 } |
| 2097 } | 2096 } |
| 2098 } | 2097 } |
| 2099 | 2098 |
| 2100 class LocalVarDescriptor extends Observable { | 2099 class LocalVarDescriptor extends Observable { |
| 2101 @reflectable final String name; | 2100 @reflectable final String name; |
| 2102 @reflectable final int index; | 2101 @reflectable final int index; |
| 2103 @reflectable final int beginPos; | 2102 @reflectable final int beginPos; |
| 2104 @reflectable final int endPos; | 2103 @reflectable final int endPos; |
| 2105 @reflectable final int scopeId; | 2104 @reflectable final int scopeId; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2155 } | 2154 } |
| 2156 _upgradeCollection(m, isolate); | 2155 _upgradeCollection(m, isolate); |
| 2157 clazz = m['class']; | 2156 clazz = m['class']; |
| 2158 size = m['size']; | 2157 size = m['size']; |
| 2159 privateKey = m['privateKey']; | 2158 privateKey = m['privateKey']; |
| 2160 } | 2159 } |
| 2161 } | 2160 } |
| 2162 | 2161 |
| 2163 class CodeInstruction extends Observable { | 2162 class CodeInstruction extends Observable { |
| 2164 @observable final int address; | 2163 @observable final int address; |
| 2164 @observable final int pcOffset; |
| 2165 @observable final String machine; | 2165 @observable final String machine; |
| 2166 @observable final String human; | 2166 @observable final String human; |
| 2167 @observable CodeInstruction jumpTarget; | 2167 @observable CodeInstruction jumpTarget; |
| 2168 @reflectable List<PcDescriptor> descriptors = | 2168 @reflectable List<PcDescriptor> descriptors = |
| 2169 new ObservableList<PcDescriptor>(); | 2169 new ObservableList<PcDescriptor>(); |
| 2170 | 2170 |
| 2171 static String formatPercent(num a, num total) { | 2171 static String formatPercent(num a, num total) { |
| 2172 var percent = 100.0 * (a / total); | 2172 var percent = 100.0 * (a / total); |
| 2173 return '${percent.toStringAsFixed(2)}%'; | 2173 return '${percent.toStringAsFixed(2)}%'; |
| 2174 } | 2174 } |
| 2175 | 2175 |
| 2176 CodeInstruction(this.address, this.machine, this.human); | 2176 CodeInstruction(this.address, this.pcOffset, this.machine, this.human); |
| 2177 | 2177 |
| 2178 @reflectable bool get isComment => address == 0; | 2178 @reflectable bool get isComment => address == 0; |
| 2179 @reflectable bool get hasDescriptors => descriptors.length > 0; | 2179 @reflectable bool get hasDescriptors => descriptors.length > 0; |
| 2180 | 2180 |
| 2181 @reflectable String formattedAddress() { | 2181 @reflectable String formattedAddress() { |
| 2182 if (address == 0) { | 2182 if (address == 0) { |
| 2183 return ''; | 2183 return ''; |
| 2184 } | 2184 } |
| 2185 return '0x${address.toRadixString(16)}'; | 2185 return '0x${address.toRadixString(16)}'; |
| 2186 } | 2186 } |
| (...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2453 @observable bool hasDisassembly = false; | 2453 @observable bool hasDisassembly = false; |
| 2454 | 2454 |
| 2455 void _processDisassembly(List<String> disassembly){ | 2455 void _processDisassembly(List<String> disassembly){ |
| 2456 assert(disassembly != null); | 2456 assert(disassembly != null); |
| 2457 instructions.clear(); | 2457 instructions.clear(); |
| 2458 assert((disassembly.length % 3) == 0); | 2458 assert((disassembly.length % 3) == 0); |
| 2459 for (var i = 0; i < disassembly.length; i += 3) { | 2459 for (var i = 0; i < disassembly.length; i += 3) { |
| 2460 var address = 0; // Assume code comment. | 2460 var address = 0; // Assume code comment. |
| 2461 var machine = disassembly[i + 1]; | 2461 var machine = disassembly[i + 1]; |
| 2462 var human = disassembly[i + 2]; | 2462 var human = disassembly[i + 2]; |
| 2463 var pcOffset = 0; |
| 2463 if (disassembly[i] != '') { | 2464 if (disassembly[i] != '') { |
| 2464 // Not a code comment, extract address. | 2465 // Not a code comment, extract address. |
| 2465 address = int.parse(disassembly[i]); | 2466 address = int.parse(disassembly[i]); |
| 2467 pcOffset = address - startAddress; |
| 2466 } | 2468 } |
| 2467 var instruction = new CodeInstruction(address, machine, human); | 2469 var instruction = new CodeInstruction(address, pcOffset, machine, human); |
| 2468 instructions.add(instruction); | 2470 instructions.add(instruction); |
| 2469 } | 2471 } |
| 2470 for (var instruction in instructions) { | 2472 for (var instruction in instructions) { |
| 2471 instruction._resolveJumpTarget(instructions); | 2473 instruction._resolveJumpTarget(instructions); |
| 2472 } | 2474 } |
| 2473 } | 2475 } |
| 2474 | 2476 |
| 2475 void _processDescriptor(Map d) { | 2477 void _processDescriptor(Map d) { |
| 2476 var address = int.parse(d['pc'], radix:16); | 2478 var pcOffset = int.parse(d['pcOffset'], radix:16); |
| 2479 var address = startAddress + pcOffset; |
| 2477 var deoptId = d['deoptId']; | 2480 var deoptId = d['deoptId']; |
| 2478 var tokenPos = d['tokenPos']; | 2481 var tokenPos = d['tokenPos']; |
| 2479 var tryIndex = d['tryIndex']; | 2482 var tryIndex = d['tryIndex']; |
| 2480 var kind = d['kind'].trim(); | 2483 var kind = d['kind'].trim(); |
| 2481 for (var instruction in instructions) { | 2484 for (var instruction in instructions) { |
| 2482 if (instruction.address == address) { | 2485 if (instruction.address == address) { |
| 2483 instruction.descriptors.add(new PcDescriptor(address, | 2486 instruction.descriptors.add(new PcDescriptor(pcOffset, |
| 2484 deoptId, | 2487 deoptId, |
| 2485 tokenPos, | 2488 tokenPos, |
| 2486 tryIndex, | 2489 tryIndex, |
| 2487 kind)); | 2490 kind)); |
| 2488 return; | 2491 return; |
| 2489 } | 2492 } |
| 2490 } | 2493 } |
| 2491 Logger.root.warning( | 2494 Logger.root.warning( |
| 2492 'Could not find instruction with pc descriptor address: $address'); | 2495 'Could not find instruction with pc descriptor address: $address'); |
| 2493 } | 2496 } |
| (...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2786 var v = list[i]; | 2789 var v = list[i]; |
| 2787 if ((v is ObservableMap) && _isServiceMap(v)) { | 2790 if ((v is ObservableMap) && _isServiceMap(v)) { |
| 2788 list[i] = owner.getFromMap(v); | 2791 list[i] = owner.getFromMap(v); |
| 2789 } else if (v is ObservableList) { | 2792 } else if (v is ObservableList) { |
| 2790 _upgradeObservableList(v, owner); | 2793 _upgradeObservableList(v, owner); |
| 2791 } else if (v is ObservableMap) { | 2794 } else if (v is ObservableMap) { |
| 2792 _upgradeObservableMap(v, owner); | 2795 _upgradeObservableMap(v, owner); |
| 2793 } | 2796 } |
| 2794 } | 2797 } |
| 2795 } | 2798 } |
| OLD | NEW |