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

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

Issue 197803004: Add dead CodeRegionTable for tracking overwritten Dart code (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: 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 /// State for a running isolate. 7 /// State for a running isolate.
8 class Isolate extends ServiceObject { 8 class Isolate extends ServiceObject {
9 final VM vm; 9 final VM vm;
10 String get link => _id; 10 String get link => _id;
11 String get hashLink => '#/$_id'; 11 String get hashLink => '#/$_id';
12 12
13 ScriptCache _scripts; 13 ScriptCache _scripts;
14 /// Script cache. 14 /// Script cache.
15 ScriptCache get scripts => _scripts; 15 ScriptCache get scripts => _scripts;
16 CodeCache _codes; 16 CodeCache _codes;
17 /// Code cache. 17 /// Code cache.
18 CodeCache get codes => _codes; 18 CodeCache get codes => _codes;
19 /// Class cache. 19 /// Class cache.
20 ClassCache _classes; 20 ClassCache _classes;
21 ClassCache get classes => _classes; 21 ClassCache get classes => _classes;
22 /// Function cache.
23 FunctionCache _functions;
24 FunctionCache get functions => _functions;
22 25
23 void _initOnce() { 26 void _initOnce() {
24 // Only called once. 27 // Only called once.
25 assert(_isolate == null); 28 assert(_isolate == null);
26 _isolate = this; 29 _isolate = this;
27 _scripts = new ScriptCache(this); 30 _scripts = new ScriptCache(this);
28 _codes = new CodeCache(this); 31 _codes = new CodeCache(this);
29 _classes = new ClassCache(this); 32 _classes = new ClassCache(this);
33 _functions = new FunctionCache(this);
30 } 34 }
31 35
32 Isolate.fromId(this.vm, String id) : super(null, id, '@Isolate') { 36 Isolate.fromId(this.vm, String id) : super(null, id, '@Isolate') {
33 _initOnce(); 37 _initOnce();
34 } 38 }
35 39
36 Isolate.fromMap(this.vm, Map map) : super.fromMap(null, map) { 40 Isolate.fromMap(this.vm, Map map) : super.fromMap(null, map) {
37 _initOnce(); 41 _initOnce();
38 } 42 }
39 43
40 /// Creates a link to [id] relative to [this]. 44 /// Creates a link to [id] relative to [this].
41 @reflectable String relativeLink(String id) => '${this.id}/$id'; 45 @reflectable String relativeLink(String id) => '${this.id}/$id';
42 /// Creates a relative link to [id] with a '#/' prefix. 46 /// Creates a relative link to [id] with a '#/' prefix.
43 @reflectable String relativeHashLink(String id) => '#/${relativeLink(id)}'; 47 @reflectable String relativeHashLink(String id) => '#/${relativeLink(id)}';
44 48
45 Future<ScriptCache> refreshCoverage() { 49 Future<ScriptCache> refreshCoverage() {
46 return get('coverage').then(_scripts._processCoverage); 50 return get('coverage').then(_scripts._processCoverage);
47 } 51 }
48 52
49 void processProfile(ServiceMap profile) { 53 void processProfile(ServiceMap profile) {
50 assert(profile.serviceType == 'Profile'); 54 assert(profile.serviceType == 'Profile');
51 var codeTable = new List<Code>(); 55 var codeTable = new List<Code>();
52 var profileCodes = profile['codes']; 56 var codeRegions = profile['codes'];
53 for (var profileCode in profileCodes) { 57 for (var codeRegion in codeRegions) {
54 Code code = profileCode['code']; 58 Code code = codeRegion['code'];
59 assert(code != null);
55 codeTable.add(code); 60 codeTable.add(code);
56 } 61 }
57 _codes._resetProfileData(); 62 _codes._resetProfileData();
58 _codes._updateProfileData(profile, codeTable); 63 _codes._updateProfileData(profile, codeTable);
59 } 64 }
60 65
61 /// Requests [serviceId] from [this]. Completes to a [ServiceObject]. 66 /// Requests [serviceId] from [this]. Completes to a [ServiceObject].
62 /// Can return pre-existing, cached, [ServiceObject]s. 67 /// Can return pre-existing, cached, [ServiceObject]s.
63 Future<ServiceObject> get(String serviceId) { 68 Future<ServiceObject> get(String serviceId) {
64 if (_scripts.cachesId(serviceId)) { 69 if (_scripts.cachesId(serviceId)) {
65 return _scripts.get(serviceId); 70 return _scripts.get(serviceId);
66 } 71 }
67 if (_codes.cachesId(serviceId)) { 72 if (_codes.cachesId(serviceId)) {
68 return _codes.get(serviceId); 73 return _codes.get(serviceId);
69 } 74 }
70 if (_classes.cachesId(serviceId)) { 75 if (_classes.cachesId(serviceId)) {
71 return _classes.get(serviceId); 76 return _classes.get(serviceId);
72 } 77 }
78 if (_functions.cachesId(serviceId)) {
79 return _functions.get(serviceId);
80 }
73 return vm.getAsMap(relativeLink(serviceId)).then((ObservableMap m) { 81 return vm.getAsMap(relativeLink(serviceId)).then((ObservableMap m) {
74 return _upgradeToServiceObject(vm, this, m); 82 return _upgradeToServiceObject(vm, this, m);
75 }); 83 });
76 } 84 }
77 85
78 @observable ServiceMap rootLib; 86 @observable ServiceMap rootLib;
79 @observable ObservableMap topFrame; 87 @observable ObservableMap topFrame;
80 88
81 @observable String name; 89 @observable String name;
82 @observable String vmName; 90 @observable String vmName;
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after
396 } 404 }
397 405
398 @reflectable String formattedInclusive(Code code) { 406 @reflectable String formattedInclusive(Code code) {
399 if (code == null) { 407 if (code == null) {
400 return ''; 408 return '';
401 } 409 }
402 var tick = code.addressTicks[address]; 410 var tick = code.addressTicks[address];
403 if (tick == null) { 411 if (tick == null) {
404 return ''; 412 return '';
405 } 413 }
414 // Don't show inclusive ticks if they are the same as exclusive ticks.
415 if (tick.inclusiveTicks == tick.exclusiveTicks) {
416 return '';
417 }
406 var pcent = formatPercent(tick.inclusiveTicks, code.totalSamplesInProfile); 418 var pcent = formatPercent(tick.inclusiveTicks, code.totalSamplesInProfile);
407 return '$pcent (${tick.inclusiveTicks})'; 419 return '$pcent (${tick.inclusiveTicks})';
408 } 420 }
409 421
410 @reflectable String formattedExclusive(Code code) { 422 @reflectable String formattedExclusive(Code code) {
411 if (code == null) { 423 if (code == null) {
412 return ''; 424 return '';
413 } 425 }
414 var tick = code.addressTicks[address]; 426 var tick = code.addressTicks[address];
415 if (tick == null) { 427 if (tick == null) {
416 return ''; 428 return '';
417 } 429 }
418 var pcent = formatPercent(tick.exclusiveTicks, code.totalSamplesInProfile); 430 var pcent = formatPercent(tick.exclusiveTicks, code.totalSamplesInProfile);
419 return '$pcent (${tick.exclusiveTicks})'; 431 return '$pcent (${tick.exclusiveTicks})';
420 } 432 }
421 } 433 }
422 434
423 class CodeKind { 435 class CodeKind {
424 final _value; 436 final _value;
425 const CodeKind._internal(this._value); 437 const CodeKind._internal(this._value);
426 String toString() => 'CodeKind.$_value'; 438 String toString() => '$_value';
427 439
428 static CodeKind fromString(String s) { 440 static CodeKind fromString(String s) {
429 if (s == 'Native') { 441 if (s == 'Native') {
430 return Native; 442 return Native;
431 } else if (s == 'Dart') { 443 } else if (s == 'Dart') {
432 return Dart; 444 return Dart;
433 } else if (s == 'Collected') { 445 } else if (s == 'Collected') {
434 return Collected; 446 return Collected;
447 } else if (s == 'Reused') {
448 return Reused;
turnidge 2014/03/13 18:09:09 What does Reused mean? The same exact code at the
Cutch 2014/03/13 20:52:26 The address is used by a newer piece of code.
435 } 449 }
450 Logger.root.warning('Unknown code kind $s');
436 throw new FallThroughError(); 451 throw new FallThroughError();
437 } 452 }
438 static const Native = const CodeKind._internal('Native'); 453 static const Native = const CodeKind._internal('Native');
439 static const Dart = const CodeKind._internal('Dart'); 454 static const Dart = const CodeKind._internal('Dart');
440 static const Collected = const CodeKind._internal('Collected'); 455 static const Collected = const CodeKind._internal('Collected');
456 static const Reused = const CodeKind._internal('Reused');
441 } 457 }
442 458
443 class CodeCallCount { 459 class CodeCallCount {
444 final Code code; 460 final Code code;
445 final int count; 461 final int count;
446 CodeCallCount(this.code, this.count); 462 CodeCallCount(this.code, this.count);
447 } 463 }
448 464
449 class Code extends ServiceObject { 465 class Code extends ServiceObject {
450 @observable CodeKind kind; 466 @observable CodeKind kind;
451 @observable int totalSamplesInProfile = 0; 467 @observable int totalSamplesInProfile = 0;
452 @reflectable int exclusiveTicks = 0; 468 @reflectable int exclusiveTicks = 0;
453 @reflectable int inclusiveTicks = 0; 469 @reflectable int inclusiveTicks = 0;
454 @reflectable int startAddress = 0; 470 @reflectable int startAddress = 0;
455 @reflectable int endAddress = 0; 471 @reflectable int endAddress = 0;
456 @reflectable final callers = new List<CodeCallCount>(); 472 @reflectable final callers = new List<CodeCallCount>();
457 @reflectable final callees = new List<CodeCallCount>(); 473 @reflectable final callees = new List<CodeCallCount>();
458 @reflectable final instructions = new ObservableList<CodeInstruction>(); 474 @reflectable final instructions = new ObservableList<CodeInstruction>();
459 @reflectable final addressTicks = new ObservableMap<int, CodeTick>(); 475 @reflectable final addressTicks = new ObservableMap<int, CodeTick>();
476 @observable String formattedInclusiveTicks = '';
477 @observable String formattedExclusiveTicks = '';
460 478
461 @observable ServiceMap function; 479 @observable ServiceMap function;
462 String name; 480 String name;
463 String vmName; 481 String vmName;
464 482
465 Code.fromMap(Isolate isolate, Map map) : super.fromMap(isolate, map); 483 Code.fromMap(Isolate isolate, Map map) : super.fromMap(isolate, map);
466 484
467 // Reset all data associated with a profile. 485 // Reset all data associated with a profile.
468 void resetProfileData() { 486 void resetProfileData() {
469 totalSamplesInProfile = 0; 487 totalSamplesInProfile = 0;
470 exclusiveTicks = 0; 488 exclusiveTicks = 0;
471 inclusiveTicks = 0; 489 inclusiveTicks = 0;
490 formattedInclusiveTicks = '';
491 formattedExclusiveTicks = '';
472 callers.clear(); 492 callers.clear();
473 callees.clear(); 493 callees.clear();
474 addressTicks.clear(); 494 addressTicks.clear();
475 } 495 }
476 496
497 /// Reload [this]. Returns a future which completes to [this] or
498 /// a [ServiceError].
499 Future<ServiceObject> reload() {
500 assert(kind != null);
501 if (kind == CodeKind.Dart) {
502 // We only reload Dart code.
503 return super.reload();
504 }
505 return new Future.value(this);
506 }
507
477 void _resolveCalls(List<CodeCallCount> calls, List data, List<Code> codes) { 508 void _resolveCalls(List<CodeCallCount> calls, List data, List<Code> codes) {
478 // Assert that this has been cleared. 509 // Assert that this has been cleared.
479 assert(calls.length == 0); 510 assert(calls.length == 0);
480 // Resolve. 511 // Resolve.
481 for (var i = 0; i < data.length; i += 2) { 512 for (var i = 0; i < data.length; i += 2) {
482 var index = int.parse(data[i]); 513 var index = int.parse(data[i]);
483 var count = int.parse(data[i + 1]); 514 var count = int.parse(data[i + 1]);
484 assert(index >= 0); 515 assert(index >= 0);
485 assert(index < codes.length); 516 assert(index < codes.length);
486 calls.add(new CodeCallCount(codes[index], count)); 517 calls.add(new CodeCallCount(codes[index], count));
487 } 518 }
488 // Sort to descending count order. 519 // Sort to descending count order.
489 calls.sort((a, b) => b.count - a.count); 520 calls.sort((a, b) => b.count - a.count);
490 } 521 }
491 522
492 523
524 static String formatPercent(num a, num total) {
525 var percent = 100.0 * (a / total);
526 return '${percent.toStringAsFixed(2)}%';
527 }
528
493 void updateProfileData(Map profileData, 529 void updateProfileData(Map profileData,
494 List<Code> codeTable, 530 List<Code> codeTable,
495 int sampleCount) { 531 int sampleCount) {
496 // Assert we have a ProfileCode entry. 532 // Assert we have a CodeRegion entry.
497 assert(profileData['type'] == 'ProfileCode'); 533 assert(profileData['type'] == 'CodeRegion');
498 // Assert we are handed profile data for this code object. 534 // Assert we are handed profile data for this code object.
499 assert(profileData['code'] == this); 535 assert(profileData['code'] == this);
500 totalSamplesInProfile = sampleCount; 536 totalSamplesInProfile = sampleCount;
501 inclusiveTicks = int.parse(profileData['inclusive_ticks']); 537 inclusiveTicks = int.parse(profileData['inclusive_ticks']);
502 exclusiveTicks = int.parse(profileData['exclusive_ticks']); 538 exclusiveTicks = int.parse(profileData['exclusive_ticks']);
503 _resolveCalls(callers, profileData['callers'], codeTable); 539 _resolveCalls(callers, profileData['callers'], codeTable);
504 _resolveCalls(callees, profileData['callees'], codeTable); 540 _resolveCalls(callees, profileData['callees'], codeTable);
505 var ticks = profileData['ticks']; 541 var ticks = profileData['ticks'];
506 if (ticks != null) { 542 if (ticks != null) {
507 _processTicks(ticks); 543 _processTicks(ticks);
508 } 544 }
545 formattedInclusiveTicks =
546 '${formatPercent(inclusiveTicks, totalSamplesInProfile)} '
547 '($inclusiveTicks)';
548 formattedExclusiveTicks =
549 '${formatPercent(exclusiveTicks, totalSamplesInProfile)} '
550 '($inclusiveTicks)';
509 } 551 }
510 552
511 void _update(ObservableMap m) { 553 void _update(ObservableMap m) {
512 assert(ServiceObject.isServiceMap(m)); 554 assert(ServiceObject.isServiceMap(m));
513 assert(m['id'] == _id); 555 assert(m['id'] == _id);
514 assert(ServiceObject.stripRef(m['type']) == _serviceType); 556 assert(ServiceObject.stripRef(m['type']) == _serviceType);
515 name = m['user_name']; 557 name = m['user_name'];
516 vmName = m['name']; 558 vmName = m['name'];
559 kind = CodeKind.fromString(m['kind']);
517 startAddress = int.parse(m['start'], radix:16); 560 startAddress = int.parse(m['start'], radix:16);
518 endAddress = int.parse(m['end'], radix:16); 561 endAddress = int.parse(m['end'], radix:16);
519 // Upgrade the function. 562 // Upgrade the function.
520 function = _upgradeToServiceObject(isolate.vm, isolate, m['function']); 563 function = _upgradeToServiceObject(isolate.vm, isolate, m['function']);
521 var disassembly = m['disassembly']; 564 var disassembly = m['disassembly'];
522 if (disassembly != null) { 565 if (disassembly != null) {
523 _processDisassembly(disassembly); 566 _processDisassembly(disassembly);
524 } 567 }
525 // We are a reference if we don't have instructions. 568 // We are a reference if we don't have instructions and are Dart code.
526 _ref = (instructions.length == 0); 569 _ref = (instructions.length == 0) && (kind == CodeKind.Dart);
570 hasDisassembly = (instructions.length != 0) && (kind == CodeKind.Dart);
527 } 571 }
528 572
573 @observable bool hasDisassembly = false;
574
529 void _processDisassembly(List<String> disassembly){ 575 void _processDisassembly(List<String> disassembly){
530 assert(disassembly != null); 576 assert(disassembly != null);
531 instructions.clear(); 577 instructions.clear();
532 assert((disassembly.length % 3) == 0); 578 assert((disassembly.length % 3) == 0);
533 for (var i = 0; i < disassembly.length; i += 3) { 579 for (var i = 0; i < disassembly.length; i += 3) {
534 var address = 0; // Assume code comment. 580 var address = 0; // Assume code comment.
535 var machine = disassembly[i + 1]; 581 var machine = disassembly[i + 1];
536 var human = disassembly[i + 2]; 582 var human = disassembly[i + 2];
537 if (disassembly[i] != '') { 583 if (disassembly[i] != '') {
538 // Not a code comment, extract address. 584 // Not a code comment, extract address.
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
579 625
580 int _callCount(List<CodeCallCount> calls, Code code) { 626 int _callCount(List<CodeCallCount> calls, Code code) {
581 for (CodeCallCount caller in calls) { 627 for (CodeCallCount caller in calls) {
582 if (caller.code == code) { 628 if (caller.code == code) {
583 return caller.count; 629 return caller.count;
584 } 630 }
585 } 631 }
586 return 0; 632 return 0;
587 } 633 }
588 } 634 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698