| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | |
| 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. | |
| 4 | |
| 5 part of app; | |
| 6 | |
| 7 /// State for a running isolate. | |
| 8 class Isolate extends Observable implements ServiceObject { | |
| 9 final VM vm; | |
| 10 String _id; | |
| 11 String _serviceType = 'Isolate'; | |
| 12 Isolate get isolate => this; | |
| 13 String get link => _id; | |
| 14 String get id => _id; | |
| 15 String get serviceType => _serviceType; | |
| 16 | |
| 17 Isolate(this.vm, this._id); | |
| 18 | |
| 19 /// Refresh [this]. Returns a future which completes to [this]. | |
| 20 Future refresh() { | |
| 21 return vm.fetchMap(_id).then((m) => update(m)).then((_) => this); | |
| 22 } | |
| 23 | |
| 24 /// Creates a link to [objectId] relative to [this]. | |
| 25 @reflectable String relativeLink(String objectId) => '$id/$objectId'; | |
| 26 /// Creates a relative link to [objectId] with a '#/' prefix. | |
| 27 @reflectable String hashLink(String objectId) => '#/${relativeLink(objectId)}'
; | |
| 28 | |
| 29 @observable Profile profile; | |
| 30 @observable final Map<String, Script> scripts = | |
| 31 toObservable(new Map<String, Script>()); | |
| 32 @observable final List<Code> codes = new List<Code>(); | |
| 33 @observable String name; | |
| 34 @observable String vmName; | |
| 35 @observable Map entry; | |
| 36 @observable String rootLib; | |
| 37 @observable final Map<String, double> timers = | |
| 38 toObservable(new Map<String, double>()); | |
| 39 | |
| 40 @observable int newHeapUsed = 0; | |
| 41 @observable int oldHeapUsed = 0; | |
| 42 | |
| 43 @observable Map topFrame = null; | |
| 44 @observable String fileAndLine = null; | |
| 45 | |
| 46 Isolate.fromId(this.vm, this._id) : name = 'isolate' {} | |
| 47 | |
| 48 Isolate.fromMap(this.vm, Map map) | |
| 49 : _id = map['id'], name = map['name'] { | |
| 50 } | |
| 51 | |
| 52 void update(Map map) { | |
| 53 if (map['type'] != 'Isolate') { | |
| 54 Logger.root.severe('Unexpected message type in Isolate.update: ${map["type
"]}'); | |
| 55 return; | |
| 56 } | |
| 57 if (map['rootLib'] == null || | |
| 58 map['timers'] == null || | |
| 59 map['heap'] == null) { | |
| 60 Logger.root.severe("Malformed 'Isolate' response: $map"); | |
| 61 return; | |
| 62 } | |
| 63 rootLib = map['rootLib']['id']; | |
| 64 vmName = map['name']; | |
| 65 if (map['entry'] != null) { | |
| 66 entry = map['entry']; | |
| 67 name = entry['name']; | |
| 68 } else { | |
| 69 // fred | |
| 70 name = 'root isolate'; | |
| 71 } | |
| 72 if (map['topFrame'] != null) { | |
| 73 topFrame = map['topFrame']; | |
| 74 } | |
| 75 | |
| 76 var timerMap = {}; | |
| 77 map['timers'].forEach((timer) { | |
| 78 timerMap[timer['name']] = timer['time']; | |
| 79 }); | |
| 80 timers['total'] = timerMap['time_total_runtime']; | |
| 81 timers['compile'] = timerMap['time_compilation']; | |
| 82 timers['gc'] = 0.0; // TODO(turnidge): Export this from VM. | |
| 83 timers['init'] = (timerMap['time_script_loading'] + | |
| 84 timerMap['time_creating_snapshot'] + | |
| 85 timerMap['time_isolate_initialization'] + | |
| 86 timerMap['time_bootstrap']); | |
| 87 timers['dart'] = timerMap['time_dart_execution']; | |
| 88 | |
| 89 newHeapUsed = map['heap']['usedNew']; | |
| 90 oldHeapUsed = map['heap']['usedOld']; | |
| 91 } | |
| 92 | |
| 93 String toString() => '$id'; | |
| 94 | |
| 95 Code findCodeByAddress(int address) { | |
| 96 for (var i = 0; i < codes.length; i++) { | |
| 97 if (codes[i].contains(address)) { | |
| 98 return codes[i]; | |
| 99 } | |
| 100 } | |
| 101 return null; | |
| 102 } | |
| 103 | |
| 104 Code findCodeByName(String name) { | |
| 105 for (var i = 0; i < codes.length; i++) { | |
| 106 if (codes[i].name == name) { | |
| 107 return codes[i]; | |
| 108 } | |
| 109 } | |
| 110 return null; | |
| 111 } | |
| 112 | |
| 113 void resetCodeTicks() { | |
| 114 Logger.root.info('Reset all code ticks.'); | |
| 115 for (var i = 0; i < codes.length; i++) { | |
| 116 codes[i].resetTicks(); | |
| 117 } | |
| 118 } | |
| 119 | |
| 120 void updateCoverage(List coverages) { | |
| 121 for (var coverage in coverages) { | |
| 122 var id = coverage['script']['id']; | |
| 123 var script = scripts[id]; | |
| 124 if (script == null) { | |
| 125 script = new Script.fromMap(coverage['script']); | |
| 126 scripts[id] = script; | |
| 127 } | |
| 128 assert(script != null); | |
| 129 script._processCoverageHits(coverage['hits']); | |
| 130 } | |
| 131 } | |
| 132 | |
| 133 // TODO(johnmccutchan): Remove this once everything is a ServiceObject. | |
| 134 void _setModelResponse(String type, String modelName, dynamic model) { | |
| 135 var response = { | |
| 136 'type': type, | |
| 137 modelName: model | |
| 138 }; | |
| 139 vm.app.setResponse(response); | |
| 140 } | |
| 141 | |
| 142 void _setResponseRequestError(HttpRequest request) { | |
| 143 String error = '${request.status} ${request.statusText}'; | |
| 144 if (request.status == 0) { | |
| 145 error = 'No service found. Did you run with --enable-vm-service ?'; | |
| 146 } | |
| 147 vm.app.setResponseError(error, 'RequestError'); | |
| 148 } | |
| 149 | |
| 150 void _requestCatchError(e, st) { | |
| 151 if (e is ProgressEvent) { | |
| 152 _setResponseRequestError(e.target); | |
| 153 } else { | |
| 154 vm.app.setResponseError('$e $st'); | |
| 155 } | |
| 156 } | |
| 157 | |
| 158 static final RegExp _codeMatcher = new RegExp(r'/code/'); | |
| 159 static bool isCodeId(objectId) => _codeMatcher.hasMatch(objectId); | |
| 160 static int codeAddressFromRequest(String objectId) { | |
| 161 Match m = _codeMatcher.matchAsPrefix(objectId); | |
| 162 if (m == null) { | |
| 163 return 0; | |
| 164 } | |
| 165 try { | |
| 166 var a = int.parse(m.input.substring(m.end), radix: 16); | |
| 167 return a; | |
| 168 } catch (e) { | |
| 169 return 0; | |
| 170 } | |
| 171 } | |
| 172 | |
| 173 /// Handle 'Code' requests | |
| 174 void _getCode(String objectId) { | |
| 175 var address = codeAddressFromRequest(objectId); | |
| 176 if (address == 0) { | |
| 177 vm.app.setResponseError('$objectId is not a valid code request.'); | |
| 178 return; | |
| 179 } | |
| 180 var code = isolate.findCodeByAddress(address); | |
| 181 if (code != null) { | |
| 182 Logger.root.info( | |
| 183 'Found code with 0x${address.toRadixString(16)} in isolate.'); | |
| 184 _setModelResponse('Code', 'code', code); | |
| 185 return; | |
| 186 } | |
| 187 getMap(objectId).then((map) { | |
| 188 assert(map['type'] == 'Code'); | |
| 189 var code = new Code.fromMap(map); | |
| 190 Logger.root.info( | |
| 191 'Added code with 0x${address.toRadixString(16)} to isolate.'); | |
| 192 isolate.codes.add(code); | |
| 193 _setModelResponse('Code', 'code', code); | |
| 194 }).catchError(_requestCatchError); | |
| 195 } | |
| 196 | |
| 197 static final RegExp _scriptMatcher = new RegExp(r'scripts/.+'); | |
| 198 static bool isScriptId(objectId) => _scriptMatcher.hasMatch(objectId); | |
| 199 void _getScript(String objectId) { | |
| 200 var script = scripts[objectId]; | |
| 201 if ((script != null) && !script.needsSource) { | |
| 202 Logger.root.info('Found script ${script.scriptRef['name']} in isolate'); | |
| 203 _setModelResponse('Script', 'script', script); | |
| 204 return; | |
| 205 } | |
| 206 if (script != null) { | |
| 207 // The isolate has the script but no script source code. | |
| 208 getMap(objectId).then((response) { | |
| 209 assert(response['type'] == 'Script'); | |
| 210 script._processSource(response['source']); | |
| 211 Logger.root.info( | |
| 212 'Grabbed script ${script.scriptRef['name']} source.'); | |
| 213 _setModelResponse('Script', 'script', script); | |
| 214 }); | |
| 215 return; | |
| 216 } | |
| 217 // New script. | |
| 218 getMap(objectId).then((response) { | |
| 219 assert(response['type'] == 'Script'); | |
| 220 var script = new Script.fromMap(response); | |
| 221 Logger.root.info( | |
| 222 'Added script ${script.scriptRef['name']} to isolate.'); | |
| 223 _setModelResponse('Script', 'script', script); | |
| 224 scripts[objectId] = script; | |
| 225 }); | |
| 226 } | |
| 227 | |
| 228 /// Requests [objectId] from [this]. Completes to a [ServiceObject]. | |
| 229 Future<ServiceObject> get(String objectId) { | |
| 230 if (isCodeId(objectId)) { | |
| 231 _getCode(objectId); | |
| 232 // TODO(johnmccutchan): FIX. | |
| 233 return null; | |
| 234 } | |
| 235 if (isScriptId(objectId)) { | |
| 236 _getScript(objectId); | |
| 237 // TODO(johnmccutchan): FIX. | |
| 238 return null; | |
| 239 } | |
| 240 return vm.fetchMap(relativeLink(objectId)).then((m) => | |
| 241 upgradeToServiceObject(objectId, m)); | |
| 242 } | |
| 243 | |
| 244 /// Requests [objectId] from [this]. Completes to a [Map]. | |
| 245 Future<ObservableMap> getMap(String objectId) { | |
| 246 return vm.fetchMap(relativeLink(objectId)); | |
| 247 } | |
| 248 | |
| 249 /// Upgrades response ([m]) for [objectId] to a [ServiceObject]. | |
| 250 ServiceObject upgradeToServiceObject(String objectId, Map m) { | |
| 251 return new ServiceMap.fromMap(this, m); | |
| 252 } | |
| 253 } | |
| OLD | NEW |