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

Side by Side Diff: runtime/bin/vmservice/client/lib/src/observatory/model.dart

Issue 135843006: Improve Code object support in service and observatory (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 11 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
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 part of observatory;
6
7 class CodeInstruction extends Observable {
8 @observable final int address;
9 @observable final String machine;
10 @observable final String human;
11 @observable int ticks = 0;
12 @observable double percent;
13 @observable String formattedTicks() {
14 if (percent == null || percent <= 0.0) {
15 return '';
16 }
17 return '${percent.toStringAsFixed(2)}% (${ticks})';
18 }
19 @observable String formattedAddress() {
20 return '0x${address.toRadixString(16)}';
21 }
22 CodeInstruction(this.address, this.machine, this.human);
23 void updateTickString(Code code) {
24 if ((code == null) || (code.inclusiveTicks == 0)) {
25 percent = null;
26 return;
27 }
28 percent = (ticks / code.inclusiveTicks) * 100.0;
29 if (percent <= 0.00) {
30 percent = null;
31 return;
32 }
33 }
34 }
35
36 class CodeKind {
37 final _value;
38 const CodeKind._internal(this._value);
39 String toString() => 'CodeKind.$_value';
40
41 static CodeKind fromString(String s) {
42 if (s == 'Native') {
43 return Native;
44 } else if (s == 'Dart') {
45 return Dart;
46 } else if (s == 'Collected') {
47 return Collected;
48 }
49 throw new FallThroughError();
50 }
51 static const Native = const CodeKind._internal('Native');
52 static const Dart = const CodeKind._internal('Dart');
53 static const Collected = const CodeKind._internal('Collected');
54 }
55
56 class CodeTick {
57 final int address;
58 final int ticks;
59 CodeTick(this.address, this.ticks);
60 }
61
62 class Code extends Observable {
63 final CodeKind kind;
64 final int startAddress;
65 final int endAddress;
66 final List<CodeTick> ticks = [];
67 int inclusiveTicks = 0;
68 int exclusiveTicks = 0;
69 @observable final List<CodeInstruction> instructions = toObservable([]);
70 @observable Map functionRef = toObservable({});
71 @observable Map codeRef = toObservable({});
72 @observable String name;
73 @observable String user_name;
74
75 Code(this.kind, this.name, this.startAddress, this.endAddress);
76
77 Code.fromMap(Map m) :
78 kind = CodeKind.Dart,
79 startAddress = int.parse(m['start'], radix:16),
80 endAddress = int.parse(m['end'], radix:16) {
81 functionRef = toObservable(m['function']);
82 codeRef = {
83 'type': '@Code',
84 'id': m['id'],
85 'name': m['name'],
86 'user_name': m['user_name']
87 };
88 name = m['name'];
89 user_name = m['user_name'];
90 _loadInstructions(m['disassembly']);
91 }
92
93 /// Resets all tick counts to 0.
94 void resetTicks() {
95 inclusiveTicks = 0;
96 exclusiveTicks = 0;
97 ticks.clear();
98 for (var instruction in instructions) {
99 instruction.ticks = 0;
100 }
101 }
102
103 /// Adds [count] to the tick count for the instruction at [address].
104 void tick(int address, int count) {
105 for (var instruction in instructions) {
106 if (instruction.address == address) {
107 instruction.ticks += count;
108 return;
109 }
110 }
111 }
112
113 /// Clears [instructions] and then adds all instructions from
114 /// [instructionList].
115 void _loadInstructions(List instructionList) {
116 instructions.clear();
117 // Load disassembly into code object.
118 for (int i = 0; i < instructionList.length; i += 3) {
119 if (instructionList[i] == '') {
120 // Code comment.
121 // TODO(johnmccutchan): Insert code comments into instructions.
122 continue;
123 }
124 var address = int.parse(instructionList[i]);
125 var machine = instructionList[i + 1];
126 var human = instructionList[i + 2];
127 instructions.add(new CodeInstruction(address, machine, human));
128 }
129 }
130
131 /// returns true if [address] is inside the address range.
132 bool contains(int address) {
133 return (address >= startAddress) && (address < endAddress);
134 }
135 }
136
137 class Profile {
138 final Isolate isolate;
139 Profile.fromMap(this.isolate, Map m) {
140 var codes = m['codes'];
141 totalSamples = m['samples'];
142 Logger.root.info('Creating profile from ${totalSamples} samples '
143 'and ${codes.length} code objects.');
144 isolate.resetCodeTicks();
145 codes.forEach((code) {
146 try {
147 _processCode(code);
148 } catch (e, st) {
149 Logger.root.warning('Error processing code object. $e $st', e, st);
150 }
151 });
152 }
153 int totalSamples = 0;
154
155 Code _processDartCode(Map dartCode) {
156 var codeObject = dartCode['code'];
157 if ((codeObject == null)) {
158 // Detached code objects are handled like 'other' code.
159 return _processOtherCode(CodeKind.Dart, dartCode);
160 }
161 var code = new Code.fromMap(codeObject);
162 return code;
163 }
164
165 Code _processOtherCode(CodeKind kind, Map otherCode) {
166 var startAddress = int.parse(otherCode['start'], radix:16);
167 var endAddress = int.parse(otherCode['end'], radix: 16);
168 var name = otherCode['name'];
169 assert(name != null);
170 return new Code(kind, name, startAddress, endAddress);
171 }
172
173 void _processCode(Map profileCode) {
174 if (profileCode['type'] != 'ProfileCode') {
175 return;
176 }
177 var kind = CodeKind.fromString(profileCode['kind']);
178 var address;
179 if (kind == CodeKind.Dart) {
180 if (profileCode['code'] != null) {
181 address = int.parse(profileCode['code']['start'], radix:16);
182 } else {
183 address = int.parse(profileCode['start'], radix:16);
184 }
185 } else {
186 address = int.parse(profileCode['start'], radix:16);
187 }
188 assert(address != null);
189 var code = isolate.findCodeByAddress(address);
190 if (code == null) {
191 if (kind == CodeKind.Dart) {
192 code = _processDartCode(profileCode);
193 } else {
194 code = _processOtherCode(kind, profileCode);
195 }
196 assert(code != null);
197 isolate.codes.add(code);
198 }
199 // Load code object tick counts and set them.
200 var inclusive = int.parse(profileCode['inclusive_ticks']);
201 var exclusive = int.parse(profileCode['exclusive_ticks']);
202 code.inclusiveTicks = inclusive;
203 code.exclusiveTicks = exclusive;
204 // Load address specific ticks.
205 List ticksList = profileCode['ticks'];
206 if (ticksList != null && (ticksList.length > 0)) {
207 for (var i = 0; i < ticksList.length; i += 2) {
208 var address = int.parse(ticksList[i], radix:16);
209 var ticks = int.parse(ticksList[i + 1]);
210 var codeTick = new CodeTick(address, ticks);
211 code.ticks.add(codeTick);
212 }
213 }
214 if ((code.ticks.length > 0) && (code.instructions.length > 0)) {
215 // Apply address ticks to instruction stream.
216 code.ticks.forEach((CodeTick tick) {
217 code.tick(tick.address, tick.ticks);
218 });
219 code.instructions.forEach((i) {
220 i.updateTickString(code);
221 });
222 }
223 }
224
225 List<Code> topExclusive(int count) {
226 List<Code> exclusive = isolate.codes;
227 exclusive.sort((Code a, Code b) {
228 return b.exclusiveTicks - a.exclusiveTicks;
229 });
230 if ((exclusive.length < count) || (count == 0)) {
231 return exclusive;
232 }
233 return exclusive.sublist(0, count);
234 }
235
236 List<Code> topInclusive(int count) {
237 List<Code> inclusive = isolate.codes;
238 inclusive.sort((Code a, Code b) {
239 return b.inclusiveTicks - a.inclusiveTicks;
240 });
241 if ((inclusive.length < count) || (count == 0)) {
242 return inclusive;
243 }
244 return inclusive.sublist(0, count);
245 }
246 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698