| OLD | NEW |
| 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 produced by dart2js when run with the `--dump-info` flag. | 5 /// Data produced by dart2js when run with the `--dump-info` flag. |
| 6 library dart2js_info.info; | 6 library dart2js_info.info; |
| 7 | 7 |
| 8 /// Common interface to many pieces of information generated by the dart2js | 8 /// Common interface to many pieces of information generated by the dart2js |
| 9 /// compiler. | 9 /// compiler. |
| 10 abstract class Info { | 10 abstract class Info { |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 | 104 |
| 105 /// Information about type defs in the program. | 105 /// Information about type defs in the program. |
| 106 List<TypedefInfo> typedefs = <TypedefInfo>[]; | 106 List<TypedefInfo> typedefs = <TypedefInfo>[]; |
| 107 | 107 |
| 108 /// Information about each class (in any library). | 108 /// Information about each class (in any library). |
| 109 List<ClassInfo> classes = <ClassInfo>[]; | 109 List<ClassInfo> classes = <ClassInfo>[]; |
| 110 | 110 |
| 111 /// Information about fields (in any class). | 111 /// Information about fields (in any class). |
| 112 List<FieldInfo> fields = <FieldInfo>[]; | 112 List<FieldInfo> fields = <FieldInfo>[]; |
| 113 | 113 |
| 114 /// Information about constants anywhere in the program. |
| 115 // TODO(sigmund): expand docs about canonicalization. We don't put these |
| 116 // inside library because a single constant can be used in more than one lib, |
| 117 // and we'll include it only once in the output. |
| 118 List<ConstantInfo> constants = <ConstantInfo>[]; |
| 119 |
| 114 /// Information about output units (should be just one entry if not using | 120 /// Information about output units (should be just one entry if not using |
| 115 /// deferred loading). | 121 /// deferred loading). |
| 116 List<OutputUnitInfo> outputUnits = <OutputUnitInfo>[]; | 122 List<OutputUnitInfo> outputUnits = <OutputUnitInfo>[]; |
| 117 | 123 |
| 118 /// Details about all deferred imports and what files would be loaded when the | 124 /// Details about all deferred imports and what files would be loaded when the |
| 119 /// import is resolved. | 125 /// import is resolved. |
| 120 // TODO(sigmund): use a different format for dump-info. This currently emits | 126 // TODO(sigmund): use a different format for dump-info. This currently emits |
| 121 // the same map that is created for the `--deferred-map` flag. | 127 // the same map that is created for the `--deferred-map` flag. |
| 122 Map<String, Map<String, dynamic>> deferredFiles; | 128 Map<String, Map<String, dynamic>> deferredFiles; |
| 123 | 129 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 170 return map; | 176 return map; |
| 171 } | 177 } |
| 172 | 178 |
| 173 Map toJson() => { | 179 Map toJson() => { |
| 174 'elements': { | 180 'elements': { |
| 175 'library': _listAsJsonMap(libraries), | 181 'library': _listAsJsonMap(libraries), |
| 176 'class': _listAsJsonMap(classes), | 182 'class': _listAsJsonMap(classes), |
| 177 'function': _listAsJsonMap(functions), | 183 'function': _listAsJsonMap(functions), |
| 178 'typedef': _listAsJsonMap(typedefs), | 184 'typedef': _listAsJsonMap(typedefs), |
| 179 'field': _listAsJsonMap(fields), | 185 'field': _listAsJsonMap(fields), |
| 186 'constant': _listAsJsonMap(constants), |
| 180 }, | 187 }, |
| 181 'holding': _extractHoldingInfo(), | 188 'holding': _extractHoldingInfo(), |
| 182 'dependencies': _extractDependencies(), | 189 'dependencies': _extractDependencies(), |
| 183 'outputUnits': outputUnits.map((u) => u.toJson()).toList(), | 190 'outputUnits': outputUnits.map((u) => u.toJson()).toList(), |
| 184 'dump_version': version, | 191 'dump_version': version, |
| 185 'deferredFiles': deferredFiles, | 192 'deferredFiles': deferredFiles, |
| 186 'dump_minor_version': '$minorVersion', | 193 'dump_minor_version': '$minorVersion', |
| 187 // TODO(sigmund): change viewer to accept an int? | 194 // TODO(sigmund): change viewer to accept an int? |
| 188 'program': program.toJson(), | 195 'program': program.toJson(), |
| 189 }; | 196 }; |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 232 | 239 |
| 233 AllInfo parseAll(Map json) { | 240 AllInfo parseAll(Map json) { |
| 234 var result = new AllInfo(); | 241 var result = new AllInfo(); |
| 235 var elements = json['elements']; | 242 var elements = json['elements']; |
| 236 result.libraries.addAll(elements['library'].values.map(parseLibrary)); | 243 result.libraries.addAll(elements['library'].values.map(parseLibrary)); |
| 237 result.classes.addAll(elements['class'].values.map(parseClass)); | 244 result.classes.addAll(elements['class'].values.map(parseClass)); |
| 238 result.functions.addAll(elements['function'].values.map(parseFunction)); | 245 result.functions.addAll(elements['function'].values.map(parseFunction)); |
| 239 result.fields.addAll(elements['field'].values.map(parseField)); | 246 result.fields.addAll(elements['field'].values.map(parseField)); |
| 240 result.typedefs.addAll(elements['typedef'].values.map(parseTypedef)); | 247 result.typedefs.addAll(elements['typedef'].values.map(parseTypedef)); |
| 241 | 248 |
| 249 // TODO(sigmund): remove null check on next breaking version |
| 250 var constants = elements['constant']; |
| 251 if (constants != null) { |
| 252 result.constants.addAll(constants.values.map(parseConstant)); |
| 253 } |
| 254 |
| 242 var idMap = {}; | 255 var idMap = {}; |
| 243 for (var f in result.functions) { | 256 for (var f in result.functions) { |
| 244 idMap[f.serializedId] = f; | 257 idMap[f.serializedId] = f; |
| 245 } | 258 } |
| 246 for (var f in result.fields) { | 259 for (var f in result.fields) { |
| 247 idMap[f.serializedId] = f; | 260 idMap[f.serializedId] = f; |
| 248 } | 261 } |
| 249 | 262 |
| 250 json['holding'].forEach((k, deps) { | 263 json['holding'].forEach((k, deps) { |
| 251 var src = idMap[k]; | 264 var src = idMap[k]; |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 309 FieldInfo parseField(Map json) { | 322 FieldInfo parseField(Map json) { |
| 310 FieldInfo result = parseId(json['id']); | 323 FieldInfo result = parseId(json['id']); |
| 311 return result..name = json['name'] | 324 return result..name = json['name'] |
| 312 ..parent = parseId(json['parent']) | 325 ..parent = parseId(json['parent']) |
| 313 ..coverageId = json['coverageId'] | 326 ..coverageId = json['coverageId'] |
| 314 ..outputUnit = parseId(json['outputUnit']) | 327 ..outputUnit = parseId(json['outputUnit']) |
| 315 ..size = json['size'] | 328 ..size = json['size'] |
| 316 ..type = json['type'] | 329 ..type = json['type'] |
| 317 ..inferredType = json['inferredType'] | 330 ..inferredType = json['inferredType'] |
| 318 ..code = json['code'] | 331 ..code = json['code'] |
| 332 ..isConst = json['const'] ?? false |
| 333 ..initializer = parseId(json['initializer']) |
| 319 ..closures = json['children'].map(parseId).toList(); | 334 ..closures = json['children'].map(parseId).toList(); |
| 320 } | 335 } |
| 321 | 336 |
| 337 ConstantInfo parseConstant(Map json) { |
| 338 ConstantInfo result = parseId(json['id']); |
| 339 return result |
| 340 ..code = json['code'] |
| 341 ..size = json['size']; |
| 342 } |
| 343 |
| 322 TypedefInfo parseTypedef(Map json) { | 344 TypedefInfo parseTypedef(Map json) { |
| 323 TypedefInfo result = parseId(json['id']); | 345 TypedefInfo result = parseId(json['id']); |
| 324 return result..name = json['name'] | 346 return result..name = json['name'] |
| 325 ..parent = parseId(json['parent']) | 347 ..parent = parseId(json['parent']) |
| 326 ..type = json['type'] | 348 ..type = json['type'] |
| 327 ..size = 0; | 349 ..size = 0; |
| 328 } | 350 } |
| 329 | 351 |
| 330 ProgramInfo parseProgram(Map json) => | 352 ProgramInfo parseProgram(Map json) => |
| 331 new ProgramInfo()..size = json['size']; | 353 new ProgramInfo()..size = json['size']; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 362 if (serializedId == null) { | 384 if (serializedId == null) { |
| 363 return null; | 385 return null; |
| 364 } else if (serializedId.startsWith('function/')) { | 386 } else if (serializedId.startsWith('function/')) { |
| 365 return new FunctionInfo._(serializedId); | 387 return new FunctionInfo._(serializedId); |
| 366 } else if (serializedId.startsWith('library/')) { | 388 } else if (serializedId.startsWith('library/')) { |
| 367 return new LibraryInfo._(serializedId); | 389 return new LibraryInfo._(serializedId); |
| 368 } else if (serializedId.startsWith('class/')) { | 390 } else if (serializedId.startsWith('class/')) { |
| 369 return new ClassInfo._(serializedId); | 391 return new ClassInfo._(serializedId); |
| 370 } else if (serializedId.startsWith('field/')) { | 392 } else if (serializedId.startsWith('field/')) { |
| 371 return new FieldInfo._(serializedId); | 393 return new FieldInfo._(serializedId); |
| 394 } else if (serializedId.startsWith('constant/')) { |
| 395 return new ConstantInfo._(serializedId); |
| 372 } else if (serializedId.startsWith('typedef/')) { | 396 } else if (serializedId.startsWith('typedef/')) { |
| 373 return new TypedefInfo._(serializedId); | 397 return new TypedefInfo._(serializedId); |
| 374 } else if (serializedId.startsWith('outputUnit/')) { | 398 } else if (serializedId.startsWith('outputUnit/')) { |
| 375 return new OutputUnitInfo._(serializedId); | 399 return new OutputUnitInfo._(serializedId); |
| 376 } | 400 } |
| 377 assert(false); | 401 assert(false); |
| 378 }); | 402 }); |
| 379 } | 403 } |
| 380 | 404 |
| 381 /// Info associated with a library element. | 405 /// Info associated with a library element. |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 458 // TODO(sigmund): change format, include only when abstract is true. | 482 // TODO(sigmund): change format, include only when abstract is true. |
| 459 'modifiers': {'abstract': isAbstract}, | 483 'modifiers': {'abstract': isAbstract}, |
| 460 'children': [] | 484 'children': [] |
| 461 ..addAll(fields.map((f) => f.serializedId)) | 485 ..addAll(fields.map((f) => f.serializedId)) |
| 462 ..addAll(functions.map((m) => m.serializedId)) | 486 ..addAll(functions.map((m) => m.serializedId)) |
| 463 }); | 487 }); |
| 464 | 488 |
| 465 void accept(InfoVisitor visitor) => visitor.visitClass(this); | 489 void accept(InfoVisitor visitor) => visitor.visitClass(this); |
| 466 } | 490 } |
| 467 | 491 |
| 492 /// Information about a constant value. |
| 493 // TODO(sigmund): add dependency data for ConstantInfo |
| 494 class ConstantInfo extends BasicInfo { |
| 495 /// The actual generated code for the field. |
| 496 String code; |
| 497 |
| 498 static int _ids = 0; |
| 499 // TODO(sigmund): Add coverage support to constants? |
| 500 ConstantInfo( |
| 501 {int size: 0, |
| 502 this.code, |
| 503 OutputUnitInfo outputUnit}) |
| 504 : super(InfoKind.constant, _ids++, null, outputUnit, size, null); |
| 505 |
| 506 ConstantInfo._(String serializedId) : super._fromId(serializedId); |
| 507 |
| 508 Map toJson() => super.toJson() |
| 509 ..addAll({'code': code}); |
| 510 |
| 511 void accept(InfoVisitor visitor) => visitor.visitConstant(this); |
| 512 } |
| 513 |
| 468 /// Information about a field element. | 514 /// Information about a field element. |
| 469 class FieldInfo extends BasicInfo with CodeInfo { | 515 class FieldInfo extends BasicInfo with CodeInfo { |
| 470 /// The type of the field. | 516 /// The type of the field. |
| 471 String type; | 517 String type; |
| 472 | 518 |
| 473 /// The type inferred by dart2js's whole program analysis | 519 /// The type inferred by dart2js's whole program analysis |
| 474 String inferredType; | 520 String inferredType; |
| 475 | 521 |
| 476 /// Nested closures seen in the field initializer. | 522 /// Nested closures seen in the field initializer. |
| 477 List<FunctionInfo> closures; | 523 List<FunctionInfo> closures; |
| 478 | 524 |
| 479 /// The actual generated code for the field. | 525 /// The actual generated code for the field. |
| 480 String code; | 526 String code; |
| 481 | 527 |
| 528 /// Whether this corresponds to a const field declaration. |
| 529 bool isConst; |
| 530 |
| 531 /// When [isConst] is true, the constant initializer expression. |
| 532 ConstantInfo initializer; |
| 533 |
| 482 static int _ids = 0; | 534 static int _ids = 0; |
| 483 FieldInfo( | 535 FieldInfo( |
| 484 {String name, | 536 {String name, |
| 485 String coverageId, | 537 String coverageId, |
| 486 int size: 0, | 538 int size: 0, |
| 487 this.type, | 539 this.type, |
| 488 this.inferredType, | 540 this.inferredType, |
| 489 this.closures, | 541 this.closures, |
| 490 this.code, | 542 this.code, |
| 491 OutputUnitInfo outputUnit}) | 543 OutputUnitInfo outputUnit, |
| 544 this.isConst}) |
| 492 : super(InfoKind.field, _ids++, name, outputUnit, size, coverageId); | 545 : super(InfoKind.field, _ids++, name, outputUnit, size, coverageId); |
| 493 | 546 |
| 494 FieldInfo._(String serializedId) : super._fromId(serializedId); | 547 FieldInfo._(String serializedId) : super._fromId(serializedId); |
| 495 | 548 |
| 496 Map toJson() => super.toJson() | 549 Map toJson() { |
| 497 ..addAll({ | 550 var result = super.toJson()..addAll({ |
| 498 'children': closures.map((i) => i.serializedId).toList(), | 551 'children': closures.map((i) => i.serializedId).toList(), |
| 499 'inferredType': inferredType, | 552 'inferredType': inferredType, |
| 500 'code': code, | 553 'code': code, |
| 501 'type': type, | 554 'type': type, |
| 502 }); | 555 }); |
| 556 if (isConst) { |
| 557 result['const'] = true; |
| 558 if (initializer != null) result['initializer'] = initializer.serializedId; |
| 559 } |
| 560 return result; |
| 561 } |
| 503 | 562 |
| 504 void accept(InfoVisitor visitor) => visitor.visitField(this); | 563 void accept(InfoVisitor visitor) => visitor.visitField(this); |
| 505 } | 564 } |
| 506 | 565 |
| 507 /// Information about a typedef declaration. | 566 /// Information about a typedef declaration. |
| 508 class TypedefInfo extends BasicInfo { | 567 class TypedefInfo extends BasicInfo { |
| 509 /// The declared type. | 568 /// The declared type. |
| 510 String type; | 569 String type; |
| 511 | 570 |
| 512 static int _ids = 0; | 571 static int _ids = 0; |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 651 'external': isExternal, | 710 'external': isExternal, |
| 652 }; | 711 }; |
| 653 } | 712 } |
| 654 | 713 |
| 655 /// Possible values of the `kind` field in the serialied infos. | 714 /// Possible values of the `kind` field in the serialied infos. |
| 656 enum InfoKind { | 715 enum InfoKind { |
| 657 library, | 716 library, |
| 658 clazz, | 717 clazz, |
| 659 function, | 718 function, |
| 660 field, | 719 field, |
| 720 constant, |
| 661 outputUnit, | 721 outputUnit, |
| 662 typedef, | 722 typedef, |
| 663 } | 723 } |
| 664 | 724 |
| 665 String _kindToString(InfoKind kind) { | 725 String _kindToString(InfoKind kind) { |
| 666 switch(kind) { | 726 switch(kind) { |
| 667 case InfoKind.library: return 'library'; | 727 case InfoKind.library: return 'library'; |
| 668 case InfoKind.clazz: return 'class'; | 728 case InfoKind.clazz: return 'class'; |
| 669 case InfoKind.function: return 'function'; | 729 case InfoKind.function: return 'function'; |
| 670 case InfoKind.field: return 'field'; | 730 case InfoKind.field: return 'field'; |
| 731 case InfoKind.constant: return 'constant'; |
| 671 case InfoKind.outputUnit: return 'outputUnit'; | 732 case InfoKind.outputUnit: return 'outputUnit'; |
| 672 case InfoKind.typedef: return 'typedef'; | 733 case InfoKind.typedef: return 'typedef'; |
| 673 default: return null; | 734 default: return null; |
| 674 } | 735 } |
| 675 } | 736 } |
| 676 | 737 |
| 677 int _idFromSerializedId(String serializedId) => | 738 int _idFromSerializedId(String serializedId) => |
| 678 int.parse(serializedId.substring(serializedId.indexOf('/') + 1)); | 739 int.parse(serializedId.substring(serializedId.indexOf('/') + 1)); |
| 679 | 740 |
| 680 InfoKind _kindFromSerializedId(String serializedId) => | 741 InfoKind _kindFromSerializedId(String serializedId) => |
| 681 _kindFromString(serializedId.substring(0, serializedId.indexOf('/'))); | 742 _kindFromString(serializedId.substring(0, serializedId.indexOf('/'))); |
| 682 | 743 |
| 683 InfoKind _kindFromString(String kind) { | 744 InfoKind _kindFromString(String kind) { |
| 684 switch(kind) { | 745 switch(kind) { |
| 685 case 'library': return InfoKind.library; | 746 case 'library': return InfoKind.library; |
| 686 case 'class': return InfoKind.clazz; | 747 case 'class': return InfoKind.clazz; |
| 687 case 'function': return InfoKind.function; | 748 case 'function': return InfoKind.function; |
| 688 case 'field': return InfoKind.field; | 749 case 'field': return InfoKind.field; |
| 750 case 'constant': return InfoKind.constant; |
| 689 case 'outputUnit': return InfoKind.outputUnit; | 751 case 'outputUnit': return InfoKind.outputUnit; |
| 690 case 'typedef': return InfoKind.typedef; | 752 case 'typedef': return InfoKind.typedef; |
| 691 default: return null; | 753 default: return null; |
| 692 } | 754 } |
| 693 } | 755 } |
| 694 | 756 |
| 695 /// A simple visitor for information produced by the dart2js compiler. | 757 /// A simple visitor for information produced by the dart2js compiler. |
| 696 class InfoVisitor { | 758 class InfoVisitor { |
| 697 visitAll(AllInfo info) {} | 759 visitAll(AllInfo info) {} |
| 698 visitProgram(ProgramInfo info) {} | 760 visitProgram(ProgramInfo info) {} |
| 699 visitLibrary(LibraryInfo info) {} | 761 visitLibrary(LibraryInfo info) {} |
| 700 visitClass(ClassInfo info) {} | 762 visitClass(ClassInfo info) {} |
| 701 visitField(FieldInfo info) {} | 763 visitField(FieldInfo info) {} |
| 764 visitConstant(ConstantInfo info) {} |
| 702 visitFunction(FunctionInfo info) {} | 765 visitFunction(FunctionInfo info) {} |
| 703 visitTypedef(TypedefInfo info) {} | 766 visitTypedef(TypedefInfo info) {} |
| 704 visitOutput(OutputUnitInfo info) {} | 767 visitOutput(OutputUnitInfo info) {} |
| 705 } | 768 } |
| 706 | 769 |
| 707 /// A visitor that recursively walks each portion of the program. Because the | 770 /// A visitor that recursively walks each portion of the program. Because the |
| 708 /// info representation is redundant, this visitor only walks the structure of | 771 /// info representation is redundant, this visitor only walks the structure of |
| 709 /// the program and skips some redundant links. For example, even though | 772 /// the program and skips some redundant links. For example, even though |
| 710 /// visitAll contains references to functions, this visitor only recurses to | 773 /// visitAll contains references to functions, this visitor only recurses to |
| 711 /// visit libraries, then from each library we visit functions and classes, and | 774 /// visit libraries, then from each library we visit functions and classes, and |
| 712 /// so on. | 775 /// so on. |
| 713 class RecursiveInfoVisitor extends InfoVisitor { | 776 class RecursiveInfoVisitor extends InfoVisitor { |
| 714 visitAll(AllInfo info) { | 777 visitAll(AllInfo info) { |
| 715 // Note: we don't visit functions, fields, classes, and typedefs because | 778 // Note: we don't visit functions, fields, classes, and typedefs because |
| 716 // they are reachable from the library info. | 779 // they are reachable from the library info. |
| 717 info.libraries.forEach(visitLibrary); | 780 info.libraries.forEach(visitLibrary); |
| 781 info.constants.forEach(visitConstant); |
| 718 } | 782 } |
| 719 | 783 |
| 720 visitLibrary(LibraryInfo info) { | 784 visitLibrary(LibraryInfo info) { |
| 721 info.topLevelFunctions.forEach(visitFunction); | 785 info.topLevelFunctions.forEach(visitFunction); |
| 722 info.topLevelVariables.forEach(visitField); | 786 info.topLevelVariables.forEach(visitField); |
| 723 info.classes.forEach(visitClass); | 787 info.classes.forEach(visitClass); |
| 724 info.typedefs.forEach(visitTypedef); | 788 info.typedefs.forEach(visitTypedef); |
| 725 } | 789 } |
| 726 | 790 |
| 727 visitClass(ClassInfo info) { | 791 visitClass(ClassInfo info) { |
| 728 info.functions.forEach(visitFunction); | 792 info.functions.forEach(visitFunction); |
| 729 info.fields.forEach(visitField); | 793 info.fields.forEach(visitField); |
| 730 } | 794 } |
| 731 | 795 |
| 732 visitField(FieldInfo info) { | 796 visitField(FieldInfo info) { |
| 733 info.closures.forEach(visitFunction); | 797 info.closures.forEach(visitFunction); |
| 734 } | 798 } |
| 735 | 799 |
| 736 visitFunction(FunctionInfo info) { | 800 visitFunction(FunctionInfo info) { |
| 737 info.closures.forEach(visitFunction); | 801 info.closures.forEach(visitFunction); |
| 738 } | 802 } |
| 739 } | 803 } |
| OLD | NEW |