| Index: pkg/compiler/lib/src/serialization/serialization.dart | 
| diff --git a/pkg/compiler/lib/src/serialization/serialization.dart b/pkg/compiler/lib/src/serialization/serialization.dart | 
| index 0379b6ad5fd67fc196b40c822198a3a11c436157..6050388ffc6431774e9fa87d1cf5684c822de29a 100644 | 
| --- a/pkg/compiler/lib/src/serialization/serialization.dart | 
| +++ b/pkg/compiler/lib/src/serialization/serialization.dart | 
| @@ -4,15 +4,12 @@ | 
|  | 
| library dart2js.serialization; | 
|  | 
| -import '../common/backend_api.dart'; | 
| import '../elements/elements.dart'; | 
| import '../constants/expressions.dart'; | 
| import '../dart_types.dart'; | 
| -import '../universe/world_impact.dart'; | 
|  | 
| import 'constant_serialization.dart'; | 
| import 'element_serialization.dart'; | 
| -import 'impact_serialization.dart'; | 
| import 'json_serializer.dart'; | 
| import 'keys.dart'; | 
| import 'type_serialization.dart'; | 
| @@ -91,6 +88,13 @@ abstract class AbstractEncoder<K> { | 
| } | 
| } | 
|  | 
| +  /// Maps the [key] entry to the [value] in the encoded object. | 
| +  void setValue(K key, Value value) { | 
| +    _checkKey(key); | 
| +    _map[key] = value; | 
| +  } | 
| + | 
| + | 
| /// Maps the [key] entry to the enum [value] in the encoded object. | 
| void setEnum(K key, var value) { | 
| _checkKey(key); | 
| @@ -581,6 +585,11 @@ class DataObject { | 
| Map<Key, Value> get map => objectValue.map; | 
| } | 
|  | 
| +/// Function used to filter which element serialized. | 
| +typedef bool ElementMatcher(Element element); | 
| + | 
| +bool includeAllElements(Element element) => true; | 
| + | 
| /// Serializer for the transitive closure of a collection of libraries. | 
| /// | 
| /// The serializer creates an [ObjectValue] model of the [Element], [DartType] | 
| @@ -607,26 +616,27 @@ class DataObject { | 
| ///       ], | 
| ///     } | 
| /// | 
| -// TODO(johnniwinther): Support per-library serialization and dependencies | 
| -// between serialized subcomponent. | 
| +// TODO(johnniwinther): Support dependencies between serialized subcomponent. | 
| class Serializer { | 
| -  final SerializationEncoder _encoder; | 
| List<SerializerPlugin> plugins = <SerializerPlugin>[]; | 
|  | 
| +  Map<Uri, dynamic> _dependencyMap = <Uri, dynamic>{}; | 
| Map<Element, DataObject> _elementMap = <Element, DataObject>{}; | 
| Map<ConstantExpression, DataObject> _constantMap = | 
| <ConstantExpression, DataObject>{}; | 
| Map<DartType, DataObject> _typeMap = <DartType, DataObject>{}; | 
| List _pendingList = []; | 
| +  ElementMatcher shouldInclude; | 
|  | 
| -  Serializer(this._encoder); | 
| +  // TODO(johnniwinther): Replace [includeElement] with a general strategy. | 
| +  Serializer({this.shouldInclude: includeAllElements}); | 
|  | 
| /// Add the transitive closure of [library] to this serializer. | 
| void serialize(LibraryElement library) { | 
| -    // Call [_getElementDataObject] for its side-effect: To create a | 
| +    // Call [_getElementId] for its side-effect: To create a | 
| // [DataObject] for [library]. If not already created, this will | 
| // put the serialization of [library] in the work queue. | 
| -    _getElementDataObject(library); | 
| +    _getElementId(library); | 
| } | 
|  | 
| void _emptyWorklist() { | 
| @@ -635,41 +645,75 @@ class Serializer { | 
| } | 
| } | 
|  | 
| -  /// Returns the [DataObject] for [element]. | 
| +  /// Returns the id [Value] for [element]. | 
| /// | 
| -  /// If [constant] has no [DataObject], a new [DataObject] is created and | 
| -  /// encoding the [ObjectValue] for [constant] is put into the work queue of | 
| +  /// If [element] has no [DataObject], a new [DataObject] is created and | 
| +  /// encoding the [ObjectValue] for [element] is put into the work queue of | 
| /// this serializer. | 
| -  DataObject _getElementDataObject(Element element) { | 
| +  Value _getElementId(Element element) { | 
| if (element == null) { | 
| throw new ArgumentError('Serializer._getElementDataObject(null)'); | 
| } | 
| DataObject dataObject = _elementMap[element]; | 
| if (dataObject == null) { | 
| -      // Run through [ELEMENT_SERIALIZERS] sequentially to find the one that | 
| -      // deals with [element]. | 
| -      for (ElementSerializer serializer in ELEMENT_SERIALIZERS) { | 
| -        SerializedElementKind kind = serializer.getSerializedKind(element); | 
| -        if (kind != null) { | 
| -          dataObject = new DataObject( | 
| -              new IntValue(_elementMap.length), new EnumValue(kind)); | 
| -          _elementMap[element] = dataObject; | 
| -          // Delay the serialization of the element itself to avoid loops, and | 
| -          // to keep the call stack small. | 
| -          _pendingList.add(() { | 
| -            ObjectEncoder encoder = new ObjectEncoder(this, dataObject.map); | 
| -            serializer.serialize(element, encoder, kind); | 
| - | 
| -            MapEncoder pluginData; | 
| -            for (SerializerPlugin plugin in plugins) { | 
| -              plugin.onElement(element, (String tag) { | 
| -                if (pluginData == null) { | 
| -                  pluginData = encoder.createMap(Key.DATA); | 
| -                } | 
| -                return pluginData.createObject(tag); | 
| -              }); | 
| -            } | 
| -          }); | 
| +      if (!shouldInclude(element)) { | 
| +        if (element.isLibrary) { | 
| +          LibraryElement library = element; | 
| +          _elementMap[element] = dataObject = new DataObject( | 
| +              new IntValue(_elementMap.length), | 
| +              new EnumValue(SerializedElementKind.EXTERNAL_LIBRARY)); | 
| +          ObjectEncoder encoder = new ObjectEncoder(this, dataObject.map); | 
| +          encoder.setUri(Key.URI, library.canonicalUri, library.canonicalUri); | 
| +        } else if (element.isStatic) { | 
| +          Value classId =_getElementId(element.enclosingClass); | 
| +          _elementMap[element] = dataObject = new DataObject( | 
| +              new IntValue(_elementMap.length), | 
| +              new EnumValue(SerializedElementKind.EXTERNAL_STATIC_MEMBER)); | 
| +          ObjectEncoder encoder = new ObjectEncoder(this, dataObject.map); | 
| +          encoder.setValue(Key.CLASS, classId); | 
| +          encoder.setString(Key.NAME, element.name); | 
| +        } else if (element.isConstructor) { | 
| +          Value classId =_getElementId(element.enclosingClass); | 
| +          _elementMap[element] = dataObject = new DataObject( | 
| +              new IntValue(_elementMap.length), | 
| +              new EnumValue(SerializedElementKind.EXTERNAL_CONSTRUCTOR)); | 
| +          ObjectEncoder encoder = new ObjectEncoder(this, dataObject.map); | 
| +          encoder.setValue(Key.CLASS, classId); | 
| +          encoder.setString(Key.NAME, element.name); | 
| +        } else { | 
| +          Value libraryId =_getElementId(element.library); | 
| +          _elementMap[element] = dataObject = new DataObject( | 
| +              new IntValue(_elementMap.length), | 
| +              new EnumValue(SerializedElementKind.EXTERNAL_LIBRARY_MEMBER)); | 
| +          ObjectEncoder encoder = new ObjectEncoder(this, dataObject.map); | 
| +          encoder.setValue(Key.LIBRARY, libraryId); | 
| +          encoder.setString(Key.NAME, element.name); | 
| +        } | 
| +      } else { | 
| +        // Run through [ELEMENT_SERIALIZERS] sequentially to find the one that | 
| +        // deals with [element]. | 
| +        for (ElementSerializer serializer in ELEMENT_SERIALIZERS) { | 
| +          SerializedElementKind kind = serializer.getSerializedKind(element); | 
| +          if (kind != null) { | 
| +            _elementMap[element] = dataObject = new DataObject( | 
| +                new IntValue(_elementMap.length), new EnumValue(kind)); | 
| +            // Delay the serialization of the element itself to avoid loops, and | 
| +            // to keep the call stack small. | 
| +            _pendingList.add(() { | 
| +              ObjectEncoder encoder = new ObjectEncoder(this, dataObject.map); | 
| +              serializer.serialize(element, encoder, kind); | 
| + | 
| +              MapEncoder pluginData; | 
| +              for (SerializerPlugin plugin in plugins) { | 
| +                plugin.onElement(element, (String tag) { | 
| +                  if (pluginData == null) { | 
| +                    pluginData = encoder.createMap(Key.DATA); | 
| +                  } | 
| +                  return pluginData.createObject(tag); | 
| +                }); | 
| +              } | 
| +            }); | 
| +          } | 
| } | 
| } | 
| } | 
| @@ -677,7 +721,7 @@ class Serializer { | 
| throw new UnsupportedError( | 
| 'Unsupported element: $element (${element.kind})'); | 
| } | 
| -    return dataObject; | 
| +    return dataObject.id; | 
| } | 
|  | 
| /// Creates the [ElementValue] for [element]. | 
| @@ -685,15 +729,15 @@ class Serializer { | 
| /// If [element] has not already been serialized, it is added to the work | 
| /// queue of this serializer. | 
| ElementValue createElementValue(Element element) { | 
| -    return new ElementValue(element, _getElementDataObject(element).id); | 
| +    return new ElementValue(element, _getElementId(element)); | 
| } | 
|  | 
| -  /// Returns the [DataObject] for [constant]. | 
| +  /// Returns the id [Value] for [constant]. | 
| /// | 
| /// If [constant] has no [DataObject], a new [DataObject] is created and | 
| /// encoding the [ObjectValue] for [constant] is put into the work queue of | 
| /// this serializer. | 
| -  DataObject _getConstantDataObject(ConstantExpression constant) { | 
| +  Value _getConstantId(ConstantExpression constant) { | 
| return _constantMap.putIfAbsent(constant, () { | 
| DataObject dataObject = new DataObject( | 
| new IntValue(_constantMap.length), new EnumValue(constant.kind)); | 
| @@ -701,7 +745,7 @@ class Serializer { | 
| // keep the call stack small. | 
| _pendingList.add(() => _encodeConstant(constant, dataObject)); | 
| return dataObject; | 
| -    }); | 
| +    }).id; | 
| } | 
|  | 
| /// Encodes [constant] into the [ObjectValue] of [dataObject]. | 
| @@ -715,23 +759,24 @@ class Serializer { | 
| /// If [constant] has not already been serialized, it is added to the work | 
| /// queue of this serializer. | 
| ConstantValue createConstantValue(ConstantExpression constant) { | 
| -    return new ConstantValue(constant, _getConstantDataObject(constant).id); | 
| +    return new ConstantValue(constant, _getConstantId(constant)); | 
| } | 
|  | 
| -  /// Returns the [DataObject] for [type]. | 
| +  /// Returns the id [Value] for [type]. | 
| /// | 
| /// If [type] has no [DataObject], a new [DataObject] is created and | 
| /// encoding the [ObjectValue] for [type] is put into the work queue of this | 
| /// serializer. | 
| -  DataObject _getTypeDataObject(DartType type) { | 
| -    return _typeMap.putIfAbsent(type, () { | 
| -      DataObject dataObject = new DataObject( | 
| +  Value _getTypeId(DartType type) { | 
| +    DataObject dataObject = _typeMap[type]; | 
| +    if (dataObject == null) { | 
| +      _typeMap[type] = dataObject = new DataObject( | 
| new IntValue(_typeMap.length), new EnumValue(type.kind)); | 
| // Delay the serialization of the type itself to avoid loops, and to keep | 
| // the call stack small. | 
| _pendingList.add(() => _encodeType(type, dataObject)); | 
| -      return dataObject; | 
| -    }); | 
| +    } | 
| +    return dataObject.id; | 
| } | 
|  | 
| /// Encodes [type] into the [ObjectValue] of [dataObject]. | 
| @@ -744,7 +789,7 @@ class Serializer { | 
| /// If [type] has not already been serialized, it is added to the work | 
| /// queue of this serializer. | 
| TypeValue createTypeValue(DartType type) { | 
| -    return new TypeValue(type, _getTypeDataObject(type).id); | 
| +    return new TypeValue(type, _getTypeId(type)); | 
| } | 
|  | 
| ObjectValue get objectValue { | 
| @@ -764,8 +809,8 @@ class Serializer { | 
| return new ObjectValue(map); | 
| } | 
|  | 
| -  String toText() { | 
| -    return _encoder.encode(objectValue); | 
| +  String toText(SerializationEncoder encoder) { | 
| +    return encoder.encode(objectValue); | 
| } | 
|  | 
| String prettyPrint() { | 
| @@ -796,10 +841,29 @@ class DeserializerPlugin { | 
| void onElement(Element element, ObjectDecoder getDecoder(String tag)) {} | 
| } | 
|  | 
| +/// Context for parallel deserialization. | 
| +class DeserializationContext { | 
| +  Map<Uri, LibraryElement> _uriMap = <Uri, LibraryElement>{}; | 
| +  List<Deserializer> deserializers = <Deserializer>[]; | 
| + | 
| +  LibraryElement lookupLibrary(Uri uri) { | 
| +    return _uriMap.putIfAbsent(uri, () { | 
| +      for (Deserializer deserializer in deserializers) { | 
| +        LibraryElement library = deserializer.lookupLibrary(uri); | 
| +        if (library != null) { | 
| +          return library; | 
| +        } | 
| +      } | 
| +      return null; | 
| +    }); | 
| +  } | 
| +} | 
| + | 
| /// Deserializer for a closed collection of libraries. | 
| // TODO(johnniwinther): Support per-library deserialization and dependencies | 
| // between deserialized subcomponent. | 
| class Deserializer { | 
| +  final DeserializationContext context; | 
| final SerializationDecoder decoder; | 
| List<DeserializerPlugin> plugins = <DeserializerPlugin>[]; | 
| ObjectDecoder _headerObject; | 
| @@ -810,8 +874,9 @@ class Deserializer { | 
| Map<int, DartType> _typeMap = {}; | 
| Map<int, ConstantExpression> _constantMap = {}; | 
|  | 
| -  Deserializer.fromText(String text, this.decoder) { | 
| +  Deserializer.fromText(this.context, String text, this.decoder) { | 
| _headerObject = new ObjectDecoder(this, decoder.decode(text)); | 
| +    context.deserializers.add(this); | 
| } | 
|  | 
| /// Returns the [ListDecoder] for the [Element]s in this deserializer. | 
| @@ -863,7 +928,38 @@ class Deserializer { | 
| Element element = _elementMap[id]; | 
| if (element == null) { | 
| ObjectDecoder decoder = elements.getObject(id); | 
| -      element = ElementDeserializer.deserialize(decoder); | 
| +      SerializedElementKind elementKind = | 
| +          decoder.getEnum(Key.KIND, SerializedElementKind.values); | 
| +      if (elementKind == SerializedElementKind.EXTERNAL_LIBRARY) { | 
| +        Uri uri = decoder.getUri(Key.URI); | 
| +        element = context.lookupLibrary(uri); | 
| +        if (element == null) { | 
| +          throw new StateError("Missing library for $uri."); | 
| +        } | 
| +      } else if (elementKind == SerializedElementKind.EXTERNAL_LIBRARY_MEMBER) { | 
| +        LibraryElement library = decoder.getElement(Key.LIBRARY); | 
| +        String name = decoder.getString(Key.NAME); | 
| +        element = library.find(name); | 
| +        if (element == null) { | 
| +          throw new StateError("Missing library member for $name in $library."); | 
| +        } | 
| +      } else if (elementKind == SerializedElementKind.EXTERNAL_STATIC_MEMBER) { | 
| +        ClassElement cls = decoder.getElement(Key.CLASS); | 
| +        String name = decoder.getString(Key.NAME); | 
| +        element = cls.lookupLocalMember(name); | 
| +        if (element == null) { | 
| +          throw new StateError("Missing static member for $name in $cls."); | 
| +        } | 
| +      } else if (elementKind == SerializedElementKind.EXTERNAL_CONSTRUCTOR) { | 
| +        ClassElement cls = decoder.getElement(Key.CLASS); | 
| +        String name = decoder.getString(Key.NAME); | 
| +        element = cls.lookupConstructor(name); | 
| +        if (element == null) { | 
| +          throw new StateError("Missing constructor for $name in $cls."); | 
| +        } | 
| +      } else { | 
| +        element = ElementDeserializer.deserialize(decoder, elementKind); | 
| +      } | 
| _elementMap[id] = element; | 
|  | 
| MapDecoder pluginData = decoder.getMap(Key.DATA, isOptional: true); | 
|  |