| 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 // Some value smaller than the object ring, so requesting a large array | 7 // Some value smaller than the object ring, so requesting a large array |
| 8 // doesn't result in an expired ref because the elements lapped it in the | 8 // doesn't result in an expired ref because the elements lapped it in the |
| 9 // object ring. | 9 // object ring. |
| 10 const int kDefaultFieldLimit = 100; | 10 const int kDefaultFieldLimit = 100; |
| (...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 388 clazz = map['class']; | 388 clazz = map['class']; |
| 389 } | 389 } |
| 390 | 390 |
| 391 if (mapIsRef) { | 391 if (mapIsRef) { |
| 392 return; | 392 return; |
| 393 } | 393 } |
| 394 size = map['size']; | 394 size = map['size']; |
| 395 } | 395 } |
| 396 } | 396 } |
| 397 | 397 |
| 398 abstract class Coverage { | |
| 399 // Following getters and functions will be provided by [ServiceObject]. | |
| 400 String get id; | |
| 401 Isolate get isolate; | |
| 402 | |
| 403 Future refreshCoverage() { | |
| 404 return refreshCallSiteData(); | |
| 405 } | |
| 406 | |
| 407 /// Default handler for coverage data. | |
| 408 void processCallSiteData(List coverageData) { | |
| 409 coverageData.forEach((scriptCoverage) { | |
| 410 assert(scriptCoverage['script'] != null); | |
| 411 scriptCoverage['script']._processCallSites(scriptCoverage['callSites']); | |
| 412 }); | |
| 413 } | |
| 414 | |
| 415 Future refreshCallSiteData() { | |
| 416 Map params = {}; | |
| 417 if (this is! Isolate) { | |
| 418 params['targetId'] = id; | |
| 419 } | |
| 420 return isolate.invokeRpcNoUpgrade('_getCallSiteData', params).then( | |
| 421 (ObservableMap map) { | |
| 422 var coverage = new ServiceObject._fromMap(isolate, map); | |
| 423 assert(coverage.type == 'CodeCoverage'); | |
| 424 var coverageList = coverage['coverage']; | |
| 425 assert(coverageList != null); | |
| 426 processCallSiteData(coverageList); | |
| 427 return this; | |
| 428 }); | |
| 429 } | |
| 430 } | |
| 431 | |
| 432 abstract class ServiceObjectOwner extends ServiceObject { | 398 abstract class ServiceObjectOwner extends ServiceObject { |
| 433 /// Creates an empty [ServiceObjectOwner]. | 399 /// Creates an empty [ServiceObjectOwner]. |
| 434 ServiceObjectOwner._empty(ServiceObjectOwner owner) : super._empty(owner); | 400 ServiceObjectOwner._empty(ServiceObjectOwner owner) : super._empty(owner); |
| 435 | 401 |
| 436 /// Builds a [ServiceObject] corresponding to the [id] from [map]. | 402 /// Builds a [ServiceObject] corresponding to the [id] from [map]. |
| 437 /// The result may come from the cache. The result will not necessarily | 403 /// The result may come from the cache. The result will not necessarily |
| 438 /// be [loaded]. | 404 /// be [loaded]. |
| 439 ServiceObject getFromMap(ObservableMap map); | 405 ServiceObject getFromMap(ObservableMap map); |
| 440 } | 406 } |
| 441 | 407 |
| (...skipping 686 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1128 print("${obj.runtimeType} should be a HeapObject"); | 1094 print("${obj.runtimeType} should be a HeapObject"); |
| 1129 } | 1095 } |
| 1130 return obj; | 1096 return obj; |
| 1131 })); | 1097 })); |
| 1132 } | 1098 } |
| 1133 return result; | 1099 return result; |
| 1134 } | 1100 } |
| 1135 } | 1101 } |
| 1136 | 1102 |
| 1137 /// State for a running isolate. | 1103 /// State for a running isolate. |
| 1138 class Isolate extends ServiceObjectOwner with Coverage { | 1104 class Isolate extends ServiceObjectOwner { |
| 1139 static const kLoggingStream = '_Logging'; | 1105 static const kLoggingStream = '_Logging'; |
| 1140 static const kExtensionStream = 'Extension'; | 1106 static const kExtensionStream = 'Extension'; |
| 1141 | 1107 |
| 1142 @reflectable VM get vm => owner; | 1108 @reflectable VM get vm => owner; |
| 1143 @reflectable Isolate get isolate => this; | 1109 @reflectable Isolate get isolate => this; |
| 1144 @observable int number; | 1110 @observable int number; |
| 1145 @observable int originNumber; | 1111 @observable int originNumber; |
| 1146 @observable DateTime startTime; | 1112 @observable DateTime startTime; |
| 1147 @observable Duration get upTime { | 1113 @observable Duration get upTime { |
| 1148 if (startTime == null) { | 1114 if (startTime == null) { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1187 if (value is Code) { | 1153 if (value is Code) { |
| 1188 Code code = value; | 1154 Code code = value; |
| 1189 code.profile = null; | 1155 code.profile = null; |
| 1190 } else if (value is ServiceFunction) { | 1156 } else if (value is ServiceFunction) { |
| 1191 ServiceFunction function = value; | 1157 ServiceFunction function = value; |
| 1192 function.profile = null; | 1158 function.profile = null; |
| 1193 } | 1159 } |
| 1194 }); | 1160 }); |
| 1195 } | 1161 } |
| 1196 | 1162 |
| 1163 static const kCallSitesReport = '_CallSites'; |
| 1164 |
| 1165 Future<ServiceMap> getSourceReport(List<String> report_kinds, |
| 1166 [Script script, |
| 1167 int startPos, |
| 1168 int endPos]) { |
| 1169 var params = { 'reports' : report_kinds }; |
| 1170 if (script != null) { |
| 1171 params['scriptId'] = script.id; |
| 1172 } |
| 1173 if (startPos != null) { |
| 1174 params['tokenPos'] = startPos; |
| 1175 } |
| 1176 if (endPos != null) { |
| 1177 params['endTokenPos'] = endPos; |
| 1178 } |
| 1179 return invokeRpc('_getSourceReport', params); |
| 1180 } |
| 1181 |
| 1197 /// Fetches and builds the class hierarchy for this isolate. Returns the | 1182 /// Fetches and builds the class hierarchy for this isolate. Returns the |
| 1198 /// Object class object. | 1183 /// Object class object. |
| 1199 Future<Class> getClassHierarchy() { | 1184 Future<Class> getClassHierarchy() { |
| 1200 return invokeRpc('getClassList', {}) | 1185 return invokeRpc('getClassList', {}) |
| 1201 .then(_loadClasses) | 1186 .then(_loadClasses) |
| 1202 .then(_buildClassHierarchy); | 1187 .then(_buildClassHierarchy); |
| 1203 } | 1188 } |
| 1204 | 1189 |
| 1205 Future<ServiceObject> getPorts() { | 1190 Future<ServiceObject> getPorts() { |
| 1206 return invokeRpc('_getPorts', {}); | 1191 return invokeRpc('_getPorts', {}); |
| (...skipping 901 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2108 | 2093 |
| 2109 LibraryDependency._(this.isImport, this.isDeferred, this.prefix, this.target); | 2094 LibraryDependency._(this.isImport, this.isDeferred, this.prefix, this.target); |
| 2110 | 2095 |
| 2111 static _fromMap(map) => new LibraryDependency._(map["isImport"], | 2096 static _fromMap(map) => new LibraryDependency._(map["isImport"], |
| 2112 map["isDeferred"], | 2097 map["isDeferred"], |
| 2113 map["prefix"], | 2098 map["prefix"], |
| 2114 map["target"]); | 2099 map["target"]); |
| 2115 } | 2100 } |
| 2116 | 2101 |
| 2117 | 2102 |
| 2118 class Library extends HeapObject with Coverage { | 2103 class Library extends HeapObject { |
| 2119 @observable String uri; | 2104 @observable String uri; |
| 2120 @reflectable final dependencies = new ObservableList<LibraryDependency>(); | 2105 @reflectable final dependencies = new ObservableList<LibraryDependency>(); |
| 2121 @reflectable final scripts = new ObservableList<Script>(); | 2106 @reflectable final scripts = new ObservableList<Script>(); |
| 2122 @reflectable final classes = new ObservableList<Class>(); | 2107 @reflectable final classes = new ObservableList<Class>(); |
| 2123 @reflectable final variables = new ObservableList<Field>(); | 2108 @reflectable final variables = new ObservableList<Field>(); |
| 2124 @reflectable final functions = new ObservableList<ServiceFunction>(); | 2109 @reflectable final functions = new ObservableList<ServiceFunction>(); |
| 2125 | 2110 |
| 2126 bool get canCache => true; | 2111 bool get canCache => true; |
| 2127 bool get immutable => false; | 2112 bool get immutable => false; |
| 2128 | 2113 |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2206 void update(List stats) { | 2191 void update(List stats) { |
| 2207 accumulated.instances = stats[ACCUMULATED]; | 2192 accumulated.instances = stats[ACCUMULATED]; |
| 2208 accumulated.bytes = stats[ACCUMULATED_SIZE]; | 2193 accumulated.bytes = stats[ACCUMULATED_SIZE]; |
| 2209 current.instances = stats[LIVE_AFTER_GC] + stats[ALLOCATED_SINCE_GC]; | 2194 current.instances = stats[LIVE_AFTER_GC] + stats[ALLOCATED_SINCE_GC]; |
| 2210 current.bytes = stats[LIVE_AFTER_GC_SIZE] + stats[ALLOCATED_SINCE_GC_SIZE]; | 2195 current.bytes = stats[LIVE_AFTER_GC_SIZE] + stats[ALLOCATED_SINCE_GC_SIZE]; |
| 2211 } | 2196 } |
| 2212 | 2197 |
| 2213 bool get empty => accumulated.empty && current.empty; | 2198 bool get empty => accumulated.empty && current.empty; |
| 2214 } | 2199 } |
| 2215 | 2200 |
| 2216 class Class extends HeapObject with Coverage { | 2201 class Class extends HeapObject { |
| 2217 @observable Library library; | 2202 @observable Library library; |
| 2218 | 2203 |
| 2219 @observable bool isAbstract; | 2204 @observable bool isAbstract; |
| 2220 @observable bool isConst; | 2205 @observable bool isConst; |
| 2221 @observable bool isFinalized; | 2206 @observable bool isFinalized; |
| 2222 @observable bool isPatch; | 2207 @observable bool isPatch; |
| 2223 @observable bool isImplemented; | 2208 @observable bool isImplemented; |
| 2224 | 2209 |
| 2225 @observable SourceLocation location; | 2210 @observable SourceLocation location; |
| 2226 | 2211 |
| (...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2585 static FunctionKind kNoSuchMethodDispatcher = new FunctionKind._internal('noSu
chMethod dispatcher'); | 2570 static FunctionKind kNoSuchMethodDispatcher = new FunctionKind._internal('noSu
chMethod dispatcher'); |
| 2586 static FunctionKind kInvokeFieldDispatcher = new FunctionKind._internal('invok
e field dispatcher'); | 2571 static FunctionKind kInvokeFieldDispatcher = new FunctionKind._internal('invok
e field dispatcher'); |
| 2587 static FunctionKind kCollected = new FunctionKind._internal('Collected'); | 2572 static FunctionKind kCollected = new FunctionKind._internal('Collected'); |
| 2588 static FunctionKind kNative = new FunctionKind._internal('Native'); | 2573 static FunctionKind kNative = new FunctionKind._internal('Native'); |
| 2589 static FunctionKind kTag = new FunctionKind._internal('Tag'); | 2574 static FunctionKind kTag = new FunctionKind._internal('Tag'); |
| 2590 static FunctionKind kStub = new FunctionKind._internal('Stub'); | 2575 static FunctionKind kStub = new FunctionKind._internal('Stub'); |
| 2591 static FunctionKind kSignatureFunction = new FunctionKind._internal('Signature
Function'); | 2576 static FunctionKind kSignatureFunction = new FunctionKind._internal('Signature
Function'); |
| 2592 static FunctionKind kUNKNOWN = new FunctionKind._internal('UNKNOWN'); | 2577 static FunctionKind kUNKNOWN = new FunctionKind._internal('UNKNOWN'); |
| 2593 } | 2578 } |
| 2594 | 2579 |
| 2595 class ServiceFunction extends HeapObject with Coverage { | 2580 class ServiceFunction extends HeapObject { |
| 2596 // owner is a Library, Class, or ServiceFunction. | 2581 // owner is a Library, Class, or ServiceFunction. |
| 2597 @observable ServiceObject dartOwner; | 2582 @observable ServiceObject dartOwner; |
| 2598 @observable Library library; | 2583 @observable Library library; |
| 2599 @observable bool isStatic; | 2584 @observable bool isStatic; |
| 2600 @observable bool isConst; | 2585 @observable bool isConst; |
| 2601 @observable SourceLocation location; | 2586 @observable SourceLocation location; |
| 2602 @observable Code code; | 2587 @observable Code code; |
| 2603 @observable Code unoptimizedCode; | 2588 @observable Code unoptimizedCode; |
| 2604 @observable bool isOptimizable; | 2589 @observable bool isOptimizable; |
| 2605 @observable bool isInlinable; | 2590 @observable bool isInlinable; |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2731 } | 2716 } |
| 2732 | 2717 |
| 2733 String toString() => 'Field(${dartOwner.name}.$name)'; | 2718 String toString() => 'Field(${dartOwner.name}.$name)'; |
| 2734 } | 2719 } |
| 2735 | 2720 |
| 2736 | 2721 |
| 2737 class ScriptLine extends Observable { | 2722 class ScriptLine extends Observable { |
| 2738 final Script script; | 2723 final Script script; |
| 2739 final int line; | 2724 final int line; |
| 2740 final String text; | 2725 final String text; |
| 2741 @observable int hits; | |
| 2742 @observable bool possibleBpt = true; | 2726 @observable bool possibleBpt = true; |
| 2743 @observable bool breakpointResolved = false; | 2727 @observable bool breakpointResolved = false; |
| 2744 @observable Set<Breakpoint> breakpoints; | 2728 @observable Set<Breakpoint> breakpoints; |
| 2745 | 2729 |
| 2746 bool get isBlank { | 2730 bool get isBlank { |
| 2747 // Compute isBlank on demand. | 2731 // Compute isBlank on demand. |
| 2748 if (_isBlank == null) { | 2732 if (_isBlank == null) { |
| 2749 _isBlank = text.trim().isEmpty; | 2733 _isBlank = text.trim().isEmpty; |
| 2750 } | 2734 } |
| 2751 return _isBlank; | 2735 return _isBlank; |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2843 | 2827 |
| 2844 operator ==(other) { | 2828 operator ==(other) { |
| 2845 return (script == other.script) && (tokenPos == other.tokenPos); | 2829 return (script == other.script) && (tokenPos == other.tokenPos); |
| 2846 } | 2830 } |
| 2847 int get hashCode => (script.hashCode << 8) | tokenPos; | 2831 int get hashCode => (script.hashCode << 8) | tokenPos; |
| 2848 | 2832 |
| 2849 String toString() => "CallSite($name, $tokenPos)"; | 2833 String toString() => "CallSite($name, $tokenPos)"; |
| 2850 } | 2834 } |
| 2851 | 2835 |
| 2852 class CallSiteEntry { | 2836 class CallSiteEntry { |
| 2853 final /* Class | Library */ receiverContainer; | 2837 final /* Class | Library */ receiver; |
| 2854 final int count; | 2838 final int count; |
| 2855 final ServiceFunction target; | 2839 final ServiceFunction target; |
| 2856 | 2840 |
| 2857 CallSiteEntry(this.receiverContainer, this.count, this.target); | 2841 CallSiteEntry(this.receiver, this.count, this.target); |
| 2858 | 2842 |
| 2859 factory CallSiteEntry.fromMap(Map entryMap) { | 2843 factory CallSiteEntry.fromMap(Map entryMap) { |
| 2860 return new CallSiteEntry(entryMap['receiverContainer'], | 2844 return new CallSiteEntry(entryMap['receiver'], |
| 2861 entryMap['count'], | 2845 entryMap['count'], |
| 2862 entryMap['target']); | 2846 entryMap['target']); |
| 2863 } | 2847 } |
| 2864 | 2848 |
| 2865 String toString() => "CallSiteEntry(${receiverContainer.name}, $count)"; | 2849 String toString() => "CallSiteEntry(${receiver.name}, $count)"; |
| 2866 } | 2850 } |
| 2867 | 2851 |
| 2868 /// The location of a local variable reference in a script. | 2852 /// The location of a local variable reference in a script. |
| 2869 class LocalVarLocation { | 2853 class LocalVarLocation { |
| 2870 final int line; | 2854 final int line; |
| 2871 final int column; | 2855 final int column; |
| 2872 final int endColumn; | 2856 final int endColumn; |
| 2873 LocalVarLocation(this.line, this.column, this.endColumn); | 2857 LocalVarLocation(this.line, this.column, this.endColumn); |
| 2874 } | 2858 } |
| 2875 | 2859 |
| 2876 class Script extends HeapObject with Coverage { | 2860 class Script extends HeapObject { |
| 2877 Set<CallSite> callSites = new Set<CallSite>(); | |
| 2878 final lines = new ObservableList<ScriptLine>(); | 2861 final lines = new ObservableList<ScriptLine>(); |
| 2879 final _hits = new Map<int, int>(); | |
| 2880 @observable String uri; | 2862 @observable String uri; |
| 2881 @observable String kind; | 2863 @observable String kind; |
| 2882 @observable int firstTokenPos; | 2864 @observable int firstTokenPos; |
| 2883 @observable int lastTokenPos; | 2865 @observable int lastTokenPos; |
| 2884 @observable int lineOffset; | 2866 @observable int lineOffset; |
| 2885 @observable int columnOffset; | 2867 @observable int columnOffset; |
| 2886 @observable Library library; | 2868 @observable Library library; |
| 2887 | 2869 |
| 2888 bool get immutable => true; | 2870 bool get immutable => true; |
| 2889 | 2871 |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3023 } | 3005 } |
| 3024 | 3006 |
| 3025 for (var line in lines) { | 3007 for (var line in lines) { |
| 3026 // Remove possible breakpoints on lines with no tokens. | 3008 // Remove possible breakpoints on lines with no tokens. |
| 3027 if (!lineSet.contains(line.line)) { | 3009 if (!lineSet.contains(line.line)) { |
| 3028 line.possibleBpt = false; | 3010 line.possibleBpt = false; |
| 3029 } | 3011 } |
| 3030 } | 3012 } |
| 3031 } | 3013 } |
| 3032 | 3014 |
| 3033 void _processCallSites(List newCallSiteMaps) { | |
| 3034 var mergedCallSites = new Set<CallSite>(); | |
| 3035 for (var callSiteMap in newCallSiteMaps) { | |
| 3036 var newSite = new CallSite.fromMap(callSiteMap, this); | |
| 3037 mergedCallSites.add(newSite); | |
| 3038 | |
| 3039 var line = newSite.line; | |
| 3040 var hit = newSite.aggregateCount; | |
| 3041 assert(line >= 1); // Lines start at 1. | |
| 3042 var oldHits = _hits[line]; | |
| 3043 if (oldHits != null) { | |
| 3044 hit += oldHits; | |
| 3045 } | |
| 3046 _hits[line] = hit; | |
| 3047 } | |
| 3048 | |
| 3049 mergedCallSites.addAll(callSites); | |
| 3050 callSites = mergedCallSites; | |
| 3051 _applyHitsToLines(); | |
| 3052 // Notify any Observers that this Script's state has changed. | |
| 3053 notifyChange(null); | |
| 3054 } | |
| 3055 | |
| 3056 void _processSource(String source) { | 3015 void _processSource(String source) { |
| 3057 if (source == null) { | 3016 if (source == null) { |
| 3058 return; | 3017 return; |
| 3059 } | 3018 } |
| 3060 var sourceLines = source.split('\n'); | 3019 var sourceLines = source.split('\n'); |
| 3061 if (sourceLines.length == 0) { | 3020 if (sourceLines.length == 0) { |
| 3062 return; | 3021 return; |
| 3063 } | 3022 } |
| 3064 lines.clear(); | 3023 lines.clear(); |
| 3065 Logger.root.info('Adding ${sourceLines.length} source lines for ${uri}'); | 3024 Logger.root.info('Adding ${sourceLines.length} source lines for ${uri}'); |
| 3066 for (var i = 0; i < sourceLines.length; i++) { | 3025 for (var i = 0; i < sourceLines.length; i++) { |
| 3067 lines.add(new ScriptLine(this, i + lineOffset + 1, sourceLines[i])); | 3026 lines.add(new ScriptLine(this, i + lineOffset + 1, sourceLines[i])); |
| 3068 } | 3027 } |
| 3069 for (var bpt in isolate.breakpoints.values) { | 3028 for (var bpt in isolate.breakpoints.values) { |
| 3070 if (bpt.location.script == this) { | 3029 if (bpt.location.script == this) { |
| 3071 _addBreakpoint(bpt); | 3030 _addBreakpoint(bpt); |
| 3072 } | 3031 } |
| 3073 } | 3032 } |
| 3074 | 3033 |
| 3075 _applyHitsToLines(); | |
| 3076 // Notify any Observers that this Script's state has changed. | 3034 // Notify any Observers that this Script's state has changed. |
| 3077 notifyChange(null); | 3035 notifyChange(null); |
| 3078 } | 3036 } |
| 3079 | 3037 |
| 3080 void _applyHitsToLines() { | |
| 3081 for (var line in lines) { | |
| 3082 var hits = _hits[line.line]; | |
| 3083 line.hits = hits; | |
| 3084 } | |
| 3085 } | |
| 3086 | |
| 3087 void _addBreakpoint(Breakpoint bpt) { | 3038 void _addBreakpoint(Breakpoint bpt) { |
| 3088 var line; | 3039 var line; |
| 3089 if (bpt.location.tokenPos != null) { | 3040 if (bpt.location.tokenPos != null) { |
| 3090 line = tokenToLine(bpt.location.tokenPos); | 3041 line = tokenToLine(bpt.location.tokenPos); |
| 3091 } else { | 3042 } else { |
| 3092 UnresolvedSourceLocation loc = bpt.location; | 3043 UnresolvedSourceLocation loc = bpt.location; |
| 3093 line = loc.line; | 3044 line = loc.line; |
| 3094 } | 3045 } |
| 3095 getLine(line).addBreakpoint(bpt); | 3046 getLine(line).addBreakpoint(bpt); |
| 3096 } | 3047 } |
| (...skipping 968 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4065 var v = list[i]; | 4016 var v = list[i]; |
| 4066 if ((v is ObservableMap) && _isServiceMap(v)) { | 4017 if ((v is ObservableMap) && _isServiceMap(v)) { |
| 4067 list[i] = owner.getFromMap(v); | 4018 list[i] = owner.getFromMap(v); |
| 4068 } else if (v is ObservableList) { | 4019 } else if (v is ObservableList) { |
| 4069 _upgradeObservableList(v, owner); | 4020 _upgradeObservableList(v, owner); |
| 4070 } else if (v is ObservableMap) { | 4021 } else if (v is ObservableMap) { |
| 4071 _upgradeObservableMap(v, owner); | 4022 _upgradeObservableMap(v, owner); |
| 4072 } | 4023 } |
| 4073 } | 4024 } |
| 4074 } | 4025 } |
| OLD | NEW |