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

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

Issue 1809533004: Support serialization of WorldImpact (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Updated cf. comments + cleanup. Created 4 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
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 library dart2js.serialization; 5 library dart2js.serialization;
6 6
7 import '../common/backend_api.dart';
7 import '../elements/elements.dart'; 8 import '../elements/elements.dart';
8 import '../constants/expressions.dart'; 9 import '../constants/expressions.dart';
9 import '../dart_types.dart'; 10 import '../dart_types.dart';
11 import '../universe/world_impact.dart';
10 12
13 import 'constant_serialization.dart';
11 import 'element_serialization.dart'; 14 import 'element_serialization.dart';
12 import 'constant_serialization.dart'; 15 import 'impact_serialization.dart';
16 import 'json_serializer.dart';
17 import 'keys.dart';
13 import 'type_serialization.dart'; 18 import 'type_serialization.dart';
14 import 'keys.dart';
15 import 'json_serializer.dart';
16 import 'values.dart'; 19 import 'values.dart';
17 20
18 /// An object that supports the encoding an [ObjectValue] for serialization. 21 /// An object that supports the encoding an [ObjectValue] for serialization.
19 /// 22 ///
20 /// The [ObjectEncoder] ensures that nominality and circularities of 23 /// The [ObjectEncoder] ensures that nominality and circularities of
21 /// non-primitive values like [Element], [DartType] and [ConstantExpression] are 24 /// non-primitive values like [Element], [DartType] and [ConstantExpression] are
22 /// handled. 25 /// handled.
23 class ObjectEncoder extends AbstractEncoder<Key> { 26 class ObjectEncoder extends AbstractEncoder<Key> {
24 /// Creates an [ObjectEncoder] in the scope of [serializer] that uses [map] 27 /// Creates an [ObjectEncoder] in the scope of [serializer] that uses [map]
25 /// as its internal storage. 28 /// as its internal storage.
(...skipping 575 matching lines...) Expand 10 before | Expand all | Expand 10 after
601 /// {...}, // [ObjectValue] of the 0th [ConstantExpression]. 604 /// {...}, // [ObjectValue] of the 0th [ConstantExpression].
602 /// ... 605 /// ...
603 /// {...}, // [ObjectValue] of the n-th [ConstantExpression]. 606 /// {...}, // [ObjectValue] of the n-th [ConstantExpression].
604 /// ], 607 /// ],
605 /// } 608 /// }
606 /// 609 ///
607 // TODO(johnniwinther): Support per-library serialization and dependencies 610 // TODO(johnniwinther): Support per-library serialization and dependencies
608 // between serialized subcomponent. 611 // between serialized subcomponent.
609 class Serializer { 612 class Serializer {
610 final SerializationEncoder _encoder; 613 final SerializationEncoder _encoder;
614 List<SerializerPlugin> plugins = <SerializerPlugin>[];
611 615
612 Map<Element, DataObject> _elementMap = <Element, DataObject>{}; 616 Map<Element, DataObject> _elementMap = <Element, DataObject>{};
613 Map<ConstantExpression, DataObject> _constantMap = 617 Map<ConstantExpression, DataObject> _constantMap =
614 <ConstantExpression, DataObject>{}; 618 <ConstantExpression, DataObject>{};
615 Map<DartType, DataObject> _typeMap = <DartType, DataObject>{}; 619 Map<DartType, DataObject> _typeMap = <DartType, DataObject>{};
616 List _pendingList = []; 620 List _pendingList = [];
617 621
618 Serializer(this._encoder); 622 Serializer(this._encoder);
619 623
620 /// Add the transitive closure of [library] to this serializer. 624 /// Add the transitive closure of [library] to this serializer.
621 void serialize(LibraryElement library) { 625 void serialize(LibraryElement library) {
622 // Call [_getElementDataObject] for its side-effect: To create a 626 // Call [_getElementDataObject] for its side-effect: To create a
623 // [DataObject] for [library]. If not already created, this will 627 // [DataObject] for [library]. If not already created, this will
624 // put the serialization of [library] in the work queue. 628 // put the serialization of [library] in the work queue.
625 _getElementDataObject(library); 629 _getElementDataObject(library);
626 _emptyWorklist();
627 } 630 }
628 631
629 void _emptyWorklist() { 632 void _emptyWorklist() {
630 while (_pendingList.isNotEmpty) { 633 while (_pendingList.isNotEmpty) {
631 _pendingList.removeLast()(); 634 _pendingList.removeLast()();
632 } 635 }
633 } 636 }
634 637
635 /// Returns the [DataObject] for [element]. 638 /// Returns the [DataObject] for [element].
636 /// 639 ///
637 /// If [constant] has no [DataObject], a new [DataObject] is created and 640 /// If [constant] has no [DataObject], a new [DataObject] is created and
638 /// encoding the [ObjectValue] for [constant] is put into the work queue of 641 /// encoding the [ObjectValue] for [constant] is put into the work queue of
639 /// this serializer. 642 /// this serializer.
640 DataObject _getElementDataObject(Element element) { 643 DataObject _getElementDataObject(Element element) {
641 if (element == null) { 644 if (element == null) {
642 throw new ArgumentError('Serializer._getElementDataObject(null)'); 645 throw new ArgumentError('Serializer._getElementDataObject(null)');
643 } 646 }
644 return _elementMap.putIfAbsent(element, () { 647 DataObject dataObject = _elementMap[element];
648 if (dataObject == null) {
645 // Run through [ELEMENT_SERIALIZERS] sequentially to find the one that 649 // Run through [ELEMENT_SERIALIZERS] sequentially to find the one that
646 // deals with [element]. 650 // deals with [element].
647 for (ElementSerializer serializer in ELEMENT_SERIALIZERS) { 651 for (ElementSerializer serializer in ELEMENT_SERIALIZERS) {
648 SerializedElementKind kind = serializer.getSerializedKind(element); 652 SerializedElementKind kind = serializer.getSerializedKind(element);
649 if (kind != null) { 653 if (kind != null) {
650 DataObject dataObject = new DataObject( 654 dataObject = new DataObject(
651 new IntValue(_elementMap.length), new EnumValue(kind)); 655 new IntValue(_elementMap.length), new EnumValue(kind));
656 _elementMap[element] = dataObject;
652 // Delay the serialization of the element itself to avoid loops, and 657 // Delay the serialization of the element itself to avoid loops, and
653 // to keep the call stack small. 658 // to keep the call stack small.
654 _pendingList.add(() { 659 _pendingList.add(() {
655 serializer.serialize( 660 ObjectEncoder encoder = new ObjectEncoder(this, dataObject.map);
656 element, new ObjectEncoder(this, dataObject.map), kind); 661 serializer.serialize(element, encoder, kind);
662
663 MapEncoder pluginData;
664 for (SerializerPlugin plugin in plugins) {
665 plugin.onElement(element, (String tag) {
666 if (pluginData == null) {
667 pluginData = encoder.createMap(Key.DATA);
668 }
669 return pluginData.createObject(tag);
670 });
671 }
657 }); 672 });
658 return dataObject;
659 } 673 }
660 } 674 }
675 }
676 if (dataObject == null) {
661 throw new UnsupportedError( 677 throw new UnsupportedError(
662 'Unsupported element: $element (${element.kind})'); 678 'Unsupported element: $element (${element.kind})');
663 }); 679 }
680 return dataObject;
664 } 681 }
665 682
666 /// Creates the [ElementValue] for [element]. 683 /// Creates the [ElementValue] for [element].
667 /// 684 ///
668 /// If [element] has not already been serialized, it is added to the work 685 /// If [element] has not already been serialized, it is added to the work
669 /// queue of this serializer. 686 /// queue of this serializer.
670 ElementValue createElementValue(Element element) { 687 ElementValue createElementValue(Element element) {
671 return new ElementValue(element, _getElementDataObject(element).id); 688 return new ElementValue(element, _getElementDataObject(element).id);
672 } 689 }
673 690
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
724 741
725 /// Creates the [TypeValue] for [type]. 742 /// Creates the [TypeValue] for [type].
726 /// 743 ///
727 /// If [type] has not already been serialized, it is added to the work 744 /// If [type] has not already been serialized, it is added to the work
728 /// queue of this serializer. 745 /// queue of this serializer.
729 TypeValue createTypeValue(DartType type) { 746 TypeValue createTypeValue(DartType type) {
730 return new TypeValue(type, _getTypeDataObject(type).id); 747 return new TypeValue(type, _getTypeDataObject(type).id);
731 } 748 }
732 749
733 ObjectValue get objectValue { 750 ObjectValue get objectValue {
751 _emptyWorklist();
752
734 Map<Key, Value> map = <Key, Value>{}; 753 Map<Key, Value> map = <Key, Value>{};
735 map[Key.ELEMENTS] = 754 map[Key.ELEMENTS] =
736 new ListValue(_elementMap.values.map((l) => l.objectValue).toList()); 755 new ListValue(_elementMap.values.map((l) => l.objectValue).toList());
737 if (_typeMap.isNotEmpty) { 756 if (_typeMap.isNotEmpty) {
738 map[Key.TYPES] = 757 map[Key.TYPES] =
739 new ListValue(_typeMap.values.map((l) => l.objectValue).toList()); 758 new ListValue(_typeMap.values.map((l) => l.objectValue).toList());
740 } 759 }
741 if (_constantMap.isNotEmpty) { 760 if (_constantMap.isNotEmpty) {
742 map[Key.CONSTANTS] = 761 map[Key.CONSTANTS] =
743 new ListValue(_constantMap.values.map((l) => l.objectValue).toList()); 762 new ListValue(_constantMap.values.map((l) => l.objectValue).toList());
744 } 763 }
745 return new ObjectValue(map); 764 return new ObjectValue(map);
746 } 765 }
747 766
748 String toText() { 767 String toText() {
749 return _encoder.encode(objectValue); 768 return _encoder.encode(objectValue);
750 } 769 }
751 770
752 String prettyPrint() { 771 String prettyPrint() {
753 PrettyPrintEncoder encoder = new PrettyPrintEncoder(); 772 PrettyPrintEncoder encoder = new PrettyPrintEncoder();
754 return encoder.toText(objectValue); 773 return encoder.toText(objectValue);
755 } 774 }
756 } 775 }
757 776
777 /// Plugin for serializing additional data for an [Element].
778 class SerializerPlugin {
779 const SerializerPlugin();
780
781 /// Called upon the serialization of [element].
782 ///
783 /// Use [creatorEncoder] to create a data object with id [tag] for storing
784 /// additional data for [element].
785 void onElement(Element element, ObjectEncoder createEncoder(String tag)) {}
786 }
787
788 /// Plugin for deserializing additional data for an [Element].
789 class DeserializerPlugin {
790 const DeserializerPlugin();
791
792 /// Called upon the deserialization of [element].
793 ///
794 /// Use [getDecoder] to retrieve the data object with id [tag] stored for
795 /// [element]. If not object is stored for [tag], [getDecoder] returns `null`.
796 void onElement(Element element, ObjectDecoder getDecoder(String tag)) {}
797 }
798
758 /// Deserializer for a closed collection of libraries. 799 /// Deserializer for a closed collection of libraries.
759 // TODO(johnniwinther): Support per-library deserialization and dependencies 800 // TODO(johnniwinther): Support per-library deserialization and dependencies
760 // between deserialized subcomponent. 801 // between deserialized subcomponent.
761 class Deserializer { 802 class Deserializer {
762 final SerializationDecoder decoder; 803 final SerializationDecoder decoder;
804 List<DeserializerPlugin> plugins = <DeserializerPlugin>[];
763 ObjectDecoder _headerObject; 805 ObjectDecoder _headerObject;
764 ListDecoder _elementList; 806 ListDecoder _elementList;
765 ListDecoder _typeList; 807 ListDecoder _typeList;
766 ListDecoder _constantList; 808 ListDecoder _constantList;
767 Map<int, Element> _elementMap = {}; 809 Map<int, Element> _elementMap = {};
768 Map<int, DartType> _typeMap = {}; 810 Map<int, DartType> _typeMap = {};
769 Map<int, ConstantExpression> _constantMap = {}; 811 Map<int, ConstantExpression> _constantMap = {};
770 812
771 Deserializer.fromText(String text, this.decoder) { 813 Deserializer.fromText(String text, this.decoder) {
772 _headerObject = new ObjectDecoder(this, decoder.decode(text)); 814 _headerObject = new ObjectDecoder(this, decoder.decode(text));
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
811 return deserializeElement(object.getInt(Key.ID)); 853 return deserializeElement(object.getInt(Key.ID));
812 } 854 }
813 } 855 }
814 } 856 }
815 return null; 857 return null;
816 } 858 }
817 859
818 /// Returns the deserialized [Element] for [id]. 860 /// Returns the deserialized [Element] for [id].
819 Element deserializeElement(int id) { 861 Element deserializeElement(int id) {
820 if (id == null) throw new ArgumentError('Deserializer.getElement(null)'); 862 if (id == null) throw new ArgumentError('Deserializer.getElement(null)');
821 return _elementMap.putIfAbsent(id, () { 863 Element element = _elementMap[id];
822 return ElementDeserializer.deserialize(elements.getObject(id)); 864 if (element == null) {
823 }); 865 ObjectDecoder decoder = elements.getObject(id);
866 element = ElementDeserializer.deserialize(decoder);
867 _elementMap[id] = element;
868
869 MapDecoder pluginData = decoder.getMap(Key.DATA, isOptional: true);
870 // Call plugins even when there is no data, so they can take action in
871 // this case.
872 for (DeserializerPlugin plugin in plugins) {
873 plugin.onElement(element,
874 (String tag) => pluginData?.getObject(tag, isOptional: true));
875 }
876 }
877 return element;
824 } 878 }
825 879
826 /// Returns the deserialized [DartType] for [id]. 880 /// Returns the deserialized [DartType] for [id].
827 DartType deserializeType(int id) { 881 DartType deserializeType(int id) {
828 if (id == null) throw new ArgumentError('Deserializer.getType(null)'); 882 if (id == null) throw new ArgumentError('Deserializer.getType(null)');
829 return _typeMap.putIfAbsent(id, () { 883 return _typeMap.putIfAbsent(id, () {
830 return TypeDeserializer.deserialize(types.getObject(id)); 884 return TypeDeserializer.deserialize(types.getObject(id));
831 }); 885 });
832 } 886 }
833 887
(...skipping 21 matching lines...) Expand all
855 909
856 /// Returns the value used to store [key] as a property in the encoding an 910 /// Returns the value used to store [key] as a property in the encoding an
857 /// [ObjectValue]. 911 /// [ObjectValue].
858 /// 912 ///
859 /// Different encodings have different restrictions and capabilities as how 913 /// Different encodings have different restrictions and capabilities as how
860 /// to store a [Key] value. For instance: A JSON encoding needs to convert 914 /// to store a [Key] value. For instance: A JSON encoding needs to convert
861 /// [Key] to a [String] to store it in a JSON object; a Dart encoding can 915 /// [Key] to a [String] to store it in a JSON object; a Dart encoding can
862 /// choose to store a [Key] as an [int] or as the [Key] itself. 916 /// choose to store a [Key] as an [int] or as the [Key] itself.
863 getObjectPropertyValue(Key key); 917 getObjectPropertyValue(Key key);
864 } 918 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698