Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(25)

Side by Side Diff: runtime/bin/vmservice/client/lib/src/service/object.dart

Issue 206213004: Add a VM page to the observatory. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: before review Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 Isolate _isolate; 10 /// The owner of this [ServiceObject]. This can be an [Isolate], a
11 /// [VM], or null.
12 @reflectable ServiceObject get owner => _owner;
13 ServiceObject _owner;
11 14
12 /// Owning isolate. 15 /// The [VM] which owns this [ServiceObject].
13 @reflectable Isolate get isolate => _isolate; 16 @reflectable VM get vm {
17 if (owner == null) {
18 assert(this is VM);
19 return this;
20 } else if (owner is VM) {
21 return owner;
22 } else {
23 assert(owner.owner is VM);
24 return owner.owner;
25 }
26 }
14 27
15 /// Owning vm. 28 /// The [Isolate] which owns this [ServiceObject]. May be null.
16 @reflectable VM get vm => _isolate.vm; 29 @reflectable Isolate get isolate {
30 if (owner == null) {
31 return null;
32 } else if (this is Isolate) {
33 return this;
34 } else {
35 assert(owner is Isolate);
36 return owner;
37 }
38 }
39
40 /// The id of this object.
41 @reflectable String get id => _id;
42 String _id;
43
44 /// The service type of this object.
45 @reflectable String get serviceType => _serviceType;
46 String _serviceType;
17 47
18 /// The complete service url of this object. 48 /// The complete service url of this object.
19 @reflectable String get link => isolate.relativeLink(_id); 49 @reflectable String get link => isolate.relativeLink(_id);
20 50
21 /// The complete service url of this object with a '#/' prefix. 51 /// The complete service url of this object with a '#/' prefix.
22 @reflectable String get hashLink => isolate.relativeHashLink(_id); 52 @reflectable String get hashLink => '#/${link}';
23 set hashLink(var o) { /* silence polymer */ } 53 set hashLink(var o) { /* silence polymer */ }
24 54
25 String _id; 55 /// Returns true if [this] has only been partially initialized via
26 /// The id of this object. 56 /// a reference. See [load].
27 @reflectable String get id => _id; 57 bool isRef() => _ref;
28
29 String _serviceType;
30 /// The service type of this object.
31 @reflectable String get serviceType => _serviceType;
32
33 bool _ref; 58 bool _ref;
34 59
35 @observable String name; 60 @observable String name;
36 @observable String vmName; 61 @observable String vmName;
62 @observable String mainPort;
37 63
38 ServiceObject(this._isolate, this._id, this._serviceType) { 64 ServiceObject(this._owner, this._id, this._serviceType) {
39 _ref = isRefType(_serviceType); 65 _ref = isRefType(_serviceType);
40 _serviceType = stripRef(_serviceType); 66 _serviceType = stripRef(_serviceType);
41 _created(); 67 _created();
42 } 68 }
43 69
44 ServiceObject.fromMap(this._isolate, ObservableMap m) { 70 ServiceObject.fromMap(this._owner, ObservableMap map) {
45 assert(isServiceMap(m)); 71 assert(isServiceMap(map));
46 _id = m['id']; 72 _id = map['id'];
47 _ref = isRefType(m['type']); 73 _ref = isRefType(map['type']);
48 _serviceType = stripRef(m['type']); 74 _serviceType = stripRef(map['type']);
75 update(map);
49 _created(); 76 _created();
50 update(m);
51 } 77 }
52 78
53 /// If [this] was created from a reference, load the full object 79 /// If [this] was created from a reference, load the full object
54 /// from the service by calling [reload]. Else, return [this]. 80 /// from the service by calling [reload]. Else, return [this].
55 Future<ServiceObject> load() { 81 Future<ServiceObject> load() {
56 if (!_ref) { 82 if (!_ref) {
57 // Not a reference. 83 // Not a reference.
58 return new Future.value(this); 84 return new Future.value(this);
59 } 85 }
60 // Call reload which will fill in the entire object. 86 // Call reload which will fill in the entire object.
61 return reload(); 87 return reload();
62 } 88 }
63 89
64 /// Reload [this]. Returns a future which completes to [this] or 90 /// Reload [this]. Returns a future which completes to [this] or
65 /// a [ServiceError]. 91 /// a [ServiceError].
66 Future<ServiceObject> reload() { 92 Future<ServiceObject> reload() {
67 assert(isolate != null);
68 if (id == '') { 93 if (id == '') {
69 // Errors don't have ids. 94 // Errors don't have ids.
70 assert(serviceType == 'Error'); 95 assert(serviceType == 'Error');
71 return new Future.value(this); 96 return new Future.value(this);
72 } 97 }
73 return isolate.vm.getAsMap(link).then(update); 98 return vm.getAsMap(link).then(update);
74 } 99 }
75 100
76 /// Update [this] using [m] as a source. [m] can be a reference. 101 /// Update [this] using [m] as a source. [m] can be a reference.
77 ServiceObject update(ObservableMap m) { 102 ServiceObject update(ObservableMap m) {
78 // Assert that m is a service map. 103 // Assert that m is a service map.
79 assert(ServiceObject.isServiceMap(m)); 104 assert(ServiceObject.isServiceMap(m));
80 if ((m['type'] == 'Error') && (_serviceType != 'Error')) { 105 if ((m['type'] == 'Error') && (_serviceType != 'Error')) {
81 // Got an unexpected error. Don't update the object. 106 // Got an unexpected error. Don't update the object.
82 return _upgradeToServiceObject(vm, isolate, m); 107 return _upgradeToServiceObject(vm, isolate, m);
83 } 108 }
84 // TODO(johnmccutchan): Should we allow for a ServiceObject's id 109 // TODO(johnmccutchan): Should we allow for a ServiceObject's id
85 // or type to change? 110 // or type to change?
86 _id = m['id']; 111 _id = m['id'];
87 _serviceType = stripRef(m['type']); 112 _serviceType = stripRef(m['type']);
88 _update(m); 113 _update(m);
89 return this; 114 return this;
90 } 115 }
91 116
92 // update internal state from [map]. [map] can be a reference. 117 // update internal state from [map]. [map] can be a reference.
93 void _update(ObservableMap map); 118 void _update(ObservableMap map);
94 119
95 /// Returns true if [this] has only been partially initialized via
96 /// a reference. See [load].
97 bool isRef() => _ref;
98
99 void _created() { 120 void _created() {
100 var refNotice = _ref ? ' Created from reference.' : ''; 121 var refNotice = _ref ? ' Created from reference.' : '';
101 Logger.root.info('Created ServiceObject for \'${_id}\' with type ' 122 Logger.root.info('Created ServiceObject for \'${_id}\' with type '
102 '\'${_serviceType}\'.' + refNotice); 123 '\'${_serviceType}\'.' + refNotice);
103 } 124 }
104 125
126 // ------------------------------------------------------
127
105 /// Returns true if [map] is a service map. i.e. it has the following keys: 128 /// Returns true if [map] is a service map. i.e. it has the following keys:
106 /// 'id' and a 'type'. 129 /// 'id' and a 'type'.
107 static bool isServiceMap(ObservableMap m) { 130 static bool isServiceMap(ObservableMap m) {
108 return (m != null) && (m['id'] != null) && (m['type'] != null); 131 return (m != null) && (m['id'] != null) && (m['type'] != null);
109 } 132 }
110 133
111 /// Returns true if [type] is a reference type. i.e. it begins with an 134 /// Returns true if [type] is a reference type. i.e. it begins with an
112 /// '@' character. 135 /// '@' character.
113 static bool isRefType(String type) { 136 static bool isRefType(String type) {
114 return type.startsWith('@'); 137 return type.startsWith('@');
115 } 138 }
116 139
117 /// Returns the unreffed version of [type]. 140 /// Returns the unreffed version of [type].
118 static String stripRef(String type) { 141 static String stripRef(String type) {
119 if (!isRefType(type)) { 142 if (!isRefType(type)) {
120 return type; 143 return type;
121 } 144 }
122 // Strip off the '@' character. 145 // Strip off the '@' character.
123 return type.substring(1); 146 return type.substring(1);
124 } 147 }
125 } 148 }
126 149
127 /// State for a VM being inspected. 150 /// State for a VM being inspected.
128 abstract class VM extends Observable { 151 abstract class VM extends ServiceObject {
129 @reflectable IsolateList _isolates; 152 @reflectable IsolateList _isolates;
130 @reflectable IsolateList get isolates => _isolates; 153 @reflectable IsolateList get isolates => _isolates;
131 154
155 @reflectable String get link => "$id";
156
157 @observable String version = 'unknown';
158 @observable String architecture = 'unknown';
159 @observable double uptime = 0.0;
160
132 void _initOnce() { 161 void _initOnce() {
133 assert(_isolates == null); 162 assert(_isolates == null);
134 _isolates = new IsolateList(this); 163 _isolates = new IsolateList(this);
164 name = "vm";
165 vmName = "vm";
135 } 166 }
136 167
137 VM() { 168 VM() : super(null, "vm", "VM") {
138 _initOnce(); 169 _initOnce();
139 } 170 }
140 171
141 /// Get [id] as an [ObservableMap] from the service directly. 172 static final RegExp _currentIsolateMatcher = new RegExp(r'isolates/\d+');
173 static final RegExp _currentObjectMatcher = new RegExp(r'isolates/\d+(/|$)');
174
175 String _parseObjectId(String id) {
176 Match m = _currentObjectMatcher.matchAsPrefix(id);
177 if (m == null) {
178 return null;
179 }
180 return m.input.substring(m.end);
181 }
182
183 String _parseIsolateId(String id) {
184 Match m = _currentIsolateMatcher.matchAsPrefix(id);
185 if (m == null) {
186 print("NO MATCH");
Cutch 2014/03/20 18:25:56 Logger.root.warning ?
turnidge 2014/03/20 19:08:02 Actually this happens legitimately on the /vm page
187 return '';
188 }
189 return id.substring(0, m.end);
190 }
191
192 Future<ServiceObject> _getDirect(String id) {
193 return vm.getAsMap(id).then((ObservableMap m) {
194 return _upgradeToServiceObject(vm, null, m);
195 });
196 }
197
198 Future<ServiceObject> get(String id) {
199 if (id.startsWith('isolates/')) {
200 String isolateId = _parseIsolateId(id);
201 if (isolateId == '') {
202 return reload();
203 } else {
204 Isolate isolate = _isolates.getIsolate(isolateId);
205 if (isolate == null) {
206 // TODO(turnidge): Isolate not found error.
207 return reload();
208 } else {
209 String objectId = _parseObjectId(id);
210 if (objectId == null) {
211 return isolate.reload();
212 } else {
213 return isolate.get(objectId);
214 }
215 }
216 }
217 } else if (id == 'vm') {
218 return reload();
219 } else {
220 return _getDirect(id);
221 }
222 }
223
224 /// Gets [id] as an [ObservableMap] from the service directly.
142 Future<ObservableMap> getAsMap(String id) { 225 Future<ObservableMap> getAsMap(String id) {
143 return getString(id).then((response) { 226 return getString(id).then((response) {
144 try { 227 try {
145 var map = JSON.decode(response); 228 var map = JSON.decode(response);
146 Logger.root.info('Decoded $id'); 229 Logger.root.info('Decoded $id');
147 return toObservable(map); 230 return toObservable(map);
148 } catch (e, st) { 231 } catch (e, st) {
149 return toObservable({ 232 return toObservable({
150 'type': 'Error', 233 'type': 'Error',
151 'id': '', 234 'id': '',
152 'kind': 'DecodeError', 235 'kind': 'DecodeError',
153 'message': '$e', 236 'message': '$e',
154 }); 237 });
155 } 238 }
156 }).catchError((error) { 239 }).catchError((error) {
157 return toObservable({ 240 return toObservable({
158 'type': 'Error', 241 'type': 'Error',
159 'id': '', 242 'id': '',
160 'kind': 'LastResort', 243 'kind': 'LastResort',
161 'message': '$error' 244 'message': '$error'
162 }); 245 });
163 }); 246 });
164 } 247 }
165 248
166 /// Get [id] as a [String] from the service directly. See [getAsMap]. 249 /// Get [id] as a [String] from the service directly. See [getAsMap].
167 Future<String> getString(String id); 250 Future<String> getString(String id);
251
252 void _update(ObservableMap map) {
253 print("$map");
Cutch 2014/03/20 18:25:56 remove?
turnidge 2014/03/20 19:08:02 Done.
254 _ref = false;
255 version = map['version'];
256 architecture = map['architecture'];
257 uptime = map['uptime'];
258 _isolates.updateIsolates(map['isolates']);
259 }
168 } 260 }
169 261
170 /// State for a running isolate. 262 /// State for a running isolate.
171 class Isolate extends ServiceObject { 263 class Isolate extends ServiceObject {
172 final VM vm;
173 String get link => _id; 264 String get link => _id;
174 String get hashLink => '#/$_id'; 265 String get hashLink => '#/$_id';
175 266
267 @observable bool pausedOnStart = false;
268 @observable bool pausedOnExit = false;
269 @observable bool running = false;
270 @observable bool idle = false;
271
176 ScriptCache _scripts; 272 ScriptCache _scripts;
177 /// Script cache. 273 /// Script cache.
178 ScriptCache get scripts => _scripts; 274 ScriptCache get scripts => _scripts;
179 CodeCache _codes; 275 CodeCache _codes;
180 /// Code cache. 276 /// Code cache.
181 CodeCache get codes => _codes; 277 CodeCache get codes => _codes;
182 /// Class cache. 278 /// Class cache.
183 ClassCache _classes; 279 ClassCache _classes;
184 ClassCache get classes => _classes; 280 ClassCache get classes => _classes;
185 /// Function cache. 281 /// Function cache.
186 FunctionCache _functions; 282 FunctionCache _functions;
187 FunctionCache get functions => _functions; 283 FunctionCache get functions => _functions;
188 284
189 void _initOnce() { 285 void _initOnce() {
190 // Only called once. 286 // Only called once.
191 assert(_isolate == null); 287 assert(_scripts == null);
192 _isolate = this;
193 _scripts = new ScriptCache(this); 288 _scripts = new ScriptCache(this);
194 _codes = new CodeCache(this); 289 _codes = new CodeCache(this);
195 _classes = new ClassCache(this); 290 _classes = new ClassCache(this);
196 _functions = new FunctionCache(this); 291 _functions = new FunctionCache(this);
197 } 292 }
198 293
199 Isolate.fromId(this.vm, String id) : super(null, id, '@Isolate') { 294 Isolate.fromId(VM vm, String id) : super(vm, id, '@Isolate') {
200 _initOnce(); 295 _initOnce();
201 } 296 }
202 297
203 Isolate.fromMap(this.vm, Map map) : super.fromMap(null, map) { 298 Isolate.fromMap(VM vm, Map map) : super.fromMap(vm, map) {
204 _initOnce(); 299 _initOnce();
205 } 300 }
206 301
207 /// Creates a link to [id] relative to [this]. 302 /// Creates a link to [id] relative to [this].
208 @reflectable String relativeLink(String id) => '${this.id}/$id'; 303 @reflectable String relativeLink(String id) => '${this.id}/$id';
209 /// Creates a relative link to [id] with a '#/' prefix. 304 /// Creates a relative link to [id] with a '#/' prefix.
210 @reflectable String relativeHashLink(String id) => '#/${relativeLink(id)}'; 305 @reflectable String relativeHashLink(String id) => '#/${relativeLink(id)}';
211 306
212 Future<ScriptCache> refreshCoverage() { 307 Future<ScriptCache> refreshCoverage() {
213 return get('coverage').then(_scripts._processCoverage); 308 return get('coverage').then(_scripts._processCoverage);
214 } 309 }
215 310
216 void processProfile(ServiceMap profile) { 311 void processProfile(ServiceMap profile) {
217 assert(profile.serviceType == 'Profile'); 312 assert(profile.serviceType == 'Profile');
218 var codeTable = new List<Code>(); 313 var codeTable = new List<Code>();
219 var codeRegions = profile['codes']; 314 var codeRegions = profile['codes'];
220 for (var codeRegion in codeRegions) { 315 for (var codeRegion in codeRegions) {
221 Code code = codeRegion['code']; 316 Code code = codeRegion['code'];
222 assert(code != null); 317 assert(code != null);
223 codeTable.add(code); 318 codeTable.add(code);
224 } 319 }
225 _codes._resetProfileData(); 320 _codes._resetProfileData();
226 _codes._updateProfileData(profile, codeTable); 321 _codes._updateProfileData(profile, codeTable);
227 var exclusiveTrie = profile['exclusive_trie']; 322 var exclusiveTrie = profile['exclusive_trie'];
228 if (exclusiveTrie != null) { 323 if (exclusiveTrie != null) {
229 profileTrieRoot = _processProfileTrie(exclusiveTrie, codeTable); 324 profileTrieRoot = _processProfileTrie(exclusiveTrie, codeTable);
230 } 325 }
231 } 326 }
232 327
233 Future<ServiceObject> getDirect(String serviceId) { 328 Future<ServiceObject> _getDirect(String serviceId) {
234 return vm.getAsMap(relativeLink(serviceId)).then((ObservableMap m) { 329 return vm.getAsMap(relativeLink(serviceId)).then((ObservableMap m) {
235 return _upgradeToServiceObject(vm, this, m); 330 return _upgradeToServiceObject(vm, this, m);
236 }); 331 });
237 } 332 }
238 333
239 /// Requests [serviceId] from [this]. Completes to a [ServiceObject]. 334 /// Requests [serviceId] from [this]. Completes to a [ServiceObject].
240 /// Can return pre-existing, cached, [ServiceObject]s. 335 /// Can return pre-existing, cached, [ServiceObject]s.
241 Future<ServiceObject> get(String serviceId) { 336 Future<ServiceObject> get(String serviceId) {
242 if (serviceId == '') { 337 if (serviceId == '') {
243 return reload(); 338 return reload();
244 } 339 }
245 if (_scripts.cachesId(serviceId)) { 340 if (_scripts.cachesId(serviceId)) {
246 return _scripts.get(serviceId); 341 return _scripts.get(serviceId);
247 } 342 }
248 if (_codes.cachesId(serviceId)) { 343 if (_codes.cachesId(serviceId)) {
249 return _codes.get(serviceId); 344 return _codes.get(serviceId);
250 } 345 }
251 if (_classes.cachesId(serviceId)) { 346 if (_classes.cachesId(serviceId)) {
252 return _classes.get(serviceId); 347 return _classes.get(serviceId);
253 } 348 }
254 if (_functions.cachesId(serviceId)) { 349 if (_functions.cachesId(serviceId)) {
255 return _functions.get(serviceId); 350 return _functions.get(serviceId);
256 } 351 }
257 return getDirect(serviceId); 352 return _getDirect(serviceId);
258 } 353 }
259 354
260 @observable ServiceMap rootLib; 355 @observable ServiceMap rootLib;
261 @observable ObservableMap topFrame; 356 @observable ObservableMap topFrame;
262 357
263 @observable String name; 358 @observable String name;
264 @observable String vmName; 359 @observable String vmName;
265 @observable Map entry; 360 @observable Map entry;
266 361
267 @observable final Map<String, double> timers = 362 @observable final Map<String, double> timers =
268 toObservable(new Map<String, double>()); 363 toObservable(new Map<String, double>());
269 364
270 @observable int newHeapUsed = 0; 365 @observable int newHeapUsed = 0;
271 @observable int oldHeapUsed = 0; 366 @observable int oldHeapUsed = 0;
272 @observable int newHeapCapacity = 0; 367 @observable int newHeapCapacity = 0;
273 @observable int oldHeapCapacity = 0; 368 @observable int oldHeapCapacity = 0;
274 369
275 @observable String fileAndLine; 370 @observable String fileAndLine;
276 371
277 void _update(ObservableMap map) { 372 void _update(ObservableMap map) {
278 upgradeCollection(map, vm, this); 373 upgradeCollection(map, vm, this);
374 mainPort = map['mainPort'];
375 name = map['name'];
376 if (ServiceObject.isRefType(map['type'])) {
377 return;
378 }
279 _ref = false; 379 _ref = false;
280 if (map['rootLib'] == null || 380 if (map['rootLib'] == null ||
281 map['timers'] == null || 381 map['timers'] == null ||
282 map['heap'] == null) { 382 map['heap'] == null) {
283 Logger.root.severe("Malformed 'Isolate' response: $map"); 383 Logger.root.severe("Malformed 'Isolate' response: $map");
284 return; 384 return;
285 } 385 }
286 rootLib = map['rootLib']; 386 rootLib = map['rootLib'];
287 vmName = map['name']; 387 vmName = map['name'];
288 if (map['entry'] != null) { 388 if (map['entry'] != null) {
289 entry = map['entry']; 389 entry = map['entry'];
290 name = entry['name'];
291 } else {
292 // fred
293 name = 'root';
294 } 390 }
295 if (map['topFrame'] != null) { 391 if (map['topFrame'] != null) {
296 topFrame = map['topFrame']; 392 topFrame = map['topFrame'];
297 } else { 393 } else {
298 topFrame = null ; 394 topFrame = null ;
299 } 395 }
300 396
301 var timerMap = {}; 397 var timerMap = {};
302 map['timers'].forEach((timer) { 398 map['timers'].forEach((timer) {
303 timerMap[timer['name']] = timer['time']; 399 timerMap[timer['name']] = timer['time'];
304 }); 400 });
305 timers['total'] = timerMap['time_total_runtime']; 401 timers['total'] = timerMap['time_total_runtime'];
306 timers['compile'] = timerMap['time_compilation']; 402 timers['compile'] = timerMap['time_compilation'];
307 timers['gc'] = 0.0; // TODO(turnidge): Export this from VM. 403 timers['gc'] = 0.0; // TODO(turnidge): Export this from VM.
308 timers['init'] = (timerMap['time_script_loading'] + 404 timers['init'] = (timerMap['time_script_loading'] +
309 timerMap['time_creating_snapshot'] + 405 timerMap['time_creating_snapshot'] +
310 timerMap['time_isolate_initialization'] + 406 timerMap['time_isolate_initialization'] +
311 timerMap['time_bootstrap']); 407 timerMap['time_bootstrap']);
312 timers['dart'] = timerMap['time_dart_execution']; 408 timers['dart'] = timerMap['time_dart_execution'];
313 409
314 newHeapUsed = map['heap']['usedNew']; 410 newHeapUsed = map['heap']['usedNew'];
315 oldHeapUsed = map['heap']['usedOld']; 411 oldHeapUsed = map['heap']['usedOld'];
316 newHeapCapacity = map['heap']['capacityNew']; 412 newHeapCapacity = map['heap']['capacityNew'];
317 oldHeapCapacity = map['heap']['capacityOld']; 413 oldHeapCapacity = map['heap']['capacityOld'];
414
415 // Isolate status
416 pausedOnStart = map['pausedOnStart'];
417 pausedOnExit = map['pausedOnExit'];
418 running = map['topFrame'] != null;
419 idle = !pausedOnStart && !pausedOnExit && !running;
318 } 420 }
319 421
320 @reflectable CodeTrieNode profileTrieRoot; 422 @reflectable CodeTrieNode profileTrieRoot;
321 // The profile trie is serialized as a list of integers. Each node 423 // The profile trie is serialized as a list of integers. Each node
322 // is recreated by consuming some portion of the list. The format is as 424 // is recreated by consuming some portion of the list. The format is as
323 // follows: 425 // follows:
324 // [0] index into codeTable of code object. 426 // [0] index into codeTable of code object.
325 // [1] tick count (number of times this stack frame occured). 427 // [1] tick count (number of times this stack frame occured).
326 // [2] child node count 428 // [2] child node count
327 // Reading the trie is done by recursively reading the tree depth-first 429 // Reading the trie is done by recursively reading the tree depth-first
(...skipping 29 matching lines...) Expand all
357 for (var i = 0; i < children; i++) { 459 for (var i = 0; i < children; i++) {
358 var child = _readTrieNode(codeTable); 460 var child = _readTrieNode(codeTable);
359 node.children.add(child); 461 node.children.add(child);
360 node.summedChildCount += child.count; 462 node.summedChildCount += child.count;
361 } 463 }
362 return node; 464 return node;
363 } 465 }
364 } 466 }
365 467
366 // TODO(johnmccutchan): Make this into an IsolateCache. 468 // TODO(johnmccutchan): Make this into an IsolateCache.
367 class IsolateList extends ServiceObject { 469 class IsolateList {
368 final VM _vm; 470 final VM _vm;
369 VM get vm => _vm;
370 @observable final isolates = new ObservableMap<String, Isolate>(); 471 @observable final isolates = new ObservableMap<String, Isolate>();
371 IsolateList(this._vm) : super(null, 'isolates', 'IsolateList') {
372 name = 'IsolateList';
373 vmName = name;
374 }
375 IsolateList.fromMap(this._vm, Map m) : super.fromMap(null, m) {
376 name = 'IsolateList';
377 vmName = name;
378 }
379 472
380 Future<ServiceObject> reload() { 473 IsolateList(this._vm);
381 return vm.getAsMap(id).then(update);
382 }
383 474
384 void _update(ObservableMap map) { 475 void updateIsolates(List<Map> members) {
385 _updateIsolates(map['members']);
386 }
387
388 void _updateIsolates(List<Map> members) {
389 // Find dead isolates. 476 // Find dead isolates.
390 var deadIsolates = []; 477 var deadIsolates = [];
391 isolates.forEach((k, v) { 478 isolates.forEach((k, v) {
392 if (!_foundIsolateInMembers(k, members)) { 479 if (!_foundIsolateInMembers(k, members)) {
393 deadIsolates.add(k); 480 deadIsolates.add(k);
394 } 481 }
395 }); 482 });
396 // Remove them. 483 // Remove them.
397 deadIsolates.forEach((id) { 484 deadIsolates.forEach((id) {
398 isolates.remove(id); 485 isolates.remove(id);
399 Logger.root.info('Isolate \'$id\' has gone away.'); 486 Logger.root.info('Isolate \'$id\' has gone away.');
400 }); 487 });
401 488
402 // Add new isolates. 489 // Add new isolates.
403 members.forEach((map) { 490 members.forEach((map) {
404 var id = map['id']; 491 var id = map['id'];
405 var isolate = isolates[id]; 492 var isolate = isolates[id];
406 if (isolate == null) { 493 if (isolate == null) {
407 isolate = new Isolate.fromMap(vm, map); 494 isolate = new Isolate.fromMap(_vm, map);
408 Logger.root.info('Created ServiceObject for \'${isolate.id}\' with ' 495 Logger.root.info('Created ServiceObject for \'${isolate.id}\' with '
409 'type \'${isolate.serviceType}\''); 496 'type \'${isolate.serviceType}\'');
410 isolates[id] = isolate; 497 isolates[id] = isolate;
411 } 498 }
412 }); 499 });
413 500
414 // After updating the isolate list, refresh each isolate. 501 // After updating the isolate list, refresh each isolate.
415 _refreshIsolates(); 502 _refreshIsolates();
416 } 503 }
417 504
418 void _refreshIsolates() { 505 void _refreshIsolates() {
419 // This is technically asynchronous but we don't need to wait for 506 // This is technically asynchronous but we don't need to wait for
420 // the result. 507 // the result.
421 isolates.forEach((k, Isolate isolate) { 508 isolates.forEach((k, Isolate isolate) {
422 isolate.reload(); 509 isolate.reload();
423 }); 510 });
424 } 511 }
425 512
426 Isolate getIsolate(String id) { 513 Isolate getIsolate(String id) {
427 assert(id.startsWith('isolates/')); 514 assert(id.startsWith('isolates/'));
428 var isolate = isolates[id]; 515 var isolate = isolates[id];
429 if (isolate != null) { 516 if (isolate != null) {
430 return isolate; 517 return isolate;
431 } 518 }
432 isolate = new Isolate.fromId(vm, id); 519 isolate = new Isolate.fromId(_vm, id);
433 isolates[id] = isolate; 520 isolates[id] = isolate;
434 isolate.load(); 521 isolate.load();
435 return isolate; 522 return isolate;
436 } 523 }
437 524
438 Isolate getIsolateFromMap(ObservableMap m) { 525 Isolate getIsolateFromMap(ObservableMap m) {
439 assert(ServiceObject.isServiceMap(m)); 526 assert(ServiceObject.isServiceMap(m));
440 String id = m['id']; 527 String id = m['id'];
441 assert(id.startsWith('isolates/')); 528 assert(id.startsWith('isolates/'));
442 var isolate = isolates[id]; 529 var isolate = isolates[id];
443 if (isolate != null) { 530 if (isolate != null) {
444 isolate.update(m); 531 isolate.update(m);
445 return isolate; 532 return isolate;
446 } 533 }
447 isolate = new Isolate.fromMap(vm, m); 534 isolate = new Isolate.fromMap(_vm, m);
448 isolates[id] = isolate; 535 isolates[id] = isolate;
449 isolate.load(); 536 isolate.load();
450 return isolate; 537 return isolate;
451 } 538 }
452 539
453 static bool _foundIsolateInMembers(String id, List<Map> members) { 540 static bool _foundIsolateInMembers(String id, List<Map> members) {
454 return members.any((E) => E['id'] == id); 541 return members.any((E) => E['id'] == id);
455 } 542 }
456 } 543 }
457 544
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
502 void notifyChange(ChangeRecord record) => _map.notifyChange(record); 589 void notifyChange(ChangeRecord record) => _map.notifyChange(record);
503 notifyPropertyChange(Symbol field, Object oldValue, Object newValue) => 590 notifyPropertyChange(Symbol field, Object oldValue, Object newValue) =>
504 _map.notifyPropertyChange(field, oldValue, newValue); 591 _map.notifyPropertyChange(field, oldValue, newValue);
505 void observed() => _map.observed(); 592 void observed() => _map.observed();
506 void unobserved() => _map.unobserved(); 593 void unobserved() => _map.unobserved();
507 Stream<List<ChangeRecord>> get changes => _map.changes; 594 Stream<List<ChangeRecord>> get changes => _map.changes;
508 bool get hasObservers => _map.hasObservers; 595 bool get hasObservers => _map.hasObservers;
509 } 596 }
510 597
511 class ServiceError extends ServiceObject { 598 class ServiceError extends ServiceObject {
512 ServiceError.fromMap(Isolate isolate, Map m) : super.fromMap(isolate, m); 599 ServiceError.fromMap(ServiceObject owner, Map m) : super.fromMap(owner, m);
513 600
514 @observable String kind; 601 @observable String kind;
515 @observable String message; 602 @observable String message;
516 603
517 void _update(ObservableMap map) { 604 void _update(ObservableMap map) {
518 kind = map['kind']; 605 kind = map['kind'];
519 message = map['message']; 606 message = map['message'];
520 name = 'ServiceError $kind'; 607 name = 'ServiceError $kind';
521 vmName = name; 608 vmName = name;
522 } 609 }
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after
859 946
860 int _callCount(List<CodeCallCount> calls, Code code) { 947 int _callCount(List<CodeCallCount> calls, Code code) {
861 for (CodeCallCount caller in calls) { 948 for (CodeCallCount caller in calls) {
862 if (caller.code == code) { 949 if (caller.code == code) {
863 return caller.count; 950 return caller.count;
864 } 951 }
865 } 952 }
866 return 0; 953 return 0;
867 } 954 }
868 } 955 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698