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

Side by Side Diff: pkg/compiler/lib/src/info/info.dart

Issue 1285743002: dart2js: add visitors and parsing support to infos (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 4 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
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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 /// Data collected by the dump-info task. 5 /// Data collected by the dump-info task.
6 library compiler.src.lib.info; 6 library compiler.src.lib.info;
7 7
8 // Note: this file intentionally doesn't import anything from the compiler. That 8 // Note: this file intentionally doesn't import anything from the compiler. That
9 // should make it easier for tools to depend on this library. The idea is that 9 // should make it easier for tools to depend on this library. The idea is that
10 // by using this library, tools can consume the information in the same way it 10 // by using this library, tools can consume the information in the same way it
11 // is produced by the compiler. 11 // is produced by the compiler.
12 // TODO(sigmund): make this a proper public API (export this explicitly at the 12 // TODO(sigmund): make this a proper public API (export this explicitly at the
13 // lib folder level.) 13 // lib folder level.)
14 14
15 /// Common interface to many pieces of information generated by the compiler. 15 /// Common interface to many pieces of information generated by the compiler.
16 abstract class Info { 16 abstract class Info {
17 /// An identifier for the kind of information. 17 /// An identifier for the kind of information.
18 String get kind; 18 InfoKind get kind;
19 19
20 /// Name of the element associated with this info. 20 /// Name of the element associated with this info.
21 String name; 21 String name;
22 22
23 /// An id to uniquely identify this info among infos of the same [kind]. 23 /// An id to uniquely identify this info among infos of the same [kind].
24 int get id; 24 int get id;
25 25
26 /// A globally unique id combining [kind] and [id] together. 26 /// A globally unique id combining [kind] and [id] together.
27 String get serializedId; 27 String get serializedId;
28 28
29 /// Bytes used in the generated code for the corresponding element. 29 /// Bytes used in the generated code for the corresponding element.
30 int size; 30 int size;
31 31
32 /// Serializes the information into a JSON format. 32 /// Serializes the information into a JSON format.
33 // TODO(sigmund): refactor and put toJson outside the class, so we can have 2 33 // TODO(sigmund): refactor and put toJson outside the class, so we can have 2
34 // different serializer/deserializers at once. 34 // different serializer/deserializers at once.
35 Map toJson(); 35 Map toJson();
36
37 void accept(InfoVisitor visitor);
36 } 38 }
37 39
38 /// Common information used for most kind of elements. 40 /// Common information used for most kind of elements.
39 // TODO(sigmund): add more: 41 // TODO(sigmund): add more:
40 // - inputSize: bytes used in the Dart source program 42 // - inputSize: bytes used in the Dart source program
41 abstract class BasicInfo implements Info { 43 abstract class BasicInfo implements Info {
42 final String kind; 44 final InfoKind kind;
43 final int id; 45 final int id;
44 int size; 46 int size;
45 47
46 String get serializedId => '$kind/$id'; 48 String get serializedId => '${_kindToString(kind)}/$id';
47 49
48 String name; 50 String name;
49 51
50 /// If using deferred libraries, where the element associated with this info 52 /// If using deferred libraries, where the element associated with this info
51 /// is generated. 53 /// is generated.
52 OutputUnitInfo outputUnit; 54 OutputUnitInfo outputUnit;
53 55
54 BasicInfo(this.kind, this.id, this.name, this.outputUnit, this.size); 56 BasicInfo(this.kind, this.id, this.name, this.outputUnit, this.size);
55 57
58 BasicInfo._fromId(String serializedId)
59 : kind = _kindFromSerializedId(serializedId),
60 id = _idFromSerializedId(serializedId);
61
56 Map toJson() { 62 Map toJson() {
57 var res = {'id': serializedId, 'kind': kind, 'name': name, 'size': size}; 63 var res = {
64 'id': serializedId,
65 'kind': _kindToString(kind),
66 'name': name,
67 'size': size,
68 };
58 // TODO(sigmund): omit this also when outputUnit.id == 0 69 // TODO(sigmund): omit this also when outputUnit.id == 0
59 // (most code is by default in the main output unit) 70 // (most code is by default in the main output unit)
60 if (outputUnit != null) res['outputUnit'] = outputUnit.serializedId; 71 if (outputUnit != null) res['outputUnit'] = outputUnit.serializedId;
61 return res; 72 return res;
62 } 73 }
63 74
64 String toString() => '$serializedId $name [$size]'; 75 String toString() => '$serializedId $name [$size]';
65 } 76 }
66 77
67 /// Info associated with elements containing executable code (like fields and 78 /// Info associated with elements containing executable code (like fields and
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
110 121
111 /// Minor version indicating non-breaking changes in the format. A change in 122 /// Minor version indicating non-breaking changes in the format. A change in
112 /// this version number means that the json parsing in this library from a 123 /// this version number means that the json parsing in this library from a
113 /// previous will continue to work after the change. This is typically 124 /// previous will continue to work after the change. This is typically
114 /// increased when adding new entries to the file format. 125 /// increased when adding new entries to the file format.
115 // Note: the dump-info.viewer app was written using a json parser version 3.2. 126 // Note: the dump-info.viewer app was written using a json parser version 3.2.
116 final int minorVersion = 3; 127 final int minorVersion = 3;
117 128
118 AllInfo(); 129 AllInfo();
119 130
131 static AllInfo parseFromJson(Map map) => new _ParseHelper().parseAll(map);
132
120 Map _listAsJsonMap(List<Info> list) { 133 Map _listAsJsonMap(List<Info> list) {
121 var map = <String, Map>{}; 134 var map = <String, Map>{};
122 for (var info in list) { 135 for (var info in list) {
123 map['${info.id}'] = info.toJson(); 136 map['${info.id}'] = info.toJson();
124 } 137 }
125 return map; 138 return map;
126 } 139 }
127 140
128 Map _extractHoldingInfo() { 141 Map _extractHoldingInfo() {
129 var map = <String, List>{}; 142 var map = <String, List>{};
130 void helper(CodeInfo info) { 143 void helper(CodeInfo info) {
131 if (info.uses.isEmpty) return; 144 if (info.uses.isEmpty) return;
132 map[info.serializedId] = info.uses.map((u) => u.toJson()).toList(); 145 map[info.serializedId] = info.uses.map((u) => u.toJson()).toList();
133 } 146 }
134 functions.forEach(helper); 147 functions.forEach(helper);
135 fields.forEach(helper); 148 fields.forEach(helper);
136 return map; 149 return map;
137 } 150 }
138 151
139 // TODO(sigmund): implement fromJson
140 Map toJson() => { 152 Map toJson() => {
141 'elements': { 153 'elements': {
142 'library': _listAsJsonMap(libraries), 154 'library': _listAsJsonMap(libraries),
143 'class': _listAsJsonMap(classes), 155 'class': _listAsJsonMap(classes),
144 'function': _listAsJsonMap(functions), 156 'function': _listAsJsonMap(functions),
145 'typedef': _listAsJsonMap(typedefs), 157 'typedef': _listAsJsonMap(typedefs),
146 'field': _listAsJsonMap(fields), 158 'field': _listAsJsonMap(fields),
147 }, 159 },
148 'holding': _extractHoldingInfo(), 160 'holding': _extractHoldingInfo(),
149 'outputUnits': outputUnits.map((u) => u.toJson()).toList(), 161 'outputUnits': outputUnits.map((u) => u.toJson()).toList(),
150 'dump_version': version, 162 'dump_version': version,
151 'deferredFiles': deferredFiles, 163 'deferredFiles': deferredFiles,
152 'dump_minor_version': '$minorVersion', 164 'dump_minor_version': '$minorVersion',
153 // TODO(sigmund): change viewer to accept an int? 165 // TODO(sigmund): change viewer to accept an int?
154 'program': program.toJson(), 166 'program': program.toJson(),
155 }; 167 };
168
169 void accept(InfoVisitor visitor) => visitor.visitAll(this);
156 } 170 }
157 171
158 class ProgramInfo { 172 class ProgramInfo {
159 int size; 173 int size;
160 String dart2jsVersion; 174 String dart2jsVersion;
161 DateTime compilationMoment; 175 DateTime compilationMoment;
162 Duration compilationDuration; 176 Duration compilationDuration;
163 // TODO(sigmund): use Duration. 177 // TODO(sigmund): use Duration.
164 int toJsonDuration; 178 int toJsonDuration;
165 int dumpInfoDuration; 179 int dumpInfoDuration;
(...skipping 13 matching lines...) Expand all
179 Map toJson() => { 193 Map toJson() => {
180 'size': size, 194 'size': size,
181 'dart2jsVersion': dart2jsVersion, 195 'dart2jsVersion': dart2jsVersion,
182 'compilationMoment': '$compilationMoment', 196 'compilationMoment': '$compilationMoment',
183 'compilationDuration': '${compilationDuration}', 197 'compilationDuration': '${compilationDuration}',
184 'toJsonDuration': toJsonDuration, 198 'toJsonDuration': toJsonDuration,
185 'dumpInfoDuration': '$dumpInfoDuration', 199 'dumpInfoDuration': '$dumpInfoDuration',
186 'noSuchMethodEnabled': noSuchMethodEnabled, 200 'noSuchMethodEnabled': noSuchMethodEnabled,
187 'minified': minified, 201 'minified': minified,
188 }; 202 };
203
204 void accept(InfoVisitor visitor) => visitor.visitProgram(this);
189 } 205 }
190 206
207 // TODO(sigmund): add unit tests.
208 class _ParseHelper {
209 Map<String, Info> registry = {};
210
211 AllInfo parseAll(Map json) {
212 var result = new AllInfo();
213 var elements = json['elements'];
214 result.libraries.addAll(elements['library'].values.map(parseLibrary));
215 result.classes.addAll(elements['class'].values.map(parseClass));
216 result.functions.addAll(elements['function'].values.map(parseFunction));
217 result.fields.addAll(elements['field'].values.map(parseField));
218 result.typedefs.addAll(elements['typedef'].values.map(parseTypedef));
219
220 var idMap = {};
221 for (var f in result.functions) {
222 idMap[f.serializedId] = f;
223 }
224 for (var f in result.fields) {
225 idMap[f.serializedId] = f;
226 }
227
228 json['holding'].forEach((k, deps) {
229 var src = idMap[k];
230 assert (src != null);
231 for (var dep in deps) {
232 var target = idMap[dep['id']];
233 assert (target != null);
234 src.uses.add(new DependencyInfo(target, dep['mask']));
235 }
236 });
237
238 result.program = parseProgram(json['program']);
239 // todo: version, etc
240 return result;
241 }
242
243 LibraryInfo parseLibrary(Map json) {
244 var result = parseId(json['id'])
245 ..name = json['name']
246 ..uri = Uri.parse(json['canonicalUri'])
247 ..outputUnit = parseId(json['outputUnit'])
248 ..size = json['size'];
249 assert(result is LibraryInfo);
250 for (var child in json['children'].map(parseId)) {
251 if (child is FunctionInfo) {
252 result.topLevelFunctions.add(child);
253 } else if (child is FieldInfo) {
254 result.topLevelVariables.add(child);
255 } else if (child is ClassInfo) {
256 result.classes.add(child);
257 } else {
258 assert(child is TypedefInfo);
259 result.typedefs.add(child);
260 }
261 }
262 return result;
263 }
264
265 ClassInfo parseClass(Map json) {
266 var result = parseId(json['id'])
267 ..name = json['name']
268 ..outputUnit = parseId(json['outputUnit'])
269 ..size = json['size']
270 ..isAbstract = json['modifiers']['abstract'] == true;
271 assert(result is ClassInfo);
272 for (var child in json['children'].map(parseId)) {
273 if (child is FunctionInfo) {
274 result.functions.add(child);
275 } else {
276 assert(child is FieldInfo);
277 result.fields.add(child);
278 }
279 }
280 return result;
281 }
282
283 FieldInfo parseField(Map json) {
284 return parseId(json['id'])
285 ..name = json['name']
286 ..outputUnit = parseId(json['outputUnit'])
287 ..size = json['size']
288 ..type = json['type']
289 ..inferredType = json['inferredType']
290 ..code = json['code']
291 ..closures = json['children'].map(parseId).toList();
292 }
293
294 TypedefInfo parseTypedef(Map json) => parseId(json['id'])
295 ..name = json['name']
296 ..type = json['type']
297 ..size = 0;
298
299 ProgramInfo parseProgram(Map json) =>
300 new ProgramInfo()..size = json['size'];
301
302 FunctionInfo parseFunction(Map json) {
303 return parseId(json['id'])
304 ..name = json['name']
305 ..outputUnit = parseId(json['outputUnit'])
306 ..size = json['size']
307 ..type = json['type']
308 ..returnType = json['returnType']
309 ..inferredReturnType = json['inferredReturnType']
310 ..parameters = json['parameters'].map(parseParameter).toList()
311 ..code = json['code']
312 ..sideEffects = json['sideEffects']
313 ..modifiers = parseModifiers(json['modifiers'])
314 ..closures = json['children'].map(parseId).toList();
315 }
316
317 ParameterInfo parseParameter(Map json) =>
318 new ParameterInfo(json['name'], json['type'], json['declaredType']);
319
320 FunctionModifiers parseModifiers(Map<String, bool> json) {
321 return new FunctionModifiers(
322 isStatic: json['static'] == true,
323 isConst: json['const'] == true,
324 isFactory: json['factory'] == true,
325 isExternal: json['external'] == true);
326 }
327
328 Info parseId(String serializedId) => registry.putIfAbsent(serializedId, () {
329 if (serializedId == null) {
330 return null;
331 } else if (serializedId.startsWith('function/')) {
332 return new FunctionInfo._(serializedId);
333 } else if (serializedId.startsWith('library/')) {
334 return new LibraryInfo._(serializedId);
335 } else if (serializedId.startsWith('class/')) {
336 return new ClassInfo._(serializedId);
337 } else if (serializedId.startsWith('field/')) {
338 return new FieldInfo._(serializedId);
339 } else if (serializedId.startsWith('typedef/')) {
340 return new TypedefInfo._(serializedId);
341 } else if (serializedId.startsWith('outputUnit/')) {
342 return new OutputUnitInfo._(serializedId);
343 }
344 assert(false);
345 });
346 }
347
348 /// Info associated with a library element.
191 class LibraryInfo extends BasicInfo { 349 class LibraryInfo extends BasicInfo {
350 /// Canonical uri that identifies the library.
192 Uri uri; 351 Uri uri;
352
353 /// Top level functions defined within the library.
193 final List<FunctionInfo> topLevelFunctions = <FunctionInfo>[]; 354 final List<FunctionInfo> topLevelFunctions = <FunctionInfo>[];
355
356 /// Top level fields defined within the library.
194 final List<FieldInfo> topLevelVariables = <FieldInfo>[]; 357 final List<FieldInfo> topLevelVariables = <FieldInfo>[];
358
359 /// Classes defined within the library.
195 final List<ClassInfo> classes = <ClassInfo>[]; 360 final List<ClassInfo> classes = <ClassInfo>[];
361
362 /// Typedefs defined within the library.
196 final List<TypedefInfo> typedefs = <TypedefInfo>[]; 363 final List<TypedefInfo> typedefs = <TypedefInfo>[];
197 364
198 static int _id = 0; 365 static int _id = 0;
199 366
367 /// Whether there is any information recorded for this library.
200 bool get isEmpty => 368 bool get isEmpty =>
201 topLevelFunctions.isEmpty && topLevelVariables.isEmpty && classes.isEmpty; 369 topLevelFunctions.isEmpty && topLevelVariables.isEmpty && classes.isEmpty;
202 370
203 LibraryInfo(String name, this.uri, OutputUnitInfo outputUnit, int size) 371 LibraryInfo(String name, this.uri, OutputUnitInfo outputUnit, int size)
204 : super('library', _id++, name, outputUnit, size); 372 : super(InfoKind.library, _id++, name, outputUnit, size);
373
374 LibraryInfo._(String serializedId) : super._fromId(serializedId);
205 375
206 Map toJson() => super.toJson() 376 Map toJson() => super.toJson()
207 ..addAll({ 377 ..addAll({
208 'children': [] 378 'children': []
209 ..addAll(topLevelFunctions.map((f) => f.serializedId)) 379 ..addAll(topLevelFunctions.map((f) => f.serializedId))
210 ..addAll(topLevelVariables.map((v) => v.serializedId)) 380 ..addAll(topLevelVariables.map((v) => v.serializedId))
211 ..addAll(classes.map((c) => c.serializedId)) 381 ..addAll(classes.map((c) => c.serializedId))
212 ..addAll(typedefs.map((t) => t.serializedId)), 382 ..addAll(typedefs.map((t) => t.serializedId)),
213 'canonicalUri': '$uri', 383 'canonicalUri': '$uri',
214 }); 384 });
385
386 void accept(InfoVisitor visitor) => visitor.visitLibrary(this);
215 } 387 }
216 388
389 /// Information about an output unit. Normally there is just one for the entire
390 /// program unless the application uses deferred imports, in which case there
391 /// would be an additional output unit per deferred chunk.
217 class OutputUnitInfo extends BasicInfo { 392 class OutputUnitInfo extends BasicInfo {
218 static int _ids = 0; 393 static int _ids = 0;
219 OutputUnitInfo(String name, int size) 394 OutputUnitInfo(String name, int size)
220 : super('outputUnit', _ids++, name, null, size); 395 : super(InfoKind.outputUnit, _ids++, name, null, size);
396
397 OutputUnitInfo._(String serializedId) : super._fromId(serializedId);
398
399 void accept(InfoVisitor visitor) => visitor.visitOutput(this);
221 } 400 }
222 401
402 /// Information about a class element.
223 class ClassInfo extends BasicInfo { 403 class ClassInfo extends BasicInfo {
404 /// Whether the class is abstract.
224 bool isAbstract; 405 bool isAbstract;
225 406
226 // TODO(sigmund): split static vs instance vs closures 407 // TODO(sigmund): split static vs instance vs closures
408 /// Functions (static or instance) defined in the class.
227 final List<FunctionInfo> functions = <FunctionInfo>[]; 409 final List<FunctionInfo> functions = <FunctionInfo>[];
410
411 /// Fields defined in the class.
412 // TODO(sigmund): currently appears to only be populated with instance fields,
413 // but this should be fixed.
228 final List<FieldInfo> fields = <FieldInfo>[]; 414 final List<FieldInfo> fields = <FieldInfo>[];
229 static int _ids = 0; 415 static int _ids = 0;
230 416
231 ClassInfo( 417 ClassInfo(
232 {String name, this.isAbstract, OutputUnitInfo outputUnit, int size: 0}) 418 {String name, this.isAbstract, OutputUnitInfo outputUnit, int size: 0})
233 : super('class', _ids++, name, outputUnit, size); 419 : super(InfoKind.clazz, _ids++, name, outputUnit, size);
420
421 ClassInfo._(String serializedId) : super._fromId(serializedId);
234 422
235 Map toJson() => super.toJson() 423 Map toJson() => super.toJson()
236 ..addAll({ 424 ..addAll({
237 // TODO(sigmund): change format, include only when abstract is true. 425 // TODO(sigmund): change format, include only when abstract is true.
238 'modifiers': {'abstract': isAbstract}, 426 'modifiers': {'abstract': isAbstract},
239 'children': [] 427 'children': []
240 ..addAll(fields.map((f) => f.serializedId)) 428 ..addAll(fields.map((f) => f.serializedId))
241 ..addAll(functions.map((m) => m.serializedId)) 429 ..addAll(functions.map((m) => m.serializedId))
242 }); 430 });
431
432 void accept(InfoVisitor visitor) => visitor.visitClass(this);
243 } 433 }
244 434
435 /// Information about a field element.
245 class FieldInfo extends BasicInfo with CodeInfo { 436 class FieldInfo extends BasicInfo with CodeInfo {
437 /// The type of the field.
246 String type; 438 String type;
439
440 /// The type inferred by dart2js's whole program analysis
247 String inferredType; 441 String inferredType;
442
443 /// Nested closures seen in the field initializer.
248 List<FunctionInfo> closures; 444 List<FunctionInfo> closures;
445
446 /// The actual generated code for the field.
249 String code; 447 String code;
250 448
251 static int _ids = 0; 449 static int _ids = 0;
252 FieldInfo( 450 FieldInfo(
253 {String name, 451 {String name,
254 int size: 0, 452 int size: 0,
255 this.type, 453 this.type,
256 this.inferredType, 454 this.inferredType,
257 this.closures, 455 this.closures,
258 this.code, 456 this.code,
259 OutputUnitInfo outputUnit}) 457 OutputUnitInfo outputUnit})
260 : super('field', _ids++, name, outputUnit, size); 458 : super(InfoKind.field, _ids++, name, outputUnit, size);
459
460 FieldInfo._(String serializedId) : super._fromId(serializedId);
261 461
262 Map toJson() => super.toJson() 462 Map toJson() => super.toJson()
263 ..addAll({ 463 ..addAll({
264 'children': closures.map((i) => i.serializedId).toList(), 464 'children': closures.map((i) => i.serializedId).toList(),
265 'inferredType': inferredType, 465 'inferredType': inferredType,
266 'code': code, 466 'code': code,
267 'type': type, 467 'type': type,
268 }); 468 });
469
470 void accept(InfoVisitor visitor) => visitor.visitField(this);
269 } 471 }
270 472
473 /// Information about a typedef declaration.
271 class TypedefInfo extends BasicInfo { 474 class TypedefInfo extends BasicInfo {
475 /// The declared type.
272 String type; 476 String type;
273 477
274 static int _ids = 0; 478 static int _ids = 0;
275 TypedefInfo(String name, this.type, OutputUnitInfo outputUnit) 479 TypedefInfo(String name, this.type, OutputUnitInfo outputUnit)
276 : super('typedef', _ids++, name, outputUnit, 0); 480 : super(InfoKind.typedef, _ids++, name, outputUnit, 0);
481
482 TypedefInfo._(String serializedId) : super._fromId(serializedId);
277 483
278 Map toJson() => super.toJson()..['type'] = '$type'; 484 Map toJson() => super.toJson()..['type'] = '$type';
485
486 void accept(InfoVisitor visitor) => visitor.visitTypedef(this);
279 } 487 }
280 488
489 /// Information about a function or method.
281 class FunctionInfo extends BasicInfo with CodeInfo { 490 class FunctionInfo extends BasicInfo with CodeInfo {
282 static const int TOP_LEVEL_FUNCTION_KIND = 0; 491 static const int TOP_LEVEL_FUNCTION_KIND = 0;
283 static const int CLOSURE_FUNCTION_KIND = 1; 492 static const int CLOSURE_FUNCTION_KIND = 1;
284 static const int METHOD_FUNCTION_KIND = 2; 493 static const int METHOD_FUNCTION_KIND = 2;
285 static const int CONSTRUCTOR_FUNCTION_KIND = 3; 494 static const int CONSTRUCTOR_FUNCTION_KIND = 3;
286 static int _ids = 0; 495 static int _ids = 0;
287 496
288 /// Kind of function (top-level function, closure, method, or constructor). 497 /// Kind of function (top-level function, closure, method, or constructor).
289 final int functionKind; 498 int functionKind;
290 499
291 /// Modifiers applied to this function. 500 /// Modifiers applied to this function.
292 final FunctionModifiers modifiers; 501 FunctionModifiers modifiers;
293 502
294 /// Nested closures that appear within the body of this function. 503 /// Nested closures that appear within the body of this function.
295 List<FunctionInfo> closures; 504 List<FunctionInfo> closures;
296 505
297 /// The type of this function. 506 /// The type of this function.
298 String type; 507 String type;
299 508
300 /// The declared return type. 509 /// The declared return type.
301 String returnType; 510 String returnType;
302 511
(...skipping 20 matching lines...) Expand all
323 this.functionKind, 532 this.functionKind,
324 this.modifiers, 533 this.modifiers,
325 this.closures, 534 this.closures,
326 this.type, 535 this.type,
327 this.returnType, 536 this.returnType,
328 this.inferredReturnType, 537 this.inferredReturnType,
329 this.parameters, 538 this.parameters,
330 this.sideEffects, 539 this.sideEffects,
331 this.inlinedCount, 540 this.inlinedCount,
332 this.code}) 541 this.code})
333 : super('function', _ids++, name, outputUnit, size); 542 : super(InfoKind.function, _ids++, name, outputUnit, size);
543
544 FunctionInfo._(String serializedId) : super._fromId(serializedId);
334 545
335 Map toJson() => super.toJson() 546 Map toJson() => super.toJson()
336 ..addAll({ 547 ..addAll({
337 'children': closures.map((i) => i.serializedId).toList(), 548 'children': closures.map((i) => i.serializedId).toList(),
338 'modifiers': modifiers.toJson(), 549 'modifiers': modifiers.toJson(),
339 'returnType': returnType, 550 'returnType': returnType,
340 'inferredReturnType': inferredReturnType, 551 'inferredReturnType': inferredReturnType,
341 'parameters': parameters.map((p) => p.toJson()).toList(), 552 'parameters': parameters.map((p) => p.toJson()).toList(),
342 'sideEffects': sideEffects, 553 'sideEffects': sideEffects,
343 'inlinedCount': inlinedCount, 554 'inlinedCount': inlinedCount,
344 'code': code, 555 'code': code,
345 'type': type, 556 'type': type,
346 // Note: version 3.2 of dump-info serializes `uses` in a section called 557 // Note: version 3.2 of dump-info serializes `uses` in a section called
347 // `holding` at the top-level. 558 // `holding` at the top-level.
348 }); 559 });
560
561 void accept(InfoVisitor visitor) => visitor.visitFunction(this);
349 } 562 }
350 563
351 /// Information about how a dependency is used. 564 /// Information about how a dependency is used.
352 class DependencyInfo { 565 class DependencyInfo {
353 /// The dependency, either a FunctionInfo or FieldInfo. 566 /// The dependency, either a FunctionInfo or FieldInfo.
354 final Info target; 567 final Info target;
355 568
356 /// Either a selector mask indicating how this is used, or 'inlined'. 569 /// Either a selector mask indicating how this is used, or 'inlined'.
357 // TODO(sigmund): split mask into an enum or something more precise to really 570 // TODO(sigmund): split mask into an enum or something more precise to really
358 // describe the dependencies in detail. 571 // describe the dependencies in detail.
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
396 // if (isExternal) res['external'] = true; 609 // if (isExternal) res['external'] = true;
397 // return res; 610 // return res;
398 // } 611 // }
399 Map toJson() => { 612 Map toJson() => {
400 'static': isStatic, 613 'static': isStatic,
401 'const': isConst, 614 'const': isConst,
402 'factory': isFactory, 615 'factory': isFactory,
403 'external': isExternal, 616 'external': isExternal,
404 }; 617 };
405 } 618 }
619
620 /// Possible values of the `kind` field in the serialied infos.
621 enum InfoKind {
622 library,
623 clazz,
624 function,
625 field,
626 outputUnit,
627 typedef,
628 }
629
630 String _kindToString(InfoKind kind) {
631 switch(kind) {
632 case InfoKind.library: return 'library';
633 case InfoKind.clazz: return 'class';
634 case InfoKind.function: return 'function';
635 case InfoKind.field: return 'field';
636 case InfoKind.outputUnit: return 'outputUnit';
637 case InfoKind.typedef: return 'typedef';
638 default: return null;
639 }
640 }
641
642 int _idFromSerializedId(String serialiedId) =>
643 int.parse(serializedId.substring(serializedId.indexOf('/') + 1));
644
645 String _kindFromSerializedId(String serializedId) =>
646 _kindFromString(serializedId.substring(0, serializedId.indexOf('/')));
647
648 InfoKind _kindFromString(String kind) {
649 switch(kind) {
650 case 'library': return InfoKind.library;
651 case 'class': return InfoKind.clazz;
652 case 'function': return InfoKind.function;
653 case 'field': return InfoKind.field;
654 case 'outputUnit': return InfoKind.outputUnit;
655 case 'typedef': return InfoKind.typedef;
656 default: return null;
657 }
658 }
659
660 /// A simple visitor for information produced by the dart2js compiler.
661 class InfoVisitor {
662 visitAll(AllInfo info) {}
663 visitProgram(ProgramInfo info) {}
664 visitLibrary(LibraryInfo info) {}
665 visitClass(ClassInfo info) {}
666 visitField(FieldInfo info) {}
667 visitFunction(FunctionInfo info) {}
668 visitTypedef(TypedefInfo info) {}
669 visitOutput(OutputUnitInfo info) {}
670 }
671
672 /// A visitor that recursively walks each portion of the program. Because the
673 /// info representation is redundant, this visitor only walks the structure of
674 /// the program and skips some redundant links. For example, even though
675 /// visitAll contains references to functions, this visitor only recurses to
676 /// visit libraries, then from each library we visit functions and classes, and
677 /// so on.
678 class RecursiveInfoVisitor extends InfoVisitor {
679 visitAll(AllInfo info) {
680 // Note: we don't visit functions, fields, classes, and typedefs because
681 // they are reachable from the library info.
682 info.libraries.forEach(visitLibrary);
683 }
684
685 visitLibrary(LibraryInfo info) {
686 info.topLevelFunctions.forEach(visitFunction);
687 info.topLevelVariables.forEach(visitField);
688 info.classes.forEach(visitClass);
689 info.typedefs.forEach(visitTypedef);
690 }
691
692 visitClass(ClassInfo info) {
693 info.functions.forEach(visitFunction);
694 info.fields.forEach(visitField);
695 }
696
697 visitField(FieldInfo info) {
698 info.closures.forEach(visitFunction);
699 }
700
701 visitFunction(FunctionInfo info) {
702 info.closures.forEach(visitFunction);
703 }
704 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698