Version 1.19.0-dev.5.0

Merge 9d2ab4d0163ba031580e9315e02f84d7a1b0612b into dev
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 64a30df..35da026 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,11 +1,20 @@
 ## 1.19.0
 
+### Language changes
+
+* The language now allows a trailing comma after the last argument of a call and
+ the last parameter of a function declaration. This can make long argument or
+ parameter lists easier to maintain, as commas can be left as-is when
+ reordering lines. For details, see SDK issue
+ [26644](https://github.com/dart-lang/sdk/issues/26644).
+
 ### Core library changes
 
 * `dart:io`
   * `Socket.connect` with source-address argument is now non-blocking
     on Mac. Was already non-blocking on all other platforms.
   * Report a better error when a bind fails because of a bad source address.
+  * Handle HTTP header `charset` parameter with empty value.
 
 ### Strong Mode
 
@@ -58,8 +67,9 @@
 ### Dart VM
 
 *   The dependency on BoringSSL has been rolled forward. Going forward, builds
-    of the Dart VM including secure sockets will require a compiler with C11
-    support, and to link against glib 2.16 or newer.
+    of the Dart VM including secure sockets will require a compiler with C++11
+    support, and to link against glibc 2.16 or newer. For details, see the
+    [Building wiki page](https://github.com/dart-lang/sdk/wiki/Building).
 
 ### Tool Changes
 
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index f72e512..3b41a24 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -40,6 +40,7 @@
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
 import 'package:analyzer/src/generated/utilities_general.dart';
+import 'package:analyzer/src/summary/pub_summary.dart';
 import 'package:analyzer/src/task/dart.dart';
 import 'package:analyzer/src/util/glob.dart';
 import 'package:analyzer/task/dart.dart';
@@ -299,6 +300,11 @@
   ResolverProvider fileResolverProvider;
 
   /**
+   * The manager of pub package summaries.
+   */
+  PubSummaryManager pubSummaryManager;
+
+  /**
    * Initialize a newly created server to receive requests from and send
    * responses to the given [channel].
    *
@@ -363,6 +369,8 @@
       });
     });
     _setupIndexInvalidation();
+    pubSummaryManager =
+        new PubSummaryManager(resourceProvider, '${io.pid}.temp');
     Notification notification =
         new ServerConnectedParams(VERSION, io.pid).toNotification();
     channel.sendNotification(notification);
@@ -1594,6 +1602,10 @@
     context.sourceFactory =
         _createSourceFactory(context, options, disposition, folder);
     context.analysisOptions = options;
+
+    // TODO(scheglov) use linked bundles
+//    analysisServer.pubSummaryManager.getLinkedBundles(context);
+
     analysisServer._onContextsChangedController
         .add(new ContextsChangedEvent(added: [context]));
     analysisServer.schedulePerformAnalysisOperation(context);
diff --git a/pkg/analysis_server/lib/src/protocol_server.dart b/pkg/analysis_server/lib/src/protocol_server.dart
index 138c20f..864f04f 100644
--- a/pkg/analysis_server/lib/src/protocol_server.dart
+++ b/pkg/analysis_server/lib/src/protocol_server.dart
@@ -17,6 +17,7 @@
 import 'package:analyzer/src/dart/ast/utilities.dart' as engine;
 import 'package:analyzer/src/generated/engine.dart' as engine;
 import 'package:analyzer/src/generated/error.dart' as engine;
+import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/source.dart' as engine;
 import 'package:analyzer/src/generated/utilities_dart.dart' as engine;
 
@@ -254,15 +255,15 @@
     engine.SourceRange range) {
   int startLine = 0;
   int startColumn = 0;
-  {
-    engine.LineInfo lineInfo = context.getLineInfo(source);
+  try {
+    engine.LineInfo lineInfo = context.computeLineInfo(source);
     if (lineInfo != null) {
       engine.LineInfo_Location offsetLocation =
           lineInfo.getLocation(range.offset);
       startLine = offsetLocation.lineNumber;
       startColumn = offsetLocation.columnNumber;
     }
-  }
+  } on AnalysisException {}
   return new Location(
       source.fullName, range.offset, range.length, startLine, startColumn);
 }
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
index e582d37..f05284d 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
@@ -286,7 +286,7 @@
     }
     _resolvedImports = <ImportElement>[];
     for (ImportElement importElem in libElem.imports) {
-      if (importElem.importedLibrary.exportNamespace == null) {
+      if (importElem.importedLibrary?.exportNamespace == null) {
         await _computeAsync(this, importElem.importedLibrary.source,
             LIBRARY_ELEMENT4, performance, 'resolve imported library');
         checkAborted();
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index 4daa06e..27f33c8 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -624,13 +624,16 @@
     } else {
       for (ImportElement import in unitLibraryElement.imports) {
         if (prefixElement is PrefixElement && import.prefix == prefixElement) {
-          targetUnit = import.importedLibrary.definingCompilationUnit;
-          Source targetSource = targetUnit.source;
-          int offset = targetSource.contents.data.length;
-          sb = new SourceBuilder(targetSource.fullName, offset);
-          prefix = '$eol';
-          suffix = '$eol';
-          break;
+          LibraryElement library = import.importedLibrary;
+          if (library != null) {
+            targetUnit = library.definingCompilationUnit;
+            Source targetSource = targetUnit.source;
+            int offset = targetSource.contents.data.length;
+            sb = new SourceBuilder(targetSource.fullName, offset);
+            prefix = '$eol';
+            suffix = '$eol';
+            break;
+          }
         }
       }
       if (sb == null) {
@@ -1283,6 +1286,7 @@
       }
       isFirst = false;
     }
+
     // merge getter/setter pairs into fields
     String prefix = utils.getIndent(1);
     for (int i = 0; i < elements.length; i++) {
diff --git a/pkg/analysis_server/lib/src/services/correction/namespace.dart b/pkg/analysis_server/lib/src/services/correction/namespace.dart
index 0aa0b8d..87c38dd 100644
--- a/pkg/analysis_server/lib/src/services/correction/namespace.dart
+++ b/pkg/analysis_server/lib/src/services/correction/namespace.dart
@@ -37,13 +37,14 @@
 }
 
 /**
- * Returns the [ImportElement] that is referenced by [prefixNode] with
- * an [PrefixElement], maybe `null`.
+ * Return the [ImportElement] that is referenced by [prefixNode], or `null` if
+ * the node does not reference a prefix or if we cannot determine which import
+ * is being referenced.
  */
 ImportElement getImportElement(SimpleIdentifier prefixNode) {
-  if (prefixNode.parent is ImportDirective) {
-    ImportDirective importDirective = prefixNode.parent;
-    return importDirective.element;
+  AstNode parent = prefixNode.parent;
+  if (parent is ImportDirective) {
+    return parent.element;
   }
   ImportElementInfo info = internal_getImportElementInfo(prefixNode);
   return info?.element;
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index b829bee..57fcdea 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -1156,6 +1156,11 @@
    * directive.
    */
   LibraryElement get exportedLibrary;
+
+  /**
+   * Return `true` if the file referenced by the import's URI exists.
+   */
+  bool get uriExists;
 }
 
 /**
@@ -1341,6 +1346,11 @@
    * prefix, or otherwise does not have an offset.
    */
   int get prefixOffset;
+
+  /**
+   * Return `true` if the file referenced by the import's URI exists.
+   */
+  bool get uriExists;
 }
 
 /**
diff --git a/pkg/analyzer/lib/src/dart/element/builder.dart b/pkg/analyzer/lib/src/dart/element/builder.dart
index 6eaaedb..668d4fc 100644
--- a/pkg/analyzer/lib/src/dart/element/builder.dart
+++ b/pkg/analyzer/lib/src/dart/element/builder.dart
@@ -154,6 +154,7 @@
       ImportElementImpl importElement = new ImportElementImpl(-1);
       importElement.importedLibrary = importLibraryMap[coreLibrarySource];
       importElement.synthetic = true;
+      importElement.uriExists = true;
       imports.add(importElement);
     }
     //
@@ -170,38 +171,38 @@
     node.element = null;
     Source exportedSource = node.source;
     int exportedTime = sourceModificationTimeMap[exportedSource] ?? -1;
-    if (exportedTime != -1) {
-      // The exported source will be null if the URI in the export
-      // directive was invalid.
-      LibraryElement exportedLibrary = exportLibraryMap[exportedSource];
-      if (exportedLibrary != null) {
-        ExportElementImpl exportElement = new ExportElementImpl(node.offset);
-        exportElement.metadata = _getElementAnnotations(node.metadata);
-        StringLiteral uriLiteral = node.uri;
+    // The exported source will be null if the URI in the export
+    // directive was invalid.
+    LibraryElement exportedLibrary = exportLibraryMap[exportedSource];
+    if (exportedLibrary != null) {
+      ExportElementImpl exportElement = new ExportElementImpl(node.offset);
+      exportElement.metadata = _getElementAnnotations(node.metadata);
+      StringLiteral uriLiteral = node.uri;
+      if (uriLiteral != null) {
+        exportElement.uriOffset = uriLiteral.offset;
+        exportElement.uriEnd = uriLiteral.end;
+      }
+      exportElement.uri = node.uriContent;
+      exportElement.uriExists = exportedTime >= 0;
+      exportElement.combinators = _buildCombinators(node);
+      exportElement.exportedLibrary = exportedLibrary;
+      setElementDocumentationComment(exportElement, node);
+      node.element = exportElement;
+      exports.add(exportElement);
+      if (exportedTime >= 0 &&
+          exportSourceKindMap[exportedSource] != SourceKind.LIBRARY) {
+        int offset = node.offset;
+        int length = node.length;
         if (uriLiteral != null) {
-          exportElement.uriOffset = uriLiteral.offset;
-          exportElement.uriEnd = uriLiteral.end;
+          offset = uriLiteral.offset;
+          length = uriLiteral.length;
         }
-        exportElement.uri = node.uriContent;
-        exportElement.combinators = _buildCombinators(node);
-        exportElement.exportedLibrary = exportedLibrary;
-        setElementDocumentationComment(exportElement, node);
-        node.element = exportElement;
-        exports.add(exportElement);
-        if (exportSourceKindMap[exportedSource] != SourceKind.LIBRARY) {
-          int offset = node.offset;
-          int length = node.length;
-          if (uriLiteral != null) {
-            offset = uriLiteral.offset;
-            length = uriLiteral.length;
-          }
-          errors.add(new AnalysisError(
-              libraryElement.source,
-              offset,
-              length,
-              CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY,
-              [uriLiteral.toSource()]));
-        }
+        errors.add(new AnalysisError(
+            libraryElement.source,
+            offset,
+            length,
+            CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY,
+            [uriLiteral.toSource()]));
       }
     }
     return null;
@@ -213,53 +214,53 @@
     node.element = null;
     Source importedSource = node.source;
     int importedTime = sourceModificationTimeMap[importedSource] ?? -1;
-    if (importedTime != -1) {
-      // The imported source will be null if the URI in the import
-      // directive was invalid.
-      LibraryElement importedLibrary = importLibraryMap[importedSource];
-      if (importedLibrary != null) {
-        if (importedLibrary.isDartCore) {
-          explicitlyImportsCore = true;
+    // The imported source will be null if the URI in the import
+    // directive was invalid.
+    LibraryElement importedLibrary = importLibraryMap[importedSource];
+    if (importedLibrary != null) {
+      if (importedLibrary.isDartCore) {
+        explicitlyImportsCore = true;
+      }
+      ImportElementImpl importElement = new ImportElementImpl(node.offset);
+      importElement.metadata = _getElementAnnotations(node.metadata);
+      StringLiteral uriLiteral = node.uri;
+      if (uriLiteral != null) {
+        importElement.uriOffset = uriLiteral.offset;
+        importElement.uriEnd = uriLiteral.end;
+      }
+      importElement.uri = node.uriContent;
+      importElement.uriExists = importedTime >= 0;
+      importElement.deferred = node.deferredKeyword != null;
+      importElement.combinators = _buildCombinators(node);
+      importElement.importedLibrary = importedLibrary;
+      setElementDocumentationComment(importElement, node);
+      SimpleIdentifier prefixNode = node.prefix;
+      if (prefixNode != null) {
+        importElement.prefixOffset = prefixNode.offset;
+        String prefixName = prefixNode.name;
+        PrefixElementImpl prefix = nameToPrefixMap[prefixName];
+        if (prefix == null) {
+          prefix = new PrefixElementImpl.forNode(prefixNode);
+          nameToPrefixMap[prefixName] = prefix;
         }
-        ImportElementImpl importElement = new ImportElementImpl(node.offset);
-        importElement.metadata = _getElementAnnotations(node.metadata);
-        StringLiteral uriLiteral = node.uri;
+        importElement.prefix = prefix;
+        prefixNode.staticElement = prefix;
+      }
+      node.element = importElement;
+      imports.add(importElement);
+      if (importedTime >= 0 &&
+          importSourceKindMap[importedSource] != SourceKind.LIBRARY) {
+        int offset = node.offset;
+        int length = node.length;
         if (uriLiteral != null) {
-          importElement.uriOffset = uriLiteral.offset;
-          importElement.uriEnd = uriLiteral.end;
+          offset = uriLiteral.offset;
+          length = uriLiteral.length;
         }
-        importElement.uri = node.uriContent;
-        importElement.deferred = node.deferredKeyword != null;
-        importElement.combinators = _buildCombinators(node);
-        importElement.importedLibrary = importedLibrary;
-        setElementDocumentationComment(importElement, node);
-        SimpleIdentifier prefixNode = node.prefix;
-        if (prefixNode != null) {
-          importElement.prefixOffset = prefixNode.offset;
-          String prefixName = prefixNode.name;
-          PrefixElementImpl prefix = nameToPrefixMap[prefixName];
-          if (prefix == null) {
-            prefix = new PrefixElementImpl.forNode(prefixNode);
-            nameToPrefixMap[prefixName] = prefix;
-          }
-          importElement.prefix = prefix;
-          prefixNode.staticElement = prefix;
-        }
-        node.element = importElement;
-        imports.add(importElement);
-        if (importSourceKindMap[importedSource] != SourceKind.LIBRARY) {
-          int offset = node.offset;
-          int length = node.length;
-          if (uriLiteral != null) {
-            offset = uriLiteral.offset;
-            length = uriLiteral.length;
-          }
-          ErrorCode errorCode = (importElement.isDeferred
-              ? StaticWarningCode.IMPORT_OF_NON_LIBRARY
-              : CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY);
-          errors.add(new AnalysisError(libraryElement.source, offset, length,
-              errorCode, [uriLiteral.toSource()]));
-        }
+        ErrorCode errorCode = importElement.isDeferred
+            ? StaticWarningCode.IMPORT_OF_NON_LIBRARY
+            : CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY;
+        errors.add(new AnalysisError(libraryElement.source, offset, length,
+            errorCode, [uriLiteral.toSource()]));
       }
     }
     return null;
@@ -975,8 +976,8 @@
       } else {
         SimpleIdentifier propertyNameNode = node.name;
         String propertyName = propertyNameNode.name;
-        FieldElementImpl field =
-            _currentHolder.getField(propertyName, synthetic: true) as FieldElementImpl;
+        FieldElementImpl field = _currentHolder.getField(propertyName,
+            synthetic: true) as FieldElementImpl;
         if (field == null) {
           field = new FieldElementImpl(node.name.name, -1);
           field.final2 = true;
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 6f1ec8d..0ac63cf 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -4157,6 +4157,23 @@
   }
 
   @override
+  bool get uriExists {
+    if (_unlinkedExportNonPublic != null) {
+      return true;
+    }
+    return hasModifier(Modifier.URI_EXISTS);
+  }
+
+  /**
+   * Set whether the file referenced by the import's URI exists to match the
+   * given flag.
+   */
+  void set uriExists(bool exists) {
+    assert(_unlinkedExportNonPublic == null);
+    setModifier(Modifier.URI_EXISTS, exists);
+  }
+
+  @override
   int get uriOffset {
     if (_unlinkedExportNonPublic != null) {
       return _unlinkedExportNonPublic.uriOffset;
@@ -5100,6 +5117,23 @@
   }
 
   @override
+  bool get uriExists {
+    if (_unlinkedImport != null) {
+      return true;
+    }
+    return hasModifier(Modifier.URI_EXISTS);
+  }
+
+  /**
+   * Set whether the file referenced by the import's URI exists to match the
+   * given flag.
+   */
+  void set uriExists(bool exists) {
+    assert(_unlinkedImport == null);
+    setModifier(Modifier.URI_EXISTS, exists);
+  }
+
+  @override
   int get uriOffset {
     if (_unlinkedImport != null) {
       if (_unlinkedImport.isImplicit) {
@@ -5668,6 +5702,7 @@
           return lib;
         }
       }
+
       void recurse(LibraryElementImpl child) {
         if (!indices.containsKey(child)) {
           // We haven't visited this child yet, so recurse on the child,
@@ -5682,6 +5717,7 @@
           root = min(root, indices[child]);
         }
       }
+
       // Recurse on all of the children in the import/export graph, filtering
       // out those for which library cycles have already been computed.
       library.exportedLibraries
@@ -5708,6 +5744,7 @@
       }
       return root;
     }
+
     scc(library);
     return _libraryCycle;
   }
@@ -5907,6 +5944,7 @@
         library.importedLibraries.forEach(invalidate);
       }
     }
+
     invalidate(this);
   }
 
@@ -6395,6 +6433,12 @@
    */
   static const Modifier SYNTHETIC = const Modifier('SYNTHETIC', 16);
 
+  /**
+   * A flag used for import and export elements that indicates whether the URI
+   * in the corresponding directive referenced a file that exists.
+   */
+  static const Modifier URI_EXISTS = const Modifier('URI_EXISTS', 17);
+
   static const List<Modifier> values = const [
     ABSTRACT,
     ASYNCHRONOUS,
@@ -6412,7 +6456,8 @@
     REFERENCES_SUPER,
     SETTER,
     STATIC,
-    SYNTHETIC
+    SYNTHETIC,
+    URI_EXISTS
   ];
 
   const Modifier(String name, int ordinal) : super(name, ordinal);
diff --git a/pkg/analyzer/lib/src/dart/element/handle.dart b/pkg/analyzer/lib/src/dart/element/handle.dart
index 6823b99..dae8fa2 100644
--- a/pkg/analyzer/lib/src/dart/element/handle.dart
+++ b/pkg/analyzer/lib/src/dart/element/handle.dart
@@ -562,6 +562,9 @@
   int get uriEnd => actualElement.uriEnd;
 
   @override
+  bool get uriExists => actualElement.uriExists;
+
+  @override
   int get uriOffset => actualElement.uriOffset;
 }
 
@@ -707,6 +710,9 @@
   int get uriEnd => actualElement.uriEnd;
 
   @override
+  bool get uriExists => actualElement.uriExists;
+
+  @override
   int get uriOffset => actualElement.uriOffset;
 }
 
diff --git a/pkg/analyzer/lib/src/dart/resolver/inheritance_manager.dart b/pkg/analyzer/lib/src/dart/resolver/inheritance_manager.dart
index 0e0229c..476334b 100644
--- a/pkg/analyzer/lib/src/dart/resolver/inheritance_manager.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/inheritance_manager.dart
@@ -28,6 +28,12 @@
   LibraryElement _library;
 
   /**
+   * A flag indicating whether abstract methods should be included when looking
+   * up the superclass chain.
+   */
+  bool _includeAbstractFromSuperclasses;
+
+  /**
    * This is a mapping between each [ClassElement] and a map between the [String] member
    * names and the associated [ExecutableElement] in the mixin and superclass chain.
    */
@@ -51,8 +57,10 @@
    *
    * @param library the library element context that the inheritance mappings are being generated
    */
-  InheritanceManager(LibraryElement library) {
+  InheritanceManager(LibraryElement library,
+      {bool includeAbstractFromSuperclasses: false}) {
     this._library = library;
+    _includeAbstractFromSuperclasses = includeAbstractFromSuperclasses;
     _classLookup = new HashMap<ClassElement, Map<String, ExecutableElement>>();
     _interfaceLookup =
         new HashMap<ClassElement, Map<String, ExecutableElement>>();
@@ -282,7 +290,8 @@
           //
           // Include the members from the superclass in the resultMap.
           //
-          _recordMapWithClassMembers(resultMap, supertype, false);
+          _recordMapWithClassMembers(
+              resultMap, supertype, _includeAbstractFromSuperclasses);
         } finally {
           visitedClasses.remove(superclassElt);
         }
@@ -311,7 +320,8 @@
             //
             // Include the members from the mixin in the resultMap.
             //
-            _recordMapWithClassMembers(map, mixin, false);
+            _recordMapWithClassMembers(
+                map, mixin, _includeAbstractFromSuperclasses);
             //
             // Add the members from map into result map.
             //
diff --git a/pkg/analyzer/lib/src/dart/resolver/scope.dart b/pkg/analyzer/lib/src/dart/resolver/scope.dart
index 9211f8a..0537269 100644
--- a/pkg/analyzer/lib/src/dart/resolver/scope.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/scope.dart
@@ -125,7 +125,8 @@
             getSource(identifier),
             identifier.offset,
             identifier.length,
-            CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION, [name]));
+            CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION,
+            [name]));
         return hiddenElement;
       }
     }
@@ -438,6 +439,51 @@
     return foundElement;
   }
 
+  @override
+  bool shouldIgnoreUndefined(Identifier node) {
+    Iterable<NamespaceCombinator> getShowCombinators(
+            ImportElement importElement) =>
+        importElement.combinators.where((NamespaceCombinator combinator) =>
+            combinator is ShowElementCombinator);
+    if (node is PrefixedIdentifier) {
+      String prefix = node.prefix.name;
+      String name = node.identifier.name;
+      List<ImportElement> imports = _definingLibrary.imports;
+      int count = imports.length;
+      for (int i = 0; i < count; i++) {
+        ImportElement importElement = imports[i];
+        if (importElement.prefix?.name == prefix && !importElement.uriExists) {
+          Iterable<NamespaceCombinator> showCombinators =
+              getShowCombinators(importElement);
+          if (showCombinators.isEmpty) {
+            return true;
+          }
+          for (ShowElementCombinator combinator in showCombinators) {
+            if (combinator.shownNames.contains(name)) {
+              return true;
+            }
+          }
+        }
+      }
+    } else if (node is SimpleIdentifier) {
+      String name = node.name;
+      List<ImportElement> imports = _definingLibrary.imports;
+      int count = imports.length;
+      for (int i = 0; i < count; i++) {
+        ImportElement importElement = imports[i];
+        if (importElement.prefix == null && !importElement.uriExists) {
+          for (ShowElementCombinator combinator
+              in getShowCombinators(importElement)) {
+            if (combinator.shownNames.contains(name)) {
+              return true;
+            }
+          }
+        }
+      }
+    }
+    return false;
+  }
+
   /**
    * Create all of the namespaces associated with the libraries imported into
    * this library. The names are not added to this scope, but are stored for
@@ -521,8 +567,7 @@
       return foundElement;
     }
     for (int i = 0; i < _importedNamespaces.length; i++) {
-      Namespace nameSpace = _importedNamespaces[i];
-      Element element = nameSpace.getPrefixed(prefix, name);
+      Element element = _importedNamespaces[i].getPrefixed(prefix, name);
       if (element != null) {
         if (foundElement == null) {
           foundElement = element;
@@ -1161,6 +1206,20 @@
   }
 
   /**
+   * Return `true` if the fact that the given [node] is not defined should be
+   * ignored (from the perspective of error reporting). This will be the case if
+   * there is at least one import that defines the node's prefix, and if that
+   * import either has no show combinators or has a show combinator that
+   * explicitly lists the node's name.
+   */
+  bool shouldIgnoreUndefined(Identifier node) {
+    if (enclosingScope != null) {
+      return enclosingScope.shouldIgnoreUndefined(node);
+    }
+    return false;
+  }
+
+  /**
    * Return the name that will be used to look up the given [element].
    */
   String _getName(Element element) {
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index 029b5c6..87d3fd2 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -711,6 +711,15 @@
     // Then check for error conditions.
     //
     ErrorCode errorCode = _checkForInvocationError(target, true, staticElement);
+    if (errorCode != null &&
+        target is SimpleIdentifier &&
+        target.staticElement is PrefixElement) {
+      Identifier functionName =
+          new PrefixedIdentifierImpl.temp(target, methodName);
+      if (_resolver.nameScope.shouldIgnoreUndefined(functionName)) {
+        return null;
+      }
+    }
     bool generatedWithTypePropagation = false;
     if (_enableHints && errorCode == null && staticElement == null) {
       // The method lookup may have failed because there were multiple
@@ -750,8 +759,10 @@
         identical(errorCode,
             CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT) ||
         identical(errorCode, StaticTypeWarningCode.UNDEFINED_FUNCTION)) {
-      _resolver.errorReporter
-          .reportErrorForNode(errorCode, methodName, [methodName.name]);
+      if (!_resolver.nameScope.shouldIgnoreUndefined(methodName)) {
+        _resolver.errorReporter
+            .reportErrorForNode(errorCode, methodName, [methodName.name]);
+      }
     } else if (identical(errorCode, StaticTypeWarningCode.UNDEFINED_METHOD)) {
       String targetTypeName;
       if (target == null) {
@@ -817,6 +828,7 @@
         }
         return type;
       }
+
       DartType targetType = getSuperType(_getStaticType(target));
       String targetTypeName = targetType?.name;
       _resolver.errorReporter.reportErrorForNode(
@@ -894,6 +906,9 @@
                 "${node.identifier.name}=", node.identifier.offset - 1)));
         element = _resolver.nameScope.lookup(setterName, _definingLibrary);
       }
+      if (element == null && _resolver.nameScope.shouldIgnoreUndefined(node)) {
+        return null;
+      }
       if (element == null) {
         if (identifier.inSetterContext()) {
           _resolver.errorReporter.reportErrorForNode(
@@ -1112,7 +1127,7 @@
             StaticWarningCode.UNDEFINED_IDENTIFIER_AWAIT,
             node,
             [_resolver.enclosingFunction.displayName]);
-      } else {
+      } else if (!_resolver.nameScope.shouldIgnoreUndefined(node)) {
         _recordUndefinedNode(_resolver.enclosingClass,
             StaticWarningCode.UNDEFINED_IDENTIFIER, node, [node.name]);
       }
@@ -1177,6 +1192,15 @@
       name.staticElement = element;
     }
     node.staticElement = element;
+    // TODO(brianwilkerson) Defer this check until we know there's an error (by
+    // in-lining _resolveArgumentsToFunction below).
+    ClassDeclaration declaration =
+        node.getAncestor((AstNode node) => node is ClassDeclaration);
+    Identifier superclassName = declaration.extendsClause?.superclass?.name;
+    if (superclassName != null &&
+        _resolver.nameScope.shouldIgnoreUndefined(superclassName)) {
+      return null;
+    }
     ArgumentList argumentList = node.argumentList;
     List<ParameterElement> parameters = _resolveArgumentsToFunction(
         isInConstConstructor, argumentList, element);
@@ -1212,7 +1236,7 @@
    * error code that should be reported, or `null` if no error should be
    * reported. The [target] is the target of the invocation, or `null` if there
    * was no target. The flag [useStaticContext] should be `true` if the
-   * invocation is in a static constant (does not have access to instance state.
+   * invocation is in a static constant (does not have access to instance state).
    */
   ErrorCode _checkForInvocationError(
       Expression target, bool useStaticContext, Element element) {
@@ -1283,6 +1307,10 @@
             targetType = _getBestType(target);
           }
           if (targetType == null) {
+            if (target is Identifier &&
+                _resolver.nameScope.shouldIgnoreUndefined(target)) {
+              return null;
+            }
             return StaticTypeWarningCode.UNDEFINED_FUNCTION;
           } else if (!targetType.isDynamic && !targetType.isBottom) {
             // Proxy-conditional warning, based on state of
diff --git a/pkg/analyzer/lib/src/generated/error.dart b/pkg/analyzer/lib/src/generated/error.dart
index db9ad7ec..bedfdd8 100644
--- a/pkg/analyzer/lib/src/generated/error.dart
+++ b/pkg/analyzer/lib/src/generated/error.dart
@@ -3317,6 +3317,7 @@
       }
       return type.displayName;
     }
+
     if (_hasEqualTypeNames(arguments)) {
       int count = arguments.length;
       for (int i = 0; i < count; i++) {
@@ -5338,6 +5339,26 @@
           false);
 
   /**
+   * 17.9 Switch: It is a static warning if all of the following conditions
+   * hold:
+   * * The switch statement does not have a 'default' clause.
+   * * The static type of <i>e</i> is an enumerated typed with elements
+   *   <i>id<sub>1</sub></i>, &hellip;, <i>id<sub>n</sub></i>.
+   * * The sets {<i>e<sub>1</sub></i>, &hellip;, <i>e<sub>k</sub></i>} and
+   *   {<i>id<sub>1</sub></i>, &hellip;, <i>id<sub>n</sub></i>} are not the
+   *   same.
+   *
+   * Parameters:
+   * 0: the name of the constant that is missing
+   */
+  static const StaticWarningCode MISSING_ENUM_CONSTANT_IN_SWITCH =
+      const StaticWarningCode(
+          'MISSING_ENUM_CONSTANT_IN_SWITCH',
+          "Missing case clause for '{0}'",
+          "Add a case clause for the missing constant or add a default clause.",
+          false);
+
+  /**
    * 13.12 Return: It is a static warning if a function contains both one or
    * more return statements of the form <i>return;</i> and one or more return
    * statements of the form <i>return e;</i>.
@@ -5861,26 +5882,6 @@
           "The return type of the getter must not be 'void'", null, false);
 
   /**
-   * 17.9 Switch: It is a static warning if all of the following conditions
-   * hold:
-   * * The switch statement does not have a 'default' clause.
-   * * The static type of <i>e</i> is an enumerated typed with elements
-   *   <i>id<sub>1</sub></i>, &hellip;, <i>id<sub>n</sub></i>.
-   * * The sets {<i>e<sub>1</sub></i>, &hellip;, <i>e<sub>k</sub></i>} and
-   *   {<i>id<sub>1</sub></i>, &hellip;, <i>id<sub>n</sub></i>} are not the
-   *   same.
-   *
-   * Parameters:
-   * 0: the name of the constant that is missing
-   */
-  static const StaticWarningCode MISSING_ENUM_CONSTANT_IN_SWITCH =
-      const StaticWarningCode(
-          'MISSING_ENUM_CONSTANT_IN_SWITCH',
-          "Missing case clause for '{0}'",
-          "Add a case clause for the missing constant or add a default clause.",
-          false);
-
-  /**
    * A flag indicating whether this warning is an error when running with strong
    * mode enabled.
    */
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 4a70c66..3f9d3d8 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -562,6 +562,7 @@
       }
       return element.isDeprecated;
     }
+
     if (!inDeprecatedMember && isDeprecated(element)) {
       String displayName = element.displayName;
       if (element is ConstructorElement) {
@@ -971,6 +972,7 @@
       }
       return false;
     }
+
     FunctionBody body = node.body;
     if (body is ExpressionFunctionBody) {
       if (isNonObjectNoSuchMethodInvocation(body.expression)) {
@@ -1916,7 +1918,7 @@
   @override
   Object visitExportDirective(ExportDirective node) {
     ExportElement exportElement = node.element;
-    if (exportElement != null) {
+    if (exportElement != null && exportElement.uriExists) {
       // The element is null when the URI is invalid
       LibraryElement library = exportElement.exportedLibrary;
       if (library != null) {
@@ -1960,8 +1962,9 @@
   @override
   Object visitImportDirective(ImportDirective node) {
     ImportElement importElement = node.element;
-    if (importElement != null) {
-      // The element is null when the URI is invalid
+    if (importElement != null && importElement.uriExists) {
+      // The element is null when the URI is invalid, but not when the URI is
+      // valid but refers to a non-existent file.
       LibraryElement library = importElement.importedLibrary;
       if (library != null) {
         for (Combinator combinator in node.combinators) {
@@ -2547,8 +2550,10 @@
       String nameOfMethod = methodName.name;
       if (property == null) {
         String elementName = nameOfMethod == '-' &&
-            node.parameters != null &&
-            node.parameters.parameters.isEmpty ? 'unary-' : nameOfMethod;
+                node.parameters != null &&
+                node.parameters.parameters.isEmpty
+            ? 'unary-'
+            : nameOfMethod;
         _enclosingExecutable = _findWithNameAndOffset(_enclosingClass.methods,
             methodName, elementName, methodName.offset);
         _expectedElements.remove(_enclosingExecutable);
@@ -3963,6 +3968,7 @@
       }
       return false;
     }
+
     AstNode parent = identifier.parent;
     if (parent is MethodInvocation && parent.methodName == identifier) {
       return recordIfTargetIsPrefixElement(parent.target);
@@ -4211,7 +4217,8 @@
     _usedImportedElementsVisitor =
         new GatherUsedImportedElementsVisitor(_library);
     _enableDart2JSHints = _context.analysisOptions.dart2jsHint;
-    _manager = new InheritanceManager(_library);
+    _manager =
+        new InheritanceManager(_library, includeAbstractFromSuperclasses: true);
     _usedLocalElementsVisitor = new GatherUsedLocalElementsVisitor(_library);
   }
 
@@ -4439,11 +4446,13 @@
     int length = _unusedImports.length;
     for (int i = 0; i < length; i++) {
       ImportDirective unusedImport = _unusedImports[i];
-      // Check that the import isn't dart:core
+      // Check that the imported URI exists and isn't dart:core
       ImportElement importElement = unusedImport.element;
       if (importElement != null) {
         LibraryElement libraryElement = importElement.importedLibrary;
-        if (libraryElement != null && libraryElement.isDartCore) {
+        if (libraryElement == null ||
+            libraryElement.isDartCore ||
+            !importElement.uriExists) {
           continue;
         }
       }
@@ -4689,8 +4698,6 @@
    * A stack of return types for all of the enclosing
    * functions and methods.
    */
-  // TODO(leafp) Handle the implicit union type for Futures
-  // https://github.com/dart-lang/sdk/issues/25322
   final List<DartType> _returnStack = <DartType>[];
 
   InferenceContext._(this._errorReporter, TypeProvider typeProvider,
@@ -4720,7 +4727,7 @@
       return;
     }
     DartType context = _returnStack.last;
-    if (context == null || context.isDynamic) {
+    if (context is! FutureUnionType) {
       DartType inferred = _inferredReturn.last;
       inferred = _typeSystem.getLeastUpperBound(_typeProvider, type, inferred);
       _inferredReturn[_inferredReturn.length - 1] = inferred;
@@ -4746,15 +4753,14 @@
    * bound of all types added with [addReturnOrYieldType].
    */
   void popReturnContext(BlockFunctionBody node) {
-    assert(_returnStack.isNotEmpty && _inferredReturn.isNotEmpty);
-    if (_returnStack.isNotEmpty) {
-      _returnStack.removeLast();
-    }
-    if (_inferredReturn.isNotEmpty) {
+    if (_returnStack.isNotEmpty && _inferredReturn.isNotEmpty) {
+      DartType context = _returnStack.removeLast() ?? DynamicTypeImpl.instance;
       DartType inferred = _inferredReturn.removeLast();
-      if (!inferred.isBottom) {
+      if (!inferred.isBottom && _typeSystem.isSubtypeOf(inferred, context)) {
         setType(node, inferred);
       }
+    } else {
+      assert(false);
     }
   }
 
@@ -4762,8 +4768,7 @@
    * Push a block function body's return type onto the return stack.
    */
   void pushReturnContext(BlockFunctionBody node) {
-    DartType returnType = getType(node);
-    _returnStack.add(returnType);
+    _returnStack.add(getContext(node));
     _inferredReturn.add(BottomTypeImpl.instance);
   }
 
@@ -4905,18 +4910,49 @@
   }
 
   /**
+   * Look for a single contextual type attached to [node], and returns the type
+   * if found, otherwise null.
+   *
+   * If [node] has a contextual union type like `T | Future<T>` this will
+   * simplify it to only return `T`. If the caller can handle a union type,
+   * [getContext] should be used instead.
+   */
+  static DartType getType(AstNode node) {
+    DartType t = getContext(node);
+    if (t is FutureUnionType) {
+      return t.type;
+    }
+    return t;
+  }
+
+  /**
    * Look for contextual type information attached to [node].  Returns
    * the type if found, otherwise null.
+   *
+   * If [node] has a contextual union type like `T | Future<T>` this will be
+   * returned. You can use [getType] if you prefer to only get the `T`.
    */
-  static DartType getType(AstNode node) => node?.getProperty(_typeProperty);
+  static DartType getContext(AstNode node) => node?.getProperty(_typeProperty);
+
+  /**
+   * Like [getContext] but expands a union type into a list of types.
+   */
+  static Iterable<DartType> getTypes(AstNode node) {
+    DartType t = getContext(node);
+    if (t == null) {
+      return DartType.EMPTY_LIST;
+    }
+    if (t is FutureUnionType) {
+      return t.types;
+    }
+    return <DartType>[t];
+  }
 
   /**
    * Attach contextual type information [type] to [node] for use during
    * inference.
    */
   static void setType(AstNode node, DartType type) {
-    // TODO(jmesserly): this sets the type even when it's dynamic.
-    // Can we skip that?
     node?.setProperty(_typeProperty, type);
   }
 
@@ -4925,7 +4961,7 @@
    * inference.
    */
   static void setTypeFromNode(AstNode innerNode, AstNode outerNode) {
-    setType(innerNode, getType(outerNode));
+    setType(innerNode, getContext(outerNode));
   }
 }
 
@@ -6009,13 +6045,11 @@
 
   @override
   Object visitAwaitExpression(AwaitExpression node) {
-    // TODO(leafp): Handle the implicit union type here
-    // https://github.com/dart-lang/sdk/issues/25322
-    DartType contextType = InferenceContext.getType(node);
+    DartType contextType = InferenceContext.getContext(node);
     if (contextType != null) {
-      InterfaceType futureT = typeProvider.futureType
-          .instantiate([contextType.flattenFutures(typeSystem)]);
-      InferenceContext.setType(node.expression, futureT);
+      var futureUnion =
+          FutureUnionType.from(contextType, typeProvider, typeSystem);
+      InferenceContext.setType(node.expression, futureUnion);
     }
     return super.visitAwaitExpression(node);
   }
@@ -6069,7 +6103,7 @@
       if (operatorType == TokenType.QUESTION_QUESTION) {
         // Set the right side, either from the context, or using the information
         // from the left side if it is more precise.
-        DartType contextType = InferenceContext.getType(node);
+        DartType contextType = InferenceContext.getContext(node);
         DartType leftType = leftOperand?.staticType;
         if (contextType == null || contextType.isDynamic) {
           contextType = leftType;
@@ -6547,8 +6581,24 @@
               matchFunctionTypeParameters(node.typeParameters, functionType);
           if (functionType is FunctionType) {
             _inferFormalParameterList(node.parameters, functionType);
-            DartType returnType =
-                _computeReturnOrYieldType(functionType.returnType);
+
+            DartType returnType;
+            if (_isFutureThenLambda(node)) {
+              var futureThenType =
+                  InferenceContext.getContext(node.parent) as FunctionType;
+
+              // Pretend the return type of Future<T>.then<S> first parameter is
+              //
+              //     T -> (S | Future<S>)
+              //
+              // We can't represent this in Dart so we populate it here during
+              // inference.
+              returnType = FutureUnionType.from(
+                  futureThenType.returnType, typeProvider, typeSystem);
+            } else {
+              returnType = _computeReturnOrYieldType(functionType.returnType);
+            }
+
             InferenceContext.setType(node.body, returnType);
           }
         }
@@ -6664,30 +6714,37 @@
   Object visitInstanceCreationExpression(InstanceCreationExpression node) {
     TypeName classTypeName = node.constructorName.type;
     if (classTypeName.typeArguments == null) {
-      DartType contextType = InferenceContext.getType(node);
-      if (contextType is InterfaceType &&
-          contextType.typeArguments != null &&
-          contextType.typeArguments.length > 0) {
-        // TODO(jmesserly): for generic methods we use the
-        // StrongTypeSystemImpl.inferGenericFunctionCall, which appears to
-        // be a tad more powerful than matchTypes.
-        //
-        // For example it can infer this case:
-        //
-        //     class E<S, T> extends A<C<S>, T> { ... }
-        //     A<C<int>, String> a0 = /*infer<int, String>*/new E("hello");
-        //
-        // See _inferArgumentTypesFromContext in this file for use of it.
-        List<DartType> targs =
-            inferenceContext.matchTypes(classTypeName.type, contextType);
-        if (targs != null && targs.any((t) => !t.isDynamic)) {
-          ClassElement classElement = classTypeName.type.element;
-          InterfaceType rawType = classElement.type;
-          InterfaceType fullType =
-              rawType.substitute2(targs, rawType.typeArguments);
-          // The element resolver uses the type on the constructor name, so
-          // infer it first
-          typeAnalyzer.inferConstructorName(node.constructorName, fullType);
+      // Given a union of context types ` T0 | T1 | ... | Tn`, find the first
+      // valid instantiation `new C<Ti>`, if it exists.
+      // TODO(jmesserly): if we support union types for real, `new C<Ti | Tj>`
+      // will become a valid possibility. Right now the only allowed union is
+      // `T | Future<T>` so we can take a simple approach.
+      for (var contextType in InferenceContext.getTypes(node)) {
+        if (contextType is InterfaceType &&
+            contextType.typeArguments != null &&
+            contextType.typeArguments.isNotEmpty) {
+          // TODO(jmesserly): for generic methods we use the
+          // StrongTypeSystemImpl.inferGenericFunctionCall, which appears to
+          // be a tad more powerful than matchTypes.
+          //
+          // For example it can infer this case:
+          //
+          //     class E<S, T> extends A<C<S>, T> { ... }
+          //     A<C<int>, String> a0 = /*infer<int, String>*/new E("hello");
+          //
+          // See _inferArgumentTypesFromContext in this file for use of it.
+          List<DartType> targs =
+              inferenceContext.matchTypes(classTypeName.type, contextType);
+          if (targs != null && targs.any((t) => !t.isDynamic)) {
+            ClassElement classElement = classTypeName.type.element;
+            InterfaceType rawType = classElement.type;
+            InterfaceType fullType =
+                rawType.substitute2(targs, rawType.typeArguments);
+            // The element resolver uses the type on the constructor name, so
+            // infer it first
+            typeAnalyzer.inferConstructorName(node.constructorName, fullType);
+            break;
+          }
         }
       }
     }
@@ -6801,7 +6858,7 @@
 
   @override
   Object visitNamedExpression(NamedExpression node) {
-    InferenceContext.setType(node.expression, InferenceContext.getType(node));
+    InferenceContext.setTypeFromNode(node.expression, node);
     return super.visitNamedExpression(node);
   }
 
@@ -6815,7 +6872,7 @@
 
   @override
   Object visitParenthesizedExpression(ParenthesizedExpression node) {
-    InferenceContext.setType(node.expression, InferenceContext.getType(node));
+    InferenceContext.setTypeFromNode(node.expression, node);
     return super.visitParenthesizedExpression(node);
   }
 
@@ -6933,7 +6990,7 @@
 
   @override
   Object visitVariableDeclaration(VariableDeclaration node) {
-    InferenceContext.setType(node.initializer, InferenceContext.getType(node));
+    InferenceContext.setTypeFromNode(node.initializer, node);
     super.visitVariableDeclaration(node);
     VariableElement element = node.element;
     if (element.initializer != null && node.initializer != null) {
@@ -7077,21 +7134,22 @@
     if (!isGenerator && !isAsynchronous) {
       return declaredType;
     }
-    if (isGenerator) {
-      if (declaredType is! InterfaceType) {
-        return null;
+    if (declaredType is InterfaceType) {
+      if (isGenerator) {
+        // If it's sync* we expect Iterable<T>
+        // If it's async* we expect Stream<T>
+        InterfaceType rawType = isAsynchronous
+            ? typeProvider.streamDynamicType
+            : typeProvider.iterableDynamicType;
+        // Match the types to instantiate the type arguments if possible
+        List<DartType> typeArgs =
+            inferenceContext.matchTypes(rawType, declaredType);
+        return (typeArgs?.length == 1) ? typeArgs[0] : null;
       }
-      // If it's synchronous, we expect Iterable<T>, otherwise Stream<T>
-      InterfaceType rawType = isAsynchronous
-          ? typeProvider.streamDynamicType
-          : typeProvider.iterableDynamicType;
-      // Match the types to instantiate the type arguments if possible
-      List<DartType> typeArgs =
-          inferenceContext.matchTypes(rawType, declaredType);
-      return (typeArgs?.length == 1) ? typeArgs[0] : null;
+      // async functions expect `Future<T> | T`
+      return new FutureUnionType(declaredType, typeProvider, typeSystem);
     }
-    // Must be asynchronous to reach here, so strip off any layers of Future
-    return declaredType.flattenFutures(typeSystem);
+    return declaredType;
   }
 
   /**
@@ -7183,6 +7241,20 @@
     if (typeAnalyzer.inferFormalParameterList(node, type)) {
       // TODO(leafp): This gets dropped on the floor if we're in the field
       // inference task.  We should probably keep these infos.
+      //
+      // TODO(jmesserly): this is reporting the context type, and therefore not
+      // necessarily the correct inferred type for the lambda.
+      //
+      // For example, `([x]) {}`  could be passed to `int -> void` but its type
+      // will really be `([int]) -> void`. Similar issue for named arguments.
+      // It can also happen if the return type is inferred later on to be
+      // more precise.
+      //
+      // This reporting bug defeats the deduplication of error messages and
+      // results in the same inference message being reported twice.
+      //
+      // To get this right, we'd have to delay reporting until we have the
+      // complete type including return type.
       inferenceContext.recordInference(node.parent, type);
     }
   }
@@ -7322,6 +7394,19 @@
   }
 
   /**
+   * Returns true if this expression is being passed to `Future.then`.
+   *
+   * If so we will apply special typing rules in strong mode, to handle the
+   * implicit union of `S | Future<S>`
+   */
+  bool _isFutureThenLambda(FunctionExpression node) {
+    Element element = node.staticParameterElement?.enclosingElement;
+    return element is MethodElement &&
+        element.name == 'then' &&
+        element.enclosingElement.type.isDartAsyncFuture;
+  }
+
+  /**
    * Return `true` if the given variable is accessed within a closure in the given
    * [AstNode] and also mutated somewhere in variable scope. This information is only
    * available for local variables (including parameters).
@@ -8542,6 +8627,11 @@
         node.type = voidType;
         return;
       }
+      if (nameScope.shouldIgnoreUndefined(typeName)) {
+        typeName.staticType = undefinedType;
+        node.type = undefinedType;
+        return;
+      }
       //
       // If not, the look to see whether we might have created the wrong AST
       // structure for a constructor name. If so, fix the AST structure and then
@@ -8558,6 +8648,11 @@
           SimpleIdentifier prefix = prefixedIdentifier.prefix;
           element = nameScope.lookup(prefix, definingLibrary);
           if (element is PrefixElement) {
+            if (nameScope.shouldIgnoreUndefined(typeName)) {
+              typeName.staticType = undefinedType;
+              node.type = undefinedType;
+              return;
+            }
             AstNode grandParent = parent.parent;
             if (grandParent is InstanceCreationExpression &&
                 grandParent.isConst) {
@@ -8592,6 +8687,11 @@
           }
         }
       }
+      if (nameScope.shouldIgnoreUndefined(typeName)) {
+        typeName.staticType = undefinedType;
+        node.type = undefinedType;
+        return;
+      }
     }
     // check element
     bool elementValid = element is! MultiplyDefinedElement;
@@ -10413,7 +10513,7 @@
     Identifier name = typeName.name;
     if (name.name == Keyword.DYNAMIC.syntax) {
       errorReporter.reportErrorForNode(dynamicTypeError, name, [name.name]);
-    } else {
+    } else if (!nameScope.shouldIgnoreUndefined(name)) {
       errorReporter.reportErrorForNode(nonTypeError, name, [name.name]);
     }
     return null;
diff --git a/pkg/analyzer/lib/src/generated/source.dart b/pkg/analyzer/lib/src/generated/source.dart
index bdaf9d9..2d0acf5d 100644
--- a/pkg/analyzer/lib/src/generated/source.dart
+++ b/pkg/analyzer/lib/src/generated/source.dart
@@ -184,19 +184,19 @@
    * A list containing the offsets of the first character of each line in the
    * source code.
    */
-  final List<int> _lineStarts;
+  final List<int> lineStarts;
 
   /**
-   * The zero-based [_lineStarts] index resulting from the last call to
+   * The zero-based [lineStarts] index resulting from the last call to
    * [getLocation].
    */
   int _previousLine = 0;
 
   /**
    * Initialize a newly created set of line information to represent the data
-   * encoded in the given list of [_lineStarts].
+   * encoded in the given list of [lineStarts].
    */
-  factory LineInfo(List<int> _lineStarts) => new LineInfoWithCount(_lineStarts);
+  factory LineInfo(List<int> lineStarts) => new LineInfoWithCount(lineStarts);
 
   /**
    * Initialize a newly created set of line information corresponding to the
@@ -207,12 +207,12 @@
 
   /**
    * Initialize a newly created set of line information to represent the data
-   * encoded in the given list of [_lineStarts].
+   * encoded in the given list of [lineStarts].
    */
-  LineInfo._(this._lineStarts) {
-    if (_lineStarts == null) {
+  LineInfo._(this.lineStarts) {
+    if (lineStarts == null) {
       throw new IllegalArgumentException("lineStarts must be non-null");
-    } else if (_lineStarts.length < 1) {
+    } else if (lineStarts.length < 1) {
       throw new IllegalArgumentException("lineStarts must be non-empty");
     }
   }
@@ -220,26 +220,26 @@
   /**
    * The number of lines.
    */
-  int get lineCount => _lineStarts.length;
+  int get lineCount => lineStarts.length;
 
   /**
    * Return the location information for the character at the given [offset].
    */
   LineInfo_Location getLocation(int offset) {
     var min = 0;
-    var max = _lineStarts.length - 1;
+    var max = lineStarts.length - 1;
 
     // Subsequent calls to [getLocation] are often for offsets near each other.
     // To take advantage of that, we cache the index of the line start we found
     // when this was last called. If the current offset is on that line or
     // later, we'll skip those early indices completely when searching.
-    if (offset >= _lineStarts[_previousLine]) {
+    if (offset >= lineStarts[_previousLine]) {
       min = _previousLine;
 
       // Before kicking off a full binary search, do a quick check here to see
       // if the new offset is on that exact line.
-      if (min == _lineStarts.length - 1 || offset < _lineStarts[min + 1]) {
-        return new LineInfo_Location(min + 1, offset - _lineStarts[min] + 1);
+      if (min == lineStarts.length - 1 || offset < lineStarts[min + 1]) {
+        return new LineInfo_Location(min + 1, offset - lineStarts[min] + 1);
       }
     }
 
@@ -247,7 +247,7 @@
     while (min < max) {
       var midpoint = (max - min + 1) ~/ 2 + min;
 
-      if (_lineStarts[midpoint] > offset) {
+      if (lineStarts[midpoint] > offset) {
         max = midpoint - 1;
       } else {
         min = midpoint;
@@ -256,7 +256,7 @@
 
     _previousLine = min;
 
-    return new LineInfo_Location(min + 1, offset - _lineStarts[min] + 1);
+    return new LineInfo_Location(min + 1, offset - lineStarts[min] + 1);
   }
 
   /**
@@ -268,7 +268,7 @@
       throw new ArgumentError(
           'Invalid line number: $lineNumber; must be between 0 and ${lineCount - 1}');
     }
-    return _lineStarts[lineNumber];
+    return lineStarts[lineNumber];
   }
 }
 
@@ -310,14 +310,9 @@
 class LineInfoWithCount extends LineInfo {
   /**
    * Initialize a newly created set of line information to represent the data
-   * encoded in the given list of [_lineStarts].
+   * encoded in the given list of [lineStarts].
    */
-  LineInfoWithCount(List<int> _lineStarts) : super._(_lineStarts);
-
-  /**
-   * Return the number of lines in the file.
-   */
-  int get lineCount => _lineStarts.length;
+  LineInfoWithCount(List<int> lineStarts) : super._(lineStarts);
 }
 
 /**
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index fa82560..6875c97 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -131,29 +131,15 @@
       }
 
       List<ParameterElement> parameters = node.parameterElements;
-
       {
-        List<DartType> normalParameterTypes = functionType.normalParameterTypes;
-        int normalCount = normalParameterTypes.length;
-        Iterable<ParameterElement> required = parameters
-            .where((p) => p.parameterKind == ParameterKind.REQUIRED)
-            .take(normalCount);
-        int index = 0;
-        for (ParameterElementImpl p in required) {
-          inferType(p, normalParameterTypes[index++]);
-        }
-      }
-
-      {
-        List<DartType> optionalParameterTypes =
-            functionType.optionalParameterTypes;
-        int optionalCount = optionalParameterTypes.length;
-        Iterable<ParameterElement> optional = parameters
-            .where((p) => p.parameterKind == ParameterKind.POSITIONAL)
-            .take(optionalCount);
-        int index = 0;
-        for (ParameterElementImpl p in optional) {
-          inferType(p, optionalParameterTypes[index++]);
+        Iterator<ParameterElement> positional = parameters
+            .where((p) => p.parameterKind != ParameterKind.NAMED)
+            .iterator;
+        Iterator<ParameterElement> fnPositional = functionType.parameters
+            .where((p) => p.parameterKind != ParameterKind.NAMED)
+            .iterator;
+        while (positional.moveNext() && fnPositional.moveNext()) {
+          inferType(positional.current, fnPositional.current.type);
         }
       }
 
@@ -518,7 +504,13 @@
     // * BlockFunctionBody, if we inferred a type from yield/return.
     // * we also normalize bottom to dynamic here.
     if (_strongMode && (computedType.isBottom || computedType.isDynamic)) {
-      computedType = InferenceContext.getType(body) ?? _dynamicType;
+      DartType contextType = InferenceContext.getContext(body);
+      if (contextType is FutureUnionType) {
+        // TODO(jmesserly): can we do something better here?
+        computedType = body.isAsynchronous ? contextType.type : _dynamicType;
+      } else {
+        computedType = contextType ?? _dynamicType;
+      }
       recordInference = !computedType.isDynamic;
     }
 
@@ -1697,6 +1689,7 @@
         visitedClasses.remove(element);
       }
     }
+
     if (type is InterfaceType) {
       _find(type);
     }
@@ -1983,8 +1976,17 @@
         }
       }
 
-      return ts.inferGenericFunctionCall(_typeProvider, fnType, paramTypes,
-          argTypes, InferenceContext.getType(node));
+      DartType returnContext = InferenceContext.getContext(node);
+      DartType returnType;
+      if (returnContext is FutureUnionType) {
+        returnType = fnType.returnType.isDartAsyncFuture
+            ? returnContext.futureOfType
+            : returnContext.type;
+      } else {
+        returnType = returnContext as DartType;
+      }
+      return ts.inferGenericFunctionCall(
+          _typeProvider, fnType, paramTypes, argTypes, returnType);
     }
     return null;
   }
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart
index 78d246f..6fcb63b 100644
--- a/pkg/analyzer/lib/src/generated/type_system.dart
+++ b/pkg/analyzer/lib/src/generated/type_system.dart
@@ -15,7 +15,9 @@
 import 'package:analyzer/src/generated/engine.dart'
     show AnalysisContext, AnalysisOptionsImpl;
 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
-import 'package:analyzer/src/generated/utilities_dart.dart';
+import 'package:analyzer/src/generated/utilities_dart.dart' show ParameterKind;
+import 'package:analyzer/src/generated/utilities_general.dart'
+    show JenkinsSmiHash;
 
 typedef bool _GuardedSubtypeChecker<T>(T t1, T t2, Set<Element> visited);
 
@@ -282,23 +284,6 @@
     var inferringTypeSystem =
         new _StrongInferenceTypeSystem(typeProvider, this, fnType.typeFormals);
 
-    // Special case inference for Future.then.
-    //
-    // We don't have union types, so Future<T>.then<S> is typed to take a
-    // callback `T -> S`. However, the lambda might actually return a
-    // Future<S>. So we handle that special case here.
-    if (argumentTypes.isNotEmpty && argumentTypes[0] is FunctionType) {
-      Element element = fnType?.element;
-      bool isFutureThen = element is MethodElement &&
-          element.name == 'then' &&
-          element.enclosingElement.type.isDartAsyncFuture;
-      if (isFutureThen) {
-        // Ignore return context. We'll let the onValue function's return type
-        // drive inference.
-        returnContextType = null;
-      }
-    }
-
     if (returnContextType != null) {
       inferringTypeSystem.isSubtypeOf(fnType.returnType, returnContextType);
     }
@@ -751,8 +736,8 @@
       return true;
     }
 
-    // The types are void, dynamic, bottom, interface types, function types
-    // and type parameters.  We proceed by eliminating these different classes
+    // The types are void, dynamic, bottom, interface types, function types,
+    // and type parameters. We proceed by eliminating these different classes
     // from consideration.
 
     // Trivially true.
@@ -1340,6 +1325,28 @@
 }
 
 /// Tracks upper and lower type bounds for a set of type parameters.
+///
+/// This class is used by calling [isSubtypeOf]. When it encounters one of
+/// the type parameters it is inferring, it will record the constraint, and
+/// optimistically assume the constraint will be satisfied.
+///
+/// For example if we are inferring type parameter A, and we ask if
+/// `A <: num`, this will record that A must be a subytpe of `num`. It also
+/// handles cases when A appears as part of the structure of another type, for
+/// example `Iterable<A> <: Iterable<num>` would infer the same constraint
+/// (due to covariant generic types) as would `() -> A <: () -> num`. In
+/// contrast `(A) -> void <: (num) -> void`.
+///
+/// Once the lower/upper bounds are determined, [_infer] should be called to
+/// finish the inference. It will instantiate a generic function type with the
+/// inferred types for each type parameter.
+///
+/// It can also optionally compute a partial solution, in case some of the type
+/// parameters could not be inferred (because the constraints cannot be
+/// satisfied), or bail on the inference when this happens.
+///
+/// As currently designed, an instance of this class should only be used to
+/// infer a single call and discarded immediately afterwards.
 class _StrongInferenceTypeSystem extends StrongTypeSystemImpl {
   final TypeProvider _typeProvider;
 
@@ -1578,6 +1585,100 @@
   }
 }
 
+/**
+ * A special union type of `Future<T> | T` used for Strong Mode inference.
+ */
+class FutureUnionType extends TypeImpl {
+  // TODO(jmesserly): a Set would be better.
+  //
+  // For now we know `Future<T> | T` is the only valid use, so we can rely on
+  // the order, which simplifies some things.
+  //
+  // This will need clean up before this can function as a real union type.
+  final List<DartType> _types;
+
+  /**
+   * Creates a union of `Future< flatten(T) > | flatten(T)`.
+   */
+  factory FutureUnionType(
+      DartType type, TypeProvider provider, TypeSystem system) {
+    type = type.flattenFutures(system);
+
+    // The order of these types is important: T could be a type variable, so
+    // we want to try and match `Future<T>` before we try and match `T`.
+    return new FutureUnionType._([
+      provider.futureType.instantiate([type]),
+      type
+    ]);
+  }
+
+  FutureUnionType._(this._types) : super(null, null);
+
+  DartType get futureOfType => _types[0];
+
+  DartType get type => _types[1];
+
+  Iterable<DartType> get types => _types;
+
+  @override
+  void appendTo(StringBuffer buffer) {
+    buffer.write('(');
+    for (int i = 0; i < _types.length; i++) {
+      if (i != 0) {
+        buffer.write(' | ');
+      }
+      (_types[i] as TypeImpl).appendTo(buffer);
+    }
+    buffer.write(')');
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    for (var t in types) {
+      hash = JenkinsSmiHash.combine(hash, t.hashCode);
+    }
+    return JenkinsSmiHash.finish(hash);
+  }
+
+  @override
+  bool operator ==(Object obj) {
+    if (obj is FutureUnionType) {
+      if (identical(obj, this)) return true;
+      return types.length == obj.types.length &&
+          types.toSet().containsAll(obj.types);
+    }
+    return false;
+  }
+
+  @override
+  bool isMoreSpecificThan(DartType type,
+          [bool withDynamic = false, Set<Element> visitedElements]) =>
+      throw new UnsupportedError(
+          'Future unions are not part of the Dart 1 type system');
+
+  @override
+  TypeImpl pruned(List<FunctionTypeAliasElement> prune) =>
+      throw new UnsupportedError('Future unions are not substituted');
+
+  @override
+  DartType substitute2(List<DartType> args, List<DartType> params,
+          [List<FunctionTypeAliasElement> prune]) =>
+      throw new UnsupportedError('Future unions are not used in typedefs');
+
+  /**
+   * Creates a union of `T | Future<T>`, unless `T` is already a future-union,
+   * in which case it simply returns `T`
+   */
+  static DartType from(
+      DartType type, TypeProvider provider, TypeSystem system) {
+    if (type is FutureUnionType) {
+      return type;
+    }
+    return new FutureUnionType(type, provider, system);
+  }
+}
+
 bool _isBottom(DartType t, {bool dynamicIsBottom: false}) {
   return (t.isDynamic && dynamicIsBottom) || t.isBottom;
 }
diff --git a/pkg/analyzer/lib/src/summary/format.dart b/pkg/analyzer/lib/src/summary/format.dart
index bc4d0ab..626f443 100644
--- a/pkg/analyzer/lib/src/summary/format.dart
+++ b/pkg/analyzer/lib/src/summary/format.dart
@@ -2099,6 +2099,7 @@
 
 class PackageBundleBuilder extends Object with _PackageBundleMixin implements idl.PackageBundle {
   String _apiSignature;
+  List<PackageDependencyInfoBuilder> _dependencies;
   List<LinkedLibraryBuilder> _linkedLibraries;
   List<String> _linkedLibraryUris;
   int _majorVersion;
@@ -2120,6 +2121,16 @@
   }
 
   @override
+  List<PackageDependencyInfoBuilder> get dependencies => _dependencies ??= <PackageDependencyInfoBuilder>[];
+
+  /**
+   * Information about the packages this package depends on, if known.
+   */
+  void set dependencies(List<PackageDependencyInfoBuilder> _value) {
+    _dependencies = _value;
+  }
+
+  @override
   List<LinkedLibraryBuilder> get linkedLibraries => _linkedLibraries ??= <LinkedLibraryBuilder>[];
 
   /**
@@ -2195,8 +2206,9 @@
     _unlinkedUnitUris = _value;
   }
 
-  PackageBundleBuilder({String apiSignature, List<LinkedLibraryBuilder> linkedLibraries, List<String> linkedLibraryUris, int majorVersion, int minorVersion, List<String> unlinkedUnitHashes, List<UnlinkedUnitBuilder> unlinkedUnits, List<String> unlinkedUnitUris})
+  PackageBundleBuilder({String apiSignature, List<PackageDependencyInfoBuilder> dependencies, List<LinkedLibraryBuilder> linkedLibraries, List<String> linkedLibraryUris, int majorVersion, int minorVersion, List<String> unlinkedUnitHashes, List<UnlinkedUnitBuilder> unlinkedUnits, List<String> unlinkedUnitUris})
     : _apiSignature = apiSignature,
+      _dependencies = dependencies,
       _linkedLibraries = linkedLibraries,
       _linkedLibraryUris = linkedLibraryUris,
       _majorVersion = majorVersion,
@@ -2209,6 +2221,7 @@
    * Flush [informative] data recursively.
    */
   void flushInformative() {
+    _dependencies = null;
     _linkedLibraries?.forEach((b) => b.flushInformative());
     _unlinkedUnitHashes = null;
     _unlinkedUnits?.forEach((b) => b.flushInformative());
@@ -2262,6 +2275,7 @@
 
   fb.Offset finish(fb.Builder fbBuilder) {
     fb.Offset offset_apiSignature;
+    fb.Offset offset_dependencies;
     fb.Offset offset_linkedLibraries;
     fb.Offset offset_linkedLibraryUris;
     fb.Offset offset_unlinkedUnitHashes;
@@ -2270,6 +2284,9 @@
     if (_apiSignature != null) {
       offset_apiSignature = fbBuilder.writeString(_apiSignature);
     }
+    if (!(_dependencies == null || _dependencies.isEmpty)) {
+      offset_dependencies = fbBuilder.writeList(_dependencies.map((b) => b.finish(fbBuilder)).toList());
+    }
     if (!(_linkedLibraries == null || _linkedLibraries.isEmpty)) {
       offset_linkedLibraries = fbBuilder.writeList(_linkedLibraries.map((b) => b.finish(fbBuilder)).toList());
     }
@@ -2289,6 +2306,9 @@
     if (offset_apiSignature != null) {
       fbBuilder.addOffset(7, offset_apiSignature);
     }
+    if (offset_dependencies != null) {
+      fbBuilder.addOffset(8, offset_dependencies);
+    }
     if (offset_linkedLibraries != null) {
       fbBuilder.addOffset(0, offset_linkedLibraries);
     }
@@ -2333,6 +2353,7 @@
   _PackageBundleImpl(this._bc, this._bcOffset);
 
   String _apiSignature;
+  List<idl.PackageDependencyInfo> _dependencies;
   List<idl.LinkedLibrary> _linkedLibraries;
   List<String> _linkedLibraryUris;
   int _majorVersion;
@@ -2348,6 +2369,12 @@
   }
 
   @override
+  List<idl.PackageDependencyInfo> get dependencies {
+    _dependencies ??= const fb.ListReader<idl.PackageDependencyInfo>(const _PackageDependencyInfoReader()).vTableGet(_bc, _bcOffset, 8, const <idl.PackageDependencyInfo>[]);
+    return _dependencies;
+  }
+
+  @override
   List<idl.LinkedLibrary> get linkedLibraries {
     _linkedLibraries ??= const fb.ListReader<idl.LinkedLibrary>(const _LinkedLibraryReader()).vTableGet(_bc, _bcOffset, 0, const <idl.LinkedLibrary>[]);
     return _linkedLibraries;
@@ -2395,6 +2422,7 @@
   Map<String, Object> toJson() {
     Map<String, Object> _result = <String, Object>{};
     if (apiSignature != '') _result["apiSignature"] = apiSignature;
+    if (dependencies.isNotEmpty) _result["dependencies"] = dependencies.map((_value) => _value.toJson()).toList();
     if (linkedLibraries.isNotEmpty) _result["linkedLibraries"] = linkedLibraries.map((_value) => _value.toJson()).toList();
     if (linkedLibraryUris.isNotEmpty) _result["linkedLibraryUris"] = linkedLibraryUris;
     if (majorVersion != 0) _result["majorVersion"] = majorVersion;
@@ -2408,6 +2436,7 @@
   @override
   Map<String, Object> toMap() => {
     "apiSignature": apiSignature,
+    "dependencies": dependencies,
     "linkedLibraries": linkedLibraries,
     "linkedLibraryUris": linkedLibraryUris,
     "majorVersion": majorVersion,
@@ -2421,6 +2450,212 @@
   String toString() => convert.JSON.encode(toJson());
 }
 
+class PackageDependencyInfoBuilder extends Object with _PackageDependencyInfoMixin implements idl.PackageDependencyInfo {
+  String _apiSignature;
+  List<String> _includedPackageNames;
+  bool _includesDartUris;
+  bool _includesFileUris;
+  String _summaryPath;
+
+  @override
+  String get apiSignature => _apiSignature ??= '';
+
+  /**
+   * API signature of this dependency.
+   */
+  void set apiSignature(String _value) {
+    _apiSignature = _value;
+  }
+
+  @override
+  List<String> get includedPackageNames => _includedPackageNames ??= <String>[];
+
+  /**
+   * If this dependency summarizes any files whose URI takes the form
+   * "package:<package_name>/...", a list of all such package names, sorted
+   * lexicographically.  Otherwise empty.
+   */
+  void set includedPackageNames(List<String> _value) {
+    _includedPackageNames = _value;
+  }
+
+  @override
+  bool get includesDartUris => _includesDartUris ??= false;
+
+  /**
+   * Indicates whether this dependency summarizes any files whose URI takes the
+   * form "dart:...".
+   */
+  void set includesDartUris(bool _value) {
+    _includesDartUris = _value;
+  }
+
+  @override
+  bool get includesFileUris => _includesFileUris ??= false;
+
+  /**
+   * Indicates whether this dependency summarizes any files whose URI takes the
+   * form "file:...".
+   */
+  void set includesFileUris(bool _value) {
+    _includesFileUris = _value;
+  }
+
+  @override
+  String get summaryPath => _summaryPath ??= '';
+
+  /**
+   * Relative path to the summary file for this dependency.  This is intended as
+   * a hint to help the analysis server locate summaries of dependencies.  We
+   * don't specify precisely what this path is relative to, but we expect it to
+   * be relative to a directory the analysis server can find (e.g. for projects
+   * built using Bazel, it would be relative to the "bazel-bin" directory).
+   *
+   * Absent if the path is not known.
+   */
+  void set summaryPath(String _value) {
+    _summaryPath = _value;
+  }
+
+  PackageDependencyInfoBuilder({String apiSignature, List<String> includedPackageNames, bool includesDartUris, bool includesFileUris, String summaryPath})
+    : _apiSignature = apiSignature,
+      _includedPackageNames = includedPackageNames,
+      _includesDartUris = includesDartUris,
+      _includesFileUris = includesFileUris,
+      _summaryPath = summaryPath;
+
+  /**
+   * Flush [informative] data recursively.
+   */
+  void flushInformative() {
+  }
+
+  /**
+   * Accumulate non-[informative] data into [signature].
+   */
+  void collectApiSignature(api_sig.ApiSignature signature) {
+    signature.addString(this._apiSignature ?? '');
+    signature.addString(this._summaryPath ?? '');
+    if (this._includedPackageNames == null) {
+      signature.addInt(0);
+    } else {
+      signature.addInt(this._includedPackageNames.length);
+      for (var x in this._includedPackageNames) {
+        signature.addString(x);
+      }
+    }
+    signature.addBool(this._includesFileUris == true);
+    signature.addBool(this._includesDartUris == true);
+  }
+
+  fb.Offset finish(fb.Builder fbBuilder) {
+    fb.Offset offset_apiSignature;
+    fb.Offset offset_includedPackageNames;
+    fb.Offset offset_summaryPath;
+    if (_apiSignature != null) {
+      offset_apiSignature = fbBuilder.writeString(_apiSignature);
+    }
+    if (!(_includedPackageNames == null || _includedPackageNames.isEmpty)) {
+      offset_includedPackageNames = fbBuilder.writeList(_includedPackageNames.map((b) => fbBuilder.writeString(b)).toList());
+    }
+    if (_summaryPath != null) {
+      offset_summaryPath = fbBuilder.writeString(_summaryPath);
+    }
+    fbBuilder.startTable();
+    if (offset_apiSignature != null) {
+      fbBuilder.addOffset(0, offset_apiSignature);
+    }
+    if (offset_includedPackageNames != null) {
+      fbBuilder.addOffset(2, offset_includedPackageNames);
+    }
+    if (_includesDartUris == true) {
+      fbBuilder.addBool(4, true);
+    }
+    if (_includesFileUris == true) {
+      fbBuilder.addBool(3, true);
+    }
+    if (offset_summaryPath != null) {
+      fbBuilder.addOffset(1, offset_summaryPath);
+    }
+    return fbBuilder.endTable();
+  }
+}
+
+class _PackageDependencyInfoReader extends fb.TableReader<_PackageDependencyInfoImpl> {
+  const _PackageDependencyInfoReader();
+
+  @override
+  _PackageDependencyInfoImpl createObject(fb.BufferContext bc, int offset) => new _PackageDependencyInfoImpl(bc, offset);
+}
+
+class _PackageDependencyInfoImpl extends Object with _PackageDependencyInfoMixin implements idl.PackageDependencyInfo {
+  final fb.BufferContext _bc;
+  final int _bcOffset;
+
+  _PackageDependencyInfoImpl(this._bc, this._bcOffset);
+
+  String _apiSignature;
+  List<String> _includedPackageNames;
+  bool _includesDartUris;
+  bool _includesFileUris;
+  String _summaryPath;
+
+  @override
+  String get apiSignature {
+    _apiSignature ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 0, '');
+    return _apiSignature;
+  }
+
+  @override
+  List<String> get includedPackageNames {
+    _includedPackageNames ??= const fb.ListReader<String>(const fb.StringReader()).vTableGet(_bc, _bcOffset, 2, const <String>[]);
+    return _includedPackageNames;
+  }
+
+  @override
+  bool get includesDartUris {
+    _includesDartUris ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 4, false);
+    return _includesDartUris;
+  }
+
+  @override
+  bool get includesFileUris {
+    _includesFileUris ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 3, false);
+    return _includesFileUris;
+  }
+
+  @override
+  String get summaryPath {
+    _summaryPath ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 1, '');
+    return _summaryPath;
+  }
+}
+
+abstract class _PackageDependencyInfoMixin implements idl.PackageDependencyInfo {
+  @override
+  Map<String, Object> toJson() {
+    Map<String, Object> _result = <String, Object>{};
+    if (apiSignature != '') _result["apiSignature"] = apiSignature;
+    if (includedPackageNames.isNotEmpty) _result["includedPackageNames"] = includedPackageNames;
+    if (includesDartUris != false) _result["includesDartUris"] = includesDartUris;
+    if (includesFileUris != false) _result["includesFileUris"] = includesFileUris;
+    if (summaryPath != '') _result["summaryPath"] = summaryPath;
+    return _result;
+  }
+
+  @override
+  Map<String, Object> toMap() => {
+    "apiSignature": apiSignature,
+    "includedPackageNames": includedPackageNames,
+    "includesDartUris": includesDartUris,
+    "includesFileUris": includesFileUris,
+    "summaryPath": summaryPath,
+  };
+
+  @override
+  String toString() => convert.JSON.encode(toJson());
+}
+
 class PackageIndexBuilder extends Object with _PackageIndexMixin implements idl.PackageIndex {
   List<idl.IndexSyntheticElementKind> _elementKinds;
   List<int> _elementNameClassMemberIds;
@@ -8406,6 +8641,7 @@
   String _libraryName;
   int _libraryNameLength;
   int _libraryNameOffset;
+  List<int> _lineStarts;
   List<UnlinkedPartBuilder> _parts;
   UnlinkedPublicNamespaceBuilder _publicNamespace;
   List<UnlinkedReferenceBuilder> _references;
@@ -8544,6 +8780,17 @@
   }
 
   @override
+  List<int> get lineStarts => _lineStarts ??= <int>[];
+
+  /**
+   * Offsets of the first character of each line in the source code.
+   */
+  void set lineStarts(List<int> _value) {
+    assert(_value == null || _value.every((e) => e >= 0));
+    _lineStarts = _value;
+  }
+
+  @override
   List<UnlinkedPartBuilder> get parts => _parts ??= <UnlinkedPartBuilder>[];
 
   /**
@@ -8597,7 +8844,7 @@
     _variables = _value;
   }
 
-  UnlinkedUnitBuilder({List<UnlinkedClassBuilder> classes, CodeRangeBuilder codeRange, List<UnlinkedEnumBuilder> enums, List<UnlinkedExecutableBuilder> executables, List<UnlinkedExportNonPublicBuilder> exports, String fallbackModePath, List<UnlinkedImportBuilder> imports, List<UnlinkedConstBuilder> libraryAnnotations, UnlinkedDocumentationCommentBuilder libraryDocumentationComment, String libraryName, int libraryNameLength, int libraryNameOffset, List<UnlinkedPartBuilder> parts, UnlinkedPublicNamespaceBuilder publicNamespace, List<UnlinkedReferenceBuilder> references, List<UnlinkedTypedefBuilder> typedefs, List<UnlinkedVariableBuilder> variables})
+  UnlinkedUnitBuilder({List<UnlinkedClassBuilder> classes, CodeRangeBuilder codeRange, List<UnlinkedEnumBuilder> enums, List<UnlinkedExecutableBuilder> executables, List<UnlinkedExportNonPublicBuilder> exports, String fallbackModePath, List<UnlinkedImportBuilder> imports, List<UnlinkedConstBuilder> libraryAnnotations, UnlinkedDocumentationCommentBuilder libraryDocumentationComment, String libraryName, int libraryNameLength, int libraryNameOffset, List<int> lineStarts, List<UnlinkedPartBuilder> parts, UnlinkedPublicNamespaceBuilder publicNamespace, List<UnlinkedReferenceBuilder> references, List<UnlinkedTypedefBuilder> typedefs, List<UnlinkedVariableBuilder> variables})
     : _classes = classes,
       _codeRange = codeRange,
       _enums = enums,
@@ -8610,6 +8857,7 @@
       _libraryName = libraryName,
       _libraryNameLength = libraryNameLength,
       _libraryNameOffset = libraryNameOffset,
+      _lineStarts = lineStarts,
       _parts = parts,
       _publicNamespace = publicNamespace,
       _references = references,
@@ -8630,6 +8878,7 @@
     _libraryDocumentationComment = null;
     _libraryNameLength = null;
     _libraryNameOffset = null;
+    _lineStarts = null;
     _parts?.forEach((b) => b.flushInformative());
     _publicNamespace?.flushInformative();
     _references?.forEach((b) => b.flushInformative());
@@ -8743,6 +8992,7 @@
     fb.Offset offset_libraryAnnotations;
     fb.Offset offset_libraryDocumentationComment;
     fb.Offset offset_libraryName;
+    fb.Offset offset_lineStarts;
     fb.Offset offset_parts;
     fb.Offset offset_publicNamespace;
     fb.Offset offset_references;
@@ -8778,6 +9028,9 @@
     if (_libraryName != null) {
       offset_libraryName = fbBuilder.writeString(_libraryName);
     }
+    if (!(_lineStarts == null || _lineStarts.isEmpty)) {
+      offset_lineStarts = fbBuilder.writeListUint32(_lineStarts);
+    }
     if (!(_parts == null || _parts.isEmpty)) {
       offset_parts = fbBuilder.writeList(_parts.map((b) => b.finish(fbBuilder)).toList());
     }
@@ -8830,6 +9083,9 @@
     if (_libraryNameOffset != null && _libraryNameOffset != 0) {
       fbBuilder.addUint32(8, _libraryNameOffset);
     }
+    if (offset_lineStarts != null) {
+      fbBuilder.addOffset(17, offset_lineStarts);
+    }
     if (offset_parts != null) {
       fbBuilder.addOffset(11, offset_parts);
     }
@@ -8879,6 +9135,7 @@
   String _libraryName;
   int _libraryNameLength;
   int _libraryNameOffset;
+  List<int> _lineStarts;
   List<idl.UnlinkedPart> _parts;
   idl.UnlinkedPublicNamespace _publicNamespace;
   List<idl.UnlinkedReference> _references;
@@ -8958,6 +9215,12 @@
   }
 
   @override
+  List<int> get lineStarts {
+    _lineStarts ??= const fb.Uint32ListReader().vTableGet(_bc, _bcOffset, 17, const <int>[]);
+    return _lineStarts;
+  }
+
+  @override
   List<idl.UnlinkedPart> get parts {
     _parts ??= const fb.ListReader<idl.UnlinkedPart>(const _UnlinkedPartReader()).vTableGet(_bc, _bcOffset, 11, const <idl.UnlinkedPart>[]);
     return _parts;
@@ -9004,6 +9267,7 @@
     if (libraryName != '') _result["libraryName"] = libraryName;
     if (libraryNameLength != 0) _result["libraryNameLength"] = libraryNameLength;
     if (libraryNameOffset != 0) _result["libraryNameOffset"] = libraryNameOffset;
+    if (lineStarts.isNotEmpty) _result["lineStarts"] = lineStarts;
     if (parts.isNotEmpty) _result["parts"] = parts.map((_value) => _value.toJson()).toList();
     if (publicNamespace != null) _result["publicNamespace"] = publicNamespace.toJson();
     if (references.isNotEmpty) _result["references"] = references.map((_value) => _value.toJson()).toList();
@@ -9026,6 +9290,7 @@
     "libraryName": libraryName,
     "libraryNameLength": libraryNameLength,
     "libraryNameOffset": libraryNameOffset,
+    "lineStarts": lineStarts,
     "parts": parts,
     "publicNamespace": publicNamespace,
     "references": references,
diff --git a/pkg/analyzer/lib/src/summary/format.fbs b/pkg/analyzer/lib/src/summary/format.fbs
index 1449743..ba46f01 100644
--- a/pkg/analyzer/lib/src/summary/format.fbs
+++ b/pkg/analyzer/lib/src/summary/format.fbs
@@ -1188,6 +1188,11 @@
   apiSignature:string (id: 7);
 
   /**
+   * Information about the packages this package depends on, if known.
+   */
+  dependencies:[PackageDependencyInfo] (id: 8);
+
+  /**
    * Linked libraries.
    */
   linkedLibraries:[LinkedLibrary] (id: 0);
@@ -1228,6 +1233,46 @@
 }
 
 /**
+ * Information about a single dependency of a summary package.
+ */
+table PackageDependencyInfo {
+  /**
+   * API signature of this dependency.
+   */
+  apiSignature:string (id: 0);
+
+  /**
+   * If this dependency summarizes any files whose URI takes the form
+   * "package:<package_name>/...", a list of all such package names, sorted
+   * lexicographically.  Otherwise empty.
+   */
+  includedPackageNames:[string] (id: 2);
+
+  /**
+   * Indicates whether this dependency summarizes any files whose URI takes the
+   * form "dart:...".
+   */
+  includesDartUris:bool (id: 4);
+
+  /**
+   * Indicates whether this dependency summarizes any files whose URI takes the
+   * form "file:...".
+   */
+  includesFileUris:bool (id: 3);
+
+  /**
+   * Relative path to the summary file for this dependency.  This is intended as
+   * a hint to help the analysis server locate summaries of dependencies.  We
+   * don't specify precisely what this path is relative to, but we expect it to
+   * be relative to a directory the analysis server can find (e.g. for projects
+   * built using Bazel, it would be relative to the "bazel-bin" directory).
+   *
+   * Absent if the path is not known.
+   */
+  summaryPath:string (id: 1);
+}
+
+/**
  * Index information about a package.
  */
 table PackageIndex {
@@ -2329,6 +2374,11 @@
   libraryNameOffset:uint (id: 8);
 
   /**
+   * Offsets of the first character of each line in the source code.
+   */
+  lineStarts:[uint] (id: 17);
+
+  /**
    * Part declarations in the compilation unit.
    */
   parts:[UnlinkedPart] (id: 11);
diff --git a/pkg/analyzer/lib/src/summary/idl.dart b/pkg/analyzer/lib/src/summary/idl.dart
index 15f81a7..70b329b 100644
--- a/pkg/analyzer/lib/src/summary/idl.dart
+++ b/pkg/analyzer/lib/src/summary/idl.dart
@@ -658,6 +658,13 @@
   String get apiSignature;
 
   /**
+   * Information about the packages this package depends on, if known.
+   */
+  @Id(8)
+  @informative
+  List<PackageDependencyInfo> get dependencies;
+
+  /**
    * Linked libraries.
    */
   @Id(0)
@@ -706,6 +713,51 @@
 }
 
 /**
+ * Information about a single dependency of a summary package.
+ */
+abstract class PackageDependencyInfo extends base.SummaryClass {
+  /**
+   * API signature of this dependency.
+   */
+  @Id(0)
+  String get apiSignature;
+
+  /**
+   * If this dependency summarizes any files whose URI takes the form
+   * "package:<package_name>/...", a list of all such package names, sorted
+   * lexicographically.  Otherwise empty.
+   */
+  @Id(2)
+  List<String> get includedPackageNames;
+
+  /**
+   * Indicates whether this dependency summarizes any files whose URI takes the
+   * form "dart:...".
+   */
+  @Id(4)
+  bool get includesDartUris;
+
+  /**
+   * Indicates whether this dependency summarizes any files whose URI takes the
+   * form "file:...".
+   */
+  @Id(3)
+  bool get includesFileUris;
+
+  /**
+   * Relative path to the summary file for this dependency.  This is intended as
+   * a hint to help the analysis server locate summaries of dependencies.  We
+   * don't specify precisely what this path is relative to, but we expect it to
+   * be relative to a directory the analysis server can find (e.g. for projects
+   * built using Bazel, it would be relative to the "bazel-bin" directory).
+   *
+   * Absent if the path is not known.
+   */
+  @Id(1)
+  String get summaryPath;
+}
+
+/**
  * Index information about a package.
  */
 @TopLevel('Indx')
@@ -2660,6 +2712,13 @@
   int get libraryNameOffset;
 
   /**
+   * Offsets of the first character of each line in the source code.
+   */
+  @informative
+  @Id(17)
+  List<int> get lineStarts;
+
+  /**
    * Part declarations in the compilation unit.
    */
   @Id(11)
diff --git a/pkg/analyzer/lib/src/summary/package_bundle_reader.dart b/pkg/analyzer/lib/src/summary/package_bundle_reader.dart
index 062ce82..7ea1c1b 100644
--- a/pkg/analyzer/lib/src/summary/package_bundle_reader.dart
+++ b/pkg/analyzer/lib/src/summary/package_bundle_reader.dart
@@ -10,11 +10,13 @@
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
+import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/idl.dart';
 import 'package:analyzer/src/summary/resynthesize.dart';
 import 'package:analyzer/src/task/dart.dart';
 import 'package:analyzer/src/util/fast_uri.dart';
 import 'package:analyzer/task/dart.dart';
+import 'package:analyzer/task/general.dart';
 import 'package:analyzer/task/model.dart';
 import 'package:path/path.dart' as pathos;
 
@@ -196,6 +198,15 @@
           return true;
         }
         return false;
+      } else if (result == LINE_INFO) {
+        UnlinkedUnit unlinkedUnit = _dataStore.unlinkedMap[uriString];
+        List<int> lineStarts = unlinkedUnit.lineStarts;
+        if (lineStarts.isNotEmpty) {
+          LineInfo lineInfo = new LineInfo(lineStarts);
+          entry.setValue(result, lineInfo, TargetedResult.EMPTY_LIST);
+          return true;
+        }
+        return false;
       }
     } else if (target is LibrarySpecificUnit) {
       if (result == CREATED_RESOLVED_UNIT1 ||
@@ -273,6 +284,15 @@
   final List<PackageBundle> bundles = <PackageBundle>[];
 
   /**
+   * List of dependency information for the package bundles in this
+   * [SummaryDataStore], in a form that is ready to store in a newly generated
+   * summary.  Computing this information has nonzero cost, so it is only
+   * recorded if the [SummaryDataStore] is constructed with the argument
+   * `recordDependencies`.  Otherwise `null`.
+   */
+  final List<PackageDependencyInfoBuilder> dependencies;
+
+  /**
    * Map from the URI of a compilation unit to the unlinked summary of that
    * compilation unit.
    */
@@ -288,7 +308,16 @@
    */
   final Map<String, String> uriToSummaryPath = <String, String>{};
 
-  SummaryDataStore(Iterable<String> summaryPaths) {
+  /**
+   * Create a [SummaryDataStore] and populate it with the summaries in
+   * [summaryPaths].  If [recordDependencyInfo] is `true`, record
+   * [PackageDependencyInfo] for each summary, for later access via
+   * [dependencies].
+   */
+  SummaryDataStore(Iterable<String> summaryPaths,
+      {bool recordDependencyInfo: false})
+      : dependencies =
+            recordDependencyInfo ? <PackageDependencyInfoBuilder>[] : null {
     summaryPaths.forEach(_fillMaps);
   }
 
@@ -297,6 +326,29 @@
    */
   void addBundle(String path, PackageBundle bundle) {
     bundles.add(bundle);
+    if (dependencies != null) {
+      Set<String> includedPackageNames = new Set<String>();
+      bool includesDartUris = false;
+      bool includesFileUris = false;
+      for (String uriString in bundle.unlinkedUnitUris) {
+        Uri uri = FastUri.parse(uriString);
+        String scheme = uri.scheme;
+        if (scheme == 'package') {
+          List<String> pathSegments = uri.pathSegments;
+          includedPackageNames.add(pathSegments.isEmpty ? '' : pathSegments[0]);
+        } else if (scheme == 'file') {
+          includesFileUris = true;
+        } else if (scheme == 'dart') {
+          includesDartUris = true;
+        }
+      }
+      dependencies.add(new PackageDependencyInfoBuilder(
+          includedPackageNames: includedPackageNames.toList()..sort(),
+          includesDartUris: includesDartUris,
+          includesFileUris: includesFileUris,
+          apiSignature: bundle.apiSignature,
+          summaryPath: path));
+    }
     for (int i = 0; i < bundle.unlinkedUnitUris.length; i++) {
       String uri = bundle.unlinkedUnitUris[i];
       uriToSummaryPath[uri] = path;
diff --git a/pkg/analyzer/lib/src/summary/pub_summary.dart b/pkg/analyzer/lib/src/summary/pub_summary.dart
new file mode 100644
index 0000000..21c074d
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary/pub_summary.dart
@@ -0,0 +1,456 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:collection';
+import 'dart:core' hide Resource;
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/error.dart';
+import 'package:analyzer/src/generated/parser.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/summary/format.dart';
+import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary/link.dart';
+import 'package:analyzer/src/summary/package_bundle_reader.dart'
+    show ResynthesizerResultProvider, SummaryDataStore;
+import 'package:analyzer/src/summary/summarize_ast.dart'
+    show serializeAstUnlinked;
+import 'package:analyzer/src/summary/summarize_elements.dart'
+    show PackageBundleAssembler;
+import 'package:analyzer/src/util/fast_uri.dart';
+import 'package:path/path.dart' as pathos;
+
+/**
+ * A package in the pub cache.
+ */
+class PubPackage {
+  final String name;
+  final Folder libFolder;
+
+  PubPackage(this.name, this.libFolder);
+
+  Folder get folder => libFolder.parent;
+
+  @override
+  int get hashCode => libFolder.hashCode;
+
+  @override
+  bool operator ==(other) {
+    return other is PubPackage && other.libFolder == libFolder;
+  }
+
+  @override
+  String toString() => '($name in $folder)';
+}
+
+/**
+ * Unlinked and linked information about a [PubPackage].
+ */
+class LinkedPubPackage {
+  final PubPackage package;
+  final PackageBundle unlinked;
+  final PackageBundle linked;
+  LinkedPubPackage(this.package, this.unlinked, this.linked);
+}
+
+/**
+ * Class that manages summaries for pub packages.
+ *
+ * The client should call [getLinkedBundles] after creating a new
+ * [AnalysisContext] and configuring its source factory, but before computing
+ * any analysis results.  The returned linked bundles can be used to create and
+ * configure [ResynthesizerResultProvider] for the context.
+ */
+class PubSummaryManager {
+  static const UNLINKED_BUNDLE_FILE_NAME = 'unlinked.ds';
+
+  final ResourceProvider resourceProvider;
+
+  /**
+   * The name of the temporary file that is used for atomic writes.
+   */
+  final String tempFileName;
+
+  /**
+   * The map from [PubPackage]s to their unlinked [PackageBundle]s in the pub
+   * cache.
+   */
+  final Map<PubPackage, PackageBundle> unlinkedBundleMap =
+      new HashMap<PubPackage, PackageBundle>();
+
+  /**
+   * The set of packages to compute unlinked summaries for.
+   */
+  final Set<PubPackage> packagesToComputeUnlinked = new Set<PubPackage>();
+
+  /**
+   * The set of already processed packages, which we have already checked
+   * for their unlinked bundle existence, or scheduled its computing.
+   */
+  final Set<PubPackage> seenPackages = new Set<PubPackage>();
+
+  /**
+   * The [Completer] that completes when computing of all scheduled unlinked
+   * bundles is complete.
+   */
+  Completer _onUnlinkedCompleteCompleter;
+
+  PubSummaryManager(this.resourceProvider, this.tempFileName);
+
+  /**
+   * The [Future] that completes when computing of all scheduled unlinked
+   * bundles is complete.
+   */
+  Future get onUnlinkedComplete {
+    if (packagesToComputeUnlinked.isEmpty) {
+      return new Future.value();
+    }
+    _onUnlinkedCompleteCompleter ??= new Completer();
+    return _onUnlinkedCompleteCompleter.future;
+  }
+
+  /**
+   * Return the [pathos.Context] corresponding to the [resourceProvider].
+   */
+  pathos.Context get pathContext => resourceProvider.pathContext;
+
+  /**
+   * Return the list of linked [LinkedPubPackage]s that can be provided at this
+   * time for a subset of the packages used by the given [context].  If
+   * information about some of the used packages is not available yet, schedule
+   * its computation, so that it might be available later for other contexts
+   * referencing the same packages.
+   */
+  List<LinkedPubPackage> getLinkedBundles(
+      AnalysisContext context, PackageBundle sdkBundle) {
+    Map<PubPackage, PackageBundle> unlinkedBundles =
+        getUnlinkedBundles(context);
+
+    // If no unlinked bundles, there is nothing we can try to link.
+    if (unlinkedBundles.isEmpty) {
+      return <LinkedPubPackage>[];
+    }
+
+    // Create graph nodes for packages.
+    List<_LinkedNode> nodes = <_LinkedNode>[];
+    Map<String, _LinkedNode> uriToNode = <String, _LinkedNode>{};
+    unlinkedBundles.forEach((package, unlinked) {
+      _LinkedNode node = new _LinkedNode(package, unlinked, uriToNode);
+      nodes.add(node);
+      for (String uri in unlinked.unlinkedUnitUris) {
+        uriToNode[uri] = node;
+      }
+    });
+
+    // Fill the store with unlinked bundles.
+    SummaryDataStore store = new SummaryDataStore(const <String>[]);
+    store.addBundle(null, sdkBundle);
+    for (PackageBundle unlinked in unlinkedBundles.values) {
+      store.addBundle(null, unlinked);
+    }
+
+    // Link each package node.
+    for (_LinkedNode node in nodes) {
+      if (!node.isEvaluated) {
+        new _LinkedWalker(store).walk(node);
+      }
+    }
+
+    // Create successfully linked packages.
+    List<LinkedPubPackage> linkedPackages = <LinkedPubPackage>[];
+    for (_LinkedNode node in nodes) {
+      if (node.linkedBuilder != null) {
+        List<int> bytes = node.linkedBuilder.toBuffer();
+        PackageBundle linkedBundle = new PackageBundle.fromBuffer(bytes);
+        linkedPackages.add(
+            new LinkedPubPackage(node.package, node.unlinked, linkedBundle));
+      }
+    }
+
+    // TODO(scheglov) compute dependency hashes and write linked bundles.
+
+    // Done.
+    return linkedPackages;
+  }
+
+  /**
+   * Return all available unlinked [PackageBundle]s for the given [context],
+   * maybe an empty map, but not `null`.
+   */
+  Map<PubPackage, PackageBundle> getUnlinkedBundles(AnalysisContext context) {
+    Map<PubPackage, PackageBundle> unlinkedBundles =
+        new HashMap<PubPackage, PackageBundle>();
+    Map<String, List<Folder>> packageMap = context.sourceFactory.packageMap;
+    if (packageMap != null) {
+      packageMap.forEach((String packageName, List<Folder> libFolders) {
+        if (libFolders.length == 1) {
+          Folder libFolder = libFolders.first;
+          if (isPathInPubCache(pathContext, libFolder.path)) {
+            PubPackage package = new PubPackage(packageName, libFolder);
+            PackageBundle unlinkedBundle = _getUnlinkedOrSchedule(package);
+            if (unlinkedBundle != null) {
+              unlinkedBundles[package] = unlinkedBundle;
+            }
+          }
+        }
+      });
+    }
+    return unlinkedBundles;
+  }
+
+  /**
+   * Compute unlinked bundle for a package from [packagesToComputeUnlinked],
+   * and schedule delayed computation for the next package, if any.
+   */
+  void _computeNextUnlinked() {
+    if (packagesToComputeUnlinked.isNotEmpty) {
+      PubPackage package = packagesToComputeUnlinked.first;
+      _computeUnlinked(package);
+      packagesToComputeUnlinked.remove(package);
+      _scheduleNextUnlinked();
+    } else {
+      if (_onUnlinkedCompleteCompleter != null) {
+        _onUnlinkedCompleteCompleter.complete(true);
+        _onUnlinkedCompleteCompleter = null;
+      }
+    }
+  }
+
+  /**
+   * Compute the unlinked bundle for the package with the given path, put
+   * it in the [unlinkedBundleMap] and store into the [resourceProvider].
+   *
+   * TODO(scheglov) Consider moving into separate isolate(s).
+   */
+  void _computeUnlinked(PubPackage package) {
+    Folder libFolder = package.libFolder;
+    String libPath = libFolder.path + pathContext.separator;
+    PackageBundleAssembler assembler = new PackageBundleAssembler();
+
+    /**
+     * Return the `package` [Uri] for the given [path] in the `lib` folder
+     * of the current package.
+     */
+    Uri getUri(String path) {
+      String pathInLib = path.substring(libPath.length);
+      String uriPath = pathos.posix.joinAll(pathContext.split(pathInLib));
+      String uriStr = 'package:${package.name}/$uriPath';
+      return FastUri.parse(uriStr);
+    }
+
+    /**
+     * If the given [file] is a Dart file, add its unlinked unit.
+     */
+    void addDartFile(File file) {
+      String path = file.path;
+      if (AnalysisEngine.isDartFileName(path)) {
+        Uri uri = getUri(path);
+        Source source = file.createSource(uri);
+        CompilationUnit unit = _parse(source);
+        UnlinkedUnitBuilder unlinkedUnit = serializeAstUnlinked(unit);
+        assembler.addUnlinkedUnit(source, unlinkedUnit);
+      }
+    }
+
+    /**
+     * Visit the [folder] recursively.
+     */
+    void addDartFiles(Folder folder) {
+      List<Resource> children = folder.getChildren();
+      for (Resource child in children) {
+        if (child is File) {
+          addDartFile(child);
+        }
+      }
+      for (Resource child in children) {
+        if (child is Folder) {
+          addDartFiles(child);
+        }
+      }
+    }
+
+    try {
+      addDartFiles(libFolder);
+      List<int> bytes = assembler.assemble().toBuffer();
+      _writeAtomic(package.folder, UNLINKED_BUNDLE_FILE_NAME, bytes);
+    } on FileSystemException {
+      // Ignore file system exceptions.
+    }
+  }
+
+  /**
+   * Return the unlinked [PackageBundle] for the given [package]. If the bundle
+   * has not been compute yet, return `null` and schedule its computation.
+   */
+  PackageBundle _getUnlinkedOrSchedule(PubPackage package) {
+    // Try to find in the cache.
+    PackageBundle bundle = unlinkedBundleMap[package];
+    if (bundle != null) {
+      return bundle;
+    }
+    // Try to read from the file system.
+    File unlinkedFile =
+        package.folder.getChildAssumingFile(UNLINKED_BUNDLE_FILE_NAME);
+    if (unlinkedFile.exists) {
+      try {
+        List<int> bytes = unlinkedFile.readAsBytesSync();
+        bundle = new PackageBundle.fromBuffer(bytes);
+        unlinkedBundleMap[package] = bundle;
+        return bundle;
+      } on FileSystemException {
+        // Ignore file system exceptions.
+      }
+    }
+    // Schedule computation in the background.
+    if (package != null && seenPackages.add(package)) {
+      if (packagesToComputeUnlinked.isEmpty) {
+        _scheduleNextUnlinked();
+      }
+      packagesToComputeUnlinked.add(package);
+    }
+    // The bundle is for available.
+    return null;
+  }
+
+  /**
+   * Parse the given [source] into AST.
+   */
+  CompilationUnit _parse(Source source) {
+    String code = source.contents.data;
+    AnalysisErrorListener errorListener = AnalysisErrorListener.NULL_LISTENER;
+    CharSequenceReader reader = new CharSequenceReader(code);
+    Scanner scanner = new Scanner(source, reader, errorListener);
+    Token token = scanner.tokenize();
+    LineInfo lineInfo = new LineInfo(scanner.lineStarts);
+    Parser parser = new Parser(source, errorListener);
+    CompilationUnit unit = parser.parseCompilationUnit(token);
+    unit.lineInfo = lineInfo;
+    return unit;
+  }
+
+  /**
+   * Schedule delayed computation of the next package unlinked bundle from the
+   * set of [packagesToComputeUnlinked].  We delay each computation because we
+   * want operations in analysis server to proceed, and computing bundles of
+   * packages is a background task.
+   */
+  void _scheduleNextUnlinked() {
+    new Future.delayed(new Duration(milliseconds: 10), _computeNextUnlinked);
+  }
+
+  /**
+   * Atomically write the given [bytes] into the file in the [folder].
+   */
+  void _writeAtomic(Folder folder, String fileName, List<int> bytes) {
+    String filePath = folder.getChildAssumingFile(fileName).path;
+    File tempFile = folder.getChildAssumingFile(tempFileName);
+    tempFile.writeAsBytesSync(bytes);
+    tempFile.renameSync(filePath);
+  }
+
+  /**
+   * Return `true` if the given absolute [path] is in the pub cache.
+   */
+  static bool isPathInPubCache(pathos.Context pathContext, String path) {
+    List<String> parts = pathContext.split(path);
+    for (int i = 0; i < parts.length - 1; i++) {
+      if (parts[i] == '.pub-cache') {
+        return true;
+      }
+      if (parts[i] == 'Pub' && parts[i + 1] == 'Cache') {
+        return true;
+      }
+    }
+    return false;
+  }
+}
+
+/**
+ * Specialization of [Node] for linking packages in proper dependency order.
+ */
+class _LinkedNode extends Node<_LinkedNode> {
+  final PubPackage package;
+  final PackageBundle unlinked;
+  final Map<String, _LinkedNode> uriToNode;
+
+  PackageBundleBuilder linkedBuilder;
+  bool failed = false;
+
+  _LinkedNode(this.package, this.unlinked, this.uriToNode);
+
+  @override
+  bool get isEvaluated => linkedBuilder != null || failed;
+
+  @override
+  List<_LinkedNode> computeDependencies() {
+    Set<String> referencedUris = new Set<String>();
+    for (UnlinkedUnit unit in unlinked.unlinkedUnits) {
+      for (UnlinkedImport import in unit.imports) {
+        String uri = import.isImplicit ? 'dart:core' : import.uri;
+        if (uri.startsWith('dart:')) {
+          // Ignore SDK imports.
+        } else if (uri.startsWith('package:')) {
+          referencedUris.add(uri);
+        } else {
+          failed = true;
+          return const <_LinkedNode>[];
+        }
+      }
+    }
+    // TODO(scheglov) fail if no corresponding node
+    return referencedUris.map((uri) => uriToNode[uri]).toSet().toList();
+  }
+
+  @override
+  String toString() => package.toString();
+}
+
+/**
+ * Specialization of [DependencyWalker] for linking packages.
+ */
+class _LinkedWalker extends DependencyWalker<_LinkedNode> {
+  final SummaryDataStore store;
+
+  _LinkedWalker(this.store);
+
+  @override
+  void evaluate(_LinkedNode v) {
+    Set<String> libraryUris = v.unlinked.unlinkedUnitUris.toSet();
+    Map<String, LinkedLibraryBuilder> map = link(libraryUris, (String absUri) {
+      LinkedLibrary dependencyLibrary = store.linkedMap[absUri];
+      if (dependencyLibrary == null) {
+        // TODO(scheglov) add test
+        v.failed = true;
+      }
+      return dependencyLibrary;
+    }, (String absUri) {
+      UnlinkedUnit unlinkedUnit = store.unlinkedMap[absUri];
+      if (unlinkedUnit == null) {
+        // TODO(scheglov) add test
+        v.failed = true;
+      }
+      return unlinkedUnit;
+    }, false);
+    if (!v.failed) {
+      PackageBundleAssembler assembler = new PackageBundleAssembler();
+      map.forEach((uri, linkedLibrary) {
+        assembler.addLinkedLibrary(uri, linkedLibrary);
+      });
+      v.linkedBuilder = assembler.assemble();
+      store.addBundle(null, v.linkedBuilder);
+    }
+  }
+
+  @override
+  void evaluateScc(List<_LinkedNode> scc) {
+    print('evaluateScc: $scc');
+    // TODO(scheglov): implement evaluateScc
+  }
+}
diff --git a/pkg/analyzer/lib/src/summary/summarize_ast.dart b/pkg/analyzer/lib/src/summary/summarize_ast.dart
index eeaef9d..ec4f609 100644
--- a/pkg/analyzer/lib/src/summary/summarize_ast.dart
+++ b/pkg/analyzer/lib/src/summary/summarize_ast.dart
@@ -511,6 +511,7 @@
     }
     compilationUnit.declarations.accept(this);
     UnlinkedUnitBuilder b = new UnlinkedUnitBuilder();
+    b.lineStarts = compilationUnit.lineInfo?.lineStarts;
     b.libraryName = libraryName;
     b.libraryNameOffset = libraryNameOffset;
     b.libraryNameLength = libraryNameLength;
diff --git a/pkg/analyzer/lib/src/summary/summarize_elements.dart b/pkg/analyzer/lib/src/summary/summarize_elements.dart
index e25da27..e62f408 100644
--- a/pkg/analyzer/lib/src/summary/summarize_elements.dart
+++ b/pkg/analyzer/lib/src/summary/summarize_elements.dart
@@ -19,6 +19,7 @@
 import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/idl.dart';
 import 'package:analyzer/src/summary/name_filter.dart';
+import 'package:analyzer/src/summary/package_bundle_reader.dart';
 import 'package:analyzer/src/summary/summarize_const_expr.dart';
 import 'package:convert/convert.dart';
 import 'package:crypto/crypto.dart';
@@ -138,7 +139,11 @@
   final List<LinkedLibraryBuilder> _linkedLibraries = <LinkedLibraryBuilder>[];
   final List<String> _unlinkedUnitUris = <String>[];
   final List<UnlinkedUnitBuilder> _unlinkedUnits = <UnlinkedUnitBuilder>[];
+  final Map<String, UnlinkedUnitBuilder> _unlinkedUnitMap =
+      <String, UnlinkedUnitBuilder>{};
   final List<String> _unlinkedUnitHashes;
+  final List<PackageDependencyInfoBuilder> _dependencies =
+      <PackageDependencyInfoBuilder>[];
   final bool _excludeHashes;
 
   /**
@@ -167,9 +172,11 @@
    */
   void addFallbackUnit(Source source) {
     String uri = source.uri.toString();
+    UnlinkedUnitBuilder unit = new UnlinkedUnitBuilder(
+        fallbackModePath: path.relative(source.fullName));
     _unlinkedUnitUris.add(uri);
-    _unlinkedUnits.add(new UnlinkedUnitBuilder(
-        fallbackModePath: path.relative(source.fullName)));
+    _unlinkedUnits.add(unit);
+    _unlinkedUnitMap[uri] = unit;
   }
 
   void addLinkedLibrary(String uri, LinkedLibraryBuilder library) {
@@ -186,6 +193,7 @@
       String uri, UnlinkedUnitBuilder unit, String hash) {
     _unlinkedUnitUris.add(uri);
     _unlinkedUnits.add(unit);
+    _unlinkedUnitMap[uri] = unit;
     _unlinkedUnitHashes?.add(hash);
   }
 
@@ -193,18 +201,24 @@
    * Assemble a new [PackageBundleBuilder] using the gathered information.
    */
   PackageBundleBuilder assemble() {
-    PackageBundleBuilder packageBundle = new PackageBundleBuilder(
+    return new PackageBundleBuilder(
         linkedLibraryUris: _linkedLibraryUris,
         linkedLibraries: _linkedLibraries,
         unlinkedUnitUris: _unlinkedUnitUris,
         unlinkedUnits: _unlinkedUnits,
         unlinkedUnitHashes: _unlinkedUnitHashes,
         majorVersion: currentMajorVersion,
-        minorVersion: currentMinorVersion);
-    ApiSignature apiSignature = new ApiSignature();
-    packageBundle.collectApiSignature(apiSignature);
-    packageBundle.apiSignature = apiSignature.toHex();
-    return packageBundle;
+        minorVersion: currentMinorVersion,
+        dependencies: _dependencies,
+        apiSignature: _computeApiSignature());
+  }
+
+  /**
+   * Use the dependency information in [summaryDataStore] to populate the
+   * dependencies in the package bundle being assembled.
+   */
+  void recordDependencies(SummaryDataStore summaryDataStore) {
+    _dependencies.addAll(summaryDataStore.dependencies);
   }
 
   /**
@@ -220,12 +234,28 @@
     _linkedLibraries.add(libraryResult.linked);
     _unlinkedUnitUris.addAll(libraryResult.unitUris);
     _unlinkedUnits.addAll(libraryResult.unlinkedUnits);
+    for (int i = 0; i < libraryResult.unitUris.length; i++) {
+      _unlinkedUnitMap[libraryResult.unitUris[i]] =
+          libraryResult.unlinkedUnits[i];
+    }
     for (Source source in libraryResult.unitSources) {
       _unlinkedUnitHashes?.add(_hash(source.contents.data));
     }
   }
 
   /**
+   * Compute the API signature for this package bundle.
+   */
+  String _computeApiSignature() {
+    ApiSignature apiSignature = new ApiSignature();
+    for (String unitUri in _unlinkedUnitMap.keys.toList()..sort()) {
+      apiSignature.addString(unitUri);
+      _unlinkedUnitMap[unitUri].collectApiSignature(apiSignature);
+    }
+    return apiSignature.toHex();
+  }
+
+  /**
    * Compute a hash of the given file contents.
    */
   String _hash(String contents) {
@@ -450,6 +480,8 @@
     }
     unlinkedUnit.variables = variables;
     unlinkedUnit.references = unlinkedReferences;
+    unlinkedUnit.lineStarts =
+        compilationUnit.context?.computeLineInfo(unitSource)?.lineStarts;
     linkedUnit.references = linkedReferences;
     unitUri = compilationUnit.source.uri.toString();
   }
diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart
index 4ff2448..c8b108b 100644
--- a/pkg/analyzer/lib/src/task/dart.dart
+++ b/pkg/analyzer/lib/src/task/dart.dart
@@ -3248,8 +3248,9 @@
       unit.accept(new Dart2JSVerifier(errorReporter));
     }
     // Dart best practices.
-    InheritanceManager inheritanceManager =
-        new InheritanceManager(libraryElement);
+    InheritanceManager inheritanceManager = new InheritanceManager(
+        libraryElement,
+        includeAbstractFromSuperclasses: true);
     TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
 
     unit.accept(new BestPracticesVerifier(
@@ -6545,8 +6546,10 @@
         int length = imports.length;
         for (int i = 0; i < length; i++) {
           ImportElement importElement = imports[i];
-          Source importedSource = importElement.importedLibrary.source;
-          _newSources.add(importedSource);
+          Source importedSource = importElement.importedLibrary?.source;
+          if (importedSource != null) {
+            _newSources.add(importedSource);
+          }
         }
       }
       if (kind == _SourceClosureKind.EXPORT ||
@@ -6555,8 +6558,10 @@
         int length = exports.length;
         for (int i = 0; i < length; i++) {
           ExportElement exportElement = exports[i];
-          Source exportedSource = exportElement.exportedLibrary.source;
-          _newSources.add(exportedSource);
+          Source exportedSource = exportElement.exportedLibrary?.source;
+          if (exportedSource != null) {
+            _newSources.add(exportedSource);
+          }
         }
       }
     }
diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart
index b20d702..ab1922f 100644
--- a/pkg/analyzer/lib/src/task/strong/checker.dart
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart
@@ -21,22 +21,31 @@
 
 import 'ast_properties.dart';
 
-bool isKnownFunction(Expression expression, {bool instanceMethods: false}) {
-  Element element = null;
+bool isKnownFunction(Expression expression) {
+  var element = _getKnownElement(expression);
+  // First class functions and static methods, where we know the original
+  // declaration, will have an exact type, so we know a downcast will fail.
+  return element is FunctionElement ||
+      element is MethodElement && element.isStatic;
+}
+
+bool _hasStrictArrow(Expression expression) {
+  var element = _getKnownElement(expression);
+  return element is FunctionElement || element is MethodElement;
+}
+
+Element _getKnownElement(Expression expression) {
   if (expression is ParenthesizedExpression) {
     expression = (expression as ParenthesizedExpression).expression;
   }
   if (expression is FunctionExpression) {
-    return true;
+    return expression.element;
   } else if (expression is PropertyAccess) {
-    element = expression.propertyName.staticElement;
+    return expression.propertyName.staticElement;
   } else if (expression is Identifier) {
-    element = expression.staticElement;
+    return expression.staticElement;
   }
-  // First class functions and static methods, where we know the original
-  // declaration, will have an exact type, so we know a downcast will fail.
-  return element is FunctionElement ||
-      element is MethodElement && (instanceMethods || element.isStatic);
+  return null;
 }
 
 DartType _elementType(Element e) {
@@ -111,6 +120,7 @@
     if (baseMethod == null || baseMethod.isStatic) return null;
     return baseMethod.type;
   }
+
   return f;
 }
 
@@ -226,14 +236,14 @@
   void visitBinaryExpression(BinaryExpression node) {
     var op = node.operator;
     if (op.isUserDefinableOperator) {
-      if (_isDynamicTarget(node.leftOperand)) {
+      var element = node.staticElement;
+      if (element == null) {
         // Dynamic invocation
         // TODO(vsm): Move this logic to the resolver?
         if (op.type != TokenType.EQ_EQ && op.type != TokenType.BANG_EQ) {
           _recordDynamicInvoke(node, node.leftOperand);
         }
       } else {
-        var element = node.staticElement;
         // Method invocation.
         if (element is MethodElement) {
           var type = element.type;
@@ -426,20 +436,18 @@
   @override
   void visitIndexExpression(IndexExpression node) {
     var target = node.realTarget;
-    if (_isDynamicTarget(target)) {
+    var element = node.staticElement;
+    if (element == null) {
       _recordDynamicInvoke(node, target);
-    } else {
-      var element = node.staticElement;
-      if (element is MethodElement) {
-        var type = element.type;
-        // Analyzer should enforce number of parameter types, but check in
-        // case we have erroneous input.
-        if (type.normalParameterTypes.isNotEmpty) {
-          checkArgument(node.index, type.normalParameterTypes[0]);
-        }
-      } else {
-        // TODO(vsm): Assert that the analyzer found an error here?
+    } else if (element is MethodElement) {
+      var type = element.type;
+      // Analyzer should enforce number of parameter types, but check in
+      // case we have erroneous input.
+      if (type.normalParameterTypes.isNotEmpty) {
+        checkArgument(node.index, type.normalParameterTypes[0]);
       }
+    } else {
+      // TODO(vsm): Assert that the analyzer found an error here?
     }
     node.visitChildren(this);
   }
@@ -523,7 +531,8 @@
   @override
   visitMethodInvocation(MethodInvocation node) {
     var target = node.realTarget;
-    if (_isDynamicTarget(target) && !_isObjectMethod(node, node.methodName)) {
+    var element = node.methodName.staticElement;
+    if (element == null && !_isObjectMethod(node, node.methodName)) {
       _recordDynamicInvoke(node, target);
 
       // Mark the tear-off as being dynamic, too. This lets us distinguish
@@ -548,7 +557,7 @@
 
   @override
   void visitPostfixExpression(PostfixExpression node) {
-    _checkUnary(node);
+    _checkUnary(node, node.staticElement);
     node.visitChildren(this);
   }
 
@@ -562,7 +571,7 @@
     if (node.operator.type == TokenType.BANG) {
       checkBoolean(node.operand);
     } else {
-      _checkUnary(node);
+      _checkUnary(node, node.staticElement);
     }
     node.visitChildren(this);
   }
@@ -751,8 +760,7 @@
   }
 
   void _checkFieldAccess(AstNode node, AstNode target, SimpleIdentifier field) {
-    if ((_isDynamicTarget(target) || field.staticElement == null) &&
-        !_isObjectProperty(target, field)) {
+    if (field.staticElement == null && !_isObjectProperty(target, field)) {
       _recordDynamicInvoke(node, target);
     }
     node.visitChildren(this);
@@ -891,12 +899,13 @@
     }
   }
 
-  void _checkUnary(/*PrefixExpression|PostfixExpression*/ node) {
+  void _checkUnary(
+      /*PrefixExpression|PostfixExpression*/ node, Element element) {
     var op = node.operator;
     if (op.isUserDefinableOperator ||
         op.type == TokenType.PLUS_PLUS ||
         op.type == TokenType.MINUS_MINUS) {
-      if (_isDynamicTarget(node.operand)) {
+      if (element == null) {
         _recordDynamicInvoke(node, node.operand);
       }
       // For ++ and --, even if it is not dynamic, we still need to check
@@ -963,7 +972,7 @@
     DartType t = expr.staticType ?? DynamicTypeImpl.instance;
 
     // Remove fuzzy arrow if possible.
-    if (t is FunctionType && isKnownFunction(expr)) {
+    if (t is FunctionType && _hasStrictArrow(expr)) {
       t = rules.functionTypeToConcreteType(typeProvider, t);
     }
 
@@ -975,7 +984,7 @@
   /// for the possibility of a call method).  Returns null
   /// if expression is not statically callable.
   FunctionType _getTypeAsCaller(Expression node) {
-    DartType t = node.staticType;
+    DartType t = _getStaticType(node);
     if (node is SimpleIdentifier) {
       Expression parent = node.parent;
       if (parent is MethodInvocation) {
@@ -1004,27 +1013,12 @@
     // a dynamic parameter type requires a dynamic call in general.
     // However, as an optimization, if we have an original definition, we know
     // dynamic is reified as Object - in this case a regular call is fine.
-    if (isKnownFunction(call, instanceMethods: true)) {
+    if (_hasStrictArrow(call)) {
       return false;
     }
     return rules.anyParameterType(ft, (pt) => pt.isDynamic);
   }
 
-  /// Returns `true` if the target expression is dynamic.
-  bool _isDynamicTarget(Expression node) {
-    if (node == null) return false;
-
-    if (_isLibraryPrefix(node)) return false;
-
-    // Null type happens when we have unknown identifiers, like a dart: import
-    // that doesn't resolve.
-    var type = node.staticType;
-    return type == null || type.isDynamic;
-  }
-
-  bool _isLibraryPrefix(Expression node) =>
-      node is SimpleIdentifier && node.staticElement is PrefixElement;
-
   bool _isObjectGetter(Expression target, SimpleIdentifier id) {
     PropertyAccessorElement element =
         typeProvider.objectType.element.getGetter(id.name);
@@ -1045,7 +1039,7 @@
     // TODO(jmesserly): we may eventually want to record if the whole operation
     // (node) was dynamic, rather than the target, but this is an easier fit
     // with what we used to do.
-    setIsDynamicInvoke(target, true);
+    if (target != null) setIsDynamicInvoke(target, true);
   }
 
   /// Records an implicit cast for the [expression] from [fromType] to [toType].
@@ -1288,6 +1282,7 @@
         seen.add(e.name);
       }
     }
+
     subType.methods.forEach(checkHelper);
     subType.accessors.forEach(checkHelper);
   }
diff --git a/pkg/analyzer/test/generated/analysis_context_factory.dart b/pkg/analyzer/test/generated/analysis_context_factory.dart
index cca5d3b..f311756 100644
--- a/pkg/analyzer/test/generated/analysis_context_factory.dart
+++ b/pkg/analyzer/test/generated/analysis_context_factory.dart
@@ -97,6 +97,8 @@
     Source coreSource = sourceFactory.forUri(DartSdk.DART_CORE);
     coreContext.setContents(coreSource, "");
     coreUnit.librarySource = coreUnit.source = coreSource;
+    ClassElementImpl overrideClassElement =
+        ElementFactory.classElement2("_Override");
     ClassElementImpl proxyClassElement = ElementFactory.classElement2("_Proxy");
     proxyClassElement.constructors = <ConstructorElement>[
       ElementFactory.constructorElement(proxyClassElement, '', true)
@@ -117,6 +119,7 @@
       provider.nullType.element,
       provider.numType.element,
       objectClassElement,
+      overrideClassElement,
       proxyClassElement,
       provider.stackTraceType.element,
       provider.stringType.element,
@@ -134,6 +137,9 @@
     ConstTopLevelVariableElementImpl deprecatedTopLevelVariableElt =
         ElementFactory.topLevelVariableElement3(
             "deprecated", true, false, provider.deprecatedType);
+    TopLevelVariableElement overrideTopLevelVariableElt =
+        ElementFactory.topLevelVariableElement3(
+            "override", true, false, overrideClassElement.type);
     {
       ClassElement deprecatedElement = provider.deprecatedType.element;
       InstanceCreationExpression initializer = AstFactory
@@ -147,12 +153,14 @@
       deprecatedTopLevelVariableElt.constantInitializer = initializer;
     }
     coreUnit.accessors = <PropertyAccessorElement>[
-      proxyTopLevelVariableElt.getter,
-      deprecatedTopLevelVariableElt.getter
+      deprecatedTopLevelVariableElt.getter,
+      overrideTopLevelVariableElt.getter,
+      proxyTopLevelVariableElt.getter
     ];
     coreUnit.topLevelVariables = <TopLevelVariableElement>[
-      proxyTopLevelVariableElt,
-      deprecatedTopLevelVariableElt
+      deprecatedTopLevelVariableElt,
+      overrideTopLevelVariableElt,
+      proxyTopLevelVariableElt
     ];
     LibraryElementImpl coreLibrary = new LibraryElementImpl.forNode(
         coreContext, AstFactory.libraryIdentifier2(["dart", "core"]));
@@ -233,7 +241,9 @@
           <TypeDefiningElement>[streamElement.typeParameters[0]],
           null);
       listenOnData.synthetic = true;
-      List<DartType> parameterTypes = <DartType>[listenOnData.type,];
+      List<DartType> parameterTypes = <DartType>[
+        listenOnData.type,
+      ];
       // TODO(brianwilkerson) This is missing the optional parameters.
       MethodElementImpl listenMethod =
           ElementFactory.methodElement('listen', returnType, parameterTypes);
diff --git a/pkg/analyzer/test/generated/element_resolver_test.dart b/pkg/analyzer/test/generated/element_resolver_test.dart
index 7ddd33b..aaefc2a 100644
--- a/pkg/analyzer/test/generated/element_resolver_test.dart
+++ b/pkg/analyzer/test/generated/element_resolver_test.dart
@@ -12,6 +12,7 @@
 import 'package:analyzer/src/generated/element_resolver.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/java_core.dart';
+import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/java_engine_io.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/source_io.dart';
@@ -827,6 +828,9 @@
     subclass.constructors = <ConstructorElement>[subConstructor];
     SuperConstructorInvocation invocation =
         AstFactory.superConstructorInvocation();
+    AstFactory.classDeclaration(null, 'C', null, null, null, null, [
+      AstFactory.constructorDeclaration(null, 'C', null, [invocation])
+    ]);
     _resolveInClass(invocation, subclass);
     expect(invocation.staticElement, superConstructor);
     _listener.assertNoErrors();
@@ -849,6 +853,9 @@
         .superConstructorInvocation([
       AstFactory.namedExpression2(parameterName, AstFactory.integer(0))
     ]);
+    AstFactory.classDeclaration(null, 'C', null, null, null, null, [
+      AstFactory.constructorDeclaration(null, 'C', null, [invocation])
+    ]);
     _resolveInClass(invocation, subclass);
     expect(invocation.staticElement, superConstructor);
     expect(
@@ -949,8 +956,9 @@
         _visitor.enclosingClass = null;
         _visitor.nameScope = outerScope;
       }
-    } catch (exception) {
-      throw new IllegalArgumentException("Could not resolve node", exception);
+    } catch (exception, stackTrace) {
+      throw new IllegalArgumentException(
+          "Could not resolve node", new CaughtException(exception, stackTrace));
     }
   }
 
diff --git a/pkg/analyzer/test/generated/hint_code_test.dart b/pkg/analyzer/test/generated/hint_code_test.dart
index 3ff98f7..e14df67 100644
--- a/pkg/analyzer/test/generated/hint_code_test.dart
+++ b/pkg/analyzer/test/generated/hint_code_test.dart
@@ -31,7 +31,6 @@
 const _Factory factory = const _Factory();
 const _Literal literal = const _Literal();
 const _MustCallSuper mustCallSuper = const _MustCallSuper();
-const _Override override = const _Override();
 const _Protected protected = const _Protected();
 const Required required = const Required();
 class Required {
@@ -48,9 +47,6 @@
 class _MustCallSuper {
   const _MustCallSuper();
 }
-class _Override {
-  const _Override();
-}
 class _Protected {
   const _Protected();
 }
@@ -2055,8 +2051,6 @@
 
   void test_overrideOnNonOverridingField_invalid() {
     Source source = addSource(r'''
-library dart.core;
-const override = null;
 class A {
 }
 class B extends A {
@@ -2070,8 +2064,6 @@
 
   void test_overrideOnNonOverridingGetter_invalid() {
     Source source = addSource(r'''
-library dart.core;
-const override = null;
 class A {
 }
 class B extends A {
@@ -2085,8 +2077,6 @@
 
   void test_overrideOnNonOverridingMethod_invalid() {
     Source source = addSource(r'''
-library dart.core;
-const override = null;
 class A {
 }
 class B extends A {
@@ -2100,8 +2090,6 @@
 
   void test_overrideOnNonOverridingSetter_invalid() {
     Source source = addSource(r'''
-library dart.core;
-const override = null;
 class A {
 }
 class B extends A {
diff --git a/pkg/analyzer/test/generated/non_hint_code_test.dart b/pkg/analyzer/test/generated/non_hint_code_test.dart
index 4ec1640..16ba3a9 100644
--- a/pkg/analyzer/test/generated/non_hint_code_test.dart
+++ b/pkg/analyzer/test/generated/non_hint_code_test.dart
@@ -488,8 +488,6 @@
 
   void test_overrideOnNonOverridingField_inInterface() {
     Source source = addSource(r'''
-library dart.core;
-const override = null;
 class A {
   int get a => 0;
   void set b(_) {}
@@ -510,8 +508,6 @@
 
   void test_overrideOnNonOverridingField_inSuperclass() {
     Source source = addSource(r'''
-library dart.core;
-const override = null;
 class A {
   int get a => 0;
   void set b(_) {}
@@ -532,8 +528,6 @@
 
   void test_overrideOnNonOverridingGetter_inInterface() {
     Source source = addSource(r'''
-library dart.core;
-const override = null;
 class A {
   int get m => 0;
 }
@@ -548,8 +542,6 @@
 
   void test_overrideOnNonOverridingGetter_inSuperclass() {
     Source source = addSource(r'''
-library dart.core;
-const override = null;
 class A {
   int get m => 0;
 }
@@ -564,8 +556,6 @@
 
   void test_overrideOnNonOverridingMethod_inInterface() {
     Source source = addSource(r'''
-library dart.core;
-const override = null;
 class A {
   int m() => 0;
 }
@@ -580,8 +570,6 @@
 
   void test_overrideOnNonOverridingMethod_inSuperclass() {
     Source source = addSource(r'''
-library dart.core;
-const override = null;
 class A {
   int m() => 0;
 }
@@ -594,10 +582,22 @@
     verify([source]);
   }
 
+  void test_overrideOnNonOverridingMethod_inSuperclass_abstract() {
+    Source source = addSource(r'''
+abstract class A {
+  int m();
+}
+class B extends A {
+  @override
+  int m() => 1;
+}''');
+    computeLibrarySourceErrors(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
   void test_overrideOnNonOverridingSetter_inInterface() {
     Source source = addSource(r'''
-library dart.core;
-const override = null;
 class A {
   set m(int x) {}
 }
@@ -612,8 +612,6 @@
 
   void test_overrideOnNonOverridingSetter_inSuperclass() {
     Source source = addSource(r'''
-library dart.core;
-const override = null;
 class A {
   set m(int x) {}
 }
diff --git a/pkg/analyzer/test/generated/simple_resolver_test.dart b/pkg/analyzer/test/generated/simple_resolver_test.dart
index fcd3a5f..dedab71 100644
--- a/pkg/analyzer/test/generated/simple_resolver_test.dart
+++ b/pkg/analyzer/test/generated/simple_resolver_test.dart
@@ -26,59 +26,6 @@
 
 @reflectiveTest
 class SimpleResolverTest extends ResolverTestCase {
-  void fail_getter_and_setter_fromMixins_property_access() {
-    // TODO(paulberry): it appears that auxiliaryElements isn't properly set on
-    // a SimpleIdentifier that's inside a property access.  This bug should be
-    // fixed.
-    Source source = addSource('''
-class B {}
-class M1 {
-  get x => null;
-  set x(value) {}
-}
-class M2 {
-  get x => null;
-  set x(value) {}
-}
-class C extends B with M1, M2 {}
-void main() {
-  new C().x += 1;
-}
-''');
-    LibraryElement library = resolve2(source);
-    assertNoErrors(source);
-    verify([source]);
-    // Verify that both the getter and setter for "x" in "new C().x" refer to
-    // the accessors defined in M2.
-    FunctionDeclaration main =
-        library.definingCompilationUnit.functions[0].computeNode();
-    BlockFunctionBody body = main.functionExpression.body;
-    ExpressionStatement stmt = body.block.statements[0];
-    AssignmentExpression assignment = stmt.expression;
-    PropertyAccess propertyAccess = assignment.leftHandSide;
-    expect(
-        propertyAccess.propertyName.staticElement.enclosingElement.name, 'M2');
-    expect(
-        propertyAccess
-            .propertyName.auxiliaryElements.staticElement.enclosingElement.name,
-        'M2');
-  }
-
-  void fail_staticInvocation() {
-    Source source = addSource(r'''
-class A {
-  static int get g => (a,b) => 0;
-}
-class B {
-  f() {
-    A.g(1,0);
-  }
-}''');
-    computeLibrarySourceErrors(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
   void test_argumentResolution_required_matching() {
     Source source = addSource(r'''
 class A {
@@ -791,6 +738,45 @@
         'M2');
   }
 
+  @failingTest
+  void test_getter_and_setter_fromMixins_property_access() {
+    // TODO(paulberry): it appears that auxiliaryElements isn't properly set on
+    // a SimpleIdentifier that's inside a property access.  This bug should be
+    // fixed.
+    Source source = addSource('''
+class B {}
+class M1 {
+  get x => null;
+  set x(value) {}
+}
+class M2 {
+  get x => null;
+  set x(value) {}
+}
+class C extends B with M1, M2 {}
+void main() {
+  new C().x += 1;
+}
+''');
+    LibraryElement library = resolve2(source);
+    assertNoErrors(source);
+    verify([source]);
+    // Verify that both the getter and setter for "x" in "new C().x" refer to
+    // the accessors defined in M2.
+    FunctionDeclaration main =
+        library.definingCompilationUnit.functions[0].computeNode();
+    BlockFunctionBody body = main.functionExpression.body;
+    ExpressionStatement stmt = body.block.statements[0];
+    AssignmentExpression assignment = stmt.expression;
+    PropertyAccess propertyAccess = assignment.leftHandSide;
+    expect(
+        propertyAccess.propertyName.staticElement.enclosingElement.name, 'M2');
+    expect(
+        propertyAccess
+            .propertyName.auxiliaryElements.staticElement.enclosingElement.name,
+        'M2');
+  }
+
   void test_getter_fromMixins_bare_identifier() {
     Source source = addSource('''
 class B {}
@@ -926,6 +912,66 @@
     verify([source]);
   }
 
+  void test_import_prefix_doesNotExist() {
+    //
+    // The primary purpose of this test is to ensure that we are only getting a
+    // single error generated when the only problem is that an imported file
+    // does not exist.
+    //
+    Source source = addNamedSource(
+        "/a.dart",
+        r'''
+import 'missing.dart' as p;
+int a = p.q + p.r.s;
+String b = p.t(a) + p.u(v: 0);
+p.T c = new p.T();
+class D<E> extends p.T {
+  D(int i) : super(i);
+  p.U f = new p.V();
+}
+class F implements p.T {
+  p.T m(p.U u) => null;
+}
+class G extends Object with p.V {}
+class H extends D<p.W> {
+  H(int i) : super(i);
+}
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [CompileTimeErrorCode.URI_DOES_NOT_EXIST]);
+    verify([source]);
+  }
+
+  void test_import_show_doesNotExist() {
+    //
+    // The primary purpose of this test is to ensure that we are only getting a
+    // single error generated when the only problem is that an imported file
+    // does not exist.
+    //
+    Source source = addNamedSource(
+        "/a.dart",
+        r'''
+import 'missing.dart' show q, r, t, u, T, U, V, W;
+int a = q + r.s;
+String b = t(a) + u(v: 0);
+T c = new T();
+class D<E> extends T {
+  D(int i) : super(i);
+  U f = new V();
+}
+class F implements T {
+  T m(U u) => null;
+}
+class G extends Object with V {}
+class H extends D<W> {
+  H(int i) : super(i);
+}
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [CompileTimeErrorCode.URI_DOES_NOT_EXIST]);
+    verify([source]);
+  }
+
   void test_import_spaceInUri() {
     addNamedSource(
         "/sub folder/lib.dart",
@@ -1679,6 +1725,22 @@
     verify([source]);
   }
 
+  @failingTest
+  void test_staticInvocation() {
+    Source source = addSource(r'''
+class A {
+  static int get g => (a,b) => 0;
+}
+class B {
+  f() {
+    A.g(1,0);
+  }
+}''');
+    computeLibrarySourceErrors(source);
+    assertNoErrors(source);
+    verify([source]);
+  }
+
   /**
    * Resolve the given source and verify that the arguments in a specific method invocation were
    * correctly resolved.
diff --git a/pkg/analyzer/test/generated/strong_mode_test.dart b/pkg/analyzer/test/generated/strong_mode_test.dart
index 6c5879f..2949909 100644
--- a/pkg/analyzer/test/generated/strong_mode_test.dart
+++ b/pkg/analyzer/test/generated/strong_mode_test.dart
@@ -121,9 +121,7 @@
     check("f2", _isFutureOfDynamic);
 
     check("f3", _isFutureOfInt);
-    // This should be int when we handle the implicit Future<T> | T union
-    // https://github.com/dart-lang/sdk/issues/25322
-    check("f4", _isFutureOfDynamic);
+    check("f4", _isFutureOfInt);
     check("f5", _isFutureOfInt);
 
     check("g0", _isFutureOfDynamic);
@@ -131,9 +129,7 @@
     check("g2", _isFutureOfDynamic);
 
     check("g3", _isFutureOfInt);
-    // This should be int when we handle the implicit Future<T> | T union
-    // https://github.com/dart-lang/sdk/issues/25322
-    check("g4", _isFutureOfDynamic);
+    check("g4", _isFutureOfInt);
     check("g5", _isFutureOfInt);
   }
 
@@ -181,9 +177,7 @@
     check("f2", _isFutureOfDynamic);
 
     check("f3", _isFutureOfInt);
-    // This should be int when we handle the implicit Future<T> | T union
-    // https://github.com/dart-lang/sdk/issues/25322
-    check("f4", _isFutureOfDynamic);
+    check("f4", _isFutureOfInt);
     check("f5", _isFutureOfInt);
 
     check("g0", _isFutureOfDynamic);
@@ -191,9 +185,7 @@
     check("g2", _isFutureOfDynamic);
 
     check("g3", _isFutureOfInt);
-    // This should be int when we handle the implicit Future<T> | T union
-    // https://github.com/dart-lang/sdk/issues/25322
-    check("g4", _isFutureOfDynamic);
+    check("g4", _isFutureOfInt);
     check("g5", _isFutureOfInt);
   }
 
diff --git a/pkg/analyzer/test/src/context/abstract_context.dart b/pkg/analyzer/test/src/context/abstract_context.dart
index be85eff..ba11f84 100644
--- a/pkg/analyzer/test/src/context/abstract_context.dart
+++ b/pkg/analyzer/test/src/context/abstract_context.dart
@@ -123,7 +123,7 @@
     return new AnalysisContextImpl();
   }
 
-  DartSdk createDartSdk() => new MockSdk();
+  DartSdk createDartSdk() => new MockSdk(resourceProvider: resourceProvider);
 
   Source newSource(String path, [String content = '']) {
     File file = resourceProvider.newFile(path, content);
@@ -143,8 +143,8 @@
     sdk = createDartSdk();
     sdkResolver = new DartUriResolver(sdk);
     resourceResolver = new ResourceUriResolver(resourceProvider);
-    sourceFactory =
-        new SourceFactory(<UriResolver>[sdkResolver, resourceResolver]);
+    sourceFactory = new SourceFactory(
+        <UriResolver>[sdkResolver, resourceResolver], null, resourceProvider);
     context = createAnalysisContext();
     if (options != null) {
       context.analysisOptions = options;
diff --git a/pkg/analyzer/test/src/context/context_test.dart b/pkg/analyzer/test/src/context/context_test.dart
index 988db56..b005734 100644
--- a/pkg/analyzer/test/src/context/context_test.dart
+++ b/pkg/analyzer/test/src/context/context_test.dart
@@ -155,6 +155,43 @@
     expect(entry.explicitlyAdded, isTrue);
   }
 
+  void test_applyChanges_addNewImport_invalidateLibraryCycle() {
+    context.analysisOptions =
+        new AnalysisOptionsImpl.from(context.analysisOptions)
+          ..strongMode = true;
+    Source embedder = addSource(
+        '/a.dart',
+        r'''
+library a;
+import 'b.dart';
+//import 'c.dart';
+''');
+    addSource(
+        '/b.dart',
+        r'''
+library b;
+import 'a.dart';
+''');
+    addSource(
+        '/c.dart',
+        r'''
+library c;
+import 'b.dart';
+''');
+    _performPendingAnalysisTasks();
+    // Add a new import into a.dart, this should invalidate its library cycle.
+    // If it doesn't, we will get a task cycle exception.
+    context.setContents(
+        embedder,
+        r'''
+library a;
+import 'b.dart';
+import 'c.dart';
+''');
+    _performPendingAnalysisTasks();
+    expect(context.getCacheEntry(embedder).exception, isNull);
+  }
+
   Future test_applyChanges_change() {
     SourcesChangedListener listener = new SourcesChangedListener();
     context.onSourcesChanged.listen(listener.onData);
@@ -378,7 +415,7 @@
     expect(sources[0], same(libA));
     libAElement = context.computeLibraryElement(libA);
     importedLibraries = libAElement.importedLibraries;
-    expect(importedLibraries, hasLength(1));
+    expect(importedLibraries, hasLength(2));
     return pumpEventQueue().then((_) {
       listener.assertEvent(wereSourcesAdded: true);
       listener.assertEvent(wereSourcesAdded: true);
@@ -487,43 +524,6 @@
     expect(context.getErrors(a).errors, hasLength(0));
   }
 
-  void test_applyChanges_addNewImport_invalidateLibraryCycle() {
-    context.analysisOptions =
-        new AnalysisOptionsImpl.from(context.analysisOptions)
-          ..strongMode = true;
-    Source embedder = addSource(
-        '/a.dart',
-        r'''
-library a;
-import 'b.dart';
-//import 'c.dart';
-''');
-    addSource(
-        '/b.dart',
-        r'''
-library b;
-import 'a.dart';
-''');
-    addSource(
-        '/c.dart',
-        r'''
-library c;
-import 'b.dart';
-''');
-    _performPendingAnalysisTasks();
-    // Add a new import into a.dart, this should invalidate its library cycle.
-    // If it doesn't, we will get a task cycle exception.
-    context.setContents(
-        embedder,
-        r'''
-library a;
-import 'b.dart';
-import 'c.dart';
-''');
-    _performPendingAnalysisTasks();
-    expect(context.getCacheEntry(embedder).exception, isNull);
-  }
-
   void test_cacheConsistencyValidator_computed_deleted() {
     CacheConsistencyValidator validator = context.cacheConsistencyValidator;
     var stat = PerformanceStatistics.cacheConsistencyValidationStatistics;
@@ -3750,6 +3750,7 @@
       MethodInvocation invocation = statement.expression;
       return invocation.argumentList.arguments[0];
     }
+
     {
       Expression argument = find42();
       expect(argument.staticParameterElement, isNull);
diff --git a/pkg/analyzer/test/src/context/mock_sdk.dart b/pkg/analyzer/test/src/context/mock_sdk.dart
index 6539e67..0ebc01f 100644
--- a/pkg/analyzer/test/src/context/mock_sdk.dart
+++ b/pkg/analyzer/test/src/context/mock_sdk.dart
@@ -29,7 +29,7 @@
 
   static Future<List/*<T>*/> wait/*<T>*/(
       Iterable<Future/*<T>*/> futures) => null;
-  Future/*<R>*/ then/*<R>*/(/*=R*/ onValue(T value)) => null;
+  Future/*<R>*/ then/*<R>*/(onValue(T value)) => null;
 }
 
 abstract class Completer<T> {
@@ -194,6 +194,10 @@
 
   /*=R*/ fold/*<R>*/(/*=R*/ initialValue,
       /*=R*/ combine(/*=R*/ previousValue, E element));
+
+  Iterable/*<T>*/ expand/*<T>*/(Iterable/*<T>*/ f(E element));
+
+  List<E> toList();
 }
 
 class List<E> implements Iterable<E> {
@@ -224,6 +228,9 @@
 
 void print(Object object) {}
 
+const proxy = const _Proxy();
+class _Proxy { const _Proxy(); }
+
 class _Override {
   const _Override();
 }
@@ -298,8 +305,7 @@
     "dart:core": "/lib/core/core.dart",
   };
 
-  final resource.MemoryResourceProvider provider =
-      new resource.MemoryResourceProvider();
+  final resource.MemoryResourceProvider provider;
 
   final Map<String, String> uriMap;
 
@@ -311,8 +317,9 @@
   @override
   final List<SdkLibrary> sdkLibraries;
 
-  MockSdk({bool dartAsync: true})
-      : sdkLibraries = dartAsync ? _LIBRARIES : [_LIB_CORE],
+  MockSdk({bool dartAsync: true, resource.ResourceProvider resourceProvider})
+      : provider = resourceProvider ?? new resource.MemoryResourceProvider(),
+        sdkLibraries = dartAsync ? _LIBRARIES : [_LIB_CORE],
         uriMap = dartAsync ? FULL_URI_MAP : NO_ASYNC_URI_MAP {
     for (_MockSdkLibrary library in sdkLibraries) {
       provider.newFile(library.path, library.content);
diff --git a/pkg/analyzer/test/src/summary/linker_test.dart b/pkg/analyzer/test/src/summary/linker_test.dart
index 196fb04..eb9e407 100644
--- a/pkg/analyzer/test/src/summary/linker_test.dart
+++ b/pkg/analyzer/test/src/summary/linker_test.dart
@@ -61,6 +61,42 @@
     expect(bundle0.apiSignature, bundle1.apiSignature);
   }
 
+  void test_apiSignature_orderChange() {
+    // A change to the order in which files are processed should not affect the
+    // API signature.
+    addNamedSource('/a.dart', 'class A {}');
+    var bundle0 = createPackageBundle('class B {}', path: '/b.dart');
+    addNamedSource('/b.dart', 'class B {}');
+    var bundle1 = createPackageBundle('class A {}', path: '/a.dart');
+    expect(bundle0.apiSignature, isNotEmpty);
+    expect(bundle1.apiSignature, isNotEmpty);
+    expect(bundle0.apiSignature, bundle1.apiSignature);
+  }
+
+  void test_apiSignature_unlinkedOnly() {
+    // The API signature of a package bundle should only contain unlinked
+    // information.  In this test, the linked information for bundle2 and
+    // bundle3 refer to class C as existing in different files.  But the
+    // unlinked information for bundle2 and bundle3 should be the same, so their
+    // API signatures should be the same.
+    addNamedSource('/a.dart', 'class C {}');
+    var bundle0 = createPackageBundle('', path: '/b.dart');
+    addNamedSource('/a.dart', '');
+    var bundle1 = createPackageBundle('class C {}', path: '/b.dart');
+    var text = '''
+import 'a.dart';
+import 'b.dart';
+class D extends C {}
+''';
+    addBundle('/bundle0.ds', bundle0);
+    var bundle2 = createPackageBundle(text, path: '/c.dart');
+    addBundle('/bundle1.ds', bundle1);
+    var bundle3 = createPackageBundle(text, path: '/c.dart');
+    expect(bundle2.apiSignature, isNotEmpty);
+    expect(bundle3.apiSignature, isNotEmpty);
+    expect(bundle2.apiSignature, bundle3.apiSignature);
+  }
+
   void test_baseClass_genericWithAccessor() {
     createLinker('''
 class B<T> {
@@ -159,6 +195,33 @@
     // No assertions--just make sure it doesn't crash.
   }
 
+  void test_bundle_refers_to_bundle() {
+    var bundle1 = createPackageBundle(
+        '''
+var x = 0;
+''',
+        path: '/a.dart');
+    addBundle('/a.ds', bundle1);
+    var bundle2 = createPackageBundle(
+        '''
+import "a.dart";
+var y = x;
+''',
+        path: '/b.dart');
+    expect(bundle2.dependencies, hasLength(1));
+    expect(bundle2.dependencies[0].summaryPath, '/a.ds');
+    expect(bundle2.dependencies[0].apiSignature, bundle1.apiSignature);
+    addBundle('/a.ds', bundle1);
+    addBundle('/b.ds', bundle2);
+    createLinker('''
+import "b.dart";
+var z = y;
+''');
+    LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri);
+    expect(_getVariable(library.getContainedName('z')).inferredType.toString(),
+        'int');
+  }
+
   void test_constCycle_viaLength() {
     createLinker('''
 class C {
@@ -206,7 +269,7 @@
 var x = () {};
 ''',
         path: '/a.dart');
-    addBundle(bundle);
+    addBundle('/a.ds', bundle);
     createLinker('''
 import 'a.dart';
 var y = x;
@@ -228,7 +291,7 @@
 class E {}
 ''',
         path: '/a.dart');
-    addBundle(bundle);
+    addBundle('/a.ds', bundle);
     createLinker('''
 import 'a.dart';
 var y = C.x;
@@ -341,7 +404,7 @@
 var y = x; // Inferred type: dynamic
 ''',
         path: '/a.dart');
-    addBundle(bundle);
+    addBundle('/a.ds', bundle);
     createLinker('''
 import 'a.dart';
 var z = y; // Inferred type: dynamic
@@ -359,7 +422,7 @@
 }
 ''',
         path: '/a.dart');
-    addBundle(bundle);
+    addBundle('/a.ds', bundle);
     createLinker('''
 import 'a.dart';
 var x = new C().f; // Inferred type: int
@@ -377,7 +440,7 @@
 }
 ''',
         path: '/a.dart');
-    addBundle(bundle);
+    addBundle('/a.ds', bundle);
     createLinker('''
 import 'a.dart';
 class D {
@@ -400,7 +463,7 @@
 }
 ''',
         path: '/a.dart');
-    addBundle(bundle);
+    addBundle('/a.ds', bundle);
     createLinker('''
 import 'a.dart';
 var x = new C().f(0); // Inferred type: int
@@ -421,7 +484,7 @@
 }
 ''',
         path: '/a.dart');
-    addBundle(bundle);
+    addBundle('/a.ds', bundle);
     createLinker('''
 import 'a.dart';
 class D extends C {
@@ -448,7 +511,7 @@
 }
 ''',
         path: '/a.dart');
-    addBundle(bundle);
+    addBundle('/a.ds', bundle);
     createLinker('''
 import 'a.dart';
 var x = new C().f(); // Inferred type: int
@@ -469,7 +532,7 @@
 }
 ''',
         path: '/a.dart');
-    addBundle(bundle);
+    addBundle('/a.ds', bundle);
     createLinker('''
 import 'a.dart';
 class D extends C {
@@ -486,7 +549,7 @@
   void test_inferredTypeFromOutsideBuildUnit_staticField() {
     var bundle =
         createPackageBundle('class C { static var f = 0; }', path: '/a.dart');
-    addBundle(bundle);
+    addBundle('/a.ds', bundle);
     createLinker('import "a.dart"; var x = C.f;', path: '/b.dart');
     expect(
         _getVariable(linker
@@ -499,7 +562,7 @@
 
   void test_inferredTypeFromOutsideBuildUnit_topLevelVariable() {
     var bundle = createPackageBundle('var a = 0;', path: '/a.dart');
-    addBundle(bundle);
+    addBundle('/a.ds', bundle);
     createLinker('import "a.dart"; var b = a;', path: '/b.dart');
     expect(
         _getVariable(linker
@@ -670,7 +733,7 @@
         ref.localIndex = 1234;
       }
     }
-    addBundle(bundle);
+    addBundle('/a.ds', bundle);
     createLinker('''
 import 'a.dart';
 var y = x;
diff --git a/pkg/analyzer/test/src/summary/package_bundle_reader_test.dart b/pkg/analyzer/test/src/summary/package_bundle_reader_test.dart
index e446d19..07ce00f 100644
--- a/pkg/analyzer/test/src/summary/package_bundle_reader_test.dart
+++ b/pkg/analyzer/test/src/summary/package_bundle_reader_test.dart
@@ -10,6 +10,7 @@
 import 'package:analyzer/src/task/dart.dart';
 import 'package:analyzer/src/util/fast_uri.dart';
 import 'package:analyzer/task/dart.dart';
+import 'package:analyzer/task/general.dart';
 import 'package:typed_mock/typed_mock.dart';
 import 'package:unittest/unittest.dart';
 
@@ -92,6 +93,19 @@
     expect(entry2.getValue(CONTAINING_LIBRARIES), unorderedEquals([source1]));
   }
 
+  test_compute_LINE_INFO_hasLineStarts() {
+    when(unlinkedUnit1.lineStarts).thenReturn(<int>[10, 20, 30]);
+    bool success = provider.compute(entry1, LINE_INFO);
+    expect(success, isTrue);
+    expect(entry1.getValue(LINE_INFO).lineStarts, <int>[10, 20, 30]);
+  }
+
+  test_compute_LINE_INFO_emptyLineStarts() {
+    when(unlinkedUnit1.lineStarts).thenReturn(<int>[]);
+    bool success = provider.compute(entry1, LINE_INFO);
+    expect(success, isFalse);
+  }
+
   test_compute_SOURCE_KIND_librarySource() {
     bool success = provider.compute(entry1, SOURCE_KIND);
     expect(success, isTrue);
@@ -113,7 +127,8 @@
 
 @reflectiveTest
 class SummaryDataStoreTest {
-  SummaryDataStore dataStore = new SummaryDataStore(<String>[]);
+  SummaryDataStore dataStore =
+      new SummaryDataStore(<String>[], recordDependencyInfo: true);
 
   PackageBundle bundle1 = new _PackageBundleMock();
   PackageBundle bundle2 = new _PackageBundleMock();
@@ -134,6 +149,7 @@
         .thenReturn(<UnlinkedUnit>[unlinkedUnit11, unlinkedUnit12]);
     when(bundle1.linkedLibraryUris).thenReturn(<String>['package:p1/u1.dart']);
     when(bundle1.linkedLibraries).thenReturn(<LinkedLibrary>[linkedLibrary1]);
+    when(bundle1.apiSignature).thenReturn('signature1');
     dataStore.addBundle('/p1.ds', bundle1);
     // bundle2
     when(unlinkedUnit21.publicNamespace).thenReturn(_namespaceWithParts([]));
@@ -141,11 +157,22 @@
     when(bundle2.unlinkedUnits).thenReturn(<UnlinkedUnit>[unlinkedUnit21]);
     when(bundle2.linkedLibraryUris).thenReturn(<String>['package:p2/u1.dart']);
     when(bundle2.linkedLibraries).thenReturn(<LinkedLibrary>[linkedLibrary2]);
+    when(bundle2.apiSignature).thenReturn('signature2');
     dataStore.addBundle('/p2.ds', bundle2);
   }
 
   test_addBundle() {
     expect(dataStore.bundles, unorderedEquals([bundle1, bundle2]));
+    expect(dataStore.dependencies[0].summaryPath, '/p1.ds');
+    expect(dataStore.dependencies[0].apiSignature, 'signature1');
+    expect(dataStore.dependencies[0].includedPackageNames, ['p1']);
+    expect(dataStore.dependencies[0].includesFileUris, false);
+    expect(dataStore.dependencies[0].includesDartUris, false);
+    expect(dataStore.dependencies[1].summaryPath, '/p2.ds');
+    expect(dataStore.dependencies[1].apiSignature, 'signature2');
+    expect(dataStore.dependencies[1].includedPackageNames, ['p2']);
+    expect(dataStore.dependencies[1].includesFileUris, false);
+    expect(dataStore.dependencies[1].includesDartUris, false);
     expect(dataStore.uriToSummaryPath,
         containsPair('package:p1/u1.dart', '/p1.ds'));
     // unlinkedMap
@@ -164,6 +191,47 @@
         containsPair('package:p2/u1.dart', linkedLibrary2));
   }
 
+  test_addBundle_dartUris() {
+    PackageBundle bundle = new _PackageBundleMock();
+    when(bundle.unlinkedUnitUris).thenReturn(<String>['dart:core']);
+    when(bundle.unlinkedUnits).thenReturn(<UnlinkedUnit>[unlinkedUnit11]);
+    when(bundle.linkedLibraryUris).thenReturn(<String>['dart:core']);
+    when(bundle.linkedLibraries).thenReturn(<LinkedLibrary>[linkedLibrary1]);
+    when(bundle.apiSignature).thenReturn('signature');
+    dataStore.addBundle('/p3.ds', bundle);
+    expect(dataStore.dependencies.last.includedPackageNames, []);
+    expect(dataStore.dependencies.last.includesFileUris, false);
+    expect(dataStore.dependencies.last.includesDartUris, true);
+  }
+
+  test_addBundle_fileUris() {
+    PackageBundle bundle = new _PackageBundleMock();
+    when(bundle.unlinkedUnitUris).thenReturn(<String>['file:/foo.dart']);
+    when(bundle.unlinkedUnits).thenReturn(<UnlinkedUnit>[unlinkedUnit11]);
+    when(bundle.linkedLibraryUris).thenReturn(<String>['file:/foo.dart']);
+    when(bundle.linkedLibraries).thenReturn(<LinkedLibrary>[linkedLibrary1]);
+    when(bundle.apiSignature).thenReturn('signature');
+    dataStore.addBundle('/p3.ds', bundle);
+    expect(dataStore.dependencies.last.includedPackageNames, []);
+    expect(dataStore.dependencies.last.includesFileUris, true);
+    expect(dataStore.dependencies.last.includesDartUris, false);
+  }
+
+  test_addBundle_multiProject() {
+    PackageBundle bundle = new _PackageBundleMock();
+    when(bundle.unlinkedUnitUris)
+        .thenReturn(<String>['package:p2/u1.dart', 'package:p1/u1.dart']);
+    when(bundle.unlinkedUnits)
+        .thenReturn(<UnlinkedUnit>[unlinkedUnit21, unlinkedUnit11]);
+    when(bundle.linkedLibraryUris)
+        .thenReturn(<String>['package:p2/u1.dart', 'package:p1/u1.dart']);
+    when(bundle.linkedLibraries)
+        .thenReturn(<LinkedLibrary>[linkedLibrary2, linkedLibrary1]);
+    when(bundle.apiSignature).thenReturn('signature');
+    dataStore.addBundle('/p3.ds', bundle);
+    expect(dataStore.dependencies.last.includedPackageNames, ['p1', 'p2']);
+  }
+
   test_getContainingLibraryUris_libraryUri() {
     String partUri = 'package:p1/u1.dart';
     List<String> uris = dataStore.getContainingLibraryUris(partUri);
diff --git a/pkg/analyzer/test/src/summary/pub_summary_test.dart b/pkg/analyzer/test/src/summary/pub_summary_test.dart
new file mode 100644
index 0000000..acc22cc
--- /dev/null
+++ b/pkg/analyzer/test/src/summary/pub_summary_test.dart
@@ -0,0 +1,261 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/source/package_map_resolver.dart';
+import 'package:analyzer/src/generated/sdk.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary/pub_summary.dart';
+import 'package:analyzer/src/summary/summarize_elements.dart';
+import 'package:path/path.dart' as pathos;
+import 'package:unittest/unittest.dart' hide ERROR;
+
+import '../../reflective_tests.dart';
+import '../../utils.dart';
+import '../context/abstract_context.dart';
+
+main() {
+  initializeTestEnvironment();
+  runReflectiveTests(PubSummaryManagerTest);
+}
+
+@reflectiveTest
+class PubSummaryManagerTest extends AbstractContextTest {
+  static const String CACHE = '/home/.pub-cache/hosted/pub.dartlang.org';
+
+  static Map<DartSdk, PackageBundle> sdkBundleMap = <DartSdk, PackageBundle>{};
+
+  PubSummaryManager manager;
+
+  void setUp() {
+    super.setUp();
+    manager = new PubSummaryManager(resourceProvider, '_.temp');
+  }
+
+  test_getLinkedBundles_noCycles() async {
+    resourceProvider.newFile(
+        '$CACHE/aaa/lib/a.dart',
+        '''
+class A {}
+int a;
+''');
+    resourceProvider.newFile(
+        '$CACHE/bbb/lib/b.dart',
+        '''
+import 'package:aaa/a.dart';
+A b;
+''');
+
+    // Configure packages resolution.
+    Folder libFolderA = resourceProvider.newFolder('$CACHE/aaa/lib');
+    Folder libFolderB = resourceProvider.newFolder('$CACHE/bbb/lib');
+    context.sourceFactory = new SourceFactory(<UriResolver>[
+      sdkResolver,
+      resourceResolver,
+      new PackageMapUriResolver(resourceProvider, {
+        'aaa': [libFolderA],
+        'bbb': [libFolderB],
+      })
+    ]);
+
+    // Ensure unlinked bundles.
+    manager.getUnlinkedBundles(context);
+    await manager.onUnlinkedComplete;
+
+    // Now we should be able to get linked bundles.
+    PackageBundle sdkBundle = getSdkBundle(sdk);
+    List<LinkedPubPackage> linkedPackages =
+        manager.getLinkedBundles(context, sdkBundle);
+    expect(linkedPackages, hasLength(2));
+
+    // package:aaa
+    {
+      LinkedPubPackage linkedPackage = linkedPackages
+          .singleWhere((linkedPackage) => linkedPackage.package.name == 'aaa');
+      PackageBundle unlinked = linkedPackage.unlinked;
+      PackageBundle linked = linkedPackage.linked;
+      expect(unlinked, isNotNull);
+      expect(linked, isNotNull);
+      expect(unlinked.unlinkedUnitUris, ['package:aaa/a.dart']);
+      expect(linked.linkedLibraryUris, ['package:aaa/a.dart']);
+      // Prepare linked `package:aaa/a.dart`.
+      UnlinkedUnit unlinkedUnitA = unlinked.unlinkedUnits[0];
+      LinkedLibrary linkedLibraryA = linked.linkedLibraries[0];
+      LinkedUnit linkedUnitA = linkedLibraryA.units[0];
+      // int a;
+      {
+        UnlinkedVariable a = unlinkedUnitA.variables[0];
+        expect(a.name, 'a');
+        _assertLinkedNameReference(unlinkedUnitA, linkedLibraryA, linkedUnitA,
+            a.type.reference, 'int', 'dart:core');
+      }
+    }
+
+    // package:bbb
+    {
+      LinkedPubPackage linkedPackage = linkedPackages
+          .singleWhere((linkedPackage) => linkedPackage.package.name == 'bbb');
+      PackageBundle unlinked = linkedPackage.unlinked;
+      PackageBundle linked = linkedPackage.linked;
+      expect(unlinked, isNotNull);
+      expect(linked, isNotNull);
+      expect(unlinked.unlinkedUnitUris, ['package:bbb/b.dart']);
+      expect(linked.linkedLibraryUris, ['package:bbb/b.dart']);
+      // Prepare linked `package:bbb/b.dart`.
+      UnlinkedUnit unlinkedUnit = unlinked.unlinkedUnits[0];
+      LinkedLibrary linkedLibrary = linked.linkedLibraries[0];
+      LinkedUnit linkedUnit = linkedLibrary.units[0];
+      // A b;
+      {
+        UnlinkedVariable b = unlinkedUnit.variables[0];
+        expect(b.name, 'b');
+        _assertLinkedNameReference(unlinkedUnit, linkedLibrary, linkedUnit,
+            b.type.reference, 'A', 'package:aaa/a.dart');
+      }
+    }
+  }
+
+  test_getUnlinkedBundles() async {
+    // Create package files.
+    resourceProvider.newFile(
+        '$CACHE/aaa/lib/a.dart',
+        '''
+class A {}
+''');
+    resourceProvider.newFile(
+        '$CACHE/aaa/lib/src/a2.dart',
+        '''
+class A2 {}
+''');
+    resourceProvider.newFile(
+        '$CACHE/bbb/lib/b.dart',
+        '''
+class B {}
+''');
+
+    // Configure packages resolution.
+    Folder libFolderA = resourceProvider.newFolder('$CACHE/aaa/lib');
+    Folder libFolderB = resourceProvider.newFolder('$CACHE/bbb/lib');
+    context.sourceFactory = new SourceFactory(<UriResolver>[
+      sdkResolver,
+      resourceResolver,
+      new PackageMapUriResolver(resourceProvider, {
+        'aaa': [libFolderA],
+        'bbb': [libFolderB],
+      })
+    ]);
+
+    // No unlinked bundles yet.
+    {
+      Map<PubPackage, PackageBundle> bundles =
+          manager.getUnlinkedBundles(context);
+      expect(bundles, isEmpty);
+    }
+
+    // The requested unlinked bundles must be available after the wait.
+    await manager.onUnlinkedComplete;
+    {
+      Map<PubPackage, PackageBundle> bundles =
+          manager.getUnlinkedBundles(context);
+      expect(bundles, hasLength(2));
+      {
+        PackageBundle bundle = _getBundleByPackageName(bundles, 'aaa');
+        expect(bundle.linkedLibraryUris, isEmpty);
+        expect(bundle.unlinkedUnitUris,
+            ['package:aaa/a.dart', 'package:aaa/src/a2.dart']);
+        expect(bundle.unlinkedUnits, hasLength(2));
+        expect(bundle.unlinkedUnits[0].classes.map((c) => c.name), ['A']);
+        expect(bundle.unlinkedUnits[1].classes.map((c) => c.name), ['A2']);
+      }
+      {
+        PackageBundle bundle = _getBundleByPackageName(bundles, 'bbb');
+        expect(bundle.linkedLibraryUris, isEmpty);
+        expect(bundle.unlinkedUnitUris, ['package:bbb/b.dart']);
+        expect(bundle.unlinkedUnits, hasLength(1));
+        expect(bundle.unlinkedUnits[0].classes.map((c) => c.name), ['B']);
+      }
+    }
+
+    // The files must be created.
+    File fileA = libFolderA.parent.getChildAssumingFile('unlinked.ds');
+    File fileB = libFolderB.parent.getChildAssumingFile('unlinked.ds');
+    expect(fileA.exists, isTrue);
+    expect(fileB.exists, isTrue);
+  }
+
+  test_getUnlinkedBundles_nullPackageMap() async {
+    context.sourceFactory =
+        new SourceFactory(<UriResolver>[sdkResolver, resourceResolver]);
+    Map<PubPackage, PackageBundle> bundles =
+        manager.getUnlinkedBundles(context);
+    expect(bundles, isEmpty);
+  }
+
+  test_isPathInPubCache_posix() {
+    expect(
+        PubSummaryManager.isPathInPubCache(pathos.posix,
+            '/home/.pub-cache/hosted/pub.dartlang.org/foo/lib/bar.dart'),
+        isTrue);
+    expect(
+        PubSummaryManager.isPathInPubCache(
+            pathos.posix, '/home/.pub-cache/foo/lib/bar.dart'),
+        isTrue);
+    expect(
+        PubSummaryManager.isPathInPubCache(
+            pathos.posix, '/home/sources/dart/foo/lib/bar.dart'),
+        isFalse);
+  }
+
+  test_isPathInPubCache_windows() {
+    expect(
+        PubSummaryManager.isPathInPubCache(pathos.windows,
+            r'C:\Users\user\Setters\Pub\Cache\hosted\foo\lib\bar.dart'),
+        isTrue);
+    expect(
+        PubSummaryManager.isPathInPubCache(
+            pathos.windows, r'C:\Users\user\Sources\Dart\foo\lib\bar.dart'),
+        isFalse);
+  }
+
+  void _assertLinkedNameReference(
+      UnlinkedUnit unlinkedUnit,
+      LinkedLibrary linkedLibrary,
+      LinkedUnit linkedUnit,
+      int typeNameReference,
+      String expectedName,
+      String expectedDependencyUri) {
+    expect(unlinkedUnit.references[typeNameReference].name, expectedName);
+    int typeNameDependency =
+        linkedUnit.references[typeNameReference].dependency;
+    expect(linkedLibrary.dependencies[typeNameDependency].uri,
+        expectedDependencyUri);
+  }
+
+  /**
+   * Compute element based summary bundle for the given [sdk].
+   */
+  static PackageBundle getSdkBundle(DartSdk sdk) {
+    return sdkBundleMap.putIfAbsent(sdk, () {
+      PackageBundleAssembler assembler = new PackageBundleAssembler();
+      for (SdkLibrary sdkLibrary in sdk.sdkLibraries) {
+        String uriStr = sdkLibrary.shortName;
+        Source source = sdk.mapDartUri(uriStr);
+        LibraryElement libraryElement =
+            sdk.context.computeLibraryElement(source);
+        assembler.serializeLibraryElement(libraryElement);
+      }
+      List<int> bytes = assembler.assemble().toBuffer();
+      return new PackageBundle.fromBuffer(bytes);
+    });
+  }
+
+  static PackageBundle _getBundleByPackageName(
+      Map<PubPackage, PackageBundle> bundles, String name) {
+    PubPackage package =
+        bundles.keys.singleWhere((package) => package.name == name);
+    return bundles[package];
+  }
+}
diff --git a/pkg/analyzer/test/src/summary/resynthesize_test.dart b/pkg/analyzer/test/src/summary/resynthesize_test.dart
index b6e8b30..679741d 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_test.dart
@@ -107,14 +107,16 @@
     expect(resynthesized.imports.length, original.imports.length,
         reason: 'imports');
     for (int i = 0; i < resynthesized.imports.length; i++) {
-      compareImportElements(resynthesized.imports[i], original.imports[i],
-          'import ${original.imports[i].uri}');
+      ImportElement originalImport = original.imports[i];
+      compareImportElements(
+          resynthesized.imports[i], originalImport, originalImport.toString());
     }
     expect(resynthesized.exports.length, original.exports.length,
         reason: 'exports');
     for (int i = 0; i < resynthesized.exports.length; i++) {
-      compareExportElements(resynthesized.exports[i], original.exports[i],
-          'export ${original.exports[i].uri}');
+      ExportElement originalExport = original.exports[i];
+      compareExportElements(
+          resynthesized.exports[i], originalExport, originalExport.toString());
     }
     expect(resynthesized.nameLength, original.nameLength);
     compareNamespaces(resynthesized.publicNamespace, original.publicNamespace,
@@ -1164,6 +1166,7 @@
       }
       return new LinkedLibrary.fromBuffer(serialized.linked.toBuffer());
     }
+
     Map<String, LinkedLibrary> linkedSummaries = <String, LinkedLibrary>{
       library.source.uri.toString(): getLinkedSummaryFor(library)
     };
@@ -1328,6 +1331,13 @@
       return false;
     } else if (modifier == Modifier.SYNTHETIC) {
       return element.isSynthetic;
+    } else if (modifier == Modifier.URI_EXISTS) {
+      if (element is ExportElement) {
+        return element.uriExists;
+      } else if (element is ImportElement) {
+        return element.uriExists;
+      }
+      return false;
     }
     throw new UnimplementedError(
         'Modifier $modifier for ${element?.runtimeType}');
@@ -1394,6 +1404,7 @@
       }
       return new LinkedLibrary.fromBuffer(serialized.linked.toBuffer());
     }
+
     Map<String, LinkedLibrary> linkedSummaries = <String, LinkedLibrary>{
       library.source.uri.toString(): getLinkedSummaryFor(library)
     };
diff --git a/pkg/analyzer/test/src/summary/summarize_ast_test.dart b/pkg/analyzer/test/src/summary/summarize_ast_test.dart
index 0ac5099..e3c7f52 100644
--- a/pkg/analyzer/test/src/summary/summarize_ast_test.dart
+++ b/pkg/analyzer/test/src/summary/summarize_ast_test.dart
@@ -15,6 +15,7 @@
 import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/idl.dart';
 import 'package:analyzer/src/summary/link.dart';
+import 'package:analyzer/src/summary/package_bundle_reader.dart';
 import 'package:analyzer/src/summary/summarize_ast.dart';
 import 'package:analyzer/src/summary/summarize_elements.dart';
 import 'package:unittest/unittest.dart';
@@ -204,7 +205,7 @@
 
   @override
   void serializeLibraryText(String text, {bool allowErrors: false}) {
-    Map<String, UnlinkedUnitBuilder> uriToUnit = this.uriToUnit;
+    Map<String, UnlinkedUnitBuilder> uriToUnit = this._filesToLink.uriToUnit;
     LinkerInputs linkerInputs = createLinkerInputs(text);
     linked = link(linkerInputs.linkedLibraries, linkerInputs.getDependency,
         linkerInputs.getUnit, strongMode)[linkerInputs.testDartUri.toString()];
@@ -287,23 +288,9 @@
  */
 abstract class SummaryLinkerTest {
   /**
-   * Map from absolute URI to the [UnlinkedUnit] for each compilation unit
-   * passed to [addNamedSource].
+   * Information about the files to be linked.
    */
-  Map<String, UnlinkedUnitBuilder> uriToUnit = <String, UnlinkedUnitBuilder>{};
-
-  /**
-   * Map from absolute URI to the [LinkedLibrary] for each compilation unit in a
-   * package bundle passed to [addBundle].
-   */
-  Map<String, LinkedLibrary> _dependentLinkedLibraries =
-      <String, LinkedLibrary>{};
-
-  /**
-   * Map from absolute URI to the [UnlinkedUnit] for each compilation unit in a
-   * package bundle passed to [addBundle].
-   */
-  Map<String, UnlinkedUnit> _dependentUnlinkedUnits = <String, UnlinkedUnit>{};
+  _FilesToLink _filesToLink = new _FilesToLink();
 
   /**
    * A test will set this to `true` if it contains `import`, `export`, or
@@ -315,15 +302,8 @@
    * Add the given package bundle as a dependency so that it may be referenced
    * by the files under test.
    */
-  void addBundle(PackageBundle bundle) {
-    for (int i = 0; i < bundle.linkedLibraryUris.length; i++) {
-      _dependentLinkedLibraries[bundle.linkedLibraryUris[i]] =
-          bundle.linkedLibraries[i];
-    }
-    for (int i = 0; i < bundle.unlinkedUnitUris.length; i++) {
-      _dependentUnlinkedUnits[bundle.unlinkedUnitUris[i]] =
-          bundle.unlinkedUnits[i];
-    }
+  void addBundle(String path, PackageBundle bundle) {
+    _filesToLink.summaryDataStore.addBundle(path, bundle);
   }
 
   /**
@@ -333,7 +313,7 @@
   Source addNamedSource(String filePath, String contents) {
     CompilationUnit unit = _parseText(contents);
     UnlinkedUnitBuilder unlinkedUnit = serializeAstUnlinked(unit);
-    uriToUnit[absUri(filePath)] = unlinkedUnit;
+    _filesToLink.uriToUnit[absUri(filePath)] = unlinkedUnit;
     // Tests using SummaryLinkerTest don't actually need the returned
     // Source, so we can safely return `null`.
     return null;
@@ -343,19 +323,16 @@
     Uri testDartUri = Uri.parse(absUri(path));
     CompilationUnit unit = _parseText(text);
     UnlinkedUnitBuilder unlinkedDefiningUnit = serializeAstUnlinked(unit);
-    uriToUnit[testDartUri.toString()] = unlinkedDefiningUnit;
+    _filesToLink.uriToUnit[testDartUri.toString()] = unlinkedDefiningUnit;
     LinkerInputs linkerInputs = new LinkerInputs(
         allowMissingFiles,
-        uriToUnit,
+        _filesToLink.uriToUnit,
         testDartUri,
         unlinkedDefiningUnit,
-        _dependentLinkedLibraries,
-        _dependentUnlinkedUnits);
-    // Reset uriToUnit, _dependentLinkedLibraries, and _dependentUnlinkedUnits
-    // in case the test needs to start a new package bundle.
-    uriToUnit = <String, UnlinkedUnitBuilder>{};
-    _dependentLinkedLibraries = <String, LinkedLibrary>{};
-    _dependentUnlinkedUnits = <String, UnlinkedUnit>{};
+        _filesToLink.summaryDataStore.linkedMap,
+        _filesToLink.summaryDataStore.unlinkedMap);
+    // Reset _filesToLink in case the test needs to start a new package bundle.
+    _filesToLink = new _FilesToLink();
     return linkerInputs;
   }
 
@@ -368,6 +345,7 @@
   PackageBundleBuilder createPackageBundle(String text,
       {String path: '/test.dart'}) {
     PackageBundleAssembler assembler = new PackageBundleAssembler();
+    assembler.recordDependencies(_filesToLink.summaryDataStore);
     LinkerInputs linkerInputs = createLinkerInputs(text, path: path);
     Map<String, LinkedLibraryBuilder> linkedLibraries = link(
         linkerInputs.linkedLibraries,
@@ -390,6 +368,27 @@
     Token token = scanner.tokenize();
     Parser parser = new Parser(null, AnalysisErrorListener.NULL_LISTENER);
     parser.parseGenericMethods = true;
-    return parser.parseCompilationUnit(token);
+    CompilationUnit unit = parser.parseCompilationUnit(token);
+    unit.lineInfo = new LineInfo(scanner.lineStarts);
+    return unit;
   }
 }
+
+/**
+ * [_FilesToLink] stores information about a set of files to be linked together.
+ * This information is grouped into a class to allow it to be reset easily when
+ * [SummaryLinkerTest.createLinkerInputs] is called.
+ */
+class _FilesToLink {
+  /**
+   * Map from absolute URI to the [UnlinkedUnit] for each compilation unit
+   * passed to [addNamedSource].
+   */
+  Map<String, UnlinkedUnitBuilder> uriToUnit = <String, UnlinkedUnitBuilder>{};
+
+  /**
+   * Information about summaries to be included in the link process.
+   */
+  SummaryDataStore summaryDataStore =
+      new SummaryDataStore([], recordDependencyInfo: true);
+}
diff --git a/pkg/analyzer/test/src/summary/summary_common.dart b/pkg/analyzer/test/src/summary/summary_common.dart
index d3e94d3..d5f2876 100644
--- a/pkg/analyzer/test/src/summary/summary_common.dart
+++ b/pkg/analyzer/test/src/summary/summary_common.dart
@@ -8659,6 +8659,17 @@
         expectedTargetUnit: 2);
   }
 
+  test_lineStarts() {
+    String text = '''
+int foo;
+class Test {}
+
+int bar;'''
+        .replaceAll('\r\n', '\n');
+    serializeLibraryText(text);
+    expect(unlinkedUnits[0].lineStarts, [0, 9, 23, 24]);
+  }
+
   test_linked_reference_reuse() {
     if (skipFullyLinkedData) {
       return;
diff --git a/pkg/analyzer/test/src/summary/test_all.dart b/pkg/analyzer/test/src/summary/test_all.dart
index 6ad0f2f..d669d0e 100644
--- a/pkg/analyzer/test/src/summary/test_all.dart
+++ b/pkg/analyzer/test/src/summary/test_all.dart
@@ -16,6 +16,7 @@
 import 'name_filter_test.dart' as name_filter_test;
 import 'package_bundle_reader_test.dart' as package_bundle_reader_test;
 import 'prelinker_test.dart' as prelinker_test;
+import 'pub_summary_test.dart' as pub_summary_test;
 import 'resynthesize_ast_test.dart' as resynthesize_ast_test;
 import 'resynthesize_strong_test.dart' as resynthesize_strong_test;
 import 'resynthesize_test.dart' as resynthesize_test;
@@ -37,6 +38,7 @@
     name_filter_test.main();
     package_bundle_reader_test.main();
     prelinker_test.main();
+    pub_summary_test.main();
     resynthesize_ast_test.main();
     resynthesize_strong_test.main();
     resynthesize_test.main();
diff --git a/pkg/analyzer/test/src/task/strong/checker_test.dart b/pkg/analyzer/test/src/task/strong/checker_test.dart
index f7ce4b2..ab82982 100644
--- a/pkg/analyzer/test/src/task/strong/checker_test.dart
+++ b/pkg/analyzer/test/src/task/strong/checker_test.dart
@@ -2687,6 +2687,18 @@
 ''');
   }
 
+  void test_methodTearoffStrictArrow() {
+    // Regression test for https://github.com/dart-lang/sdk/issues/26393
+    checkFile(r'''
+class A {
+  void foo(dynamic x) {}
+  void test(void f(int x)) {
+    test(foo);
+  }
+}
+    ''');
+  }
+
   void test_mixinOverrideOfGrandInterface_interfaceOfAbstractSuperclass() {
     checkFile('''
 class A {}
@@ -2965,6 +2977,16 @@
 ''');
   }
 
+  void test_optionalParams() {
+    // Regression test for https://github.com/dart-lang/sdk/issues/26155
+    checkFile(r'''
+void takesF(void f(int x)) {
+  takesF(/*info:INFERRED_TYPE_CLOSURE,info:INFERRED_TYPE_CLOSURE*/([x]) { bool z = x.isEven; });
+  takesF(/*info:INFERRED_TYPE_CLOSURE*/(y) { bool z = y.isEven; });
+}
+    ''');
+  }
+
   void test_privateOverride() {
     addFile(
         '''
@@ -3002,6 +3024,44 @@
 ''');
   }
 
+  void test_proxy() {
+    checkFile(r'''
+@proxy class C {}
+@proxy class D {
+  var f;
+  m() => null;
+  operator -() => null;
+  operator +(int other) => null;
+  operator [](int index) => null;
+  call() => null;
+}
+@proxy class F implements Function { noSuchMethod(i) => 42; }
+
+
+m() {
+  D d = new D();
+  d.m();
+  d.m;
+  d.f;
+  -d;
+  d + 7;
+  d[7];
+  d();
+
+  C c = new C();
+  /*info:DYNAMIC_INVOKE*/c.m();
+  /*info:DYNAMIC_INVOKE*/c.m;
+  /*info:DYNAMIC_INVOKE*/-c;
+  /*info:DYNAMIC_INVOKE*/c + 7;
+  /*info:DYNAMIC_INVOKE*/c[7];
+  /*error:INVOCATION_OF_NON_FUNCTION,info:DYNAMIC_INVOKE*/c();
+
+  F f = new F();
+  /*info:DYNAMIC_INVOKE*/f();
+}
+    ''');
+  }
+
   void test_redirectingConstructor() {
     checkFile('''
 class A {
diff --git a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
index 4dbcbfe..816d2d6 100644
--- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
+++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
@@ -900,7 +900,7 @@
 import 'dart:async';
 Future test() async {
   dynamic d;
-  List<int> l0 = /*warning:DOWN_CAST_COMPOSITE should be pass*/await /*pass should be info:INFERRED_TYPE_LITERAL*/[d];
+  List<int> l0 = await /*info:INFERRED_TYPE_LITERAL*/[/*info:DYNAMIC_CAST*/d];
   List<int> l1 = await /*info:INFERRED_TYPE_ALLOCATION*/new Future.value(/*info:INFERRED_TYPE_LITERAL*/[/*info:DYNAMIC_CAST*/d]);
 }
 ''');
@@ -1523,7 +1523,53 @@
     checkFile('''
 import 'dart:async';
 Future f;
-Future<int> t1 = f.then((_) => new Future<int>.value(42));
+Future<int> t1 = f.then((_) async => await new Future<int>.value(3));
+Future<int> t2 = f.then(/*info:INFERRED_TYPE_CLOSURE*/(_) async {return await new Future<int>.value(3);});
+Future<int> t3 = f.then((_) async => 3);
+Future<int> t4 = f.then(/*info:INFERRED_TYPE_CLOSURE*/(_) async {return 3;});
+Future<int> t5 = f.then((_) => new Future<int>.value(3));
+Future<int> t6 = f.then((_) {return new Future<int>.value(3);});
+Future<int> t7 = f.then((_) async => new Future<int>.value(3));
+Future<int> t8 = f.then(/*info:INFERRED_TYPE_CLOSURE*/(_) async {return new Future<int>.value(3);});
+''');
+  }
+
+  void test_futureThen_conditional() {
+    checkFile('''
+import 'dart:async';
+Future<bool> f;
+Future<int> t1 = f.then((x) async => x ? 2 : await new Future<int>.value(3));
+Future<int> t2 = f.then(/*info:INFERRED_TYPE_CLOSURE*/(x) async {return await x ? 2 : new Future<int>.value(3);});
+Future<int> t5 = f.then((x) => x ? 2 : new Future<int>.value(3));
+Future<int> t6 = f.then((x) {return x ? 2 : new Future<int>.value(3);});
+''');
+  }
+
+  void test_futureUnion_asyncConditional() {
+    checkFile('''
+import 'dart:async';
+
+Future<int> g1(bool x) async { return x ? 42 : /*info:INFERRED_TYPE_ALLOCATION*/new Future.value(42); }
+Future<int> g2(bool x) async => x ? 42 : /*info:INFERRED_TYPE_ALLOCATION*/new Future.value(42);
+
+Future<int> g3(bool x) async {
+  var y = x ? 42 : /*info:INFERRED_TYPE_ALLOCATION*/new Future.value(42);
+  return y;
+}
+    ''');
+  }
+
+  void test_futureUnion_downwards() {
+    checkFile('''
+import 'dart:async';
+Future f;
+// Instantiates Future<int>
+Future<int> t1 = f.then((_) => /*info:INFERRED_TYPE_ALLOCATION*/new Future.value(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/'hi'));
+
+// Instantiates List<int>
+Future<List<int>> t2 = f.then((_) => /*info:INFERRED_TYPE_LITERAL*/[3]);
+Future<List<int>> g2() async { return /*info:INFERRED_TYPE_LITERAL*/[3]; }
+Future<List<int>> g3() async { return /*info:INFERRED_TYPE_ALLOCATION*/new Future.value(/*info:INFERRED_TYPE_LITERAL*/[3]); }
 ''');
   }
 
@@ -2280,7 +2326,7 @@
                         // conected component.
 var g = -3;
 var h = new A() + 3;
-var i = /*error:UNDEFINED_OPERATOR*/- new A();
+var i = /*error:UNDEFINED_OPERATOR,info:DYNAMIC_INVOKE*/- new A();
 var j = null as B;
 
 test1() {
@@ -2554,6 +2600,18 @@
     expect(fns[9].type.toString(), '() → Stream<int>');
   }
 
+  void test_inferReturnOfStatementLambda() {
+    // Regression test for https://github.com/dart-lang/sdk/issues/26139
+    checkFile(r'''
+List<String> strings() {
+  var stuff = [].expand(/*info:INFERRED_TYPE_CLOSURE*/(i) {
+    return <String>[];
+  });
+  return stuff.toList();
+}
+    ''');
+  }
+
   void test_inferred_nonstatic_field_depends_on_static_field_complex() {
     var mainUnit = checkFile('''
 class C {
diff --git a/pkg/analyzer_cli/lib/src/build_mode.dart b/pkg/analyzer_cli/lib/src/build_mode.dart
index 6d3555f..5b9ec2c 100644
--- a/pkg/analyzer_cli/lib/src/build_mode.dart
+++ b/pkg/analyzer_cli/lib/src/build_mode.dart
@@ -137,9 +137,14 @@
   PackageBundleAssembler assembler;
   final Set<Source> processedSources = new Set<Source>();
   final Map<Uri, UnlinkedUnit> uriToUnit = <Uri, UnlinkedUnit>{};
+  PackageBundle sdkBundle;
 
   BuildMode(this.resourceProvider, this.options, this.stats);
 
+  bool get _shouldOutputSummary =>
+      options.buildSummaryOutput != null ||
+      options.buildSummaryOutputSemantic != null;
+
   /**
    * Perform package analysis according to the given [options].
    */
@@ -188,8 +193,7 @@
     assembler = new PackageBundleAssembler(
         excludeHashes: options.buildSummaryExcludeInformative &&
             options.buildSummaryOutputSemantic == null);
-    if (options.buildSummaryOutput != null ||
-        options.buildSummaryOutputSemantic != null) {
+    if (_shouldOutputSummary) {
       if (options.buildSummaryOnlyAst && !options.buildSummaryFallback) {
         _serializeAstBasedSummary(explicitSources);
       } else {
@@ -208,21 +212,26 @@
           }
         }
       }
+      if (!options.buildSummaryOnlyAst) {
+        // In non-AST mode, the SDK bundle wasn't added to the summaryDataStore
+        // because it is automatically loaded during analysis.  However we still
+        // want the SDK bundle to be noted as a dependency, so add it now.
+        summaryDataStore.addBundle(null, sdkBundle);
+      }
       // Write the whole package bundle.
-      PackageBundleBuilder sdkBundle = assembler.assemble();
+      assembler.recordDependencies(summaryDataStore);
+      PackageBundleBuilder bundle = assembler.assemble();
       if (options.buildSummaryExcludeInformative) {
-        sdkBundle.flushInformative();
+        bundle.flushInformative();
       }
       if (options.buildSummaryOutput != null) {
         io.File file = new io.File(options.buildSummaryOutput);
-        file.writeAsBytesSync(sdkBundle.toBuffer(),
-            mode: io.FileMode.WRITE_ONLY);
+        file.writeAsBytesSync(bundle.toBuffer(), mode: io.FileMode.WRITE_ONLY);
       }
       if (options.buildSummaryOutputSemantic != null) {
-        sdkBundle.flushInformative();
+        bundle.flushInformative();
         io.File file = new io.File(options.buildSummaryOutputSemantic);
-        file.writeAsBytesSync(sdkBundle.toBuffer(),
-            mode: io.FileMode.WRITE_ONLY);
+        file.writeAsBytesSync(bundle.toBuffer(), mode: io.FileMode.WRITE_ONLY);
       }
     }
 
@@ -254,10 +263,10 @@
 
   void _createContext() {
     // Read the summaries.
-    summaryDataStore = new SummaryDataStore(options.buildSummaryInputs);
+    summaryDataStore = new SummaryDataStore(options.buildSummaryInputs,
+        recordDependencyInfo: _shouldOutputSummary);
 
     DartSdk sdk;
-    PackageBundle sdkBundle;
     if (options.dartSdkSummaryPath != null) {
       SummaryBasedDartSdk summarySdk = new SummaryBasedDartSdk(
           options.dartSdkSummaryPath, options.strongMode);
diff --git a/pkg/compiler/bin/resolver.dart b/pkg/compiler/bin/resolver.dart
index aa70e4d..054ba50 100644
--- a/pkg/compiler/bin/resolver.dart
+++ b/pkg/compiler/bin/resolver.dart
@@ -6,12 +6,11 @@
 
 import 'package:args/args.dart';
 import 'package:compiler/src/apiimpl.dart';
-import 'package:compiler/src/dart2js.dart';
 import 'package:compiler/src/filenames.dart';
 import 'package:compiler/src/null_compiler_output.dart';
-import 'package:compiler/src/source_file_provider.dart';
 import 'package:compiler/src/options.dart';
 import 'package:compiler/src/serialization/json_serializer.dart';
+import 'package:compiler/src/source_file_provider.dart';
 import 'package:package_config/discovery.dart';
 
 main(var argv) async {
@@ -19,6 +18,8 @@
   parser.addOption('deps', abbr: 'd', allowMultiple: true);
   parser.addOption('out', abbr: 'o');
   parser.addOption('library-root', abbr: 'l');
+  parser.addOption('packages', abbr: 'p');
+  parser.addOption('bazel-config');
   var args = parser.parse(argv);
 
   var resolutionInputs = args['deps']
@@ -28,18 +29,31 @@
   var libraryRoot = root == null
       ? Platform.script.resolve('../../../sdk/')
       : currentDirectory.resolve(nativeToUriPath(root));
+
   var options = new CompilerOptions(
       libraryRoot: libraryRoot,
+      packageConfig: args['packages'] == null
+          ? null
+          : currentDirectory.resolve(args['packages']),
       resolveOnly: true,
       resolutionInputs: resolutionInputs,
       packagesDiscoveryProvider: findPackages);
-  var inputProvider = new CompilerSourceFileProvider();
+
+  var bazelConfigPath = args['bazel-config'];
+  var inputProvider = bazelConfigPath != null
+      ? new BazelInputProvider(bazelConfigPath)
+      : new CompilerSourceFileProvider();
+
   var outputProvider = const NullCompilerOutput();
   var diagnostics = new FormattingDiagnosticHandler(inputProvider);
-
   var compiler =
       new CompilerImpl(inputProvider, outputProvider, diagnostics, options);
 
+  if (args.rest.isEmpty) {
+    print('missing input files');
+    exit(1);
+  }
+
   var inputs = args.rest
       .map((uri) => currentDirectory.resolve(nativeToUriPath(uri)))
       .toList();
diff --git a/pkg/compiler/lib/compiler.dart b/pkg/compiler/lib/compiler.dart
index 11e99b3..e030673 100644
--- a/pkg/compiler/lib/compiler.dart
+++ b/pkg/compiler/lib/compiler.dart
@@ -5,10 +5,12 @@
 library compiler;
 
 import 'dart:async';
+
 import 'package:package_config/packages.dart';
+
 import 'compiler_new.dart' as new_api;
-import 'src/options.dart' show CompilerOptions;
 import 'src/old_to_new_api.dart';
+import 'src/options.dart' show CompilerOptions;
 
 // Unless explicitly allowed, passing [:null:] for any argument to the
 // methods of library will result in an Error being thrown.
diff --git a/pkg/compiler/lib/compiler_new.dart b/pkg/compiler/lib/compiler_new.dart
index 51de3810..5ba94cb 100644
--- a/pkg/compiler/lib/compiler_new.dart
+++ b/pkg/compiler/lib/compiler_new.dart
@@ -8,10 +8,11 @@
 library compiler_new;
 
 import 'dart:async';
+
+import 'compiler.dart' show Diagnostic;
 import 'src/apiimpl.dart';
 import 'src/options.dart' show CompilerOptions;
 
-import 'compiler.dart' show Diagnostic;
 export 'compiler.dart' show Diagnostic, PackagesDiscoveryProvider;
 
 // Unless explicitly allowed, passing `null` for any argument to the
@@ -39,9 +40,9 @@
 /// files, source map files, dump info files, etc.
 abstract class CompilerOutput {
   /// Returns an [EventSink] that will serve as compiler output for the given
-  ///  component.
+  /// component.
   ///
-  ///  Components are identified by [name] and [extension]. By convention,
+  /// Components are identified by [name] and [extension]. By convention,
   /// the empty string [:"":] will represent the main script
   /// (corresponding to the script parameter of [compile]) even if the
   /// main script is a library. For libraries that are compiled
diff --git a/pkg/compiler/lib/src/apiimpl.dart b/pkg/compiler/lib/src/apiimpl.dart
index 98d931a..3bddb9b 100644
--- a/pkg/compiler/lib/src/apiimpl.dart
+++ b/pkg/compiler/lib/src/apiimpl.dart
@@ -5,7 +5,6 @@
 library leg_apiimpl;
 
 import 'dart:async';
-import 'dart:convert';
 
 import 'package:package_config/packages.dart';
 import 'package:package_config/packages_file.dart' as pkgs;
@@ -16,7 +15,6 @@
 import '../compiler_new.dart' as api;
 import 'common/tasks.dart' show GenericTask, Measurer;
 import 'common.dart';
-import 'common/backend_api.dart' show Backend;
 import 'compiler.dart';
 import 'diagnostics/messages.dart' show Message;
 import 'elements/elements.dart' as elements;
@@ -26,7 +24,6 @@
 import 'platform_configuration.dart' as platform_configuration;
 import 'resolved_uri_translator.dart';
 import 'script.dart';
-import 'serialization/system.dart';
 
 /// Implements the [Compiler] using a [api.CompilerInput] for supplying the
 /// sources.
diff --git a/pkg/compiler/lib/src/closure.dart b/pkg/compiler/lib/src/closure.dart
index 0cffc40..7b71e69 100644
--- a/pkg/compiler/lib/src/closure.dart
+++ b/pkg/compiler/lib/src/closure.dart
@@ -4,23 +4,23 @@
 
 library closureToClassMapper;
 
-import 'common.dart';
 import 'common/names.dart' show Identifiers;
 import 'common/resolution.dart' show ParsingContext, Resolution;
 import 'common/tasks.dart' show CompilerTask;
+import 'common.dart';
 import 'compiler.dart' show Compiler;
 import 'constants/expressions.dart';
 import 'dart_types.dart';
 import 'elements/elements.dart';
 import 'elements/modelx.dart'
-    show BaseFunctionElementX, ClassElementX, ElementX, LocalFunctionElementX;
+    show BaseFunctionElementX, ClassElementX, ElementX;
 import 'elements/visitor.dart' show ElementVisitor;
 import 'js_backend/js_backend.dart' show JavaScriptBackend;
 import 'resolution/tree_elements.dart' show TreeElements;
 import 'tokens/token.dart' show Token;
 import 'tree/tree.dart';
-import 'util/util.dart';
 import 'universe/universe.dart' show Universe;
+import 'util/util.dart';
 
 class ClosureTask extends CompilerTask {
   Map<Node, ClosureClassMap> closureMappingCache;
diff --git a/pkg/compiler/lib/src/common/codegen.dart b/pkg/compiler/lib/src/common/codegen.dart
index 8a26860..cee2fcb 100644
--- a/pkg/compiler/lib/src/common/codegen.dart
+++ b/pkg/compiler/lib/src/common/codegen.dart
@@ -4,7 +4,6 @@
 
 library dart2js.common.codegen;
 
-import '../closure.dart' show SynthesizedCallMethodElementX;
 import '../common.dart';
 import '../compiler.dart' show Compiler;
 import '../constants/values.dart' show ConstantValue;
diff --git a/pkg/compiler/lib/src/common/resolution.dart b/pkg/compiler/lib/src/common/resolution.dart
index d48603d..841e77c 100644
--- a/pkg/compiler/lib/src/common/resolution.dart
+++ b/pkg/compiler/lib/src/common/resolution.dart
@@ -5,8 +5,8 @@
 library dart2js.common.resolution;
 
 import '../common.dart';
-import '../compiler.dart' show Compiler;
 import '../compile_time_constants.dart';
+import '../compiler.dart' show Compiler;
 import '../constants/expressions.dart' show ConstantExpression;
 import '../constants/values.dart' show ConstantValue;
 import '../core_types.dart' show CoreClasses, CoreTypes;
diff --git a/pkg/compiler/lib/src/common/tasks.dart b/pkg/compiler/lib/src/common/tasks.dart
index 100181c..2c5d62c 100644
--- a/pkg/compiler/lib/src/common/tasks.dart
+++ b/pkg/compiler/lib/src/common/tasks.dart
@@ -20,6 +20,11 @@
 
   int asyncCount = 0;
 
+  // Each task has a fixed, lazily computed, ZoneSpecification and zoneValues
+  // for [_measureZoned].
+  ZoneSpecification _zoneSpecification;
+  Map _zoneValues;
+
   CompilerTask(Measurer measurer)
       : measurer = measurer,
         _watch = measurer.enableTaskMeasurements ? new Stopwatch() : null;
@@ -97,49 +102,49 @@
     // The current zone is already measuring `this` task.
     if (Zone.current[measurer] == this) return action();
 
-    /// Run [f] in [zone]. Running must be delegated to [parent] to ensure that
-    /// various state is set up correctly (in particular that `Zone.current`
-    /// has the right value). Since [_measureZoned] can be called recursively
-    /// (synchronously), some of the measuring zones we create will be parents
-    /// of other measuring zones, but we still need to call through the parent
-    /// chain. Consequently, we use a zone value keyed by [measurer] to see if
-    /// we should measure or not when delegating.
-    run(Zone self, ZoneDelegate parent, Zone zone, f()) {
-      if (zone[measurer] != this) return parent.run(zone, f);
-      CompilerTask previous = _start();
-      try {
-        return parent.run(zone, f);
-      } finally {
-        _stop(previous);
-      }
-    }
-
-    /// Same as [run] except that [f] takes one argument, [arg].
-    runUnary(Zone self, ZoneDelegate parent, Zone zone, f(arg), arg) {
-      if (zone[measurer] != this) return parent.runUnary(zone, f, arg);
-      CompilerTask previous = _start();
-      try {
-        return parent.runUnary(zone, f, arg);
-      } finally {
-        _stop(previous);
-      }
-    }
-
-    /// Same as [run] except that [f] takes two arguments ([a1] and [a2]).
-    runBinary(Zone self, ZoneDelegate parent, Zone zone, f(a1, a2), a1, a2) {
-      if (zone[measurer] != this) return parent.runBinary(zone, f, a1, a2);
-      CompilerTask previous = _start();
-      try {
-        return parent.runBinary(zone, f, a1, a2);
-      } finally {
-        _stop(previous);
-      }
-    }
-
     return runZoned(action,
-        zoneValues: {measurer: this},
-        zoneSpecification: new ZoneSpecification(
-            run: run, runUnary: runUnary, runBinary: runBinary));
+        zoneValues: _zoneValues ??= {measurer: this},
+        zoneSpecification: _zoneSpecification ??= new ZoneSpecification(
+            run: _run, runUnary: _runUnary, runBinary: _runBinary));
+  }
+
+  /// Run [f] in [zone]. Running must be delegated to [parent] to ensure that
+  /// various state is set up correctly (in particular that `Zone.current`
+  /// has the right value). Since [_measureZoned] can be called recursively
+  /// (synchronously), some of the measuring zones we create will be parents
+  /// of other measuring zones, but we still need to call through the parent
+  /// chain. Consequently, we use a zone value keyed by [measurer] to see if
+  /// we should measure or not when delegating.
+  _run(Zone self, ZoneDelegate parent, Zone zone, f()) {
+    if (zone[measurer] != this) return parent.run(zone, f);
+    CompilerTask previous = _start();
+    try {
+      return parent.run(zone, f);
+    } finally {
+      _stop(previous);
+    }
+  }
+
+  /// Same as [run] except that [f] takes one argument, [arg].
+  _runUnary(Zone self, ZoneDelegate parent, Zone zone, f(arg), arg) {
+    if (zone[measurer] != this) return parent.runUnary(zone, f, arg);
+    CompilerTask previous = _start();
+    try {
+      return parent.runUnary(zone, f, arg);
+    } finally {
+      _stop(previous);
+    }
+  }
+
+  /// Same as [run] except that [f] takes two arguments ([a1] and [a2]).
+  _runBinary(Zone self, ZoneDelegate parent, Zone zone, f(a1, a2), a1, a2) {
+    if (zone[measurer] != this) return parent.runBinary(zone, f, a1, a2);
+    CompilerTask previous = _start();
+    try {
+      return parent.runBinary(zone, f, a1, a2);
+    } finally {
+      _stop(previous);
+    }
   }
 
   /// Asynchronous version of [measure]. Use this when action returns a future
diff --git a/pkg/compiler/lib/src/compile_time_constants.dart b/pkg/compiler/lib/src/compile_time_constants.dart
index 1c066ed..8853b2f 100644
--- a/pkg/compiler/lib/src/compile_time_constants.dart
+++ b/pkg/compiler/lib/src/compile_time_constants.dart
@@ -4,9 +4,9 @@
 
 library dart2js.compile_time_constant_evaluator;
 
-import 'common.dart';
 import 'common/resolution.dart' show Resolution;
 import 'common/tasks.dart' show CompilerTask, Measurer;
+import 'common.dart';
 import 'compiler.dart' show Compiler;
 import 'constant_system_dart.dart';
 import 'constants/constant_system.dart';
@@ -16,13 +16,12 @@
 import 'core_types.dart' show CoreTypes;
 import 'dart_types.dart';
 import 'elements/elements.dart';
-import 'elements/modelx.dart'
-    show FieldElementX, FunctionElementX, ConstantVariableMixin;
-import 'resolution/tree_elements.dart' show TreeElements;
+import 'elements/modelx.dart' show ConstantVariableMixin;
 import 'resolution/operators.dart';
+import 'resolution/tree_elements.dart' show TreeElements;
 import 'tree/tree.dart';
-import 'util/util.dart' show Link;
 import 'universe/call_structure.dart' show CallStructure;
+import 'util/util.dart' show Link;
 
 /// A [ConstantEnvironment] provides access for constants compiled for variable
 /// initializers.
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index bdda974..762e315 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -1992,6 +1992,9 @@
         message: "Element $element must be the declaration."));
     assert(invariant(element, hasResolvedAst(element),
         message: "ResolvedAst not available for $element."));
+    if (compiler.serialization.isDeserialized(element)) {
+      return compiler.serialization.getResolvedAst(element);
+    }
     return element.resolvedAst;
   }
 
diff --git a/pkg/compiler/lib/src/constants/constant_constructors.dart b/pkg/compiler/lib/src/constants/constant_constructors.dart
index 4628f28..996f8b1 100644
--- a/pkg/compiler/lib/src/constants/constant_constructors.dart
+++ b/pkg/compiler/lib/src/constants/constant_constructors.dart
@@ -16,7 +16,6 @@
 import '../resolution/tree_elements.dart' show TreeElements;
 import '../tree/tree.dart';
 import '../universe/call_structure.dart' show CallStructure;
-
 import 'constructors.dart';
 import 'expressions.dart';
 
diff --git a/pkg/compiler/lib/src/constants/constant_system.dart b/pkg/compiler/lib/src/constants/constant_system.dart
index 07787fd..1a0da6a 100644
--- a/pkg/compiler/lib/src/constants/constant_system.dart
+++ b/pkg/compiler/lib/src/constants/constant_system.dart
@@ -4,8 +4,8 @@
 
 library dart2js.constant_system;
 
-import '../dart_types.dart';
 import '../compiler.dart' show Compiler;
+import '../dart_types.dart';
 import '../resolution/operators.dart';
 import '../tree/dartstring.dart' show DartString;
 import 'values.dart';
diff --git a/pkg/compiler/lib/src/constants/expressions.dart b/pkg/compiler/lib/src/constants/expressions.dart
index 2ea05a8..6fc55de 100644
--- a/pkg/compiler/lib/src/constants/expressions.dart
+++ b/pkg/compiler/lib/src/constants/expressions.dart
@@ -133,7 +133,7 @@
   /// if it contains positional or named references, used to define constant
   /// constructors.
   // TODO(johnniwinther): Maybe make this final if we use it outside assertions.
-  bool get isPotential => true;
+  bool get isPotential => false;
 }
 
 /// A synthetic constant used to recover from errors.
@@ -195,9 +195,6 @@
   ConstantExpressionKind get kind => ConstantExpressionKind.SYNTHETIC;
 
   @override
-  bool get isPotential => false;
-
-  @override
   bool get isImplicit => false;
 }
 
@@ -1270,9 +1267,7 @@
   }
 
   @override
-  bool get isPotential {
-    return true;
-  }
+  bool get isPotential => true;
 }
 
 /// A reference to a named parameter.
@@ -1311,9 +1306,7 @@
   }
 
   @override
-  bool get isPotential {
-    return true;
-  }
+  bool get isPotential => true;
 }
 
 abstract class FromEnvironmentConstantExpression extends ConstantExpression {
diff --git a/pkg/compiler/lib/src/constants/values.dart b/pkg/compiler/lib/src/constants/values.dart
index fbda202..cba4e69 100644
--- a/pkg/compiler/lib/src/constants/values.dart
+++ b/pkg/compiler/lib/src/constants/values.dart
@@ -12,6 +12,23 @@
 import '../tree/dartstring.dart';
 import '../util/util.dart' show Hashing;
 
+enum ConstantValueKind {
+  FUNCTION,
+  NULL,
+  INT,
+  DOUBLE,
+  BOOL,
+  STRING,
+  LIST,
+  MAP,
+  CONSTRUCTED,
+  TYPE,
+  INTERCEPTOR,
+  SYNTHETIC,
+  DEFERRED,
+  NON_CONSTANT,
+}
+
 abstract class ConstantValueVisitor<R, A> {
   const ConstantValueVisitor();
 
@@ -84,6 +101,8 @@
   /// Returns a structured representation of this constant suited for debugging.
   String toStructuredText();
 
+  ConstantValueKind get kind;
+
   String toString() {
     assertDebugMode("Use ConstantValue.toDartText() or "
         "ConstantValue.toStructuredText() "
@@ -118,6 +137,8 @@
 
   accept(ConstantValueVisitor visitor, arg) => visitor.visitFunction(this, arg);
 
+  ConstantValueKind get kind => ConstantValueKind.FUNCTION;
+
   String toDartText() {
     if (element.isStatic) {
       return '${element.enclosingClass.name}.${element.name}';
@@ -177,6 +198,8 @@
 
   accept(ConstantValueVisitor visitor, arg) => visitor.visitNull(this, arg);
 
+  ConstantValueKind get kind => ConstantValueKind.NULL;
+
   String toStructuredText() => 'NullConstant';
 }
 
@@ -258,6 +281,8 @@
 
   accept(ConstantValueVisitor visitor, arg) => visitor.visitInt(this, arg);
 
+  ConstantValueKind get kind => ConstantValueKind.INT;
+
   String toStructuredText() => 'IntConstant(${toDartText()})';
 }
 
@@ -320,6 +345,8 @@
 
   accept(ConstantValueVisitor visitor, arg) => visitor.visitDouble(this, arg);
 
+  ConstantValueKind get kind => ConstantValueKind.DOUBLE;
+
   String toStructuredText() => 'DoubleConstant(${toDartText()})';
 }
 
@@ -338,6 +365,8 @@
 
   accept(ConstantValueVisitor visitor, arg) => visitor.visitBool(this, arg);
 
+  ConstantValueKind get kind => ConstantValueKind.BOOL;
+
   String toStructuredText() => 'BoolConstant(${toDartText()})';
 }
 
@@ -414,6 +443,8 @@
 
   accept(ConstantValueVisitor visitor, arg) => visitor.visitString(this, arg);
 
+  ConstantValueKind get kind => ConstantValueKind.STRING;
+
   // TODO(johnniwinther): Ensure correct escaping.
   String toDartText() => '"${primitiveValue.slowToString()}"';
 
@@ -457,6 +488,8 @@
 
   accept(ConstantValueVisitor visitor, arg) => visitor.visitType(this, arg);
 
+  ConstantValueKind get kind => ConstantValueKind.TYPE;
+
   String toDartText() => '$representedType';
 
   String toStructuredText() => 'TypeConstant(${representedType})';
@@ -492,6 +525,8 @@
 
   accept(ConstantValueVisitor visitor, arg) => visitor.visitList(this, arg);
 
+  ConstantValueKind get kind => ConstantValueKind.LIST;
+
   String toDartText() {
     StringBuffer sb = new StringBuffer();
     _unparseTypeArguments(sb);
@@ -567,6 +602,8 @@
 
   accept(ConstantValueVisitor visitor, arg) => visitor.visitMap(this, arg);
 
+  ConstantValueKind get kind => ConstantValueKind.MAP;
+
   String toDartText() {
     StringBuffer sb = new StringBuffer();
     _unparseTypeArguments(sb);
@@ -621,6 +658,8 @@
 
   DartType getType(CoreTypes types) => const DynamicType();
 
+  ConstantValueKind get kind => ConstantValueKind.INTERCEPTOR;
+
   String toDartText() {
     return 'interceptor($dispatchedType)';
   }
@@ -632,9 +671,9 @@
 
 class SyntheticConstantValue extends ConstantValue {
   final payload;
-  final kind;
+  final valueKind;
 
-  SyntheticConstantValue(this.kind, this.payload);
+  SyntheticConstantValue(this.valueKind, this.payload);
 
   bool get isDummy => true;
 
@@ -642,7 +681,7 @@
     return other is SyntheticConstantValue && payload == other.payload;
   }
 
-  get hashCode => payload.hashCode * 17 + kind.hashCode;
+  get hashCode => payload.hashCode * 17 + valueKind.hashCode;
 
   List<ConstantValue> getDependencies() => const <ConstantValue>[];
 
@@ -652,9 +691,11 @@
 
   DartType getType(CoreTypes types) => const DynamicType();
 
-  String toDartText() => 'synthetic($kind, $payload)';
+  ConstantValueKind get kind => ConstantValueKind.SYNTHETIC;
 
-  String toStructuredText() => 'SyntheticConstant($kind, $payload)';
+  String toDartText() => 'synthetic($valueKind, $payload)';
+
+  String toStructuredText() => 'SyntheticConstant($valueKind, $payload)';
 }
 
 class ConstructedConstantValue extends ObjectConstantValue {
@@ -693,6 +734,8 @@
     return visitor.visitConstructed(this, arg);
   }
 
+  ConstantValueKind get kind => ConstantValueKind.CONSTRUCTED;
+
   String toDartText() {
     StringBuffer sb = new StringBuffer();
     sb.write(type.name);
@@ -752,6 +795,8 @@
 
   DartType getType(CoreTypes types) => referenced.getType(types);
 
+  ConstantValueKind get kind => ConstantValueKind.DEFERRED;
+
   String toDartText() => 'deferred(${referenced.toDartText()})';
 
   String toStructuredText() {
@@ -776,6 +821,8 @@
   @override
   DartType getType(CoreTypes types) => const DynamicType();
 
+  ConstantValueKind get kind => ConstantValueKind.NON_CONSTANT;
+
   @override
   String toStructuredText() => 'NonConstant';
 
diff --git a/pkg/compiler/lib/src/cps_ir/backward_null_check_remover.dart b/pkg/compiler/lib/src/cps_ir/backward_null_check_remover.dart
index 5bdfc6c..57621fb 100644
--- a/pkg/compiler/lib/src/cps_ir/backward_null_check_remover.dart
+++ b/pkg/compiler/lib/src/cps_ir/backward_null_check_remover.dart
@@ -1,9 +1,9 @@
 library dart2js.cps_ir.backward_null_check_remover;
 
+import 'cps_fragment.dart';
 import 'cps_ir_nodes.dart';
 import 'optimizers.dart';
 import 'type_mask_system.dart';
-import 'cps_fragment.dart';
 
 /// Removes null checks that are follwed by another instruction that will
 /// perform the same check.
diff --git a/pkg/compiler/lib/src/cps_ir/bounds_checker.dart b/pkg/compiler/lib/src/cps_ir/bounds_checker.dart
index b4ca8e1..ee5adec 100644
--- a/pkg/compiler/lib/src/cps_ir/bounds_checker.dart
+++ b/pkg/compiler/lib/src/cps_ir/bounds_checker.dart
@@ -4,16 +4,16 @@
 
 library dart2js.cps_ir.bounds_checker;
 
-import 'cps_ir_nodes.dart';
-import 'optimizers.dart' show Pass;
-import 'octagon.dart';
 import '../constants/values.dart';
-import 'cps_fragment.dart';
-import 'type_mask_system.dart';
 import '../types/types.dart';
 import '../world.dart';
-import 'loop_effects.dart';
+import 'cps_fragment.dart';
+import 'cps_ir_nodes.dart';
 import 'effects.dart';
+import 'loop_effects.dart';
+import 'octagon.dart';
+import 'optimizers.dart' show Pass;
+import 'type_mask_system.dart';
 
 /// Eliminates bounds checks when they can be proven safe.
 ///
diff --git a/pkg/compiler/lib/src/cps_ir/cps_fragment.dart b/pkg/compiler/lib/src/cps_ir/cps_fragment.dart
index 4e22d0e..b7c7b9b 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_fragment.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_fragment.dart
@@ -4,12 +4,12 @@
 
 library cps_ir.cps_fragment;
 
-import 'cps_ir_nodes.dart';
 import '../constants/values.dart';
-import '../universe/selector.dart' show Selector;
-import '../types/types.dart' show TypeMask;
-import '../io/source_information.dart';
 import '../elements/elements.dart';
+import '../io/source_information.dart';
+import '../types/types.dart' show TypeMask;
+import '../universe/selector.dart' show Selector;
+import 'cps_ir_nodes.dart';
 
 /// Builds a CPS fragment that can be plugged into another CPS term.
 ///
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_integrity.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_integrity.dart
index cee7a1e..6363c88 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_integrity.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_integrity.dart
@@ -1,8 +1,8 @@
 library dart2js.cps_ir_integrity;
 
+import '../tracer.dart' as tracer;
 import 'cps_ir_nodes.dart';
 import 'cps_ir_nodes_sexpr.dart';
-import '../tracer.dart' as tracer;
 
 /// Dump S-expressions on error if the tracer is enabled.
 ///
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart
index d788549..8d32d04 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart
@@ -5,9 +5,9 @@
 library dart2js.ir_nodes_sexpr;
 
 import '../constants/values.dart';
+import '../universe/call_structure.dart' show CallStructure;
 import '../util/util.dart';
 import 'cps_ir_nodes.dart';
-import '../universe/call_structure.dart' show CallStructure;
 
 /// A [Decorator] is a function used by [SExpressionStringifier] to augment the
 /// output produced for a node or reference.  It can be provided to the
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_tracer.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_tracer.dart
index f70c586..3f13ee7 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_tracer.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_tracer.dart
@@ -5,8 +5,9 @@
 library dart2js.ir_tracer;
 
 import 'dart:async' show EventSink;
-import 'cps_ir_nodes.dart' as cps_ir;
+
 import '../tracer.dart';
+import 'cps_ir_nodes.dart' as cps_ir;
 
 /**
  * If true, show LetCont expressions in output.
diff --git a/pkg/compiler/lib/src/cps_ir/eagerly_load_statics.dart b/pkg/compiler/lib/src/cps_ir/eagerly_load_statics.dart
index 60a7977..b936885 100644
--- a/pkg/compiler/lib/src/cps_ir/eagerly_load_statics.dart
+++ b/pkg/compiler/lib/src/cps_ir/eagerly_load_statics.dart
@@ -4,10 +4,10 @@
 
 library dart2js.cps_ir.eagerly_load_statics;
 
-import 'cps_ir_nodes.dart';
-import 'optimizers.dart' show Pass;
 import '../elements/elements.dart';
 import 'cps_fragment.dart';
+import 'cps_ir_nodes.dart';
+import 'optimizers.dart' show Pass;
 
 /// Replaces [GetLazyStatic] with [GetStatic] when the static field is known
 /// to have been initialized.
diff --git a/pkg/compiler/lib/src/cps_ir/effects.dart b/pkg/compiler/lib/src/cps_ir/effects.dart
index 29d3172..2a28785 100644
--- a/pkg/compiler/lib/src/cps_ir/effects.dart
+++ b/pkg/compiler/lib/src/cps_ir/effects.dart
@@ -4,6 +4,7 @@
 library dart2js.cps_ir.effects;
 
 import 'dart:typed_data';
+
 import '../universe/side_effects.dart' show SideEffects;
 
 /// Bitmasks for tracking non-local side effects and dependencies.
diff --git a/pkg/compiler/lib/src/cps_ir/finalize.dart b/pkg/compiler/lib/src/cps_ir/finalize.dart
index e583f49..7f0e7e0 100644
--- a/pkg/compiler/lib/src/cps_ir/finalize.dart
+++ b/pkg/compiler/lib/src/cps_ir/finalize.dart
@@ -1,11 +1,11 @@
 library dart2js.cps_ir.finalize;
 
-import 'cps_ir_nodes.dart';
-import 'cps_fragment.dart';
-import 'optimizers.dart' show Pass;
-import '../js_backend/js_backend.dart' show JavaScriptBackend;
-import '../js_backend/backend_helpers.dart';
 import '../js/js.dart' as js;
+import '../js_backend/backend_helpers.dart';
+import '../js_backend/js_backend.dart' show JavaScriptBackend;
+import 'cps_fragment.dart';
+import 'cps_ir_nodes.dart';
+import 'optimizers.dart' show Pass;
 
 /// A transformation pass that must run immediately before the tree IR builder.
 ///
diff --git a/pkg/compiler/lib/src/cps_ir/gvn.dart b/pkg/compiler/lib/src/cps_ir/gvn.dart
index 8970f5c..4c49d7a 100644
--- a/pkg/compiler/lib/src/cps_ir/gvn.dart
+++ b/pkg/compiler/lib/src/cps_ir/gvn.dart
@@ -4,16 +4,16 @@
 
 library dart2js.cps_ir.gvn;
 
-import 'cps_ir_nodes.dart';
-import '../elements/elements.dart';
-import 'optimizers.dart' show Pass;
-import 'loop_hierarchy.dart';
-import 'loop_effects.dart';
-import '../world.dart';
 import '../compiler.dart' show Compiler;
+import '../elements/elements.dart';
 import '../js_backend/js_backend.dart' show JavaScriptBackend;
-import 'type_mask_system.dart';
+import '../world.dart';
+import 'cps_ir_nodes.dart';
 import 'effects.dart';
+import 'loop_effects.dart';
+import 'loop_hierarchy.dart';
+import 'optimizers.dart' show Pass;
+import 'type_mask_system.dart';
 
 /// Eliminates redundant primitives by reusing the value of another primitive
 /// that is known to have the same result.  Primitives are also hoisted out of
diff --git a/pkg/compiler/lib/src/cps_ir/insert_refinements.dart b/pkg/compiler/lib/src/cps_ir/insert_refinements.dart
index 28d013f..e57f43f 100644
--- a/pkg/compiler/lib/src/cps_ir/insert_refinements.dart
+++ b/pkg/compiler/lib/src/cps_ir/insert_refinements.dart
@@ -5,12 +5,13 @@
 library cps_ir.optimization.insert_refinements;
 
 import 'dart:math' show min;
-import 'optimizers.dart' show Pass;
-import 'cps_ir_nodes.dart';
-import '../elements/elements.dart';
+
 import '../common/names.dart';
+import '../elements/elements.dart';
 import '../types/types.dart' show TypeMask;
 import '../universe/selector.dart';
+import 'cps_ir_nodes.dart';
+import 'optimizers.dart' show Pass;
 import 'type_mask_system.dart';
 
 /// Inserts [Refinement] nodes in the IR to allow for sparse path-sensitive
diff --git a/pkg/compiler/lib/src/cps_ir/loop_effects.dart b/pkg/compiler/lib/src/cps_ir/loop_effects.dart
index d7c3c6f..e2f5e22 100644
--- a/pkg/compiler/lib/src/cps_ir/loop_effects.dart
+++ b/pkg/compiler/lib/src/cps_ir/loop_effects.dart
@@ -1,9 +1,9 @@
 library dart2js.cps_ir.loop_effects;
 
-import 'cps_ir_nodes.dart';
-import 'loop_hierarchy.dart';
 import '../world.dart';
+import 'cps_ir_nodes.dart';
 import 'effects.dart';
+import 'loop_hierarchy.dart';
 
 /// Determines the side effects that may occur in each loop.
 class LoopSideEffects extends TrampolineRecursiveVisitor {
diff --git a/pkg/compiler/lib/src/cps_ir/loop_hierarchy.dart b/pkg/compiler/lib/src/cps_ir/loop_hierarchy.dart
index 60129af..4433510 100644
--- a/pkg/compiler/lib/src/cps_ir/loop_hierarchy.dart
+++ b/pkg/compiler/lib/src/cps_ir/loop_hierarchy.dart
@@ -4,8 +4,8 @@
 
 library dart2js.cps_ir.loop_hierarchy;
 
-import 'cps_ir_nodes.dart';
 import 'cps_fragment.dart';
+import 'cps_ir_nodes.dart';
 
 /// Determines the effective nesting of loops.
 ///
diff --git a/pkg/compiler/lib/src/cps_ir/loop_invariant_branch.dart b/pkg/compiler/lib/src/cps_ir/loop_invariant_branch.dart
index 95ee597..8d84f0f 100644
--- a/pkg/compiler/lib/src/cps_ir/loop_invariant_branch.dart
+++ b/pkg/compiler/lib/src/cps_ir/loop_invariant_branch.dart
@@ -1,9 +1,9 @@
 library dart2js.cps_ir.loop_invariant_branch;
 
-import 'cps_ir_nodes.dart';
-import 'optimizers.dart';
-import 'loop_hierarchy.dart';
 import 'cps_fragment.dart';
+import 'cps_ir_nodes.dart';
+import 'loop_hierarchy.dart';
+import 'optimizers.dart';
 import 'redundant_join.dart' show AlphaRenamer;
 
 /// Hoists branches out of loops, where:
diff --git a/pkg/compiler/lib/src/cps_ir/optimize_interceptors.dart b/pkg/compiler/lib/src/cps_ir/optimize_interceptors.dart
index 65500a5..59ef662 100644
--- a/pkg/compiler/lib/src/cps_ir/optimize_interceptors.dart
+++ b/pkg/compiler/lib/src/cps_ir/optimize_interceptors.dart
@@ -4,17 +4,17 @@
 
 library dart2js.cps_ir.optimize_interceptors;
 
-import 'optimizers.dart';
-import 'cps_ir_nodes.dart';
-import 'loop_hierarchy.dart';
-import 'cps_fragment.dart';
 import '../constants/values.dart';
 import '../elements/elements.dart';
+import '../io/source_information.dart' show SourceInformation;
 import '../js_backend/backend_helpers.dart' show BackendHelpers;
 import '../js_backend/js_backend.dart' show JavaScriptBackend;
 import '../types/types.dart' show TypeMask;
-import '../io/source_information.dart' show SourceInformation;
 import '../world.dart';
+import 'cps_fragment.dart';
+import 'cps_ir_nodes.dart';
+import 'loop_hierarchy.dart';
+import 'optimizers.dart';
 import 'type_mask_system.dart';
 
 /// Replaces `getInterceptor` calls with interceptor constants when possible,
diff --git a/pkg/compiler/lib/src/cps_ir/optimizers.dart b/pkg/compiler/lib/src/cps_ir/optimizers.dart
index 8af5154..3e22e10 100644
--- a/pkg/compiler/lib/src/cps_ir/optimizers.dart
+++ b/pkg/compiler/lib/src/cps_ir/optimizers.dart
@@ -4,30 +4,30 @@
 
 library dart2js.cps_ir.optimizers;
 
-import 'cps_ir_nodes.dart';
-import '../constants/values.dart';
 import '../common/names.dart';
+import '../constants/values.dart';
 import '../universe/selector.dart';
+import 'cps_ir_nodes.dart';
 
-export 'type_propagation.dart' show TypePropagator;
-export 'scalar_replacement.dart' show ScalarReplacer;
-export 'redundant_phi.dart' show RedundantPhiEliminator;
-export 'redundant_join.dart' show RedundantJoinEliminator;
-export 'shrinking_reductions.dart' show ShrinkingReducer;
-export 'mutable_ssa.dart' show MutableVariableEliminator;
-export 'insert_refinements.dart' show InsertRefinements;
-export 'update_refinements.dart' show UpdateRefinements;
-export 'redundant_refinement.dart' show RedundantRefinementEliminator;
-export 'optimize_interceptors.dart' show OptimizeInterceptors;
-export 'bounds_checker.dart' show BoundsChecker;
 export 'backward_null_check_remover.dart' show BackwardNullCheckRemover;
+export 'bounds_checker.dart' show BoundsChecker;
+export 'eagerly_load_statics.dart' show EagerlyLoadStatics;
 export 'gvn.dart' show GVN;
 export 'inline.dart' show Inliner;
-export 'eagerly_load_statics.dart' show EagerlyLoadStatics;
+export 'insert_refinements.dart' show InsertRefinements;
 export 'loop_invariant_branch.dart' show LoopInvariantBranchMotion;
-export 'path_based_optimizer.dart' show PathBasedOptimizer;
-export 'use_field_initializers.dart' show UseFieldInitializers;
+export 'mutable_ssa.dart' show MutableVariableEliminator;
+export 'optimize_interceptors.dart' show OptimizeInterceptors;
 export 'parent_visitor.dart' show ParentVisitor;
+export 'path_based_optimizer.dart' show PathBasedOptimizer;
+export 'redundant_join.dart' show RedundantJoinEliminator;
+export 'redundant_phi.dart' show RedundantPhiEliminator;
+export 'redundant_refinement.dart' show RedundantRefinementEliminator;
+export 'scalar_replacement.dart' show ScalarReplacer;
+export 'shrinking_reductions.dart' show ShrinkingReducer;
+export 'type_propagation.dart' show TypePropagator;
+export 'update_refinements.dart' show UpdateRefinements;
+export 'use_field_initializers.dart' show UseFieldInitializers;
 
 /// An optimization pass over the CPS IR.
 abstract class Pass {
diff --git a/pkg/compiler/lib/src/cps_ir/path_based_optimizer.dart b/pkg/compiler/lib/src/cps_ir/path_based_optimizer.dart
index 933111e..d7f4acc 100644
--- a/pkg/compiler/lib/src/cps_ir/path_based_optimizer.dart
+++ b/pkg/compiler/lib/src/cps_ir/path_based_optimizer.dart
@@ -3,10 +3,10 @@
 // BSD-style license that can be found in the LICENSE file.
 library dart2js.cps_ir.path_based_optimizer;
 
+import '../js_backend/js_backend.dart';
+import 'cps_fragment.dart';
 import 'cps_ir_nodes.dart';
 import 'optimizers.dart';
-import 'cps_fragment.dart';
-import '../js_backend/js_backend.dart';
 import 'type_mask_system.dart';
 
 /// Optimizations based on intraprocedural forward dataflow analysis, taking
diff --git a/pkg/compiler/lib/src/cps_ir/scalar_replacement.dart b/pkg/compiler/lib/src/cps_ir/scalar_replacement.dart
index a913f08..b66f88f 100644
--- a/pkg/compiler/lib/src/cps_ir/scalar_replacement.dart
+++ b/pkg/compiler/lib/src/cps_ir/scalar_replacement.dart
@@ -3,8 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 library dart2js.cps_ir.scalar_replacement;
 
-import 'optimizers.dart';
-
 import 'dart:collection' show Queue;
 
 import '../common.dart';
@@ -14,6 +12,7 @@
 import '../types/types.dart';
 import '../world.dart' show World;
 import 'cps_ir_nodes.dart';
+import 'optimizers.dart';
 
 /**
  * Replaces aggregates with a set of local values.  Performs inlining of
diff --git a/pkg/compiler/lib/src/cps_ir/type_propagation.dart b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
index 4ee963c..75ede1f 100644
--- a/pkg/compiler/lib/src/cps_ir/type_propagation.dart
+++ b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
@@ -3,8 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 library dart2js.cps_ir.type_propagation;
 
-import 'optimizers.dart';
-
 import '../closure.dart' show ClosureClassElement;
 import '../common.dart';
 import '../common/names.dart' show Identifiers, Selectors;
@@ -15,18 +13,19 @@
 import '../elements/elements.dart';
 import '../io/source_information.dart' show SourceInformation;
 import '../js_backend/backend_helpers.dart' show BackendHelpers;
-import '../js_backend/js_backend.dart' show JavaScriptBackend;
 import '../js_backend/codegen/task.dart' show CpsFunctionCompiler;
+import '../js_backend/js_backend.dart' show JavaScriptBackend;
 import '../resolution/operators.dart';
 import '../tree/tree.dart' as ast;
-import '../types/types.dart';
 import '../types/abstract_value_domain.dart' show AbstractBool;
+import '../types/types.dart';
 import '../universe/selector.dart' show Selector;
 import '../world.dart' show World;
 import 'cps_fragment.dart';
 import 'cps_ir_nodes.dart';
-import 'type_mask_system.dart';
 import 'effects.dart';
+import 'optimizers.dart';
+import 'type_mask_system.dart';
 
 class ConstantPropagationLattice {
   final TypeMaskSystem typeSystem;
diff --git a/pkg/compiler/lib/src/cps_ir/update_refinements.dart b/pkg/compiler/lib/src/cps_ir/update_refinements.dart
index 09f5d7a..20d333f 100644
--- a/pkg/compiler/lib/src/cps_ir/update_refinements.dart
+++ b/pkg/compiler/lib/src/cps_ir/update_refinements.dart
@@ -1,9 +1,9 @@
 library dart2js.cps_ir.update_refinements;
 
+import '../world.dart';
 import 'cps_ir_nodes.dart';
 import 'optimizers.dart' show Pass;
 import 'type_mask_system.dart';
-import '../world.dart';
 
 /// Updates all references to use the most refined version in scope.
 ///
diff --git a/pkg/compiler/lib/src/cps_ir/use_field_initializers.dart b/pkg/compiler/lib/src/cps_ir/use_field_initializers.dart
index 1b218af..6019742 100644
--- a/pkg/compiler/lib/src/cps_ir/use_field_initializers.dart
+++ b/pkg/compiler/lib/src/cps_ir/use_field_initializers.dart
@@ -3,10 +3,10 @@
 // BSD-style license that can be found in the LICENSE file.
 library dart2js.cps_ir.use_field_initializers;
 
-import 'cps_ir_nodes.dart';
-import 'optimizers.dart';
 import '../elements/elements.dart';
 import '../js_backend/js_backend.dart';
+import 'cps_ir_nodes.dart';
+import 'optimizers.dart';
 
 /// Eliminates [SetField] instructions when the value can instead be passed into
 /// the field initializer of a [CreateInstance] instruction.
diff --git a/pkg/compiler/lib/src/dart2js.dart b/pkg/compiler/lib/src/dart2js.dart
index c4ab29f..5efe438 100644
--- a/pkg/compiler/lib/src/dart2js.dart
+++ b/pkg/compiler/lib/src/dart2js.dart
@@ -11,9 +11,8 @@
 import 'package:package_config/discovery.dart' show findPackages;
 
 import '../compiler_new.dart' as api;
-import 'apiimpl.dart';
-import 'common/names.dart' show Uris;
 import 'commandline_options.dart';
+import 'common/names.dart' show Uris;
 import 'filenames.dart';
 import 'io/source_file.dart';
 import 'null_compiler_output.dart';
diff --git a/pkg/compiler/lib/src/dart2js_profile_many.dart b/pkg/compiler/lib/src/dart2js_profile_many.dart
index e29ec46..8288a9a 100644
--- a/pkg/compiler/lib/src/dart2js_profile_many.dart
+++ b/pkg/compiler/lib/src/dart2js_profile_many.dart
@@ -4,9 +4,10 @@
 
 library dart2js.profile_many;
 
-import 'dart2js.dart' as cmdline;
 import 'dart:async';
 
+import 'dart2js.dart' as cmdline;
+
 const String USAGE = """
 Usage: dart2js_profile_many.dart [OPTIONS] [FILES]
 
diff --git a/pkg/compiler/lib/src/deferred_load.dart b/pkg/compiler/lib/src/deferred_load.dart
index b3668c1..449a434 100644
--- a/pkg/compiler/lib/src/deferred_load.dart
+++ b/pkg/compiler/lib/src/deferred_load.dart
@@ -8,8 +8,7 @@
 import 'common/tasks.dart' show CompilerTask;
 import 'common.dart';
 import 'compiler.dart' show Compiler;
-import 'constants/expressions.dart'
-    show ConstantExpression, ConstantExpressionKind;
+import 'constants/expressions.dart' show ConstantExpression;
 import 'constants/values.dart'
     show
         ConstantValue,
@@ -180,12 +179,22 @@
     return _elementToOutputUnit[element];
   }
 
+  /// Direct access to the output-unit to element relation used for testing.
+  OutputUnit getOutputUnitForElementForTesting(Element element) {
+    return _elementToOutputUnit[element];
+  }
+
   /// Returns the [OutputUnit] where [constant] belongs.
   OutputUnit outputUnitForConstant(ConstantValue constant) {
     if (!isProgramSplit) return mainOutputUnit;
     return _constantToOutputUnit[constant];
   }
 
+  /// Direct access to the output-unit to constants map used for testing.
+  Map<ConstantValue, OutputUnit> get outputUnitForConstantsForTesting {
+    return _constantToOutputUnit;
+  }
+
   bool isDeferred(Element element) {
     return outputUnitForElement(element) != mainOutputUnit;
   }
@@ -348,7 +357,7 @@
         treeElements.forEachConstantNode(
             (ast.Node node, ConstantExpression expression) {
           if (compiler.serialization.isDeserialized(analyzableElement)) {
-            if (!expression.isImplicit && !expression.isPotential) {
+            if (!expression.isPotential) {
               // Enforce evaluation of [expression].
               backend.constants.getConstantValue(expression);
             }
@@ -926,7 +935,8 @@
 
     StringBuffer sb = new StringBuffer();
     for (OutputUnit outputUnit in allOutputUnits) {
-      sb.write(outputUnit.name);
+      sb.write('\n-------------------------------\n');
+      sb.write('Output unit: ${outputUnit.name}');
       List<String> elements = elementMap[outputUnit];
       if (elements != null) {
         sb.write('\n elements:');
diff --git a/pkg/compiler/lib/src/diagnostics/diagnostic_listener.dart b/pkg/compiler/lib/src/diagnostics/diagnostic_listener.dart
index 0a9c5f5..e12c09c 100644
--- a/pkg/compiler/lib/src/diagnostics/diagnostic_listener.dart
+++ b/pkg/compiler/lib/src/diagnostics/diagnostic_listener.dart
@@ -4,11 +4,11 @@
 
 library dart2js.diagnostic_listener;
 
+import '../elements/elements.dart' show Element;
 import '../options.dart' show DiagnosticOptions;
+import 'messages.dart';
 import 'source_span.dart' show SourceSpan;
 import 'spannable.dart' show Spannable;
-import '../elements/elements.dart' show Element;
-import 'messages.dart';
 
 // TODO(johnniwinther): Rename and cleanup this interface. Add severity enum.
 abstract class DiagnosticReporter {
diff --git a/pkg/compiler/lib/src/diagnostics/messages.dart b/pkg/compiler/lib/src/diagnostics/messages.dart
index 472e016..8baffd6 100644
--- a/pkg/compiler/lib/src/diagnostics/messages.dart
+++ b/pkg/compiler/lib/src/diagnostics/messages.dart
@@ -63,12 +63,10 @@
 library dart2js.messages;
 
 import '../tokens/token.dart' show ErrorToken, Token;
-
+import 'generated/shared_messages.dart' as shared_messages;
 import 'invariant.dart' show invariant;
 import 'spannable.dart' show CURRENT_ELEMENT_SPANNABLE;
 
-import 'generated/shared_messages.dart' as shared_messages;
-
 const DONT_KNOW_HOW_TO_FIX = "Computer says no!";
 
 /// Keys for the [MessageTemplate]s.
diff --git a/pkg/compiler/lib/src/dump_info.dart b/pkg/compiler/lib/src/dump_info.dart
index a8c39fa..93f1312 100644
--- a/pkg/compiler/lib/src/dump_info.dart
+++ b/pkg/compiler/lib/src/dump_info.dart
@@ -16,7 +16,6 @@
 import 'deferred_load.dart' show OutputUnit;
 import 'elements/elements.dart';
 import 'elements/visitor.dart';
-import 'info/send_info.dart' show collectSendMeasurements;
 import 'js/js.dart' as jsAst;
 import 'js_backend/js_backend.dart' show JavaScriptBackend;
 import 'js_emitter/full_emitter/emitter.dart' as full show Emitter;
@@ -313,9 +312,6 @@
     }
     info.closures = nestedClosures;
     result.functions.add(info);
-    if (const bool.fromEnvironment('send_stats')) {
-      info.measurements = collectSendMeasurements(element, compiler);
-    }
     return info;
   }
 
diff --git a/pkg/compiler/lib/src/elements/common.dart b/pkg/compiler/lib/src/elements/common.dart
index 0eb92a6..b3a43ca 100644
--- a/pkg/compiler/lib/src/elements/common.dart
+++ b/pkg/compiler/lib/src/elements/common.dart
@@ -10,7 +10,6 @@
 import '../core_types.dart' show CoreClasses;
 import '../dart_types.dart' show DartType, InterfaceType, FunctionType;
 import '../util/util.dart' show Link;
-
 import 'elements.dart';
 
 abstract class ElementCommon implements Element {
diff --git a/pkg/compiler/lib/src/elements/elements.dart b/pkg/compiler/lib/src/elements/elements.dart
index aac0b0d..67cdd60 100644
--- a/pkg/compiler/lib/src/elements/elements.dart
+++ b/pkg/compiler/lib/src/elements/elements.dart
@@ -11,16 +11,15 @@
 import '../constants/expressions.dart';
 import '../core_types.dart' show CoreClasses;
 import '../dart_types.dart';
+import '../ordered_typeset.dart' show OrderedTypeSet;
 import '../resolution/scope.dart' show Scope;
 import '../resolution/tree_elements.dart' show TreeElements;
-import '../ordered_typeset.dart' show OrderedTypeSet;
 import '../script.dart';
 import '../tokens/token.dart'
     show Token, isUserDefinableOperator, isMinusOperator;
 import '../tree/tree.dart';
 import '../util/characters.dart' show $_;
 import '../util/util.dart';
-
 import 'visitor.dart' show ElementVisitor;
 
 part 'names.dart';
diff --git a/pkg/compiler/lib/src/elements/modelx.dart b/pkg/compiler/lib/src/elements/modelx.dart
index 265eb2e..b8a2987 100644
--- a/pkg/compiler/lib/src/elements/modelx.dart
+++ b/pkg/compiler/lib/src/elements/modelx.dart
@@ -15,9 +15,9 @@
 import '../diagnostics/messages.dart' show MessageTemplate;
 import '../ordered_typeset.dart' show OrderedTypeSet;
 import '../resolution/class_members.dart' show ClassMemberMixin;
+import '../resolution/resolution.dart' show AnalyzableElementX;
 import '../resolution/scope.dart'
     show ClassScope, LibraryScope, Scope, TypeDeclarationScope;
-import '../resolution/resolution.dart' show AnalyzableElementX;
 import '../resolution/tree_elements.dart' show TreeElements;
 import '../resolution/typedefs.dart' show TypedefCyclicVisitor;
 import '../script.dart';
@@ -25,7 +25,6 @@
 import '../tokens/token_constants.dart' as Tokens show EOF_TOKEN;
 import '../tree/tree.dart';
 import '../util/util.dart';
-
 import 'common.dart';
 import 'elements.dart';
 import 'visitor.dart' show ElementVisitor;
diff --git a/pkg/compiler/lib/src/elements/visitor.dart b/pkg/compiler/lib/src/elements/visitor.dart
index 2a1c917..0779288 100644
--- a/pkg/compiler/lib/src/elements/visitor.dart
+++ b/pkg/compiler/lib/src/elements/visitor.dart
@@ -4,9 +4,9 @@
 
 library visitor;
 
-import 'elements.dart';
 import '../closure.dart'
     show BoxFieldElement, ClosureClassElement, ClosureFieldElement;
+import 'elements.dart';
 
 abstract class ElementVisitor<R, A> {
   const ElementVisitor();
diff --git a/pkg/compiler/lib/src/hash/sha1.dart b/pkg/compiler/lib/src/hash/sha1.dart
index 8e5eec2..56ae8b9 100644
--- a/pkg/compiler/lib/src/hash/sha1.dart
+++ b/pkg/compiler/lib/src/hash/sha1.dart
@@ -8,8 +8,8 @@
  */
 library sha1;
 
-import 'dart:math' show pow;
 import 'dart:convert';
+import 'dart:math' show pow;
 
 import '../io/code_output.dart' show CodeOutputListener;
 
diff --git a/pkg/compiler/lib/src/helpers/helpers.dart b/pkg/compiler/lib/src/helpers/helpers.dart
index 6c4cc63..14a7887 100644
--- a/pkg/compiler/lib/src/helpers/helpers.dart
+++ b/pkg/compiler/lib/src/helpers/helpers.dart
@@ -10,14 +10,13 @@
 import '../common.dart';
 import '../diagnostics/invariant.dart' show DEBUG_MODE;
 import '../util/util.dart';
-
 import 'trace.dart';
 
 export 'debug_collection.dart';
-export 'trace.dart';
 export 'expensive_map.dart';
 export 'expensive_set.dart';
 export 'stats.dart';
+export 'trace.dart';
 export 'track_map.dart';
 
 /// Global flag to enable [debugPrint]. This should always be `true` by default
diff --git a/pkg/compiler/lib/src/inferrer/closure_tracer.dart b/pkg/compiler/lib/src/inferrer/closure_tracer.dart
index ed2d198..80b7e3d 100644
--- a/pkg/compiler/lib/src/inferrer/closure_tracer.dart
+++ b/pkg/compiler/lib/src/inferrer/closure_tracer.dart
@@ -4,13 +4,13 @@
 
 library compiler.src.inferrer.closure_tracer;
 
-import '../types/types.dart' show TypeMask;
 import '../common/names.dart' show Names;
 import '../elements/elements.dart';
+import '../types/types.dart' show TypeMask;
 import '../universe/selector.dart' show Selector;
+import 'debug.dart' as debug;
 import 'node_tracer.dart';
 import 'type_graph_nodes.dart';
-import 'debug.dart' as debug;
 
 class ClosureTracerVisitor extends TracerVisitor<ApplyableTypeInformation> {
   final Iterable<FunctionElement> tracedElements;
diff --git a/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart b/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart
index 8286b33..eebe56f 100644
--- a/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart
+++ b/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart
@@ -16,8 +16,8 @@
 import '../resolution/semantic_visitor.dart';
 import '../resolution/tree_elements.dart' show TreeElements;
 import '../tree/tree.dart';
-import '../types/types.dart' show TypeMask;
 import '../types/constants.dart' show computeTypeMask;
+import '../types/types.dart' show TypeMask;
 import '../universe/call_structure.dart' show CallStructure;
 import '../universe/selector.dart' show Selector;
 import '../util/util.dart';
diff --git a/pkg/compiler/lib/src/inferrer/list_tracer.dart b/pkg/compiler/lib/src/inferrer/list_tracer.dart
index 83f2e8b..d0985e0 100644
--- a/pkg/compiler/lib/src/inferrer/list_tracer.dart
+++ b/pkg/compiler/lib/src/inferrer/list_tracer.dart
@@ -7,7 +7,6 @@
 import '../elements/elements.dart';
 import '../universe/selector.dart' show Selector;
 import '../util/util.dart' show Setlet;
-
 import 'node_tracer.dart';
 import 'type_graph_nodes.dart';
 
diff --git a/pkg/compiler/lib/src/inferrer/map_tracer.dart b/pkg/compiler/lib/src/inferrer/map_tracer.dart
index 3bd0e41..22a9f0f 100644
--- a/pkg/compiler/lib/src/inferrer/map_tracer.dart
+++ b/pkg/compiler/lib/src/inferrer/map_tracer.dart
@@ -6,7 +6,6 @@
 
 import '../elements/elements.dart';
 import '../universe/selector.dart' show Selector;
-
 import 'node_tracer.dart';
 import 'type_graph_nodes.dart';
 
diff --git a/pkg/compiler/lib/src/inferrer/node_tracer.dart b/pkg/compiler/lib/src/inferrer/node_tracer.dart
index dca18a5..cc890bf 100644
--- a/pkg/compiler/lib/src/inferrer/node_tracer.dart
+++ b/pkg/compiler/lib/src/inferrer/node_tracer.dart
@@ -9,10 +9,9 @@
 import '../elements/elements.dart';
 import '../types/types.dart' show ContainerTypeMask, MapTypeMask;
 import '../util/util.dart' show Setlet;
-
+import 'debug.dart' as debug;
 import 'type_graph_inferrer.dart' show TypeGraphInferrerEngine;
 import 'type_graph_nodes.dart';
-import 'debug.dart' as debug;
 
 // A set of selectors we know do not escape the elements inside the
 // list.
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_dump.dart b/pkg/compiler/lib/src/inferrer/type_graph_dump.dart
index 3e68725..8024e52 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_dump.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_dump.dart
@@ -4,10 +4,11 @@
 library dart2js.inferrer.type_graph_dump;
 
 import 'dart:async';
-import 'type_graph_nodes.dart';
-import 'type_graph_inferrer.dart';
+
 import '../elements/elements.dart';
 import '../types/types.dart';
+import 'type_graph_inferrer.dart';
+import 'type_graph_nodes.dart';
 
 /// Dumps the type inference graph in Graphviz Dot format into the `typegraph`
 /// subfolder of the current working directory. Each function body is dumped in
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
index 4f185c2..d610c54 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
@@ -15,8 +15,8 @@
 import '../elements/elements.dart';
 import '../js_backend/js_backend.dart' show Annotations, JavaScriptBackend;
 import '../resolution/tree_elements.dart' show TreeElementMapping;
-import '../tree/tree.dart' as ast show Node, LiteralBool, TryStatement;
 import '../tree/dartstring.dart' show DartString;
+import '../tree/tree.dart' as ast show Node, LiteralBool, TryStatement;
 import '../types/constants.dart' show computeTypeMask;
 import '../types/types.dart'
     show ContainerTypeMask, MapTypeMask, TypeMask, TypesInferrer;
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
index 1a6842f..c21b118 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
@@ -13,9 +13,8 @@
 import '../cps_ir/cps_ir_nodes.dart' as cps_ir show Node;
 import '../dart_types.dart' show DartType, FunctionType, TypeKind;
 import '../elements/elements.dart';
-import '../native/native.dart' as native;
-import '../tree/tree.dart' as ast show Node, LiteralBool, Send;
 import '../tree/dartstring.dart' show DartString;
+import '../tree/tree.dart' as ast show Node, LiteralBool, Send;
 import '../types/types.dart'
     show
         ContainerTypeMask,
diff --git a/pkg/compiler/lib/src/info/analysis_result.dart b/pkg/compiler/lib/src/info/analysis_result.dart
deleted file mode 100644
index 5266a01..0000000
--- a/pkg/compiler/lib/src/info/analysis_result.dart
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/// API to get results from a static analysis of the source program.
-library compiler.src.stats.analysis_result;
-
-import '../tree/tree.dart' show Node;
-import '../universe/selector.dart' show Selector;
-
-/// A three-value logic bool (yes, no, maybe). We say that `yes` and `maybe` are
-/// "truthy", while `no` and `maybe` are "falsy".
-// TODO(sigmund): is it worth using an enum? or switch to true/false/null?
-enum Boolish { yes, no, maybe }
-
-/// Specifies results of some kind of static analysis on a source program.
-abstract class AnalysisResult {
-  /// Information computed about a specific [receiver].
-  ReceiverInfo infoForReceiver(Node receiver);
-
-  /// Information computed about a specific [selector] applied to a specific
-  /// [receiver].
-  SelectorInfo infoForSelector(Node receiver, Selector selector);
-}
-
-/// Analysis information about a receiver of a send.
-abstract class ReceiverInfo {
-  /// Receiver node for which this information is computed.
-  Node get receiver;
-
-  /// Return whether [receiver] resolves to a value that implements no such
-  /// method. The answer is `yes` if all values that [receiver] could evaluate
-  /// to at runtime contain it, or `no` if none of them does. Maybe if it
-  /// depends on some context or we can't determine this information precisely.
-  Boolish get hasNoSuchMethod;
-
-  /// When [hasNoSuchMethod] is yes, the precise number of possible noSuchMethod
-  /// handlers for this receiver.
-  int get possibleNsmTargets;
-
-  /// Return whether [receiver] may ever be null.
-  Boolish get isNull;
-}
-
-/// Information about a specific selector applied to a specific receiver.
-abstract class SelectorInfo {
-  /// Receiver node of the [selector].
-  Node get receiver;
-
-  /// Specific selector on [receiver] for which this information is computed.
-  Selector get selector;
-
-  /// Whether a member matching [selector] exists in [receiver].
-  Boolish get exists;
-
-  /// Whether [receiver] needs an interceptor to implement [selector].
-  Boolish get usesInterceptor;
-
-  /// Possible total number of methods that could be the target of the selector.
-  /// This needs to be combined with [isAccurate] to correctly understand the
-  /// value. Some invariants:
-  ///
-  ///   * If [exists] is `no`, the value here should be 0, regardless of
-  ///   accuracy.
-  ///   * If [exists] is `yes`, the value is always considered 1 or more.
-  ///     If [isAccurate] is false, we treat it as there may be many possible
-  ///     targets.
-  ///   * If [exists] is `maybe`, the value is considered 0 or more.
-  int get possibleTargets;
-
-  /// Whether the information about [possibleTargets] is accurate.
-  bool get isAccurate;
-}
diff --git a/pkg/compiler/lib/src/info/naive_analysis_result.dart b/pkg/compiler/lib/src/info/naive_analysis_result.dart
deleted file mode 100644
index d18dc91..0000000
--- a/pkg/compiler/lib/src/info/naive_analysis_result.dart
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/// API to get results from a static analysis of the source program.
-// TODO(sigmund): split out implementations out of this file.
-library compiler.src.stats.naive_analysis_result;
-
-import 'analysis_result.dart';
-import '../tree/tree.dart' show Node;
-import '../universe/selector.dart' show Selector;
-
-/// A naive [AnalysisResult] that tells us very little. This is the most
-/// conservative we can be when we only use information from the AST structure
-/// and from resolution, but no type information.
-class NaiveAnalysisResult implements AnalysisResult {
-  NaiveAnalysisResult();
-
-  ReceiverInfo infoForReceiver(Node receiver) =>
-      new NaiveReceiverInfo(receiver);
-  SelectorInfo infoForSelector(Node receiver, Selector selector) =>
-      new NaiveSelectorInfo(receiver, selector);
-}
-
-class NaiveReceiverInfo implements ReceiverInfo {
-  final Node receiver;
-
-  NaiveReceiverInfo(this.receiver);
-  Boolish get hasNoSuchMethod => Boolish.maybe;
-  Boolish get isNull => Boolish.maybe;
-  int get possibleNsmTargets => -1;
-}
-
-class NaiveSelectorInfo implements SelectorInfo {
-  final Node receiver;
-  final Selector selector;
-
-  NaiveSelectorInfo(this.receiver, this.selector);
-
-  Boolish get exists => Boolish.maybe;
-  Boolish get usesInterceptor => Boolish.maybe;
-  int get possibleTargets => -1;
-  bool get isAccurate => false;
-}
diff --git a/pkg/compiler/lib/src/info/send_info.dart b/pkg/compiler/lib/src/info/send_info.dart
deleted file mode 100644
index 86f3845..0000000
--- a/pkg/compiler/lib/src/info/send_info.dart
+++ /dev/null
@@ -1,2415 +0,0 @@
-// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/// Computes measurements about sends in a function.
-library compiler.src.info.send_info;
-
-import 'package:dart2js_info/src/measurements.dart';
-import 'package:dart2js_info/src/util.dart' show recursiveDiagnosticString;
-
-import '../closure.dart';
-import '../common.dart';
-import '../compiler.dart' show Compiler;
-import '../constants/expressions.dart';
-import '../dart_types.dart';
-import '../elements/elements.dart';
-import '../elements/visitor.dart' show ElementVisitor;
-import '../parser/partial_elements.dart' show PartialElement;
-import '../resolution/operators.dart';
-import '../resolution/semantic_visitor.dart';
-import '../resolution/tree_elements.dart';
-import '../tree/tree.dart';
-import '../universe/call_structure.dart' show CallStructure;
-import '../universe/selector.dart' show Selector;
-import 'analysis_result.dart';
-import 'naive_analysis_result.dart';
-import 'trusted_types_analysis_result.dart';
-
-/// Collects a set of [Measurements] about send expressions in the function [f].
-// TODO(sigmund): collect information on initializers too.
-Measurements collectSendMeasurements(FunctionElement f, Compiler compiler) {
-  DiagnosticReporter reporter = compiler.reporter;
-  return reporter.withCurrentElement(f, () {
-    // TODO(sigmund): enable for platform too.
-    if (f.library.isPlatformLibrary) return null;
-    if (!f.hasNode) {
-      if (f is PartialElement) return const Measurements.unreachableFunction();
-      assert(f is ConstructorElement && f.isSynthesized);
-      // TODO(sigmund): measure synthethic forwarding sends, measure
-      // initializers
-      return new Measurements.reachableFunction();
-    }
-    if (!f.hasResolvedAst) {
-      _debug('no resolved ast ${f.runtimeType}');
-      return null;
-    }
-    var resolvedAst = f.resolvedAst;
-    if (resolvedAst.node == null) {
-      _debug('no node ${f.runtimeType}');
-      return null;
-    }
-    var def = resolvedAst.elements.getFunctionDefinition(resolvedAst.node);
-    if (def == null) {
-      assert(f is PartialElement);
-      return const Measurements.unreachableFunction();
-    }
-
-    var visitor = new _StatsTraversalVisitor(compiler, resolvedAst.elements,
-        reporter.spanFromSpannable(resolvedAst.node).uri);
-    resolvedAst.node.accept(visitor);
-    return visitor.measurements;
-  });
-}
-
-/// Visitor that categorizes data about an individual send.
-class _StatsVisitor<T> extends Visitor
-    with SemanticSendResolvedMixin<dynamic, T>
-    implements SemanticSendVisitor<dynamic, T> {
-  // TODO(sigmund): consider passing in several AnalysisResults at once, so we
-  // can compute the different metrics together.
-  /// Information we know about the program from static analysis.
-  final AnalysisResult info;
-
-  /// Results from this function.
-  final Measurements measurements;
-
-  final DiagnosticReporter reporter;
-  final TreeElements elements;
-
-  SemanticSendVisitor<dynamic, T> get sendVisitor => this;
-
-  _StatsVisitor(this.reporter, this.elements, this.info, Uri sourceUri)
-      : measurements = new Measurements.reachableFunction(sourceUri);
-
-  visitNode(Node node) => throw "unhandled ${node.runtimeType}: $node";
-  apply(Node node, T arg) => throw "missing apply ${node.runtimeType}: $node";
-  internalError(Node node, String arg) => throw "internal error on $node";
-
-  visitSend(Send node) {
-    _checkInvariant(node, 'before');
-    var span = reporter.spanFromSpannable(node);
-    measurements.record(Metric.send, span.begin, span.end);
-    if (node is SendSet) {
-      if ((node.assignmentOperator != null &&
-              node.assignmentOperator.source != '=') ||
-          node.isPrefix ||
-          node.isPostfix) {
-        assert(!node.isIfNullAssignment);
-        // We count get and set separately in case one of them is defined by the
-        // other could be a nSM error.
-        measurements.record(Metric.send, span.begin, span.end);
-        measurements.record(Metric.send, span.begin, span.end);
-      } else if (node.isIfNullAssignment) {
-        measurements.record(Metric.send, span.begin, span.end);
-      }
-    }
-    super.visitSend(node);
-    _checkInvariant(node, 'after ');
-  }
-
-  visitNewExpression(NewExpression node) {
-    _checkInvariant(node, 'before');
-    var span = reporter.spanFromSpannable(node);
-    measurements.record(Metric.send, span.begin, span.end);
-    super.visitNewExpression(node);
-    _checkInvariant(node, 'after ');
-  }
-
-  /// A monomorphic local variable read.
-  ///
-  /// See [Metric.send] for a full categorization of sends.
-  handleLocal(Node node) {
-    var span = reporter.spanFromSpannable(node);
-    measurements.record(Metric.monomorphicSend, span.begin, span.end);
-    measurements.record(Metric.localSend, span.begin, span.end);
-  }
-
-  /// A monomorphic virual call on [node], where we know which function is the
-  /// target of the call (for example, because only one type in a class
-  /// hierarchy implements a function with a given name).
-  ///
-  /// See [Metric.send] for a full categorization of sends.
-  handleSingleInstance(Node node) {
-    var span = reporter.spanFromSpannable(node);
-    measurements.record(Metric.monomorphicSend, span.begin, span.end);
-    measurements.record(Metric.instanceSend, span.begin, span.end);
-  }
-
-  /// A monomorphic call that goes through an interceptor. This is equivalent in
-  /// terms of what the compiler knows as we do with [handleSignleInstance], and
-  /// because we know the target of the call, we also know that it doesn't live
-  /// in the object instance, but on an interceptor on the side.
-  ///
-  /// See [Metric.send] for a full categorization of sends.
-  handleSingleInterceptor(Node node) {
-    var span = reporter.spanFromSpannable(node);
-    measurements.record(Metric.monomorphicSend, span.begin, span.end);
-    measurements.record(Metric.interceptorSend, span.begin, span.end);
-  }
-
-  /// A polymorphic call that goes through an interceptor.
-  ///
-  /// See [Metric.send] for a full categorization of sends.
-  handleMultiInterceptor(Node node) {
-    var span = reporter.spanFromSpannable(node);
-    measurements.record(Metric.polymorphicSend, span.begin, span.end);
-    measurements.record(Metric.multiInterceptorSend, span.begin, span.end);
-  }
-
-  handleConstructor(Node node) {
-    var span = reporter.spanFromSpannable(node);
-    measurements.record(Metric.monomorphicSend, span.begin, span.end);
-    measurements.record(Metric.constructorSend, span.begin, span.end);
-  }
-
-  handleDynamic(Node node) {
-    var span = reporter.spanFromSpannable(node);
-    measurements.record(Metric.polymorphicSend, span.begin, span.end);
-    measurements.record(Metric.dynamicSend, span.begin, span.end);
-  }
-
-  handleVirtual(Node node) {
-    var span = reporter.spanFromSpannable(node);
-    measurements.record(Metric.polymorphicSend, span.begin, span.end);
-    measurements.record(Metric.virtualSend, span.begin, span.end);
-  }
-
-  handleNSMError(Node node) {
-    var span = reporter.spanFromSpannable(node);
-    measurements.record(Metric.monomorphicSend, span.begin, span.end);
-    measurements.record(Metric.nsmErrorSend, span.begin, span.end);
-  }
-
-  handleNSMSingle(Node node) {
-    var span = reporter.spanFromSpannable(node);
-    measurements.record(Metric.monomorphicSend, span.begin, span.end);
-    measurements.record(Metric.singleNsmCallSend, span.begin, span.end);
-  }
-
-  handleNSMSuper(Node node, ClassElement type) {
-    var superclass = type.superclass;
-    var member = superclass.lookupMember('noSuchMethod');
-    if (!member.enclosingClass.isObject) {
-      handleNSMSingle(node);
-    } else {
-      handleNSMError(node);
-    }
-  }
-
-  handleNSMAny(Node node) {
-    var span = reporter.spanFromSpannable(node);
-    measurements.record(Metric.polymorphicSend, span.begin, span.end);
-    measurements.record(Metric.multiNsmCallSend, span.begin, span.end);
-  }
-
-  handleSuper(Node node) {
-    var span = reporter.spanFromSpannable(node);
-    measurements.record(Metric.monomorphicSend, span.begin, span.end);
-    measurements.record(Metric.superSend, span.begin, span.end);
-  }
-
-  handleTypeVariable(Node node) {
-    var span = reporter.spanFromSpannable(node);
-    measurements.record(Metric.monomorphicSend, span.begin, span.end);
-    measurements.record(Metric.typeVariableSend, span.begin, span.end);
-  }
-
-  handleStatic(Node node) {
-    var span = reporter.spanFromSpannable(node);
-    measurements.record(Metric.monomorphicSend, span.begin, span.end);
-    measurements.record(Metric.staticSend, span.begin, span.end);
-  }
-
-  handleNoSend(Node node) {
-    measurements.popLast(Metric.send);
-  }
-
-  void handleDynamicProperty(Node node, Node receiver, Selector selector) {
-    // staticSend: no (automatically)
-    // superSend: no (automatically)
-    // localSend: no (automatically)
-    // constructorSend: no (automatically)
-    // typeVariableSend: no (automatically)
-
-    // nsmErrorSend:      receiver has no `selector` nor nSM.
-    // singleNsmCallSend: receiver has no `selector`, but definitely has `nSM`
-    // instanceSend:      receiver has `selector`, no need to use an interceptor
-    // interceptorSend:   receiver has `selector`, but we know we need an
-    //                    interceptor to get it
-
-    // multiNsmCallSend:  receiver has no `selector`, not sure if receiver has
-    //                    nSM, or not sure which nSM is called (does this one
-    //                    matter, or does nSM is treated like an instance method
-    //                    call)?
-    // virtualSend:       receiver has `selector`, we know we do not need an
-    //                    interceptor, not sure which specific type implements
-    //                    the selector.
-    // multiInterceptorSend: multiple possible receiver types, all using an
-    //                       interceptor to get the `selector`, might be
-    //                       possbile to pick a special selector logic for this
-    //                       combination?
-    // dynamicSend: any combination of the above.
-
-    ReceiverInfo receiverInfo = info.infoForReceiver(receiver);
-    SelectorInfo selectorInfo = info.infoForSelector(receiver, selector);
-    Boolish hasSelector = selectorInfo.exists;
-    Boolish hasNsm = receiverInfo.hasNoSuchMethod;
-
-    if (hasSelector == Boolish.no) {
-      if (hasNsm == Boolish.no) {
-        handleNSMError(node);
-      } else if (hasNsm == Boolish.yes) {
-        if (receiverInfo.possibleNsmTargets == 1) {
-          handleNSMSingle(node);
-        } else {
-          handleNSMAny(node);
-        }
-      } else {
-        handleDynamic(node);
-      }
-      return;
-    }
-
-    Boolish usesInterceptor = selectorInfo.usesInterceptor;
-    if (hasSelector == Boolish.yes) {
-      if (selectorInfo.isAccurate && selectorInfo.possibleTargets == 1) {
-        assert(usesInterceptor != Boolish.maybe);
-        if (usesInterceptor == Boolish.yes) {
-          handleSingleInterceptor(node);
-        } else {
-          handleSingleInstance(node);
-        }
-      } else {
-        if (usesInterceptor == Boolish.no) {
-          handleVirtual(node);
-        } else if (usesInterceptor == Boolish.yes) {
-          handleMultiInterceptor(node);
-        } else {
-          handleDynamic(node);
-        }
-      }
-      return;
-    }
-    handleDynamic(node);
-  }
-
-  void handleThisProperty(Send node, Selector selector) {
-    handleDynamicProperty(node, node.receiver, selector);
-  }
-
-  void handleIndex(Node node) {
-    handleDynamic(node);
-  }
-
-  void handleOperator(Node node) {
-    handleDynamic(node);
-  }
-
-  void handleInvoke(Node node) {
-    handleDynamic(node);
-  }
-
-  void handleEquals(Node node) {
-    handleDynamic(node);
-  }
-
-  // Constructors
-
-  void visitAbstractClassConstructorInvoke(
-      NewExpression node,
-      ConstructorElement element,
-      InterfaceType type,
-      NodeList arguments,
-      CallStructure callStructure,
-      T arg) {
-    handleConstructor(node);
-  }
-
-  void visitBoolFromEnvironmentConstructorInvoke(NewExpression node,
-      BoolFromEnvironmentConstantExpression constant, T arg) {
-    handleConstructor(node);
-  }
-
-  void visitConstConstructorInvoke(
-      NewExpression node, ConstructedConstantExpression constant, T arg) {
-    handleConstructor(node);
-  }
-
-  void visitGenerativeConstructorInvoke(
-      NewExpression node,
-      ConstructorElement constructor,
-      InterfaceType type,
-      NodeList arguments,
-      CallStructure callStructure,
-      T arg) {
-    handleConstructor(node);
-  }
-
-  void visitIntFromEnvironmentConstructorInvoke(NewExpression node,
-      IntFromEnvironmentConstantExpression constant, T arg) {
-    handleConstructor(node);
-  }
-
-  void visitRedirectingFactoryConstructorInvoke(
-      NewExpression node,
-      ConstructorElement constructor,
-      InterfaceType type,
-      ConstructorElement effectiveTarget,
-      InterfaceType effectiveTargetType,
-      NodeList arguments,
-      CallStructure callStructure,
-      T arg) {
-    handleConstructor(node);
-  }
-
-  void visitRedirectingGenerativeConstructorInvoke(
-      NewExpression node,
-      ConstructorElement constructor,
-      InterfaceType type,
-      NodeList arguments,
-      CallStructure callStructure,
-      T arg) {
-    handleConstructor(node);
-  }
-
-  void visitStringFromEnvironmentConstructorInvoke(NewExpression node,
-      StringFromEnvironmentConstantExpression constant, T arg) {
-    handleConstructor(node);
-  }
-
-  // Dynamic sends
-
-  // TODO(sigmund): many many things to add:
-  // -- support for operators, indexers, etc.
-  // -- logic about nullables
-  // -- int, JSArray
-  // -- all interceptors
-
-  void visitBinary(
-      Send node, Node left, BinaryOperator operator, Node right, T arg) {
-    handleOperator(node);
-  }
-
-  void visitCompoundIndexSet(SendSet node, Node receiver, Node index,
-      AssignmentOperator operator, Node rhs, T arg) {
-    handleIndex(node); // t1 = receiver[index]
-    handleOperator(node); // t2 = t1 op rhs
-    handleIndex(node); // receiver[index] = t2
-  }
-
-  void visitDynamicPropertyCompound(Send node, Node receiver, Name name,
-      AssignmentOperator operator, Node rhs, T arg) {
-    handleDynamicProperty(node, receiver, new Selector.getter(name));
-    handleOperator(node);
-    handleDynamicProperty(node, receiver, new Selector.setter(name));
-  }
-
-  void visitDynamicPropertyGet(Send node, Node receiver, Name name, T arg) {
-    handleDynamicProperty(node, receiver, new Selector.getter(name));
-  }
-
-  void visitDynamicPropertyInvoke(
-      Send node, Node receiver, NodeList arguments, Selector selector, T arg) {
-    handleDynamicProperty(node, receiver, selector);
-  }
-
-  void visitDynamicPropertyPostfix(
-      Send node, Node receiver, Name name, IncDecOperator operator, T arg) {
-    handleDynamicProperty(node, receiver, new Selector.getter(name));
-    handleOperator(node);
-    handleDynamicProperty(node, receiver, new Selector.setter(name));
-  }
-
-  void visitDynamicPropertyPrefix(
-      Send node, Node receiver, Name name, IncDecOperator operator, T arg) {
-    handleDynamicProperty(node, receiver, new Selector.getter(name));
-    handleOperator(node);
-    handleDynamicProperty(node, receiver, new Selector.setter(name));
-  }
-
-  void visitDynamicPropertySet(
-      SendSet node, Node receiver, Name name, Node rhs, T arg) {
-    handleDynamicProperty(node, receiver, new Selector.setter(name));
-  }
-
-  void visitDynamicPropertySetIfNull(
-      Send node, Node receiver, Name name, Node rhs, T arg) {
-    // read to check for null?
-    handleDynamicProperty(node, receiver, new Selector.getter(name));
-    handleDynamicProperty(node, receiver, new Selector.setter(name));
-  }
-
-  void visitEquals(Send node, Node left, Node right, T arg) {
-    handleEquals(node);
-  }
-
-  void visitExpressionInvoke(Send node, Node expression, NodeList arguments,
-      CallStructure callStructure, T arg) {
-    handleInvoke(node);
-  }
-
-  void visitIfNotNullDynamicPropertyCompound(Send node, Node receiver,
-      Name name, AssignmentOperator operator, Node rhs, T arg) {
-    handleDynamicProperty(node, receiver, new Selector.getter(name));
-    handleOperator(node);
-    handleDynamicProperty(node, receiver, new Selector.setter(name));
-  }
-
-  void visitIfNotNullDynamicPropertyGet(
-      Send node, Node receiver, Name name, T arg) {
-    handleDynamicProperty(node, receiver, new Selector.getter(name));
-  }
-
-  void visitIfNotNullDynamicPropertyInvoke(
-      Send node, Node receiver, NodeList arguments, Selector selector, T arg) {
-    handleDynamicProperty(node, receiver, selector);
-  }
-
-  void visitIfNotNullDynamicPropertyPostfix(
-      Send node, Node receiver, Name name, IncDecOperator operator, T arg) {
-    handleDynamicProperty(node, receiver, new Selector.getter(name));
-    handleOperator(node);
-    handleDynamicProperty(node, receiver, new Selector.setter(name));
-  }
-
-  void visitIfNotNullDynamicPropertyPrefix(
-      Send node, Node receiver, Name name, IncDecOperator operator, T arg) {
-    handleDynamicProperty(node, receiver, new Selector.getter(name));
-    handleOperator(node);
-    handleDynamicProperty(node, receiver, new Selector.setter(name));
-  }
-
-  void visitIfNotNullDynamicPropertySet(
-      SendSet node, Node receiver, Name name, Node rhs, T arg) {
-    handleDynamicProperty(node, receiver, new Selector.setter(name));
-  }
-
-  void visitIfNotNullDynamicPropertySetIfNull(
-      Send node, Node receiver, Name name, Node rhs, T arg) {
-    handleDynamicProperty(node, receiver, new Selector.getter(name));
-    handleDynamicProperty(node, receiver, new Selector.setter(name));
-  }
-
-  void visitIndex(Send node, Node receiver, Node index, T arg) {
-    handleIndex(node);
-  }
-
-  void visitIndexPostfix(
-      Send node, Node receiver, Node index, IncDecOperator operator, T arg) {
-    handleIndex(node);
-    handleOperator(node);
-    handleIndex(node);
-  }
-
-  void visitIndexPrefix(
-      Send node, Node receiver, Node index, IncDecOperator operator, T arg) {
-    handleIndex(node);
-    handleOperator(node);
-    handleIndex(node);
-  }
-
-  void visitIndexSet(SendSet node, Node receiver, Node index, Node rhs, T arg) {
-    handleIndex(node);
-  }
-
-  void visitLocalVariableCompound(Send node, LocalVariableElement variable,
-      AssignmentOperator operator, Node rhs, T arg) {
-    handleLocal(node);
-    handleOperator(node);
-    handleLocal(node);
-  }
-
-  void visitLocalVariableInvoke(Send node, LocalVariableElement variable,
-      NodeList arguments, CallStructure callStructure, T arg) {
-    handleInvoke(node);
-  }
-
-  void visitLocalVariablePostfix(Send node, LocalVariableElement variable,
-      IncDecOperator operator, T arg) {
-    handleLocal(node);
-    handleOperator(node);
-    handleLocal(node);
-  }
-
-  void visitLocalVariablePrefix(Send node, LocalVariableElement variable,
-      IncDecOperator operator, T arg) {
-    handleLocal(node);
-    handleOperator(node);
-    handleLocal(node);
-  }
-
-  void visitNotEquals(Send node, Node left, Node right, T arg) {
-    handleEquals(node);
-  }
-
-  void visitParameterCompound(Send node, ParameterElement parameter,
-      AssignmentOperator operator, Node rhs, T arg) {
-    handleLocal(node);
-    handleOperator(node);
-    handleLocal(node);
-  }
-
-  void visitParameterInvoke(Send node, ParameterElement parameter,
-      NodeList arguments, CallStructure callStructure, T arg) {
-    handleInvoke(node);
-  }
-
-  void visitParameterPostfix(
-      Send node, ParameterElement parameter, IncDecOperator operator, T arg) {
-    handleLocal(node);
-    handleOperator(node);
-    handleLocal(node);
-  }
-
-  void visitParameterPrefix(
-      Send node, ParameterElement parameter, IncDecOperator operator, T arg) {
-    handleLocal(node);
-    handleOperator(node);
-    handleLocal(node);
-  }
-
-  void visitStaticFieldCompound(Send node, FieldElement field,
-      AssignmentOperator operator, Node rhs, T arg) {
-    handleStatic(node);
-    handleOperator(node);
-    handleStatic(node);
-  }
-
-  void visitStaticFieldInvoke(Send node, FieldElement field, NodeList arguments,
-      CallStructure callStructure, T arg) {
-    handleInvoke(node);
-  }
-
-  void visitStaticFieldPostfix(
-      Send node, FieldElement field, IncDecOperator operator, T arg) {
-    handleStatic(node);
-    handleOperator(node);
-    handleStatic(node);
-  }
-
-  void visitStaticFieldPrefix(
-      Send node, FieldElement field, IncDecOperator operator, T arg) {
-    handleStatic(node);
-    handleOperator(node);
-    handleStatic(node);
-  }
-
-  void visitStaticGetterInvoke(Send node, FunctionElement getter,
-      NodeList arguments, CallStructure callStructure, T arg) {
-    handleInvoke(node);
-  }
-
-  void visitStaticGetterSetterCompound(Send node, FunctionElement getter,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, T arg) {
-    handleStatic(node);
-    handleOperator(node);
-    handleStatic(node);
-  }
-
-  void visitStaticGetterSetterPostfix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, T arg) {
-    handleStatic(node);
-    handleOperator(node);
-    handleStatic(node);
-  }
-
-  void visitStaticGetterSetterPrefix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, T arg) {
-    handleStatic(node);
-    handleOperator(node);
-    handleStatic(node);
-  }
-
-  void visitSuperFieldCompound(Send node, FieldElement field,
-      AssignmentOperator operator, Node rhs, T arg) {
-    handleSuper(node);
-    handleOperator(node);
-    handleSuper(node);
-  }
-
-  void visitSuperFieldFieldCompound(Send node, FieldElement readField,
-      FieldElement writtenField, AssignmentOperator operator, Node rhs, T arg) {
-    handleSuper(node);
-    handleOperator(node);
-    handleSuper(node);
-  }
-
-  void visitSuperFieldFieldPostfix(Send node, FieldElement readField,
-      FieldElement writtenField, IncDecOperator operator, T arg) {
-    handleSuper(node);
-    handleOperator(node);
-    handleSuper(node);
-  }
-
-  void visitSuperFieldFieldPrefix(Send node, FieldElement readField,
-      FieldElement writtenField, IncDecOperator operator, T arg) {
-    handleSuper(node);
-    handleOperator(node);
-    handleSuper(node);
-  }
-
-  void visitSuperFieldFieldSetIfNull(Send node, FieldElement readField,
-      FieldElement writtenField, Node rhs, T arg) {
-    handleSuper(node);
-    handleNSMSuper(node, readField.enclosingClass);
-  }
-
-  void visitSuperFieldInvoke(Send node, FieldElement field, NodeList arguments,
-      CallStructure callStructure, T arg) {
-    handleInvoke(node);
-  }
-
-  void visitSuperFieldPostfix(
-      Send node, FieldElement field, IncDecOperator operator, T arg) {
-    handleSuper(node);
-    handleOperator(node);
-    handleSuper(node);
-  }
-
-  void visitSuperFieldPrefix(
-      Send node, FieldElement field, IncDecOperator operator, T arg) {
-    handleSuper(node);
-    handleOperator(node);
-    handleSuper(node);
-  }
-
-  void visitSuperFieldSetterCompound(Send node, FieldElement field,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, T arg) {
-    handleSuper(node);
-    handleOperator(node);
-    handleSuper(node);
-  }
-
-  void visitSuperFieldSetterPostfix(Send node, FieldElement field,
-      FunctionElement setter, IncDecOperator operator, T arg) {
-    handleSuper(node);
-    handleOperator(node);
-    handleSuper(node);
-  }
-
-  void visitSuperFieldSetterPrefix(Send node, FieldElement field,
-      FunctionElement setter, IncDecOperator operator, T arg) {
-    handleSuper(node);
-    handleOperator(node);
-    handleSuper(node);
-  }
-
-  void visitSuperFieldSetterSetIfNull(
-      Send node, FieldElement field, FunctionElement setter, Node rhs, T arg) {
-    handleSuper(node);
-    handleSuper(node);
-  }
-
-  void visitSuperGetterFieldCompound(Send node, FunctionElement getter,
-      FieldElement field, AssignmentOperator operator, Node rhs, T arg) {
-    handleSuper(node);
-    handleOperator(node);
-    handleSuper(node);
-  }
-
-  void visitSuperGetterFieldPostfix(Send node, FunctionElement getter,
-      FieldElement field, IncDecOperator operator, T arg) {
-    handleSuper(node);
-    handleOperator(node);
-    handleSuper(node);
-  }
-
-  void visitSuperGetterFieldPrefix(Send node, FunctionElement getter,
-      FieldElement field, IncDecOperator operator, T arg) {
-    handleSuper(node);
-    handleOperator(node);
-    handleSuper(node);
-  }
-
-  void visitSuperGetterFieldSetIfNull(
-      Send node, FunctionElement getter, FieldElement field, Node rhs, T arg) {
-    handleSuper(node);
-    handleSuper(node);
-  }
-
-  void visitSuperGetterInvoke(Send node, FunctionElement getter,
-      NodeList arguments, CallStructure callStructure, T arg) {
-    handleInvoke(node);
-  }
-
-  void visitSuperGetterSetterCompound(Send node, FunctionElement getter,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, T arg) {
-    handleSuper(node);
-    handleOperator(node);
-    handleSuper(node);
-  }
-
-  void visitSuperGetterSetterPostfix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, T arg) {
-    handleSuper(node);
-    handleOperator(node);
-    handleSuper(node);
-  }
-
-  void visitSuperGetterSetterPrefix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, T arg) {
-    handleSuper(node);
-    handleOperator(node);
-    handleSuper(node);
-  }
-
-  void visitSuperGetterSetterSetIfNull(Send node, FunctionElement getter,
-      FunctionElement setter, Node rhs, T arg) {
-    handleSuper(node);
-    handleSuper(node);
-  }
-
-  void visitSuperIndexPostfix(
-      Send node,
-      MethodElement indexFunction,
-      MethodElement indexSetFunction,
-      Node index,
-      IncDecOperator operator,
-      T arg) {
-    handleSuper(node);
-    handleOperator(node);
-    handleSuper(node);
-  }
-
-  void visitSuperIndexPrefix(
-      Send node,
-      MethodElement indexFunction,
-      MethodElement indexSetFunction,
-      Node index,
-      IncDecOperator operator,
-      T arg) {
-    handleSuper(node);
-    handleOperator(node);
-    handleSuper(node);
-  }
-
-  void visitSuperMethodSetterCompound(Send node, FunctionElement method,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, T arg) {
-    handleSuper(node);
-    handleNSMSuper(node, method.enclosingClass);
-    handleSuper(node);
-  }
-
-  void visitSuperMethodSetterPostfix(Send node, FunctionElement method,
-      FunctionElement setter, IncDecOperator operator, T arg) {
-    handleSuper(node);
-    handleNSMSuper(node, method.enclosingClass);
-    handleSuper(node);
-  }
-
-  void visitSuperMethodSetterPrefix(Send node, FunctionElement method,
-      FunctionElement setter, IncDecOperator operator, T arg) {
-    handleSuper(node);
-    handleNSMSuper(node, method.enclosingClass);
-    handleSuper(node);
-  }
-
-  void visitSuperMethodSetterSetIfNull(Send node, FunctionElement method,
-      FunctionElement setter, Node rhs, T arg) {
-    handleSuper(node);
-    handleSuper(node);
-  }
-
-  void visitThisPropertyCompound(
-      Send node, Name name, AssignmentOperator operator, Node rhs, T arg) {
-    handleThisProperty(node, new Selector.getter(name));
-    handleOperator(node);
-    handleThisProperty(node, new Selector.setter(name));
-  }
-
-  void visitThisPropertyInvoke(
-      Send node, NodeList arguments, Selector selector, T arg) {
-    handleThisProperty(node, selector);
-  }
-
-  void visitThisPropertyPostfix(
-      Send node, Name name, IncDecOperator operator, T arg) {
-    handleThisProperty(node, new Selector.getter(name));
-    handleOperator(node);
-    handleThisProperty(node, new Selector.setter(name));
-  }
-
-  void visitThisPropertyPrefix(
-      Send node, Name name, IncDecOperator operator, T arg) {
-    handleThisProperty(node, new Selector.getter(name));
-    handleOperator(node);
-    handleThisProperty(node, new Selector.setter(name));
-  }
-
-  void visitTopLevelFieldCompound(Send node, FieldElement field,
-      AssignmentOperator operator, Node rhs, T arg) {
-    handleStatic(node);
-    handleOperator(node);
-    handleStatic(node);
-  }
-
-  void visitTopLevelFieldInvoke(Send node, FieldElement field,
-      NodeList arguments, CallStructure callStructure, T arg) {
-    handleInvoke(node);
-  }
-
-  void visitTopLevelFieldPostfix(
-      Send node, FieldElement field, IncDecOperator operator, T arg) {
-    handleStatic(node);
-    handleOperator(node);
-    handleStatic(node);
-  }
-
-  void visitTopLevelFieldPrefix(
-      Send node, FieldElement field, IncDecOperator operator, T arg) {
-    handleStatic(node);
-    handleOperator(node);
-    handleStatic(node);
-  }
-
-  void visitTopLevelGetterInvoke(Send node, FunctionElement getter,
-      NodeList arguments, CallStructure callStructure, T arg) {
-    handleInvoke(node);
-  }
-
-  void visitTopLevelGetterSetterCompound(Send node, FunctionElement getter,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, T arg) {
-    handleStatic(node);
-    handleOperator(node);
-    handleStatic(node);
-  }
-
-  void visitTopLevelGetterSetterPostfix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, T arg) {
-    handleStatic(node);
-    handleOperator(node);
-    handleStatic(node);
-  }
-
-  void visitTopLevelGetterSetterPrefix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, T arg) {
-    handleStatic(node);
-    handleOperator(node);
-    handleStatic(node);
-  }
-
-  void visitUnary(Send node, UnaryOperator operator, Node expression, T arg) {
-    handleDynamic(node);
-  }
-
-  // Local variable sends
-
-  void visitLocalFunctionGet(Send node, LocalFunctionElement function, T arg) {
-    handleLocal(node);
-  }
-
-  void visitLocalFunctionInvoke(Send node, LocalFunctionElement function,
-      NodeList arguments, CallStructure callStructure, T arg) {
-    handleLocal(node);
-  }
-
-  void visitLocalVariableGet(Send node, LocalVariableElement variable, T arg) {
-    handleLocal(node);
-  }
-
-  void visitLocalVariableSet(
-      SendSet node, LocalVariableElement variable, Node rhs, T arg) {
-    handleLocal(node);
-  }
-
-  void visitLocalVariableSetIfNull(
-      SendSet node, LocalVariableElement variable, Node rhs, T arg) {
-    handleLocal(node);
-    handleLocal(node);
-  }
-
-  void visitParameterGet(Send node, ParameterElement parameter, T arg) {
-    handleLocal(node);
-  }
-
-  void visitParameterSet(
-      SendSet node, ParameterElement parameter, Node rhs, T arg) {
-    handleLocal(node);
-  }
-
-  void visitParameterSetIfNull(
-      Send node, ParameterElement parameter, Node rhs, T arg) {
-    handleLocal(node);
-    handleLocal(node);
-  }
-
-  // Super monomorphic sends
-
-  void visitSuperBinary(Send node, FunctionElement function,
-      BinaryOperator operator, Node argument, T arg) {
-    handleSuper(node);
-  }
-
-  void visitSuperEquals(
-      Send node, FunctionElement function, Node argument, T arg) {
-    handleSuper(node);
-  }
-
-  void visitSuperFieldGet(Send node, FieldElement field, T arg) {
-    handleSuper(node);
-  }
-
-  void visitSuperFieldSet(SendSet node, FieldElement field, Node rhs, T arg) {
-    handleSuper(node);
-  }
-
-  void visitSuperFieldSetIfNull(
-      SendSet node, FieldElement field, Node rhs, T arg) {
-    handleSuper(node);
-    handleSuper(node);
-  }
-
-  void visitSuperGetterGet(Send node, FunctionElement getter, T arg) {
-    handleSuper(node);
-  }
-
-  void visitSuperGetterSet(
-      SendSet node, FunctionElement getter, Node rhs, T arg) {
-    handleSuper(node);
-  }
-
-  void visitSuperIndex(Send node, FunctionElement function, Node index, T arg) {
-    handleSuper(node);
-  }
-
-  void visitSuperIndexSet(
-      SendSet node, FunctionElement function, Node index, Node rhs, T arg) {
-    handleSuper(node);
-  }
-
-  void visitSuperMethodGet(Send node, MethodElement method, T arg) {
-    handleSuper(node);
-  }
-
-  void visitSuperMethodInvoke(Send node, MethodElement method,
-      NodeList arguments, CallStructure callStructure, T arg) {
-    handleSuper(node);
-  }
-
-  void visitSuperNotEquals(
-      Send node, FunctionElement function, Node argument, T arg) {
-    handleSuper(node);
-  }
-
-  void visitSuperSetterSet(
-      SendSet node, FunctionElement setter, Node rhs, T arg) {
-    handleSuper(node);
-  }
-
-  void visitSuperUnary(
-      Send node, UnaryOperator operator, FunctionElement function, T arg) {
-    handleSuper(node);
-  }
-
-  // Statically known "no such method" sends
-
-  void visitConstructorIncompatibleInvoke(
-      NewExpression node,
-      ConstructorElement constructor,
-      InterfaceType type,
-      NodeList arguments,
-      CallStructure callStructure,
-      T arg) {
-    handleNSMError(node);
-  }
-
-  void visitFinalLocalVariableCompound(Send node, LocalVariableElement variable,
-      AssignmentOperator operator, Node rhs, T arg) {
-    handleLocal(node);
-    handleOperator(node);
-    handleNSMError(node);
-  }
-
-  void visitFinalLocalVariablePostfix(Send node, LocalVariableElement variable,
-      IncDecOperator operator, T arg) {
-    handleLocal(node);
-    handleOperator(node);
-    handleNSMError(node);
-  }
-
-  void visitFinalLocalVariablePrefix(Send node, LocalVariableElement variable,
-      IncDecOperator operator, T arg) {
-    handleLocal(node);
-    handleOperator(node);
-    handleNSMError(node);
-  }
-
-  void visitFinalLocalVariableSet(
-      SendSet node, LocalVariableElement variable, Node rhs, T arg) {
-    handleNSMError(node);
-  }
-
-  void visitFinalLocalVariableSetIfNull(
-      SendSet node, LocalVariableElement variable, Node rhs, T arg) {
-    handleLocal(node); // read for null
-    handleNSMError(node); // set fails
-  }
-
-  void visitFinalParameterCompound(Send node, ParameterElement parameter,
-      AssignmentOperator operator, Node rhs, T arg) {
-    handleLocal(node);
-    handleOperator(node);
-    handleNSMError(node);
-  }
-
-  void visitFinalParameterPostfix(
-      Send node, ParameterElement parameter, IncDecOperator operator, T arg) {
-    handleLocal(node);
-    handleOperator(node);
-    handleNSMError(node);
-  }
-
-  void visitFinalParameterPrefix(
-      Send node, ParameterElement parameter, IncDecOperator operator, T arg) {
-    handleLocal(node);
-    handleOperator(node);
-    handleNSMError(node);
-  }
-
-  void visitFinalParameterSet(
-      SendSet node, ParameterElement parameter, Node rhs, T arg) {
-    handleNSMError(node);
-  }
-
-  void visitFinalParameterSetIfNull(
-      SendSet node, ParameterElement parameter, Node rhs, T arg) {
-    handleLocal(node);
-    handleNSMError(node);
-  }
-
-  void visitFinalStaticFieldCompound(Send node, FieldElement field,
-      AssignmentOperator operator, Node rhs, T arg) {
-    handleStatic(node);
-    handleOperator(node);
-    handleNSMError(node);
-  }
-
-  void visitFinalStaticFieldPostfix(
-      Send node, FieldElement field, IncDecOperator operator, T arg) {
-    handleStatic(node);
-    handleOperator(node);
-    handleNSMError(node);
-  }
-
-  void visitFinalStaticFieldPrefix(
-      Send node, FieldElement field, IncDecOperator operator, T arg) {
-    handleStatic(node);
-    handleOperator(node);
-    handleNSMError(node);
-  }
-
-  void visitFinalStaticFieldSet(
-      SendSet node, FieldElement field, Node rhs, T arg) {
-    handleNSMError(node);
-  }
-
-  void visitFinalStaticFieldSetIfNull(
-      SendSet node, FieldElement field, Node rhs, T arg) {
-    handleStatic(node);
-    handleNSMError(node);
-  }
-
-  void visitFinalSuperFieldSetIfNull(
-      Send node, FieldElement field, Node rhs, T arg) {
-    handleSuper(node);
-    handleNSMSuper(node, field.enclosingClass);
-  }
-
-  void visitFinalSuperFieldCompound(Send node, FieldElement field,
-      AssignmentOperator operator, Node rhs, T arg) {
-    handleSuper(node);
-    handleOperator(node);
-    handleNSMSuper(node, field.enclosingClass);
-  }
-
-  void visitFinalSuperFieldPostfix(
-      Send node, FieldElement field, IncDecOperator operator, T arg) {
-    handleSuper(node);
-    handleOperator(node);
-    handleNSMSuper(node, field.enclosingClass);
-  }
-
-  void visitFinalSuperFieldPrefix(
-      Send node, FieldElement field, IncDecOperator operator, T arg) {
-    handleSuper(node);
-    handleOperator(node);
-    handleNSMSuper(node, field.enclosingClass);
-  }
-
-  void visitFinalSuperFieldSet(
-      SendSet node, FieldElement field, Node rhs, T arg) {
-    handleNSMSuper(node, field.enclosingClass);
-  }
-
-  void visitFinalTopLevelFieldCompound(Send node, FieldElement field,
-      AssignmentOperator operator, Node rhs, T arg) {
-    handleStatic(node);
-    handleOperator(node);
-    handleNSMError(node);
-  }
-
-  void visitFinalTopLevelFieldPostfix(
-      Send node, FieldElement field, IncDecOperator operator, T arg) {
-    handleStatic(node);
-    handleOperator(node);
-    handleNSMError(node);
-  }
-
-  void visitFinalTopLevelFieldPrefix(
-      Send node, FieldElement field, IncDecOperator operator, T arg) {
-    handleStatic(node);
-    handleOperator(node);
-    handleNSMError(node);
-  }
-
-  void visitFinalTopLevelFieldSet(
-      SendSet node, FieldElement field, Node rhs, T arg) {
-    handleNSMError(node);
-  }
-
-  void visitFinalTopLevelFieldSetIfNull(
-      SendSet node, FieldElement field, Node rhs, T arg) {
-    handleStatic(node);
-    handleNSMError(node);
-  }
-
-  void visitTopLevelGetterSetterSetIfNull(Send node, FunctionElement getter,
-      FunctionElement setter, Node rhs, T arg) {
-    handleStatic(node);
-    handleStatic(node);
-  }
-
-  void visitTopLevelMethodSetterSetIfNull(Send node, FunctionElement method,
-      FunctionElement setter, Node rhs, T arg) {
-    handleStatic(node);
-    handleStatic(node);
-  }
-
-  void visitTopLevelMethodSetIfNull(
-      Send node, FunctionElement method, Node rhs, T arg) {
-    handleStatic(node);
-    handleNSMError(node);
-  }
-
-  void visitLocalFunctionIncompatibleInvoke(
-      Send node,
-      LocalFunctionElement function,
-      NodeList arguments,
-      CallStructure callStructure,
-      T arg) {
-    handleNSMError(node);
-  }
-
-  void visitLocalFunctionCompound(Send node, LocalFunctionElement function,
-      AssignmentOperator operator, Node rhs, T arg) {
-    handleLocal(node);
-    handleNSMError(node);
-    handleNoSend(node);
-  }
-
-  void visitLocalFunctionPostfix(Send node, LocalFunctionElement function,
-      IncDecOperator operator, T arg) {
-    handleLocal(node);
-    handleNSMError(node);
-    handleNoSend(node);
-  }
-
-  void visitLocalFunctionPrefix(Send node, LocalFunctionElement function,
-      IncDecOperator operator, T arg) {
-    handleLocal(node);
-    handleNSMError(node);
-    handleNoSend(node);
-  }
-
-  void visitLocalFunctionSet(
-      SendSet node, LocalFunctionElement function, Node rhs, T arg) {
-    handleNSMError(node);
-  }
-
-  void visitLocalFunctionSetIfNull(
-      SendSet node, LocalFunctionElement function, Node rhs, T arg) {
-    handleLocal(node);
-    handleNSMError(node);
-  }
-
-  void visitStaticFunctionIncompatibleInvoke(Send node, MethodElement function,
-      NodeList arguments, CallStructure callStructure, T arg) {
-    handleNSMError(node);
-  }
-
-  void visitStaticFunctionSet(
-      Send node, MethodElement function, Node rhs, T arg) {
-    handleNSMError(node);
-  }
-
-  void visitStaticMethodCompound(Send node, MethodElement method,
-      AssignmentOperator operator, Node rhs, T arg) {
-    handleStatic(node);
-    handleNSMError(node); // operator on a method closure yields nSM
-    handleNoSend(node); // setter is not invoked, don't count it.
-  }
-
-  void visitStaticMethodPostfix(
-      Send node, MethodElement method, IncDecOperator operator, T arg) {
-    handleStatic(node);
-    handleNSMError(node);
-    handleNoSend(node);
-  }
-
-  void visitStaticMethodPrefix(
-      Send node, MethodElement method, IncDecOperator operator, T arg) {
-    handleStatic(node);
-    handleNSMError(node);
-    handleNoSend(node);
-  }
-
-  void visitStaticMethodSetterCompound(Send node, MethodElement method,
-      MethodElement setter, AssignmentOperator operator, Node rhs, T arg) {
-    handleStatic(node);
-    handleNSMError(node); // operator on a method closure yields nSM
-    handleNoSend(node); // setter is not invoked, don't count it.
-  }
-
-  void visitStaticMethodSetterPostfix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, T arg) {
-    handleStatic(node);
-    handleNSMError(node);
-    handleNoSend(node);
-  }
-
-  void visitStaticMethodSetterPrefix(Send node, FunctionElement getter,
-      FunctionElement setter, IncDecOperator operator, T arg) {
-    handleStatic(node);
-    handleNSMError(node);
-    handleNoSend(node);
-  }
-
-  void visitStaticSetterGet(Send node, FunctionElement setter, T arg) {
-    handleNSMError(node);
-  }
-
-  void visitStaticSetterInvoke(Send node, FunctionElement setter,
-      NodeList arguments, CallStructure callStructure, T arg) {
-    handleNSMError(node);
-  }
-
-  void visitSuperMethodCompound(Send node, FunctionElement method,
-      AssignmentOperator operator, Node rhs, T arg) {
-    handleSuper(node);
-
-    // An operator send on a method closure yields nSM
-    handleNSMSuper(node, method.enclosingClass);
-
-    handleNoSend(node); // setter is not invoked, don't count it.
-  }
-
-  void visitSuperMethodIncompatibleInvoke(Send node, MethodElement method,
-      NodeList arguments, CallStructure callStructure, T arg) {
-    handleNSMSuper(node, method.enclosingClass);
-  }
-
-  void visitSuperMethodPostfix(
-      Send node, FunctionElement method, IncDecOperator operator, T arg) {
-    handleSuper(node);
-    handleNSMSuper(node, method.enclosingClass);
-    handleNoSend(node);
-  }
-
-  void visitSuperMethodPrefix(
-      Send node, FunctionElement method, IncDecOperator operator, T arg) {
-    handleSuper(node);
-    handleNSMSuper(node, method.enclosingClass);
-    handleNoSend(node);
-  }
-
-  void visitSuperMethodSet(Send node, MethodElement method, Node rhs, T arg) {
-    handleNSMSuper(node, method.enclosingClass);
-  }
-
-  void visitSuperMethodSetIfNull(
-      Send node, MethodElement method, Node rhs, T arg) {
-    handleNSMSuper(node, method.enclosingClass);
-  }
-
-  void visitSuperSetterGet(Send node, FunctionElement setter, T arg) {
-    handleNSMSuper(node, setter.enclosingClass);
-  }
-
-  void visitSuperSetterInvoke(Send node, FunctionElement setter,
-      NodeList arguments, CallStructure callStructure, T arg) {
-    handleNSMSuper(node, setter.enclosingClass);
-  }
-
-  void visitTopLevelFunctionIncompatibleInvoke(
-      Send node,
-      MethodElement function,
-      NodeList arguments,
-      CallStructure callStructure,
-      T arg) {
-    handleNSMError(node);
-  }
-
-  void visitTopLevelFunctionSet(
-      Send node, MethodElement function, Node rhs, T arg) {
-    handleNSMError(node);
-  }
-
-  void visitTopLevelGetterSet(
-      SendSet node, FunctionElement getter, Node rhs, T arg) {
-    handleNSMError(node);
-  }
-
-  void visitTopLevelMethodCompound(Send node, FunctionElement method,
-      AssignmentOperator operator, Node rhs, T arg) {
-    handleStatic(node);
-    handleNSMError(node); // operator on a method closure yields nSM
-    handleNoSend(node); // setter is not invoked, don't count it.
-  }
-
-  void visitTopLevelMethodPostfix(
-      Send node, MethodElement method, IncDecOperator operator, T arg) {
-    handleStatic(node);
-    handleNSMError(node);
-    handleNoSend(node);
-  }
-
-  void visitTopLevelMethodPrefix(
-      Send node, MethodElement method, IncDecOperator operator, T arg) {
-    handleStatic(node);
-    handleNSMError(node);
-    handleNoSend(node);
-  }
-
-  void visitTopLevelMethodSetterCompound(Send node, FunctionElement method,
-      FunctionElement setter, AssignmentOperator operator, Node rhs, T arg) {
-    handleStatic(node);
-    handleNSMError(node); // operator on a method closure yields nSM
-    handleNoSend(node); // setter is not invoked, don't count it.
-  }
-
-  void visitTopLevelMethodSetterPostfix(Send node, FunctionElement method,
-      FunctionElement setter, IncDecOperator operator, T arg) {
-    handleStatic(node);
-    handleNSMError(node);
-    handleNoSend(node);
-  }
-
-  void visitTopLevelMethodSetterPrefix(Send node, FunctionElement method,
-      FunctionElement setter, IncDecOperator operator, T arg) {
-    handleStatic(node);
-    handleNSMError(node);
-    handleNoSend(node);
-  }
-
-  void visitTopLevelSetterGet(Send node, FunctionElement setter, T arg) {
-    handleNSMError(node);
-  }
-
-  void visitTopLevelSetterInvoke(Send node, FunctionElement setter,
-      NodeList arguments, CallStructure callStructure, T arg) {
-    handleNSMError(node);
-  }
-
-  void visitTypeVariableTypeLiteralCompound(
-      Send node,
-      TypeVariableElement element,
-      AssignmentOperator operator,
-      Node rhs,
-      T arg) {
-    handleTypeVariable(node);
-    handleNSMError(node); // operator on a method closure yields nSM
-    handleNoSend(node); // setter is not invoked, don't count it.
-  }
-
-  void visitTypeVariableTypeLiteralGet(
-      Send node, TypeVariableElement element, T arg) {
-    handleTypeVariable(node);
-  }
-
-  void visitTypeVariableTypeLiteralInvoke(
-      Send node,
-      TypeVariableElement element,
-      NodeList arguments,
-      CallStructure callStructure,
-      T arg) {
-    handleNSMError(node);
-  }
-
-  void visitTypeVariableTypeLiteralPostfix(
-      Send node, TypeVariableElement element, IncDecOperator operator, T arg) {
-    handleTypeVariable(node);
-    handleNSMError(node);
-    handleNoSend(node);
-  }
-
-  void visitTypeVariableTypeLiteralPrefix(
-      Send node, TypeVariableElement element, IncDecOperator operator, T arg) {
-    handleTypeVariable(node);
-    handleNSMError(node);
-    handleNoSend(node);
-  }
-
-  void visitTypeVariableTypeLiteralSet(
-      SendSet node, TypeVariableElement element, Node rhs, T arg) {
-    handleNSMError(node);
-  }
-
-  void visitTypeVariableTypeLiteralSetIfNull(
-      SendSet node, TypeVariableElement element, Node rhs, T arg) {
-    handleTypeVariable(node);
-    handleNSMError(node);
-  }
-
-  void visitTypedefTypeLiteralCompound(Send node, ConstantExpression constant,
-      AssignmentOperator operator, Node rhs, T arg) {
-    handleTypeVariable(node);
-    handleNSMError(node);
-    handleNoSend(node);
-  }
-
-  void visitTypedefTypeLiteralGet(
-      Send node, ConstantExpression constant, T arg) {
-    handleTypeVariable(node);
-  }
-
-  void visitTypedefTypeLiteralInvoke(Send node, ConstantExpression constant,
-      NodeList arguments, CallStructure callStructure, T arg) {
-    handleNSMError(node);
-  }
-
-  void visitTypedefTypeLiteralPostfix(
-      Send node, ConstantExpression constant, IncDecOperator operator, T arg) {
-    handleTypeVariable(node);
-    handleNSMError(node);
-    handleNoSend(node);
-  }
-
-  void visitTypedefTypeLiteralPrefix(
-      Send node, ConstantExpression constant, IncDecOperator operator, T arg) {
-    handleTypeVariable(node);
-    handleNSMError(node);
-    handleNoSend(node);
-  }
-
-  void visitTypedefTypeLiteralSet(
-      SendSet node, ConstantExpression constant, Node rhs, T arg) {
-    handleNSMError(node);
-  }
-
-  void visitTypedefTypeLiteralSetIfNull(
-      SendSet node, ConstantExpression constant, Node rhs, T arg) {
-    handleStatic(node);
-    handleNSMError(node);
-  }
-
-  void visitUnresolvedClassConstructorInvoke(
-      NewExpression node,
-      Element element,
-      DartType type,
-      NodeList arguments,
-      Selector selector,
-      T arg) {
-    handleNSMError(node);
-  }
-
-  void visitUnresolvedCompound(Send node, Element element,
-      AssignmentOperator operator, Node rhs, T arg) {
-    handleNSMError(node);
-    handleNoSend(node);
-    handleNoSend(node);
-  }
-
-  void visitUnresolvedConstructorInvoke(NewExpression node, Element constructor,
-      DartType type, NodeList arguments, Selector selector, T arg) {
-    handleNSMError(node);
-  }
-
-  void visitUnresolvedGet(Send node, Element element, T arg) {
-    handleNSMError(node);
-  }
-
-  void visitUnresolvedInvoke(Send node, Element element, NodeList arguments,
-      Selector selector, T arg) {
-    handleNSMError(node);
-  }
-
-  void visitUnresolvedPostfix(
-      Send node, Element element, IncDecOperator operator, T arg) {
-    handleNSMError(node);
-    handleNoSend(node);
-    handleNoSend(node);
-  }
-
-  void visitUnresolvedPrefix(
-      Send node, Element element, IncDecOperator operator, T arg) {
-    handleNSMError(node);
-    handleNoSend(node);
-    handleNoSend(node);
-  }
-
-  void visitUnresolvedRedirectingFactoryConstructorInvoke(
-      NewExpression node,
-      ConstructorElement constructor,
-      InterfaceType type,
-      NodeList arguments,
-      CallStructure callStructure,
-      T arg) {
-    handleNSMError(node);
-  }
-
-  void visitUnresolvedSet(Send node, Element element, Node rhs, T arg) {
-    handleNSMError(node);
-  }
-
-  void visitUnresolvedSetIfNull(Send node, Element element, Node rhs, T arg) {
-    handleNSMError(node);
-    handleNoSend(node);
-  }
-
-  void visitUnresolvedStaticGetterCompound(Send node, Element element,
-      MethodElement setter, AssignmentOperator operator, Node rhs, T arg) {
-    handleNSMError(node);
-    handleNoSend(node);
-    handleNoSend(node);
-  }
-
-  void visitUnresolvedStaticGetterPostfix(Send node, Element element,
-      MethodElement setter, IncDecOperator operator, T arg) {
-    handleNSMError(node);
-    handleNoSend(node);
-    handleNoSend(node);
-  }
-
-  void visitUnresolvedStaticGetterPrefix(Send node, Element element,
-      MethodElement setter, IncDecOperator operator, T arg) {
-    handleNSMError(node);
-    handleNoSend(node);
-    handleNoSend(node);
-  }
-
-  void visitUnresolvedStaticGetterSetIfNull(
-      Send node, Element element, MethodElement setter, Node rhs, T arg) {
-    handleNSMError(node);
-    handleNoSend(node);
-  }
-
-  void visitUnresolvedStaticSetterCompound(Send node, MethodElement getter,
-      Element element, AssignmentOperator operator, Node rhs, T arg) {
-    handleNSMError(node);
-    handleNoSend(node);
-    handleNoSend(node);
-  }
-
-  void visitUnresolvedStaticSetterPostfix(Send node, MethodElement getter,
-      Element element, IncDecOperator operator, T arg) {
-    handleNSMError(node);
-    handleNoSend(node);
-    handleNoSend(node);
-  }
-
-  void visitUnresolvedStaticSetterPrefix(Send node, MethodElement getter,
-      Element element, IncDecOperator operator, T arg) {
-    handleNSMError(node);
-    handleNoSend(node);
-    handleNoSend(node);
-  }
-
-  void visitUnresolvedStaticSetterSetIfNull(
-      Send node, MethodElement getter, Element element, Node rhs, T arg) {
-    handleNSMError(node);
-    handleNoSend(node);
-  }
-
-  void visitUnresolvedSuperBinary(Send node, Element element,
-      BinaryOperator operator, Node argument, T arg) {
-    handleNSMSuper(node, element.enclosingClass);
-  }
-
-  void visitUnresolvedSuperCompound(Send node, Element element,
-      AssignmentOperator operator, Node rhs, T arg) {
-    handleNSMSuper(node, element.enclosingClass);
-    // TODO(sigmund): we should only count the next 2 if we know that the
-    // superclass has a nSM method.
-    handleOperator(node);
-    handleNSMSuper(node, element.enclosingClass);
-  }
-
-  void visitUnresolvedSuperCompoundIndexSet(Send node, Element element,
-      Node index, AssignmentOperator operator, Node rhs, T arg) {
-    handleNSMSuper(node, element.enclosingClass);
-    handleNoSend(node);
-    handleNSMSuper(node, element.enclosingClass);
-  }
-
-  void visitUnresolvedSuperGet(Send node, Element element, T arg) {
-    handleNSMSuper(node, element.enclosingClass);
-  }
-
-  void visitUnresolvedSuperSet(Send node, Element element, Node rhs, T arg) {
-    handleNSMSuper(node, element.enclosingClass);
-  }
-
-  void visitUnresolvedSuperSetIfNull(
-      Send node, Element element, Node rhs, T arg) {
-    handleNSMSuper(node, element.enclosingClass);
-    handleNoSend(node);
-  }
-
-  void visitUnresolvedSuperGetterCompound(Send node, Element element,
-      MethodElement setter, AssignmentOperator operator, Node rhs, T arg) {
-    handleNSMSuper(node, element.enclosingClass);
-    handleOperator(node);
-    handleSuper(node);
-  }
-
-  void visitUnresolvedSuperGetterCompoundIndexSet(
-      Send node,
-      Element element,
-      MethodElement setter,
-      Node index,
-      AssignmentOperator operator,
-      Node rhs,
-      T arg) {
-    handleNSMSuper(node, element.enclosingClass);
-    handleOperator(node);
-    handleSuper(node);
-  }
-
-  void visitUnresolvedSuperGetterIndexPostfix(Send node, Element element,
-      MethodElement setter, Node index, IncDecOperator operator, T arg) {
-    handleNSMSuper(node, element.enclosingClass);
-    handleOperator(node);
-    handleSuper(node);
-  }
-
-  void visitUnresolvedSuperGetterIndexPrefix(Send node, Element element,
-      MethodElement setter, Node index, IncDecOperator operator, T arg) {
-    handleNSMSuper(node, element.enclosingClass);
-    handleOperator(node);
-    handleSuper(node);
-  }
-
-  void visitUnresolvedSuperGetterPostfix(Send node, Element element,
-      MethodElement setter, IncDecOperator operator, T arg) {
-    handleNSMSuper(node, element.enclosingClass);
-    handleOperator(node);
-    handleSuper(node);
-  }
-
-  void visitUnresolvedSuperGetterPrefix(Send node, Element element,
-      MethodElement setter, IncDecOperator operator, T arg) {
-    handleNSMSuper(node, element.enclosingClass);
-    handleOperator(node);
-    handleSuper(node);
-  }
-
-  void visitUnresolvedSuperGetterSetIfNull(
-      Send node, Element element, MethodElement setter, Node rhs, T arg) {
-    handleNSMSuper(node, element.enclosingClass);
-    handleSuper(node);
-  }
-
-  void visitUnresolvedSuperIndex(
-      Send node, Element element, Node index, T arg) {
-    handleNSMSuper(node, element.enclosingClass);
-  }
-
-  void visitUnresolvedSuperIndexPostfix(
-      Send node, Element element, Node index, IncDecOperator operator, T arg) {
-    handleNSMSuper(node, element.enclosingClass);
-    handleOperator(node);
-    handleNSMSuper(node, element.enclosingClass);
-  }
-
-  void visitUnresolvedSuperIndexPrefix(
-      Send node, Element element, Node index, IncDecOperator operator, T arg) {
-    handleNSMSuper(node, element.enclosingClass);
-    handleOperator(node);
-    handleNSMSuper(node, element.enclosingClass);
-  }
-
-  void visitUnresolvedSuperIndexSet(
-      Send node, Element element, Node index, Node rhs, T arg) {
-    handleNSMSuper(node, element.enclosingClass);
-  }
-
-  void visitUnresolvedSuperInvoke(Send node, Element element,
-      NodeList arguments, Selector selector, T arg) {
-    handleNSMSuper(node, element.enclosingClass);
-  }
-
-  void visitUnresolvedSuperPostfix(
-      Send node, Element element, IncDecOperator operator, T arg) {
-    handleNSMSuper(node, element.enclosingClass);
-    handleOperator(node);
-    handleNSMSuper(node, element.enclosingClass);
-  }
-
-  void visitUnresolvedSuperPrefix(
-      Send node, Element element, IncDecOperator operator, T arg) {
-    handleNSMSuper(node, element.enclosingClass);
-    handleOperator(node);
-    handleNSMSuper(node, element.enclosingClass);
-  }
-
-  void visitUnresolvedSuperSetterCompound(Send node, MethodElement getter,
-      Element element, AssignmentOperator operator, Node rhs, T arg) {
-    handleSuper(node);
-    handleOperator(node);
-    handleNSMSuper(node, element.enclosingClass);
-  }
-
-  void visitUnresolvedSuperSetterCompoundIndexSet(
-      Send node,
-      MethodElement getter,
-      Element element,
-      Node index,
-      AssignmentOperator operator,
-      Node rhs,
-      T arg) {
-    handleSuper(node);
-    handleOperator(node);
-    handleNSMSuper(node, element.enclosingClass);
-  }
-
-  void visitUnresolvedSuperSetterIndexPostfix(
-      Send node,
-      MethodElement indexFunction,
-      Element element,
-      Node index,
-      IncDecOperator operator,
-      T arg) {
-    handleSuper(node);
-    handleOperator(node);
-    handleNSMSuper(node, element.enclosingClass);
-  }
-
-  void visitUnresolvedSuperSetterIndexPrefix(
-      Send node,
-      MethodElement indexFunction,
-      Element element,
-      Node index,
-      IncDecOperator operator,
-      T arg) {
-    handleSuper(node);
-    handleOperator(node);
-    handleNSMSuper(node, element.enclosingClass);
-  }
-
-  void visitUnresolvedSuperSetterPostfix(Send node, MethodElement getter,
-      Element element, IncDecOperator operator, T arg) {
-    handleSuper(node);
-    handleOperator(node);
-    handleNSMSuper(node, element.enclosingClass);
-  }
-
-  void visitUnresolvedSuperSetterPrefix(Send node, MethodElement getter,
-      Element element, IncDecOperator operator, T arg) {
-    handleSuper(node);
-    handleOperator(node);
-    handleNSMSuper(node, element.enclosingClass);
-  }
-
-  void visitUnresolvedSuperSetterSetIfNull(
-      Send node, MethodElement getter, Element element, Node rhs, T arg) {
-    handleSuper(node);
-    handleNSMSuper(node, element.enclosingClass);
-  }
-
-  void visitUnresolvedSuperUnary(
-      Send node, UnaryOperator operator, Element element, T arg) {
-    handleNSMSuper(node, element.enclosingClass);
-  }
-
-  void visitUnresolvedTopLevelGetterCompound(Send node, Element element,
-      MethodElement setter, AssignmentOperator operator, Node rhs, T arg) {
-    handleNSMError(node);
-    handleNoSend(node);
-    handleNoSend(node);
-  }
-
-  void visitUnresolvedTopLevelGetterPostfix(Send node, Element element,
-      MethodElement setter, IncDecOperator operator, T arg) {
-    handleNSMError(node);
-    handleNoSend(node);
-    handleNoSend(node);
-  }
-
-  void visitUnresolvedTopLevelGetterPrefix(Send node, Element element,
-      MethodElement setter, IncDecOperator operator, T arg) {
-    handleNSMError(node);
-    handleNoSend(node);
-    handleNoSend(node);
-  }
-
-  void visitUnresolvedTopLevelGetterSetIfNull(
-      Send node, Element element, MethodElement setter, Node rhs, T arg) {
-    handleNSMError(node);
-    handleNoSend(node);
-  }
-
-  void visitUnresolvedTopLevelSetterCompound(Send node, MethodElement getter,
-      Element element, AssignmentOperator operator, Node rhs, T arg) {
-    handleNSMError(node);
-    handleNoSend(node);
-    handleNoSend(node);
-  }
-
-  void visitUnresolvedTopLevelSetterPostfix(Send node, MethodElement getter,
-      Element element, IncDecOperator operator, T arg) {
-    handleNSMError(node);
-    handleNoSend(node);
-    handleNoSend(node);
-  }
-
-  void visitUnresolvedTopLevelSetterPrefix(Send node, MethodElement getter,
-      Element element, IncDecOperator operator, T arg) {
-    handleNSMError(node);
-    handleNoSend(node);
-    handleNoSend(node);
-  }
-
-  void visitUnresolvedTopLevelSetterSetIfNull(
-      Send node, MethodElement getter, Element element, Node rhs, T arg) {
-    handleNSMError(node);
-    handleNoSend(node);
-  }
-
-  // Static
-
-  void visitConstantGet(Send node, ConstantExpression constant, T arg) {
-    handleStatic(node);
-  }
-
-  void visitConstantInvoke(Send node, ConstantExpression constant,
-      NodeList arguments, CallStructure callStreucture, T arg) {
-    handleStatic(node);
-  }
-
-  void visitFactoryConstructorInvoke(
-      NewExpression node,
-      ConstructorElement constructor,
-      InterfaceType type,
-      NodeList arguments,
-      CallStructure callStructure,
-      T arg) {
-    handleStatic(node);
-  }
-
-  void visitStaticFieldGet(Send node, FieldElement field, T arg) {
-    handleStatic(node);
-  }
-
-  void visitStaticFieldSet(SendSet node, FieldElement field, Node rhs, T arg) {
-    handleStatic(node);
-  }
-
-  void visitStaticFieldSetIfNull(
-      SendSet node, FieldElement field, Node rhs, T arg) {
-    handleStatic(node);
-    handleStatic(node);
-  }
-
-  void visitStaticFunctionGet(Send node, MethodElement function, T arg) {
-    handleStatic(node);
-  }
-
-  void visitStaticFunctionInvoke(Send node, MethodElement function,
-      NodeList arguments, CallStructure callStructure, T arg) {
-    handleStatic(node);
-  }
-
-  void visitStaticGetterGet(Send node, FunctionElement getter, T arg) {
-    handleStatic(node);
-  }
-
-  void visitStaticGetterSet(
-      SendSet node, FunctionElement getter, Node rhs, T arg) {
-    handleStatic(node);
-  }
-
-  void visitStaticSetterSet(
-      SendSet node, FunctionElement setter, Node rhs, T arg) {
-    handleStatic(node);
-  }
-
-  void visitStaticGetterSetterSetIfNull(Send node, FunctionElement getter,
-      FunctionElement setter, Node rhs, T arg) {
-    handleStatic(node);
-    handleStatic(node);
-  }
-
-  void visitStaticMethodSetterSetIfNull(
-      Send node, MethodElement method, MethodElement setter, Node rhs, T arg) {
-    handleStatic(node);
-    handleStatic(node);
-  }
-
-  void visitStaticMethodSetIfNull(
-      Send node, FunctionElement method, Node rhs, T arg) {
-    handleStatic(node);
-    handleNSMError(node);
-  }
-
-  void visitTopLevelFieldGet(Send node, FieldElement field, T arg) {
-    handleStatic(node);
-  }
-
-  void visitTopLevelFieldSet(
-      SendSet node, FieldElement field, Node rhs, T arg) {
-    handleStatic(node);
-  }
-
-  void visitTopLevelFieldSetIfNull(
-      SendSet node, FieldElement field, Node rhs, T arg) {
-    handleStatic(node);
-    handleStatic(node);
-  }
-
-  void visitTopLevelFunctionGet(Send node, MethodElement function, T arg) {
-    handleStatic(node);
-  }
-
-  void visitTopLevelFunctionInvoke(Send node, MethodElement function,
-      NodeList arguments, CallStructure callStructure, T arg) {
-    handleStatic(node);
-  }
-
-  void visitTopLevelGetterGet(Send node, FunctionElement getter, T arg) {
-    handleStatic(node);
-  }
-
-  void visitTopLevelSetterSet(
-      SendSet node, FunctionElement setter, Node rhs, T arg) {
-    handleStatic(node);
-  }
-
-  // Virtual
-
-  void visitSuperCompoundIndexSet(
-      SendSet node,
-      MethodElement getter,
-      MethodElement setter,
-      Node index,
-      AssignmentOperator operator,
-      Node rhs,
-      T arg) {
-    handleSuper(node);
-    handleOperator(node);
-    handleSuper(node);
-  }
-
-  void visitThisGet(Identifier node, T arg) {
-    handleLocal(node); // TODO(sigmund): should we add a metric for "this"?
-  }
-
-  void visitThisInvoke(
-      Send node, NodeList arguments, CallStructure callStructure, T arg) {
-    // TODO(sigmund): implement (treat like this.call())
-    handleDynamic(node);
-  }
-
-  void visitThisPropertyGet(Send node, Name name, T arg) {
-    handleThisProperty(node, new Selector.getter(name));
-  }
-
-  void visitThisPropertySet(SendSet node, Name name, Node rhs, T arg) {
-    handleThisProperty(node, new Selector.setter(name));
-  }
-
-  void visitThisPropertySetIfNull(Send node, Name name, Node rhs, T arg) {
-    handleThisProperty(node, new Selector.getter(name));
-    handleThisProperty(node, new Selector.setter(name));
-  }
-
-  // Not count
-
-  void errorNonConstantConstructorInvoke(NewExpression node, Element element,
-      DartType type, NodeList arguments, CallStructure callStructure, T arg) {
-    handleNoSend(node);
-  }
-
-  void errorUndefinedBinaryExpression(
-      Send node, Node left, Operator operator, Node right, T arg) {
-    handleNoSend(node);
-  }
-
-  void errorUndefinedUnaryExpression(
-      Send node, Operator operator, Node expression, T arg) {
-    handleNoSend(node);
-  }
-
-  void errorInvalidGet(Send node, ErroneousElement error, T arg) {
-    handleNoSend(node);
-  }
-
-  void errorInvalidInvoke(Send node, ErroneousElement error, NodeList arguments,
-      Selector selector, T arg) {
-    handleNoSend(node);
-  }
-
-  void errorInvalidSet(Send node, ErroneousElement error, Node rhs, T arg) {
-    handleNoSend(node);
-  }
-
-  void errorInvalidSetIfNull(
-      Send node, ErroneousElement error, Node rhs, T arg) {
-    handleNoSend(node);
-    handleNoSend(node);
-  }
-
-  void errorInvalidPrefix(
-      Send node, ErroneousElement error, IncDecOperator operator, T arg) {
-    handleNoSend(node);
-  }
-
-  void errorInvalidPostfix(
-      Send node, ErroneousElement error, IncDecOperator operator, T arg) {
-    handleNoSend(node);
-  }
-
-  void errorInvalidCompound(Send node, ErroneousElement error,
-      AssignmentOperator operator, Node rhs, T arg) {
-    handleNoSend(node);
-  }
-
-  void errorInvalidUnary(
-      Send node, UnaryOperator operator, ErroneousElement error, T arg) {
-    handleNoSend(node);
-  }
-
-  void errorInvalidEquals(
-      Send node, ErroneousElement error, Node right, T arg) {
-    handleNoSend(node);
-  }
-
-  void errorInvalidNotEquals(
-      Send node, ErroneousElement error, Node right, T arg) {
-    handleNoSend(node);
-  }
-
-  void errorInvalidBinary(Send node, ErroneousElement error,
-      BinaryOperator operator, Node right, T arg) {
-    handleNoSend(node);
-  }
-
-  void errorInvalidIndex(Send node, ErroneousElement error, Node index, T arg) {
-    handleNoSend(node);
-  }
-
-  void errorInvalidIndexSet(
-      Send node, ErroneousElement error, Node index, Node rhs, T arg) {
-    handleNoSend(node);
-  }
-
-  void errorInvalidCompoundIndexSet(Send node, ErroneousElement error,
-      Node index, AssignmentOperator operator, Node rhs, T arg) {
-    handleNoSend(node);
-    handleNoSend(node);
-    handleNoSend(node);
-  }
-
-  void errorInvalidIndexPrefix(Send node, ErroneousElement error, Node index,
-      IncDecOperator operator, T arg) {
-    handleNoSend(node);
-    handleNoSend(node);
-  }
-
-  void errorInvalidIndexPostfix(Send node, ErroneousElement error, Node index,
-      IncDecOperator operator, T arg) {
-    handleNoSend(node);
-    handleNoSend(node);
-  }
-
-  void previsitDeferredAccess(Send node, PrefixElement prefix, T arg) {}
-
-  void visitAs(Send node, Node expression, DartType type, T arg) {
-    handleNoSend(node);
-  }
-
-  void visitClassTypeLiteralCompound(Send node, ConstantExpression constant,
-      AssignmentOperator operator, Node rhs, T arg) {
-    handleStatic(node);
-    handleNSMError(node);
-    handleNoSend(node);
-  }
-
-  void visitClassTypeLiteralGet(Send node, ConstantExpression constant, T arg) {
-    handleStatic(node);
-  }
-
-  void visitClassTypeLiteralInvoke(Send node, ConstantExpression constant,
-      NodeList arguments, CallStructure callStructure, T arg) {
-    handleNSMError(node);
-  }
-
-  void visitClassTypeLiteralPostfix(
-      Send node, ConstantExpression constant, IncDecOperator operator, T arg) {
-    handleStatic(node);
-    handleNSMError(node);
-    handleNoSend(node);
-  }
-
-  void visitClassTypeLiteralPrefix(
-      Send node, ConstantExpression constant, IncDecOperator operator, T arg) {
-    handleStatic(node);
-    handleNSMError(node);
-    handleNoSend(node);
-  }
-
-  void visitClassTypeLiteralSet(
-      SendSet node, ConstantExpression constant, Node rhs, T arg) {
-    handleNSMError(node);
-  }
-
-  void visitClassTypeLiteralSetIfNull(
-      SendSet node, ConstantExpression constant, Node rhs, T arg) {
-    handleStatic(node);
-    handleNSMError(node);
-  }
-
-  void visitDynamicTypeLiteralCompound(Send node, ConstantExpression constant,
-      AssignmentOperator operator, Node rhs, T arg) {
-    handleStatic(node);
-    handleNSMError(node);
-    handleNoSend(node);
-  }
-
-  void visitDynamicTypeLiteralGet(
-      Send node, ConstantExpression constant, T arg) {
-    handleNSMError(node);
-  }
-
-  void visitDynamicTypeLiteralInvoke(Send node, ConstantExpression constant,
-      NodeList arguments, CallStructure callStructure, T arg) {
-    handleNSMError(node);
-  }
-
-  void visitDynamicTypeLiteralPostfix(
-      Send node, ConstantExpression constant, IncDecOperator operator, T arg) {
-    handleStatic(node);
-    handleNSMError(node);
-    handleNoSend(node);
-  }
-
-  void visitDynamicTypeLiteralPrefix(
-      Send node, ConstantExpression constant, IncDecOperator operator, T arg) {
-    handleStatic(node);
-    handleNSMError(node);
-    handleNoSend(node);
-  }
-
-  void visitDynamicTypeLiteralSet(
-      SendSet node, ConstantExpression constant, Node rhs, T arg) {
-    handleNSMError(node);
-  }
-
-  void visitDynamicTypeLiteralSetIfNull(
-      SendSet node, ConstantExpression constant, Node rhs, T arg) {
-    handleStatic(node);
-    handleNSMError(node);
-  }
-
-  @override
-  errorInvalidIndexSetIfNull(
-      SendSet node, ErroneousElement error, Node index, Node rhs, T arg) {
-    handleNoSend(node);
-  }
-
-  @override
-  visitIndexSetIfNull(
-      SendSet node, Node receiver, Node index, Node rhs, T arg) {
-    handleIndex(node); // t1 = receiver[index]
-    handleIndex(node); // receiver[index] = t2
-  }
-
-  @override
-  visitSuperIndexSetIfNull(SendSet node, MethodElement getter,
-      MethodElement setter, Node index, Node rhs, T arg) {
-    handleSuper(node); // t1 = super[index]
-    handleSuper(node); // super[index] = t2
-  }
-
-  @override
-  visitUnresolvedSuperGetterIndexSetIfNull(Send node, Element element,
-      MethodElement setter, Node index, Node rhs, T arg) {
-    handleNSMSuper(node, element.enclosingClass);
-    handleNSMSuper(node, element.enclosingClass);
-  }
-
-  @override
-  visitUnresolvedSuperIndexSetIfNull(
-      Send node, Element element, Node index, Node rhs, T arg) {
-    handleNSMSuper(node, element.enclosingClass);
-    handleNSMSuper(node, element.enclosingClass);
-  }
-
-  @override
-  visitUnresolvedSuperSetterIndexSetIfNull(Send node, MethodElement getter,
-      Element element, Node index, Node rhs, T arg) {
-    handleSuper(node); // t1 = super[index]
-    handleNSMSuper(node, element.enclosingClass);
-  }
-
-  void visitIfNull(Send node, Node left, Node right, T arg) {
-    handleNoSend(node);
-  }
-
-  void visitIs(Send node, Node expression, DartType type, T arg) {
-    handleNoSend(node);
-  }
-
-  void visitIsNot(Send node, Node expression, DartType type, T arg) {
-    handleNoSend(node);
-  }
-
-  void visitLogicalAnd(Send node, Node left, Node right, T arg) {
-    handleNoSend(node);
-  }
-
-  void visitLogicalOr(Send node, Node left, Node right, T arg) {
-    handleNoSend(node);
-  }
-
-  void visitNot(Send node, Node expression, T arg) {
-    handleNoSend(node);
-  }
-
-  String last;
-  _checkInvariant(node, String msg) {
-    msg = '$msg ${recursiveDiagnosticString(measurements, Metric.send)}';
-    if (!measurements.checkInvariant(Metric.send) ||
-        !measurements.checkInvariant(Metric.monomorphicSend) ||
-        !measurements.checkInvariant(Metric.polymorphicSend)) {
-      reporter.reportErrorMessage(node, MessageKind.GENERIC,
-          {'text': 'bad\n-- $msg\nlast:\n-- $last\n'});
-      last = msg;
-    } else {
-      last = msg;
-    }
-  }
-}
-
-/// Visitor that collects statistics for a single function.
-class _StatsTraversalVisitor<T> extends TraversalVisitor<dynamic, T>
-    implements SemanticSendVisitor<dynamic, T> {
-  final DiagnosticReporter reporter;
-  final _StatsVisitor statsVisitor;
-  Measurements get measurements => statsVisitor.measurements;
-  _StatsTraversalVisitor(
-      Compiler compiler, TreeElements elements, Uri sourceUri)
-      : reporter = compiler.reporter,
-        statsVisitor = new _StatsVisitor(
-            compiler.reporter,
-            elements,
-                // TODO(sigmund): accept a list of analyses, so we can compare them
-                // together.
-                true
-                ? new TrustTypesAnalysisResult(elements, compiler.world)
-                : new NaiveAnalysisResult(),
-            sourceUri),
-        super(elements);
-
-  void visitSend(Send node) {
-    try {
-      node.accept(statsVisitor);
-    } catch (e, t) {
-      reporter
-          .reportErrorMessage(node, MessageKind.GENERIC, {'text': '$e\n$t'});
-    }
-    super.visitSend(node);
-  }
-
-  void visitNewExpression(NewExpression node) {
-    try {
-      node.accept(statsVisitor);
-    } catch (e, t) {
-      reporter
-          .reportErrorMessage(node, MessageKind.GENERIC, {'text': '$e\n$t'});
-    }
-    super.visitNewExpression(node);
-  }
-}
-
-/// Helper to visit elements recursively
-// TODO(sigmund): maybe generalize and move to elements/visitor.dart?
-abstract class RecursiveElementVisitor<R, A> extends ElementVisitor<R, A> {
-  @override
-  R visitWarnOnUseElement(WarnOnUseElement e, A arg) =>
-      e.wrappedElement.accept(this, arg);
-
-  R visitScopeContainerElement(ScopeContainerElement e, A arg) {
-    e.forEachLocalMember((l) => l.accept(this, arg));
-    return null;
-  }
-
-  @override
-  R visitCompilationUnitElement(CompilationUnitElement e, A arg) {
-    e.forEachLocalMember((l) => l.accept(this, arg));
-    return null;
-  }
-
-  @override
-  R visitLibraryElement(LibraryElement e, A arg) {
-    e.implementation.compilationUnits.forEach((u) => u.accept(this, arg));
-    return null;
-  }
-
-  R visitVariableElement(VariableElement e, A arg) => null;
-
-  @override
-  R visitParameterElement(ParameterElement e, A arg) => null;
-
-  @override
-  R visitFormalElement(FormalElement e, A arg) => null;
-
-  @override
-  R visitFieldElement(FieldElement e, A arg) => null;
-
-  @override
-  R visitFieldParameterElement(InitializingFormalElement e, A arg) => null;
-
-  @override
-  R visitAbstractFieldElement(AbstractFieldElement e, A arg) => null;
-
-  R visitFunctionElement(FunctionElement e, A arg) => null;
-
-  @override
-  R visitConstructorElement(ConstructorElement e, A arg) {
-    return visitFunctionElement(e, arg);
-  }
-
-  @override
-  R visitConstructorBodyElement(ConstructorBodyElement e, A arg) {
-    return visitFunctionElement(e.constructor, arg);
-  }
-
-  @override
-  R visitClassElement(ClassElement e, A arg) {
-    return visitScopeContainerElement(e, arg);
-  }
-
-  @override
-  R visitEnumClassElement(EnumClassElement e, A arg) {
-    return visitClassElement(e, arg);
-  }
-
-  @override
-  R visitBoxFieldElement(BoxFieldElement e, A arg) => null;
-
-  @override
-  R visitClosureClassElement(ClosureClassElement e, A arg) {
-    return visitClassElement(e, arg);
-  }
-
-  @override
-  R visitClosureFieldElement(ClosureFieldElement e, A arg) {
-    return visitVariableElement(e, arg);
-  }
-}
-
-// TODO(sigmund): get rid of debug messages.
-_debug(String message) {
-  print('debug: $message');
-}
diff --git a/pkg/compiler/lib/src/info/trusted_types_analysis_result.dart b/pkg/compiler/lib/src/info/trusted_types_analysis_result.dart
deleted file mode 100644
index 5653f2e..0000000
--- a/pkg/compiler/lib/src/info/trusted_types_analysis_result.dart
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/// API to get results from a static analysis of the source program.
-// TODO(sigmund): split out implementations out of this file.
-library compiler.src.stats.trusted_types_analysis_result;
-
-import 'analysis_result.dart';
-import '../tree/tree.dart' show Node;
-import '../universe/selector.dart' show Selector;
-import '../resolution/tree_elements.dart' show TreeElements;
-import '../world.dart' show ClassWorld;
-import '../dart_types.dart' show InterfaceType;
-
-/// An [AnalysisResult] produced by using type-propagation based on
-/// trusted type annotations.
-class TrustTypesAnalysisResult implements AnalysisResult {
-  final ClassWorld world;
-  final TreeElements elements;
-
-  TrustTypesAnalysisResult(this.elements, this.world);
-
-  ReceiverInfo infoForReceiver(Node receiver) => new TrustTypesReceiverInfo(
-      receiver, elements.typesCache[receiver], world);
-  SelectorInfo infoForSelector(Node receiver, Selector selector) =>
-      new TrustTypesSelectorInfo(
-          receiver, elements.typesCache[receiver], selector, world);
-}
-
-class _SelectorLookupResult {
-  final Boolish exists;
-  // TODO(sigmund): implement
-  final Boolish usesInterceptor = Boolish.no;
-  final int possibleTargets;
-
-  _SelectorLookupResult(this.exists, this.possibleTargets);
-
-  const _SelectorLookupResult.dontKnow()
-      : exists = Boolish.maybe,
-        possibleTargets = -1;
-}
-
-_SelectorLookupResult _lookupSelector(
-    String selectorName, InterfaceType type, ClassWorld world) {
-  if (type == null) return const _SelectorLookupResult.dontKnow();
-  bool isNsm = selectorName == 'noSuchMethod';
-  bool notFound = false;
-  var uniqueTargets = new Set();
-  for (var cls in world.subtypesOf(type.element)) {
-    var member = cls.lookupMember(selectorName);
-    if (member != null &&
-        !member.isAbstract
-        // Don't match nsm in Object
-        &&
-        (!isNsm || !member.enclosingClass.isObject)) {
-      uniqueTargets.add(member);
-    } else {
-      notFound = true;
-    }
-  }
-  Boolish exists = uniqueTargets.length > 0
-      ? (notFound ? Boolish.maybe : Boolish.yes)
-      : Boolish.no;
-  return new _SelectorLookupResult(exists, uniqueTargets.length);
-}
-
-class TrustTypesReceiverInfo implements ReceiverInfo {
-  final Node receiver;
-  final Boolish hasNoSuchMethod;
-  final int possibleNsmTargets;
-  final Boolish isNull = Boolish.maybe;
-
-  factory TrustTypesReceiverInfo(
-      Node receiver, InterfaceType type, ClassWorld world) {
-    // TODO(sigmund): refactor, maybe just store nsm as a SelectorInfo
-    var res = _lookupSelector('noSuchMethod', type, world);
-    return new TrustTypesReceiverInfo._(
-        receiver, res.exists, res.possibleTargets);
-  }
-
-  TrustTypesReceiverInfo._(
-      this.receiver, this.hasNoSuchMethod, this.possibleNsmTargets);
-}
-
-class TrustTypesSelectorInfo implements SelectorInfo {
-  final Node receiver;
-  final Selector selector;
-
-  final Boolish exists;
-  final Boolish usesInterceptor;
-  final int possibleTargets;
-  final bool isAccurate;
-
-  factory TrustTypesSelectorInfo(
-      Node receiver, InterfaceType type, Selector selector, ClassWorld world) {
-    var res =
-        _lookupSelector(selector != null ? selector.name : null, type, world);
-    return new TrustTypesSelectorInfo._(receiver, selector, res.exists,
-        res.usesInterceptor, res.possibleTargets, res.exists != Boolish.maybe);
-  }
-  TrustTypesSelectorInfo._(this.receiver, this.selector, this.exists,
-      this.usesInterceptor, this.possibleTargets, this.isAccurate);
-}
diff --git a/pkg/compiler/lib/src/io/position_information.dart b/pkg/compiler/lib/src/io/position_information.dart
index 321943f..b4a764f 100644
--- a/pkg/compiler/lib/src/io/position_information.dart
+++ b/pkg/compiler/lib/src/io/position_information.dart
@@ -9,11 +9,11 @@
 
 import '../common.dart';
 import '../elements/elements.dart'
-    show AstElement, FieldElement, ResolvedAst, ResolvedAstKind;
+    show AstElement, ResolvedAst, ResolvedAstKind;
 import '../js/js.dart' as js;
 import '../js/js_debug.dart';
 import '../js/js_source_mapping.dart';
-import '../tree/tree.dart' show FunctionExpression, Node, Send;
+import '../tree/tree.dart' show Node, Send;
 import 'code_output.dart' show CodeBuffer;
 import 'source_file.dart';
 import 'source_information.dart';
diff --git a/pkg/compiler/lib/src/io/source_file.dart b/pkg/compiler/lib/src/io/source_file.dart
index 93e6189..8b137c0 100644
--- a/pkg/compiler/lib/src/io/source_file.dart
+++ b/pkg/compiler/lib/src/io/source_file.dart
@@ -4,8 +4,8 @@
 
 library dart2js.io.source_file;
 
-import 'dart:math';
 import 'dart:convert' show UTF8;
+import 'dart:math';
 import 'dart:typed_data' show Uint8List;
 
 import 'line_column_provider.dart';
diff --git a/pkg/compiler/lib/src/io/source_map_builder.dart b/pkg/compiler/lib/src/io/source_map_builder.dart
index f6fa478..c3e6f5f 100644
--- a/pkg/compiler/lib/src/io/source_map_builder.dart
+++ b/pkg/compiler/lib/src/io/source_map_builder.dart
@@ -4,8 +4,8 @@
 
 library dart2js.source_map_builder;
 
-import '../util/util.dart';
 import '../util/uri_extras.dart' show relativize;
+import '../util/util.dart';
 import 'line_column_provider.dart';
 import 'source_information.dart' show SourceLocation;
 
diff --git a/pkg/compiler/lib/src/io/start_end_information.dart b/pkg/compiler/lib/src/io/start_end_information.dart
index 1734aa9..b246958 100644
--- a/pkg/compiler/lib/src/io/start_end_information.dart
+++ b/pkg/compiler/lib/src/io/start_end_information.dart
@@ -9,8 +9,7 @@
 
 import '../common.dart';
 import '../diagnostics/messages.dart' show MessageTemplate;
-import '../elements/elements.dart'
-    show AstElement, ResolvedAst, ResolvedAstKind;
+import '../elements/elements.dart' show ResolvedAst, ResolvedAstKind;
 import '../js/js.dart' as js;
 import '../js/js_source_mapping.dart';
 import '../tokens/token.dart' show Token;
diff --git a/pkg/compiler/lib/src/js/rewrite_async.dart b/pkg/compiler/lib/src/js/rewrite_async.dart
index 9578f3f..a70b5d3 100644
--- a/pkg/compiler/lib/src/js/rewrite_async.dart
+++ b/pkg/compiler/lib/src/js/rewrite_async.dart
@@ -4,15 +4,14 @@
 
 library rewrite_async;
 
-import "dart:math" show max;
 import 'dart:collection';
+import "dart:math" show max;
 
 import 'package:js_runtime/shared/async_await_error_codes.dart' as error_codes;
 
-import "js.dart" as js;
-
 import '../common.dart';
 import '../util/util.dart' show Pair;
+import "js.dart" as js;
 
 /// Rewrites a [js.Fun] with async/sync*/async* functions and await and yield
 /// (with dart-like semantics) to an equivalent function without these.
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index 4bf0d1e..0ab92e4 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -2,7 +2,84 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-part of js_backend;
+library js_backend.backend;
+
+import 'dart:async' show Future;
+
+import 'package:js_runtime/shared/embedded_names.dart' as embeddedNames;
+
+import '../closure.dart';
+import '../common.dart';
+import '../common/backend_api.dart'
+    show Backend, ImpactTransformer, ForeignResolver, NativeRegistry;
+import '../common/codegen.dart' show CodegenImpact, CodegenWorkItem;
+import '../common/names.dart' show Identifiers, Selectors, Uris;
+import '../common/registry.dart' show EagerRegistry, Registry;
+import '../common/resolution.dart'
+    show
+        Feature,
+        Frontend,
+        ListLiteralUse,
+        MapLiteralUse,
+        Resolution,
+        ResolutionImpact;
+import '../common/tasks.dart' show CompilerTask;
+import '../common/work.dart' show ItemCompilationContext;
+import '../compiler.dart' show Compiler;
+import '../constants/constant_system.dart';
+import '../constants/expressions.dart';
+import '../constants/values.dart';
+import '../core_types.dart' show CoreClasses, CoreTypes;
+import '../dart_types.dart';
+import '../deferred_load.dart' show DeferredLoadTask;
+import '../dump_info.dart' show DumpInfoTask;
+import '../elements/elements.dart';
+import '../enqueue.dart' show Enqueuer, ResolutionEnqueuer;
+import '../io/position_information.dart' show PositionSourceInformationStrategy;
+import '../io/source_information.dart' show SourceInformationStrategy;
+import '../io/start_end_information.dart'
+    show StartEndSourceInformationStrategy;
+import '../js/js.dart' as jsAst;
+import '../js/js.dart' show js;
+import '../js/js_source_mapping.dart' show JavaScriptSourceInformationStrategy;
+import '../js/rewrite_async.dart';
+import '../js_emitter/js_emitter.dart' show CodeEmitterTask;
+import '../library_loader.dart' show LibraryLoader, LoadedLibraries;
+import '../native/native.dart' as native;
+import '../ssa/builder.dart' show SsaFunctionCompiler;
+import '../ssa/nodes.dart' show HInstruction;
+import '../tree/tree.dart';
+import '../types/types.dart';
+import '../universe/call_structure.dart' show CallStructure;
+import '../universe/selector.dart' show Selector, SelectorKind;
+import '../universe/universe.dart';
+import '../universe/use.dart'
+    show DynamicUse, StaticUse, StaticUseKind, TypeUse, TypeUseKind;
+import '../universe/world_impact.dart'
+    show
+        ImpactStrategy,
+        ImpactUseCase,
+        TransformedWorldImpact,
+        WorldImpact,
+        WorldImpactVisitor;
+import '../util/util.dart';
+import '../world.dart' show ClassWorld;
+import 'backend_helpers.dart';
+import 'backend_impact.dart';
+import 'backend_serialization.dart' show JavaScriptBackendSerialization;
+import 'checked_mode_helpers.dart';
+import 'codegen/task.dart';
+import 'constant_handler_javascript.dart';
+import 'custom_elements_analysis.dart';
+import 'js_interop_analysis.dart' show JsInteropAnalysis;
+import 'lookup_map_analysis.dart' show LookupMapAnalysis;
+import 'namer.dart';
+import 'native_data.dart' show NativeData;
+import 'no_such_method_registry.dart';
+import 'patch_resolver.dart';
+import 'type_variable_handler.dart';
+
+part 'runtime_types.dart';
 
 const VERBOSE_OPTIMIZER_HINTS = false;
 
diff --git a/pkg/compiler/lib/src/js_backend/backend_helpers.dart b/pkg/compiler/lib/src/js_backend/backend_helpers.dart
index 7613305..b9e011d 100644
--- a/pkg/compiler/lib/src/js_backend/backend_helpers.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_helpers.dart
@@ -23,7 +23,6 @@
 import '../library_loader.dart' show LoadedLibraries;
 import '../universe/call_structure.dart' show CallStructure;
 import '../universe/selector.dart' show Selector;
-
 import 'js_backend.dart';
 
 /// Helper classes and functions for the JavaScript backend.
diff --git a/pkg/compiler/lib/src/js_backend/backend_impact.dart b/pkg/compiler/lib/src/js_backend/backend_impact.dart
index ee1dab9..7606e4d 100644
--- a/pkg/compiler/lib/src/js_backend/backend_impact.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_impact.dart
@@ -8,7 +8,6 @@
 import '../core_types.dart' show CoreClasses;
 import '../dart_types.dart' show InterfaceType;
 import '../elements/elements.dart' show ClassElement, Element;
-
 import 'backend_helpers.dart';
 import 'constant_system_javascript.dart';
 import 'js_backend.dart';
diff --git a/pkg/compiler/lib/src/js_backend/backend_serialization.dart b/pkg/compiler/lib/src/js_backend/backend_serialization.dart
index 471456cb..523f188 100644
--- a/pkg/compiler/lib/src/js_backend/backend_serialization.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_serialization.dart
@@ -4,15 +4,14 @@
 
 library js_backend.serialization;
 
-import '../common.dart';
 import '../common/backend_api.dart' show BackendSerialization;
 import '../dart_types.dart';
 import '../elements/elements.dart';
 import '../js/js.dart' as js;
 import '../native/native.dart';
+import '../serialization/keys.dart';
 import '../serialization/serialization.dart'
     show DeserializerPlugin, ObjectDecoder, ObjectEncoder, SerializerPlugin;
-import '../serialization/keys.dart';
 import '../universe/side_effects.dart';
 import 'js_backend.dart';
 
diff --git a/pkg/compiler/lib/src/js_backend/checked_mode_helpers.dart b/pkg/compiler/lib/src/js_backend/checked_mode_helpers.dart
index 409c44d..38e0070 100644
--- a/pkg/compiler/lib/src/js_backend/checked_mode_helpers.dart
+++ b/pkg/compiler/lib/src/js_backend/checked_mode_helpers.dart
@@ -2,7 +2,16 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-part of js_backend;
+import '../compiler.dart' show Compiler;
+import '../dart_types.dart';
+import '../elements/elements.dart';
+import '../js/js.dart' as jsAst;
+import '../js/js.dart' show js;
+import '../ssa/codegen.dart' show SsaCodeGenerator;
+import '../ssa/nodes.dart' show HTypeConversion;
+import '../universe/call_structure.dart' show CallStructure;
+import '../universe/use.dart' show StaticUse;
+import 'backend.dart';
 
 class CheckedModeHelper {
   final String name;
diff --git a/pkg/compiler/lib/src/js_backend/codegen/codegen.dart b/pkg/compiler/lib/src/js_backend/codegen/codegen.dart
index d2c539d..add58ce 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/codegen.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/codegen.dart
@@ -4,8 +4,6 @@
 
 library code_generator;
 
-import 'glue.dart';
-
 import '../../closure.dart' show ClosureClassElement;
 import '../../common/codegen.dart' show CodegenRegistry;
 import '../../constants/values.dart';
@@ -21,6 +19,7 @@
 import '../../universe/selector.dart' show Selector;
 import '../../universe/use.dart' show DynamicUse, StaticUse, TypeUse;
 import '../../util/maplet.dart';
+import 'glue.dart';
 
 class CodegenBailout {
   final tree_ir.Node node;
diff --git a/pkg/compiler/lib/src/js_backend/codegen/task.dart b/pkg/compiler/lib/src/js_backend/codegen/task.dart
index 69b13f3..859647a 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/task.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/task.dart
@@ -5,39 +5,37 @@
 /// Generate code using the cps-based IR pipeline.
 library code_generator_task;
 
-import 'glue.dart';
-import 'codegen.dart';
-import 'unsugar.dart';
-
-import '../js_backend.dart';
-
 import '../../common.dart';
 import '../../common/codegen.dart' show CodegenWorkItem;
 import '../../common/tasks.dart' show CompilerTask, GenericTask;
 import '../../compiler.dart' show Compiler;
 import '../../constants/constant_system.dart';
 import '../../cps_ir/cps_ir_builder_task.dart';
+import '../../cps_ir/cps_ir_integrity.dart';
 import '../../cps_ir/cps_ir_nodes.dart' as cps;
 import '../../cps_ir/cps_ir_nodes_sexpr.dart';
-import '../../cps_ir/cps_ir_integrity.dart';
+import '../../cps_ir/finalize.dart' show Finalize;
 import '../../cps_ir/optimizers.dart';
 import '../../cps_ir/optimizers.dart' as cps_opt;
 import '../../cps_ir/type_mask_system.dart';
-import '../../cps_ir/finalize.dart' show Finalize;
 import '../../diagnostics/invariant.dart' show DEBUG_MODE;
 import '../../elements/elements.dart';
+import '../../io/source_information.dart' show SourceInformationStrategy;
 import '../../js/js.dart' as js;
 import '../../js_backend/codegen/codegen.dart';
-import '../../io/source_information.dart' show SourceInformationStrategy;
-import '../../tree_ir/tree_ir_builder.dart' as tree_builder;
-import '../../tracer.dart';
 import '../../ssa/ssa.dart' as ssa;
+import '../../tracer.dart';
 import '../../tree_ir/optimization/optimization.dart';
 import '../../tree_ir/optimization/optimization.dart' as tree_opt;
+import '../../tree_ir/tree_ir_builder.dart' as tree_builder;
 import '../../tree_ir/tree_ir_integrity.dart';
 import '../../tree_ir/tree_ir_nodes.dart' as tree_ir;
 import '../../types/types.dart'
     show FlatTypeMask, ForwardingTypeMask, TypeMask, UnionTypeMask;
+import '../js_backend.dart';
+import 'codegen.dart';
+import 'glue.dart';
+import 'unsugar.dart';
 
 class CpsFunctionCompiler implements FunctionCompiler {
   final ConstantSystem constantSystem;
diff --git a/pkg/compiler/lib/src/js_backend/codegen/unsugar.dart b/pkg/compiler/lib/src/js_backend/codegen/unsugar.dart
index 3c0f485..02db2c4 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/unsugar.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/unsugar.dart
@@ -1,14 +1,13 @@
 library dart2js.unsugar_cps;
 
-import '../../cps_ir/cps_ir_nodes.dart';
-
-import '../../cps_ir/optimizers.dart' show Pass;
+import '../../common/names.dart';
 import '../../constants/values.dart';
+import '../../cps_ir/cps_fragment.dart';
+import '../../cps_ir/cps_ir_nodes.dart';
+import '../../cps_ir/optimizers.dart' show Pass;
 import '../../elements/elements.dart';
 import '../../js_backend/codegen/glue.dart';
 import '../../universe/selector.dart' show Selector;
-import '../../cps_ir/cps_fragment.dart';
-import '../../common/names.dart';
 
 class ExplicitReceiverParameterEntity implements Local {
   String get name => 'receiver';
diff --git a/pkg/compiler/lib/src/js_backend/constant_emitter.dart b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
index eba60d9..391a35c 100644
--- a/pkg/compiler/lib/src/js_backend/constant_emitter.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
@@ -2,7 +2,17 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-part of js_backend;
+import '../common.dart';
+import '../compiler.dart' show Compiler;
+import '../constants/values.dart';
+import '../dart_types.dart';
+import '../elements/elements.dart';
+import '../io/code_output.dart';
+import '../js/js.dart' as jsAst;
+import '../js/js.dart' show js;
+import 'backend.dart';
+import 'constant_system_javascript.dart';
+import 'namer.dart';
 
 typedef jsAst.Expression _ConstantReferenceGenerator(ConstantValue constant);
 
@@ -269,7 +279,7 @@
 
   @override
   jsAst.Expression visitSynthetic(SyntheticConstantValue constant, [_]) {
-    switch (constant.kind) {
+    switch (constant.valueKind) {
       case SyntheticConstantKind.DUMMY_INTERCEPTOR:
       case SyntheticConstantKind.EMPTY_VALUE:
         return new jsAst.LiteralNumber('0');
diff --git a/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart b/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart
index 8e6de54..2ab684e 100644
--- a/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart
@@ -2,7 +2,16 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-part of js_backend;
+import '../compile_time_constants.dart';
+import '../compiler.dart' show Compiler;
+import '../constants/constant_system.dart';
+import '../constants/expressions.dart';
+import '../constants/values.dart';
+import '../elements/elements.dart';
+import '../elements/visitor.dart' show BaseElementVisitor;
+import '../resolution/tree_elements.dart' show TreeElements;
+import '../tree/tree.dart';
+import 'constant_system_javascript.dart';
 
 /// [ConstantCompilerTask] for compilation of constants for the JavaScript
 /// backend.
diff --git a/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart b/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart
index 4bbf530..e717466 100644
--- a/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart
@@ -5,9 +5,9 @@
 library dart2js.constant_system.js;
 
 import '../compiler.dart' show Compiler;
+import '../constant_system_dart.dart';
 import '../constants/constant_system.dart';
 import '../constants/values.dart';
-import '../constant_system_dart.dart';
 import '../core_types.dart' show CoreTypes;
 import '../dart_types.dart';
 import '../elements/elements.dart' show ClassElement, FieldElement;
diff --git a/pkg/compiler/lib/src/js_backend/custom_elements_analysis.dart b/pkg/compiler/lib/src/js_backend/custom_elements_analysis.dart
index 450b826..b496a14 100644
--- a/pkg/compiler/lib/src/js_backend/custom_elements_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/custom_elements_analysis.dart
@@ -2,7 +2,13 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-part of js_backend;
+import '../compiler.dart' show Compiler;
+import '../constants/values.dart';
+import '../dart_types.dart';
+import '../elements/elements.dart';
+import '../enqueue.dart' show Enqueuer;
+import '../universe/use.dart' show StaticUse;
+import 'backend.dart';
 
 /**
  * Support for Custom Elements.
diff --git a/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart b/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart
index cfc0136..7ac77d5 100644
--- a/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart
+++ b/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-part of js_backend;
+part of js_backend.namer;
 
 abstract class _MinifiedFieldNamer implements Namer {
   _FieldNamingRegistry get fieldRegistry;
diff --git a/pkg/compiler/lib/src/js_backend/frequency_namer.dart b/pkg/compiler/lib/src/js_backend/frequency_namer.dart
index 7698c3d..9636e67 100644
--- a/pkg/compiler/lib/src/js_backend/frequency_namer.dart
+++ b/pkg/compiler/lib/src/js_backend/frequency_namer.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-part of js_backend;
+part of js_backend.namer;
 
 class FrequencyBasedNamer extends Namer
     with _MinifiedFieldNamer, _MinifiedOneShotInterceptorNamer
diff --git a/pkg/compiler/lib/src/js_backend/js_backend.dart b/pkg/compiler/lib/src/js_backend/js_backend.dart
index 5e5424f..aa31961 100644
--- a/pkg/compiler/lib/src/js_backend/js_backend.dart
+++ b/pkg/compiler/lib/src/js_backend/js_backend.dart
@@ -4,96 +4,11 @@
 
 library js_backend;
 
-import 'dart:async' show Future;
-import 'dart:collection' show HashMap;
-
-import 'package:js_runtime/shared/embedded_names.dart' as embeddedNames;
-import 'package:js_runtime/shared/embedded_names.dart' show JsGetName;
-
-import '../closure.dart';
-import '../common.dart';
-import '../common/backend_api.dart'
-    show Backend, ImpactTransformer, ForeignResolver, NativeRegistry;
-import '../common/codegen.dart' show CodegenImpact, CodegenWorkItem;
-import '../common/names.dart' show Identifiers, Names, Selectors, Uris;
-import '../common/registry.dart' show EagerRegistry, Registry;
-import '../common/resolution.dart'
-    show
-        Feature,
-        Frontend,
-        ListLiteralUse,
-        MapLiteralUse,
-        Resolution,
-        ResolutionImpact;
-import '../common/tasks.dart' show CompilerTask;
-import '../common/work.dart' show ItemCompilationContext;
-import '../compile_time_constants.dart';
-import '../compiler.dart' show Compiler;
-import '../constants/constant_system.dart';
-import '../constants/expressions.dart';
-import '../constants/values.dart';
-import '../core_types.dart' show CoreClasses, CoreTypes;
-import '../dart_types.dart';
-import '../deferred_load.dart' show DeferredLoadTask;
-import '../diagnostics/invariant.dart' show DEBUG_MODE;
-import '../dump_info.dart' show DumpInfoTask;
-import '../elements/elements.dart';
-import '../elements/visitor.dart' show BaseElementVisitor;
-import '../enqueue.dart' show Enqueuer, ResolutionEnqueuer;
-import '../io/code_output.dart';
-import '../io/position_information.dart' show PositionSourceInformationStrategy;
-import '../io/source_information.dart' show SourceInformationStrategy;
-import '../io/start_end_information.dart'
-    show StartEndSourceInformationStrategy;
-import '../js/js.dart' as jsAst;
-import '../js/js.dart' show js;
-import '../js/js_source_mapping.dart' show JavaScriptSourceInformationStrategy;
-import '../js/rewrite_async.dart';
-import '../js_emitter/js_emitter.dart'
-    show CodeEmitterTask, MetadataCollector, Placeholder;
-import '../library_loader.dart' show LibraryLoader, LoadedLibraries;
-import '../native/native.dart' as native;
-import '../resolution/tree_elements.dart' show TreeElements;
-import '../ssa/builder.dart' show SsaFunctionCompiler;
-import '../ssa/codegen.dart' show SsaCodeGenerator;
-import '../ssa/nodes.dart' show HTypeConversion, HInstruction;
-import '../tree/tree.dart';
-import '../types/types.dart';
-import '../universe/call_structure.dart' show CallStructure;
-import '../universe/selector.dart' show Selector, SelectorKind;
-import '../universe/universe.dart';
-import '../universe/use.dart'
-    show DynamicUse, StaticUse, StaticUseKind, TypeUse, TypeUseKind;
-import '../universe/world_impact.dart'
-    show
-        ImpactStrategy,
-        ImpactUseCase,
-        TransformedWorldImpact,
-        WorldImpact,
-        WorldImpactVisitor;
-import '../util/characters.dart';
-import '../util/util.dart';
-import '../world.dart' show ClassWorld;
-import 'backend_helpers.dart';
-import 'backend_impact.dart';
-import 'backend_serialization.dart' show JavaScriptBackendSerialization;
-import 'codegen/task.dart';
-import 'constant_system_javascript.dart';
-import 'js_interop_analysis.dart' show JsInteropAnalysis;
-import 'lookup_map_analysis.dart' show LookupMapAnalysis;
-import 'native_data.dart' show NativeData;
-import 'patch_resolver.dart';
-
-part 'backend.dart';
-part 'checked_mode_helpers.dart';
-part 'constant_emitter.dart';
-part 'constant_handler_javascript.dart';
-part 'custom_elements_analysis.dart';
-part 'field_naming_mixin.dart';
-part 'frequency_namer.dart';
-part 'minify_namer.dart';
-part 'namer.dart';
-part 'namer_names.dart';
-part 'no_such_method_registry.dart';
-part 'runtime_types.dart';
-part 'type_variable_handler.dart';
+export 'backend.dart';
+export 'checked_mode_helpers.dart';
+export 'constant_emitter.dart';
+export 'constant_handler_javascript.dart';
+export 'custom_elements_analysis.dart';
+export 'namer.dart';
+export 'no_such_method_registry.dart';
+export 'type_variable_handler.dart';
diff --git a/pkg/compiler/lib/src/js_backend/minify_namer.dart b/pkg/compiler/lib/src/js_backend/minify_namer.dart
index ff76d87..3e689d4 100644
--- a/pkg/compiler/lib/src/js_backend/minify_namer.dart
+++ b/pkg/compiler/lib/src/js_backend/minify_namer.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-part of js_backend;
+part of js_backend.namer;
 
 /**
  * Assigns JavaScript identifiers to Dart variables, class-names and members.
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index aeea76e..7cc4621 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -2,7 +2,37 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-part of js_backend;
+library js_backend.namer;
+
+import 'dart:collection' show HashMap;
+
+import 'package:js_runtime/shared/embedded_names.dart' show JsGetName;
+
+import '../closure.dart';
+import '../common.dart';
+import '../common/names.dart' show Identifiers, Selectors;
+import '../compiler.dart' show Compiler;
+import '../constants/values.dart';
+import '../core_types.dart' show CoreClasses;
+import '../dart_types.dart';
+import '../diagnostics/invariant.dart' show DEBUG_MODE;
+import '../elements/elements.dart';
+import '../js/js.dart' as jsAst;
+import '../js/js.dart' show js;
+import '../tree/tree.dart';
+import '../universe/call_structure.dart' show CallStructure;
+import '../universe/selector.dart' show Selector, SelectorKind;
+import '../util/characters.dart';
+import '../util/util.dart';
+import '../world.dart' show ClassWorld;
+import 'backend.dart';
+import 'backend_helpers.dart';
+import 'constant_system_javascript.dart';
+
+part 'field_naming_mixin.dart';
+part 'frequency_namer.dart';
+part 'minify_namer.dart';
+part 'namer_names.dart';
 
 /**
  * Assigns JavaScript identifiers to Dart variables, class-names and members.
@@ -1768,7 +1798,7 @@
 
   @override
   void visitSynthetic(SyntheticConstantValue constant, [_]) {
-    switch (constant.kind) {
+    switch (constant.valueKind) {
       case SyntheticConstantKind.DUMMY_INTERCEPTOR:
         add('dummy_receiver');
         break;
@@ -1888,7 +1918,7 @@
 
   @override
   int visitSynthetic(SyntheticConstantValue constant, [_]) {
-    switch (constant.kind) {
+    switch (constant.valueKind) {
       case SyntheticConstantKind.TYPEVARIABLE_REFERENCE:
         // These contain a deferred opaque index into metadata. There is nothing
         // we can access that is stable between compiles.  Luckily, since they
diff --git a/pkg/compiler/lib/src/js_backend/namer_names.dart b/pkg/compiler/lib/src/js_backend/namer_names.dart
index 4baffb5..7e8e76f 100644
--- a/pkg/compiler/lib/src/js_backend/namer_names.dart
+++ b/pkg/compiler/lib/src/js_backend/namer_names.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-part of js_backend;
+part of js_backend.namer;
 
 abstract class _NamerName extends jsAst.Name {
   int get _kind;
diff --git a/pkg/compiler/lib/src/js_backend/no_such_method_registry.dart b/pkg/compiler/lib/src/js_backend/no_such_method_registry.dart
index d9e8681..4464214 100644
--- a/pkg/compiler/lib/src/js_backend/no_such_method_registry.dart
+++ b/pkg/compiler/lib/src/js_backend/no_such_method_registry.dart
@@ -2,7 +2,13 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-part of js_backend;
+import '../common.dart';
+import '../common/names.dart' show Identifiers, Names, Selectors;
+import '../compiler.dart' show Compiler;
+import '../elements/elements.dart';
+import '../tree/tree.dart';
+import '../types/types.dart';
+import 'backend.dart';
 
 /**
  * Categorizes `noSuchMethod` implementations.
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types.dart b/pkg/compiler/lib/src/js_backend/runtime_types.dart
index e3f74b7..1e8cc1c 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-part of js_backend;
+part of js_backend.backend;
 
 /// For each class, stores the possible class subtype tests that could succeed.
 abstract class TypeChecks {
diff --git a/pkg/compiler/lib/src/js_backend/type_variable_handler.dart b/pkg/compiler/lib/src/js_backend/type_variable_handler.dart
index faf8539..ada9d16 100644
--- a/pkg/compiler/lib/src/js_backend/type_variable_handler.dart
+++ b/pkg/compiler/lib/src/js_backend/type_variable_handler.dart
@@ -2,7 +2,21 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-part of js_backend;
+import '../common.dart';
+import '../common/registry.dart' show Registry;
+import '../compiler.dart' show Compiler;
+import '../constants/expressions.dart';
+import '../constants/values.dart';
+import '../dart_types.dart';
+import '../elements/elements.dart';
+import '../enqueue.dart' show Enqueuer;
+import '../js/js.dart' as jsAst;
+import '../js_emitter/js_emitter.dart'
+    show CodeEmitterTask, MetadataCollector, Placeholder;
+import '../universe/call_structure.dart' show CallStructure;
+import '../universe/use.dart' show StaticUse;
+import '../util/util.dart';
+import 'backend.dart';
 
 /**
  * Handles construction of TypeVariable constants needed at runtime.
diff --git a/pkg/compiler/lib/src/js_emitter/constant_ordering.dart b/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
index 57ce762..6baa377 100644
--- a/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
+++ b/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
@@ -5,11 +5,10 @@
 library dart2js.js_emitter.constant_ordering;
 
 import '../constants/values.dart';
-
 import '../dart_types.dart';
 import '../elements/elements.dart' show Element, Elements, FieldElement;
-import '../tree/dartstring.dart' show DartString;
 import '../js_backend/js_backend.dart' show SyntheticConstantKind;
+import '../tree/dartstring.dart' show DartString;
 
 /// A canonical but arbrary ordering of constants. The ordering is 'stable'
 /// under perturbation of the source.
@@ -148,11 +147,11 @@
     // as elements of a few constants.  If this becomes a source of instability,
     // we will need to add a total ordering on JavaScript ASTs including
     // deferred elements.
-    SyntheticConstantKind aKind = a.kind;
-    SyntheticConstantKind bKind = b.kind;
+    SyntheticConstantKind aKind = a.valueKind;
+    SyntheticConstantKind bKind = b.valueKind;
     int r = aKind.index - bKind.index;
     if (r != 0) return r;
-    switch (a.kind) {
+    switch (aKind) {
       case SyntheticConstantKind.DUMMY_INTERCEPTOR:
       case SyntheticConstantKind.EMPTY_VALUE:
         // Never emitted.
diff --git a/pkg/compiler/lib/src/js_emitter/lazy_emitter/model_emitter.dart b/pkg/compiler/lib/src/js_emitter/lazy_emitter/model_emitter.dart
index 138062e..352d7f7 100644
--- a/pkg/compiler/lib/src/js_emitter/lazy_emitter/model_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/lazy_emitter/model_emitter.dart
@@ -4,17 +4,6 @@
 
 library dart2js.js_emitter.lazy_emitter.model_emitter;
 
-import '../../compiler.dart' show Compiler;
-import '../../constants/values.dart' show ConstantValue, FunctionConstantValue;
-import '../../core_types.dart' show CoreClasses;
-import '../../elements/elements.dart' show ClassElement, FunctionElement;
-import '../../js/js.dart' as js;
-import '../../js_backend/js_backend.dart'
-    show JavaScriptBackend, Namer, ConstantEmitter;
-
-import '../js_emitter.dart' show NativeEmitter;
-import '../constant_ordering.dart' show deepCompareConstants;
-
 import 'package:js_runtime/shared/embedded_names.dart'
     show
         CREATE_NEW_ISOLATE,
@@ -31,6 +20,15 @@
         TYPE_TO_INTERCEPTOR_MAP,
         TYPES;
 
+import '../../compiler.dart' show Compiler;
+import '../../constants/values.dart' show ConstantValue, FunctionConstantValue;
+import '../../core_types.dart' show CoreClasses;
+import '../../elements/elements.dart' show ClassElement, FunctionElement;
+import '../../js/js.dart' as js;
+import '../../js_backend/js_backend.dart'
+    show JavaScriptBackend, Namer, ConstantEmitter;
+import '../constant_ordering.dart' show deepCompareConstants;
+import '../js_emitter.dart' show NativeEmitter;
 import '../js_emitter.dart' show NativeGenerator, buildTearOffCode;
 import '../model.dart';
 
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
index 072e8cb..07be9d6 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
@@ -14,12 +14,10 @@
     show ClassElement, Element, FieldElement, FunctionElement;
 import '../../js/js.dart' as js;
 import '../../js_backend/js_backend.dart' show JavaScriptBackend, Namer;
-
 import '../js_emitter.dart' show NativeEmitter;
 import '../js_emitter.dart' as emitterTask show Emitter;
-import '../program_builder/program_builder.dart' show ProgramBuilder;
 import '../model.dart';
-
+import '../program_builder/program_builder.dart' show ProgramBuilder;
 import 'model_emitter.dart';
 
 class Emitter implements emitterTask.Emitter {
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
index b3be363..046fa6f 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
@@ -31,8 +31,8 @@
         TYPES;
 
 import '../../common.dart';
-import '../../constants/values.dart' show ConstantValue, FunctionConstantValue;
 import '../../compiler.dart' show Compiler;
+import '../../constants/values.dart' show ConstantValue, FunctionConstantValue;
 import '../../core_types.dart' show CoreClasses;
 import '../../elements/elements.dart' show ClassElement, FunctionElement;
 import '../../hash/sha1.dart' show Hasher;
@@ -44,11 +44,9 @@
 import '../../js_backend/js_backend.dart'
     show JavaScriptBackend, Namer, ConstantEmitter;
 import '../../util/uri_extras.dart' show relativize;
-
 import '../constant_ordering.dart' show deepCompareConstants;
 import '../headers.dart';
 import '../js_emitter.dart' show NativeEmitter;
-
 import '../js_emitter.dart' show buildTearOffCode, NativeGenerator;
 import '../model.dart';
 
diff --git a/pkg/compiler/lib/src/native/behavior.dart b/pkg/compiler/lib/src/native/behavior.dart
index a4e2922..57ef61a 100644
--- a/pkg/compiler/lib/src/native/behavior.dart
+++ b/pkg/compiler/lib/src/native/behavior.dart
@@ -15,7 +15,6 @@
 import '../tree/tree.dart';
 import '../universe/side_effects.dart' show SideEffects;
 import '../util/util.dart';
-
 import 'enqueue.dart';
 import 'js.dart';
 
diff --git a/pkg/compiler/lib/src/native/js.dart b/pkg/compiler/lib/src/native/js.dart
index 1251fe5..e7c7079 100644
--- a/pkg/compiler/lib/src/native/js.dart
+++ b/pkg/compiler/lib/src/native/js.dart
@@ -4,7 +4,6 @@
 
 import '../js/js.dart' as js;
 import '../universe/side_effects.dart' show SideEffects;
-
 import 'behavior.dart';
 
 class HasCapturedPlaceholders extends js.BaseVisitor {
diff --git a/pkg/compiler/lib/src/native/scanner.dart b/pkg/compiler/lib/src/native/scanner.dart
index f22b866..c1bc40d 100644
--- a/pkg/compiler/lib/src/native/scanner.dart
+++ b/pkg/compiler/lib/src/native/scanner.dart
@@ -4,7 +4,6 @@
 
 import '../common.dart';
 import '../parser/element_listener.dart' show ElementListener;
-import '../parser/listener.dart' show Listener;
 import '../tokens/token.dart' show BeginGroupToken, Token;
 import '../tokens/token_constants.dart' as Tokens show STRING_TOKEN;
 
diff --git a/pkg/compiler/lib/src/null_compiler_output.dart b/pkg/compiler/lib/src/null_compiler_output.dart
index acc323f..ed5a186 100644
--- a/pkg/compiler/lib/src/null_compiler_output.dart
+++ b/pkg/compiler/lib/src/null_compiler_output.dart
@@ -6,9 +6,10 @@
 
 library compiler.null_api;
 
-import '../compiler_new.dart';
 import 'dart:async';
 
+import '../compiler_new.dart';
+
 /// Null pattern implementation of the [CompilerOutput] interface.
 class NullCompilerOutput implements CompilerOutput {
   const NullCompilerOutput();
diff --git a/pkg/compiler/lib/src/old_to_new_api.dart b/pkg/compiler/lib/src/old_to_new_api.dart
index 7954091..d79b5f9 100644
--- a/pkg/compiler/lib/src/old_to_new_api.dart
+++ b/pkg/compiler/lib/src/old_to_new_api.dart
@@ -8,9 +8,10 @@
 library compiler.api.legacy;
 
 import 'dart:async' show EventSink, Future;
-import 'null_compiler_output.dart' show NullSink;
+
 import '../compiler.dart';
 import '../compiler_new.dart';
+import 'null_compiler_output.dart' show NullSink;
 
 /// Implementation of [CompilerInput] using a [CompilerInputProvider].
 class LegacyCompilerInput implements CompilerInput {
diff --git a/pkg/compiler/lib/src/options.dart b/pkg/compiler/lib/src/options.dart
index 98b88e0..b1aaeb0 100644
--- a/pkg/compiler/lib/src/options.dart
+++ b/pkg/compiler/lib/src/options.dart
@@ -4,8 +4,8 @@
 
 library dart2js.src.options;
 
-import 'commandline_options.dart' show Flags;
 import '../compiler.dart' show PackagesDiscoveryProvider;
+import 'commandline_options.dart' show Flags;
 
 /// Options used for parsing.
 ///
diff --git a/pkg/compiler/lib/src/parser/class_element_parser.dart b/pkg/compiler/lib/src/parser/class_element_parser.dart
index b85114d..3d3cd27 100644
--- a/pkg/compiler/lib/src/parser/class_element_parser.dart
+++ b/pkg/compiler/lib/src/parser/class_element_parser.dart
@@ -4,10 +4,9 @@
 
 library dart2js.parser.classes;
 
-import '../tokens/token.dart' show Token;
-
-import 'listener.dart' show Listener;
 import '../options.dart' show ParserOptions;
+import '../tokens/token.dart' show Token;
+import 'listener.dart' show Listener;
 import 'partial_parser.dart' show PartialParser;
 
 class ClassElementParser extends PartialParser {
diff --git a/pkg/compiler/lib/src/parser/diet_parser_task.dart b/pkg/compiler/lib/src/parser/diet_parser_task.dart
index 3c48a31..002bba0 100644
--- a/pkg/compiler/lib/src/parser/diet_parser_task.dart
+++ b/pkg/compiler/lib/src/parser/diet_parser_task.dart
@@ -9,11 +9,10 @@
 import '../common/tasks.dart' show CompilerTask, Measurer;
 import '../elements/elements.dart' show CompilationUnitElement;
 import '../id_generator.dart';
-import '../tokens/token.dart' show Token;
-
-import 'listener.dart' show ParserError;
-import 'element_listener.dart' show ElementListener, ScannerOptions;
 import '../options.dart' show ParserOptions;
+import '../tokens/token.dart' show Token;
+import 'element_listener.dart' show ElementListener, ScannerOptions;
+import 'listener.dart' show ParserError;
 import 'partial_parser.dart' show PartialParser;
 
 class DietParserTask extends CompilerTask {
diff --git a/pkg/compiler/lib/src/parser/element_listener.dart b/pkg/compiler/lib/src/parser/element_listener.dart
index 6d9bd82..ae1c592 100644
--- a/pkg/compiler/lib/src/parser/element_listener.dart
+++ b/pkg/compiler/lib/src/parser/element_listener.dart
@@ -4,7 +4,6 @@
 
 library dart2js.parser.element_listener;
 
-import '../compiler.dart' show Compiler;
 import '../common.dart';
 import '../diagnostics/messages.dart' show MessageTemplate;
 import '../elements/elements.dart'
@@ -30,7 +29,7 @@
 import '../tokens/token_constants.dart' as Tokens show EOF_TOKEN;
 import '../tree/tree.dart';
 import '../util/util.dart' show Link, LinkBuilder;
-
+import 'listener.dart' show closeBraceFor, Listener, ParserError, VERBOSE;
 import 'partial_elements.dart'
     show
         PartialClassElement,
@@ -39,7 +38,6 @@
         PartialFunctionElement,
         PartialMetadataAnnotation,
         PartialTypedefElement;
-import 'listener.dart' show closeBraceFor, Listener, ParserError, VERBOSE;
 
 /// Options used for scanning.
 ///
diff --git a/pkg/compiler/lib/src/parser/parser.dart b/pkg/compiler/lib/src/parser/parser.dart
index 3ac4900..f9998ca 100644
--- a/pkg/compiler/lib/src/parser/parser.dart
+++ b/pkg/compiler/lib/src/parser/parser.dart
@@ -4,8 +4,8 @@
 
 library dart2js.parser;
 
-import '../options.dart' show ParserOptions;
 import '../common.dart';
+import '../options.dart' show ParserOptions;
 import '../tokens/keyword.dart' show Keyword;
 import '../tokens/precedence.dart' show PrecedenceInfo;
 import '../tokens/precedence_constants.dart'
@@ -58,7 +58,6 @@
         STRING_TOKEN;
 import '../util/characters.dart' as Characters show $CLOSE_CURLY_BRACKET;
 import '../util/util.dart' show Link;
-
 import 'listener.dart' show Listener;
 
 class FormalParameterType {
diff --git a/pkg/compiler/lib/src/parser/parser_task.dart b/pkg/compiler/lib/src/parser/parser_task.dart
index 02c3719..07734b9 100644
--- a/pkg/compiler/lib/src/parser/parser_task.dart
+++ b/pkg/compiler/lib/src/parser/parser_task.dart
@@ -11,7 +11,6 @@
 import '../options.dart' show ParserOptions;
 import '../tokens/token.dart' show Token;
 import '../tree/tree.dart' show Node;
-
 import 'element_listener.dart' show ScannerOptions;
 import 'listener.dart' show ParserError;
 import 'node_listener.dart' show NodeListener;
diff --git a/pkg/compiler/lib/src/parser/partial_parser.dart b/pkg/compiler/lib/src/parser/partial_parser.dart
index 514a058..0868265 100644
--- a/pkg/compiler/lib/src/parser/partial_parser.dart
+++ b/pkg/compiler/lib/src/parser/partial_parser.dart
@@ -6,10 +6,9 @@
 
 import '../common.dart';
 import '../options.dart' show ParserOptions;
-import '../util/characters.dart' as Characters show $CLOSE_CURLY_BRACKET;
 import '../tokens/token.dart' show BeginGroupToken, ErrorToken, Token;
 import '../tokens/token_constants.dart' as Tokens show EOF_TOKEN;
-
+import '../util/characters.dart' as Characters show $CLOSE_CURLY_BRACKET;
 import 'listener.dart' show Listener;
 import 'parser.dart' show Parser;
 
diff --git a/pkg/compiler/lib/src/platform_configuration.dart b/pkg/compiler/lib/src/platform_configuration.dart
index 56a48df..e721001 100644
--- a/pkg/compiler/lib/src/platform_configuration.dart
+++ b/pkg/compiler/lib/src/platform_configuration.dart
@@ -6,7 +6,9 @@
 library plaform_configuration;
 
 import "dart:async";
+
 import "package:charcode/ascii.dart";
+
 import "../compiler_new.dart" as api;
 
 /// Parses an Ini-like format.
diff --git a/pkg/compiler/lib/src/resolution/access_semantics.dart b/pkg/compiler/lib/src/resolution/access_semantics.dart
index fdd8410..ffb71f9 100644
--- a/pkg/compiler/lib/src/resolution/access_semantics.dart
+++ b/pkg/compiler/lib/src/resolution/access_semantics.dart
@@ -8,8 +8,8 @@
 library dart2js.access_semantics;
 
 import '../constants/expressions.dart';
-import '../elements/elements.dart';
 import '../dart_types.dart';
+import '../elements/elements.dart';
 
 /// Enum representing the different kinds of destinations which a property
 /// access or method or function invocation might refer to.
diff --git a/pkg/compiler/lib/src/resolution/class_hierarchy.dart b/pkg/compiler/lib/src/resolution/class_hierarchy.dart
index 39fe5e1..cdc5c02 100644
--- a/pkg/compiler/lib/src/resolution/class_hierarchy.dart
+++ b/pkg/compiler/lib/src/resolution/class_hierarchy.dart
@@ -19,9 +19,8 @@
         UnnamedMixinApplicationElementX;
 import '../ordered_typeset.dart' show OrderedTypeSet, OrderedTypeSetBuilder;
 import '../tree/tree.dart';
-import '../util/util.dart' show Link, Setlet;
 import '../universe/call_structure.dart' show CallStructure;
-
+import '../util/util.dart' show Link, Setlet;
 import 'enum_creator.dart';
 import 'members.dart' show lookupInScope;
 import 'registry.dart' show ResolutionRegistry;
diff --git a/pkg/compiler/lib/src/resolution/class_members.dart b/pkg/compiler/lib/src/resolution/class_members.dart
index 7c28777..b4ae169 100644
--- a/pkg/compiler/lib/src/resolution/class_members.dart
+++ b/pkg/compiler/lib/src/resolution/class_members.dart
@@ -7,7 +7,6 @@
 import '../common.dart';
 import '../common/names.dart' show Identifiers, Names;
 import '../common/resolution.dart' show Resolution;
-import '../compiler.dart' show Compiler;
 import '../dart_types.dart';
 import '../elements/elements.dart'
     show
diff --git a/pkg/compiler/lib/src/resolution/constructors.dart b/pkg/compiler/lib/src/resolution/constructors.dart
index 50f51d1..1d2ac2f 100644
--- a/pkg/compiler/lib/src/resolution/constructors.dart
+++ b/pkg/compiler/lib/src/resolution/constructors.dart
@@ -23,10 +23,9 @@
         InitializingFormalElementX,
         ParameterElementX;
 import '../tree/tree.dart';
-import '../util/util.dart' show Link;
 import '../universe/call_structure.dart' show CallStructure;
 import '../universe/use.dart' show StaticUse;
-
+import '../util/util.dart' show Link;
 import 'members.dart' show lookupInScope, ResolverVisitor;
 import 'registry.dart' show ResolutionRegistry;
 import 'resolution_common.dart' show CommonResolverVisitor;
diff --git a/pkg/compiler/lib/src/resolution/members.dart b/pkg/compiler/lib/src/resolution/members.dart
index 97f59bc..8ef45c0 100644
--- a/pkg/compiler/lib/src/resolution/members.dart
+++ b/pkg/compiler/lib/src/resolution/members.dart
@@ -20,7 +20,6 @@
         ConstructorElementX,
         ErroneousElementX,
         FunctionElementX,
-        InitializingFormalElementX,
         JumpTargetX,
         LocalFunctionElementX,
         LocalParameterElementX,
diff --git a/pkg/compiler/lib/src/resolution/registry.dart b/pkg/compiler/lib/src/resolution/registry.dart
index 753d9a7..4d9606b 100644
--- a/pkg/compiler/lib/src/resolution/registry.dart
+++ b/pkg/compiler/lib/src/resolution/registry.dart
@@ -7,26 +7,22 @@
 import '../common.dart';
 import '../common/backend_api.dart'
     show Backend, ForeignResolver, NativeRegistry;
+import '../common/registry.dart' show Registry;
 import '../common/resolution.dart'
     show Feature, ListLiteralUse, MapLiteralUse, ResolutionImpact, Target;
-import '../common/registry.dart' show Registry;
-import '../compiler.dart' show Compiler;
 import '../constants/expressions.dart';
 import '../dart_types.dart';
 import '../diagnostics/source_span.dart';
-import '../enqueue.dart' show ResolutionEnqueuer;
 import '../elements/elements.dart';
 import '../tree/tree.dart';
-import '../util/util.dart' show Setlet;
 import '../universe/call_structure.dart' show CallStructure;
 import '../universe/selector.dart' show Selector;
 import '../universe/use.dart' show DynamicUse, StaticUse, TypeUse;
 import '../universe/world_impact.dart' show WorldImpact, WorldImpactBuilder;
 import '../util/enumset.dart' show EnumSet;
-
-import 'send_structure.dart';
-
+import '../util/util.dart' show Setlet;
 import 'members.dart' show ResolverVisitor;
+import 'send_structure.dart';
 import 'tree_elements.dart' show TreeElementMapping;
 
 class _ResolutionWorldImpact extends ResolutionImpact
diff --git a/pkg/compiler/lib/src/resolution/semantic_visitor.dart b/pkg/compiler/lib/src/resolution/semantic_visitor.dart
index 6f0005e..c4fe79a 100644
--- a/pkg/compiler/lib/src/resolution/semantic_visitor.dart
+++ b/pkg/compiler/lib/src/resolution/semantic_visitor.dart
@@ -7,11 +7,10 @@
 import '../common.dart';
 import '../constants/expressions.dart';
 import '../dart_types.dart';
-import '../tree/tree.dart';
 import '../elements/elements.dart';
+import '../tree/tree.dart';
 import '../universe/call_structure.dart' show CallStructure;
 import '../universe/selector.dart' show Selector;
-
 import 'operators.dart';
 import 'send_resolver.dart';
 import 'send_structure.dart';
diff --git a/pkg/compiler/lib/src/resolution/send_resolver.dart b/pkg/compiler/lib/src/resolution/send_resolver.dart
index 7ef2a86..d53d4ec 100644
--- a/pkg/compiler/lib/src/resolution/send_resolver.dart
+++ b/pkg/compiler/lib/src/resolution/send_resolver.dart
@@ -9,7 +9,6 @@
 import '../dart_types.dart';
 import '../elements/elements.dart';
 import '../tree/tree.dart';
-
 import 'semantic_visitor.dart';
 import 'send_structure.dart';
 import 'tree_elements.dart';
diff --git a/pkg/compiler/lib/src/resolution/send_structure.dart b/pkg/compiler/lib/src/resolution/send_structure.dart
index b26087e..52bf4dd 100644
--- a/pkg/compiler/lib/src/resolution/send_structure.dart
+++ b/pkg/compiler/lib/src/resolution/send_structure.dart
@@ -12,7 +12,6 @@
 import '../tree/tree.dart';
 import '../universe/call_structure.dart' show CallStructure;
 import '../universe/selector.dart' show Selector;
-
 import 'access_semantics.dart';
 import 'operators.dart';
 import 'semantic_visitor.dart';
diff --git a/pkg/compiler/lib/src/resolution/tree_elements.dart b/pkg/compiler/lib/src/resolution/tree_elements.dart
index 974981c..bae0857 100644
--- a/pkg/compiler/lib/src/resolution/tree_elements.dart
+++ b/pkg/compiler/lib/src/resolution/tree_elements.dart
@@ -9,11 +9,10 @@
 import '../dart_types.dart';
 import '../diagnostics/source_span.dart';
 import '../elements/elements.dart';
-import '../types/types.dart' show TypeMask;
 import '../tree/tree.dart';
-import '../util/util.dart';
+import '../types/types.dart' show TypeMask;
 import '../universe/selector.dart' show Selector;
-
+import '../util/util.dart';
 import 'secret_tree_element.dart' show getTreeElement, setTreeElement;
 import 'send_structure.dart';
 
diff --git a/pkg/compiler/lib/src/resolution/typedefs.dart b/pkg/compiler/lib/src/resolution/typedefs.dart
index 7f18141..eed801b 100644
--- a/pkg/compiler/lib/src/resolution/typedefs.dart
+++ b/pkg/compiler/lib/src/resolution/typedefs.dart
@@ -4,8 +4,6 @@
 
 library dart2js.resolution.typedefs;
 
-import 'dart:developer';
-
 import '../common.dart';
 import '../common/resolution.dart';
 import '../dart_types.dart';
@@ -14,7 +12,6 @@
 import '../elements/modelx.dart' show ErroneousElementX, TypedefElementX;
 import '../tree/tree.dart';
 import '../util/util.dart' show Link;
-
 import 'class_hierarchy.dart' show TypeDefinitionVisitor;
 import 'registry.dart' show ResolutionRegistry;
 import 'scope.dart' show MethodScope, TypeDeclarationScope;
diff --git a/pkg/compiler/lib/src/resolution/variables.dart b/pkg/compiler/lib/src/resolution/variables.dart
index 28d5372..77a8f4e 100644
--- a/pkg/compiler/lib/src/resolution/variables.dart
+++ b/pkg/compiler/lib/src/resolution/variables.dart
@@ -10,7 +10,6 @@
 import '../tree/tree.dart';
 import '../universe/use.dart' show TypeUse;
 import '../util/util.dart' show Link;
-
 import 'members.dart' show ResolverVisitor;
 import 'registry.dart' show ResolutionRegistry;
 import 'resolution_common.dart' show CommonResolverVisitor;
diff --git a/pkg/compiler/lib/src/scanner/array_based_scanner.dart b/pkg/compiler/lib/src/scanner/array_based_scanner.dart
index 2496daa..edd22ae 100644
--- a/pkg/compiler/lib/src/scanner/array_based_scanner.dart
+++ b/pkg/compiler/lib/src/scanner/array_based_scanner.dart
@@ -15,7 +15,6 @@
     show LT_TOKEN, OPEN_CURLY_BRACKET_TOKEN, STRING_INTERPOLATION_TOKEN;
 import '../util/characters.dart' show $LF, $STX;
 import '../util/util.dart' show Link;
-
 import 'scanner.dart' show AbstractScanner;
 
 abstract class ArrayBasedScanner extends AbstractScanner {
diff --git a/pkg/compiler/lib/src/scanner/scanner.dart b/pkg/compiler/lib/src/scanner/scanner.dart
index 30d5caf..63f4bd0 100644
--- a/pkg/compiler/lib/src/scanner/scanner.dart
+++ b/pkg/compiler/lib/src/scanner/scanner.dart
@@ -11,7 +11,6 @@
 import '../tokens/token.dart';
 import '../tokens/token_constants.dart';
 import '../util/characters.dart';
-
 import 'string_scanner.dart' show StringScanner;
 import 'utf8_bytes_scanner.dart' show Utf8BytesScanner;
 
diff --git a/pkg/compiler/lib/src/scanner/scanner_task.dart b/pkg/compiler/lib/src/scanner/scanner_task.dart
index 6b25efd..1977248 100644
--- a/pkg/compiler/lib/src/scanner/scanner_task.dart
+++ b/pkg/compiler/lib/src/scanner/scanner_task.dart
@@ -7,12 +7,11 @@
 import '../common/tasks.dart' show CompilerTask, Measurer;
 import '../diagnostics/diagnostic_listener.dart' show DiagnosticReporter;
 import '../elements/elements.dart' show CompilationUnitElement, LibraryElement;
-import '../script.dart' show Script;
 import '../parser/diet_parser_task.dart' show DietParserTask;
+import '../script.dart' show Script;
 import '../tokens/token.dart' show Token;
 import '../tokens/token_constants.dart' as Tokens show COMMENT_TOKEN, EOF_TOKEN;
 import '../tokens/token_map.dart' show TokenMap;
-
 import 'scanner.dart' show Scanner;
 import 'string_scanner.dart' show StringScanner;
 
diff --git a/pkg/compiler/lib/src/scanner/string_scanner.dart b/pkg/compiler/lib/src/scanner/string_scanner.dart
index 5c6604e..7e1f995d 100644
--- a/pkg/compiler/lib/src/scanner/string_scanner.dart
+++ b/pkg/compiler/lib/src/scanner/string_scanner.dart
@@ -7,7 +7,6 @@
 import '../io/source_file.dart' show SourceFile;
 import '../tokens/precedence.dart' show PrecedenceInfo;
 import '../tokens/token.dart' show StringToken, Token;
-
 import 'array_based_scanner.dart' show ArrayBasedScanner;
 
 /**
diff --git a/pkg/compiler/lib/src/scanner/utf8_bytes_scanner.dart b/pkg/compiler/lib/src/scanner/utf8_bytes_scanner.dart
index c4b87ed..ea46e35 100644
--- a/pkg/compiler/lib/src/scanner/utf8_bytes_scanner.dart
+++ b/pkg/compiler/lib/src/scanner/utf8_bytes_scanner.dart
@@ -9,7 +9,6 @@
 import '../io/source_file.dart' show SourceFile;
 import '../tokens/precedence.dart' show PrecedenceInfo;
 import '../tokens/token.dart' show StringToken, Token;
-
 import 'array_based_scanner.dart' show ArrayBasedScanner;
 
 /**
diff --git a/pkg/compiler/lib/src/serialization/constant_serialization.dart b/pkg/compiler/lib/src/serialization/constant_serialization.dart
index ae3040a..fae3d2f 100644
--- a/pkg/compiler/lib/src/serialization/constant_serialization.dart
+++ b/pkg/compiler/lib/src/serialization/constant_serialization.dart
@@ -10,8 +10,8 @@
 import '../elements/elements.dart' show FieldElement;
 import '../resolution/operators.dart';
 import '../universe/call_structure.dart' show CallStructure;
-import 'serialization.dart';
 import 'keys.dart';
+import 'serialization.dart';
 
 /// Visitor that serializes a [ConstantExpression] by encoding it into an
 /// [ObjectEncoder].
diff --git a/pkg/compiler/lib/src/serialization/element_serialization.dart b/pkg/compiler/lib/src/serialization/element_serialization.dart
index 3a63bbc..3b14778 100644
--- a/pkg/compiler/lib/src/serialization/element_serialization.dart
+++ b/pkg/compiler/lib/src/serialization/element_serialization.dart
@@ -5,7 +5,6 @@
 library dart2js.serialization.elements;
 
 import '../common.dart';
-import '../common/names.dart';
 import '../constants/constructors.dart';
 import '../constants/expressions.dart';
 import '../dart_types.dart';
diff --git a/pkg/compiler/lib/src/serialization/equivalence.dart b/pkg/compiler/lib/src/serialization/equivalence.dart
index 6cb175c..fccc44e 100644
--- a/pkg/compiler/lib/src/serialization/equivalence.dart
+++ b/pkg/compiler/lib/src/serialization/equivalence.dart
@@ -7,9 +7,9 @@
 library dart2js.serialization.equivalence;
 
 import '../closure.dart';
-import '../common.dart';
 import '../common/resolution.dart';
 import '../constants/expressions.dart';
+import '../constants/values.dart';
 import '../dart_types.dart';
 import '../elements/elements.dart';
 import '../elements/visitor.dart';
@@ -63,6 +63,31 @@
   return remaining.isEmpty;
 }
 
+/// Returns `true` if the content of [map1] and [map2] is equivalent using
+/// [keyEquivalence] and [valueEquivalence] to determine key/value equivalence.
+bool areMapsEquivalent(Map map1, Map map2,
+    [bool keyEquivalence(a, b) = equality,
+    bool valueEquivalence(a, b) = equality]) {
+  Set remaining = map2.keys.toSet();
+  for (var key1 in map1.keys) {
+    bool found = false;
+    for (var key2 in map2.keys) {
+      if (keyEquivalence(key2, key2)) {
+        found = true;
+        remaining.remove(key2);
+        if (!valueEquivalence(map1[key1], map2[key2])) {
+          return false;
+        }
+        break;
+      }
+    }
+    if (!found) {
+      return false;
+    }
+  }
+  return remaining.isEmpty;
+}
+
 /// Returns `true` if elements [a] and [b] are equivalent.
 bool areElementsEquivalent(Element a, Element b) {
   if (identical(a, b)) return true;
@@ -77,13 +102,20 @@
   return const TypeEquivalence().visit(a, b);
 }
 
-/// Returns `true` if constants [a] and [b] are equivalent.
+/// Returns `true` if constants [exp1] and [exp2] are equivalent.
 bool areConstantsEquivalent(ConstantExpression exp1, ConstantExpression exp2) {
   if (identical(exp1, exp2)) return true;
   if (exp1 == null || exp2 == null) return false;
   return const ConstantEquivalence().visit(exp1, exp2);
 }
 
+/// Returns `true` if constant values [value1] and [value2] are equivalent.
+bool areConstantValuesEquivalent(ConstantValue value1, ConstantValue value2) {
+  if (identical(value1, value2)) return true;
+  if (value1 == null || value2 == null) return false;
+  return const ConstantValueEquivalence().visit(value1, value2);
+}
+
 /// Returns `true` if the lists of elements, [a] and [b], are equivalent.
 bool areElementListsEquivalent(List<Element> a, List<Element> b) {
   return areListsEquivalent(a, b, areElementsEquivalent);
@@ -100,6 +132,12 @@
   return areListsEquivalent(a, b, areConstantsEquivalent);
 }
 
+/// Returns `true` if the lists of constant values, [a] and [b], are equivalent.
+bool areConstantValueListsEquivalent(
+    List<ConstantValue> a, List<ConstantValue> b) {
+  return areListsEquivalent(a, b, areConstantValuesEquivalent);
+}
+
 /// Returns `true` if the selectors [a] and [b] are equivalent.
 bool areSelectorsEquivalent(Selector a, Selector b) {
   if (identical(a, b)) return true;
@@ -307,6 +345,12 @@
     return areSetsEquivalent(set1, set2, elementEquivalence);
   }
 
+  bool testMaps(var object1, var object2, String property, Map map1, Map map2,
+      [bool keyEquivalence(a, b) = equality,
+      bool valueEquivalence(a, b) = equality]) {
+    return areMapsEquivalent(map1, map2, keyEquivalence, valueEquivalence);
+  }
+
   bool testElements(Object object1, Object object2, String property,
       Element element1, Element element2) {
     return areElementsEquivalent(element1, element2);
@@ -322,6 +366,11 @@
     return areConstantsEquivalent(exp1, exp2);
   }
 
+  bool testConstantValues(Object object1, Object object2, String property,
+      ConstantValue value1, ConstantValue value2) {
+    return areConstantValuesEquivalent(value1, value2);
+  }
+
   bool testTypeLists(Object object1, Object object2, String property,
       List<DartType> list1, List<DartType> list2) {
     return areTypeListsEquivalent(list1, list2);
@@ -332,6 +381,11 @@
     return areConstantListsEquivalent(list1, list2);
   }
 
+  bool testConstantValueLists(Object object1, Object object2, String property,
+      List<ConstantValue> list1, List<ConstantValue> list2) {
+    return areConstantValueListsEquivalent(list1, list2);
+  }
+
   bool testNodes(
       Object object1, Object object2, String property, Node node1, Node node2) {
     return areNodesEquivalent(node1, node2);
@@ -780,9 +834,130 @@
   @override
   bool visitDeferred(
       DeferredConstantExpression exp1, DeferredConstantExpression exp2) {
-    // TODO(johnniwinther): Implement this.
+    return strategy.testElements(
+            exp1, exp2, 'prefix', exp1.prefix, exp2.prefix) &&
+        strategy.testConstants(
+            exp1, exp2, 'expression', exp1.expression, exp2.expression);
+  }
+}
+
+/// Visitor that checks for structural equivalence of [ConstantValue]s.
+class ConstantValueEquivalence
+    implements ConstantValueVisitor<bool, ConstantValue> {
+  final TestStrategy strategy;
+
+  const ConstantValueEquivalence([this.strategy = const TestStrategy()]);
+
+  bool visit(ConstantValue value1, ConstantValue value2) {
+    if (identical(value1, value2)) return true;
+    return strategy.test(value1, value2, 'kind', value1.kind, value2.kind) &&
+        value1.accept(this, value2);
+  }
+
+  @override
+  bool visitConstructed(
+      ConstructedConstantValue value1, ConstructedConstantValue value2) {
+    return strategy.testTypes(
+            value1, value2, 'type', value1.type, value2.type) &&
+        strategy.testMaps(
+            value1,
+            value2,
+            'fields',
+            value1.fields,
+            value2.fields,
+            areElementsEquivalent,
+            (a, b) => strategy.testConstantValues(
+                value1, value2, 'fields.values', a, b));
+  }
+
+  @override
+  bool visitFunction(
+      FunctionConstantValue value1, FunctionConstantValue value2) {
+    return strategy.testElements(
+        value1, value2, 'element', value1.element, value2.element);
+  }
+
+  @override
+  bool visitList(ListConstantValue value1, ListConstantValue value2) {
+    return strategy.testTypes(
+            value1, value2, 'type', value1.type, value2.type) &&
+        strategy.testConstantValueLists(
+            value1, value2, 'entries', value1.entries, value2.entries);
+  }
+
+  @override
+  bool visitMap(MapConstantValue value1, MapConstantValue value2) {
+    return strategy.testTypes(
+            value1, value2, 'type', value1.type, value2.type) &&
+        strategy.testConstantValueLists(
+            value1, value2, 'keys', value1.keys, value2.keys) &&
+        strategy.testConstantValueLists(
+            value1, value2, 'values', value1.values, value2.values);
+  }
+
+  @override
+  bool visitType(TypeConstantValue value1, TypeConstantValue value2) {
+    return strategy.testTypes(value1, value2, 'type', value1.type, value2.type);
+  }
+
+  @override
+  bool visitBool(BoolConstantValue value1, BoolConstantValue value2) {
+    return strategy.test(value1, value2, 'primitiveValue',
+        value1.primitiveValue, value2.primitiveValue);
+  }
+
+  @override
+  bool visitDouble(DoubleConstantValue value1, DoubleConstantValue value2) {
+    return strategy.test(value1, value2, 'primitiveValue',
+        value1.primitiveValue, value2.primitiveValue);
+  }
+
+  @override
+  bool visitInt(IntConstantValue value1, IntConstantValue value2) {
+    return strategy.test(value1, value2, 'primitiveValue',
+        value1.primitiveValue, value2.primitiveValue);
+  }
+
+  @override
+  bool visitNull(NullConstantValue value1, NullConstantValue value2) {
     return true;
   }
+
+  @override
+  bool visitString(StringConstantValue value1, StringConstantValue value2) {
+    return strategy.test(value1, value2, 'primitiveValue',
+        value1.primitiveValue, value2.primitiveValue);
+  }
+
+  @override
+  bool visitDeferred(
+      DeferredConstantValue value1, DeferredConstantValue value2) {
+    return strategy.testElements(
+            value1, value2, 'prefix', value1.prefix, value2.prefix) &&
+        strategy.testConstantValues(
+            value1, value2, 'referenced', value1.referenced, value2.referenced);
+  }
+
+  @override
+  bool visitNonConstant(NonConstantValue value1, NonConstantValue value2) {
+    return true;
+  }
+
+  @override
+  bool visitSynthetic(
+      SyntheticConstantValue value1, SyntheticConstantValue value2) {
+    return strategy.test(
+            value1, value2, 'payload', value1.payload, value2.payload) &&
+        strategy.test(
+            value1, value2, 'valueKind', value1.valueKind, value2.valueKind);
+  }
+
+  @override
+  bool visitInterceptor(
+      InterceptorConstantValue value1, InterceptorConstantValue value2) {
+    return strategy.testTypes(value1, value2, 'dispatchedType',
+        value1.dispatchedType, value2.dispatchedType);
+  }
 }
 
 /// Tests the equivalence of [impact1] and [impact2] using [strategy].
diff --git a/pkg/compiler/lib/src/serialization/impact_serialization.dart b/pkg/compiler/lib/src/serialization/impact_serialization.dart
index b2aa0455..62671e2 100644
--- a/pkg/compiler/lib/src/serialization/impact_serialization.dart
+++ b/pkg/compiler/lib/src/serialization/impact_serialization.dart
@@ -4,7 +4,6 @@
 
 library dart2js.serialization.impact;
 
-import '../common.dart';
 import '../common/resolution.dart';
 import '../constants/expressions.dart';
 import '../dart_types.dart';
diff --git a/pkg/compiler/lib/src/serialization/json_serializer.dart b/pkg/compiler/lib/src/serialization/json_serializer.dart
index 32c6500..52e9f96 100644
--- a/pkg/compiler/lib/src/serialization/json_serializer.dart
+++ b/pkg/compiler/lib/src/serialization/json_serializer.dart
@@ -5,6 +5,7 @@
 library dart2js.serialization.json;
 
 import 'dart:convert';
+
 import 'keys.dart';
 import 'serialization.dart';
 import 'values.dart';
diff --git a/pkg/compiler/lib/src/serialization/modelz.dart b/pkg/compiler/lib/src/serialization/modelz.dart
index 55ab23e..a6ba195 100644
--- a/pkg/compiler/lib/src/serialization/modelz.dart
+++ b/pkg/compiler/lib/src/serialization/modelz.dart
@@ -10,7 +10,6 @@
 library dart2js.serialization.modelz;
 
 import '../common.dart';
-import '../common/names.dart';
 import '../common/resolution.dart' show Resolution;
 import '../constants/constructors.dart';
 import '../constants/expressions.dart';
@@ -31,7 +30,6 @@
 import '../util/util.dart' show Link, LinkBuilder;
 import 'keys.dart';
 import 'serialization.dart';
-import 'serialization_util.dart';
 
 /// Compute a [Link] from an [Iterable].
 Link toLink(Iterable iterable) {
diff --git a/pkg/compiler/lib/src/serialization/resolved_ast_serialization.dart b/pkg/compiler/lib/src/serialization/resolved_ast_serialization.dart
index bce66ac..c3ef366 100644
--- a/pkg/compiler/lib/src/serialization/resolved_ast_serialization.dart
+++ b/pkg/compiler/lib/src/serialization/resolved_ast_serialization.dart
@@ -25,7 +25,6 @@
 import 'modelz.dart';
 import 'serialization.dart';
 import 'serialization_util.dart';
-import 'modelz.dart';
 
 /// Visitor that computes a node-index mapping.
 class AstIndexComputer extends Visitor {
diff --git a/pkg/compiler/lib/src/serialization/serialization.dart b/pkg/compiler/lib/src/serialization/serialization.dart
index 4230ca0..b1418f6 100644
--- a/pkg/compiler/lib/src/serialization/serialization.dart
+++ b/pkg/compiler/lib/src/serialization/serialization.dart
@@ -11,7 +11,6 @@
 import '../elements/elements.dart';
 import '../library_loader.dart' show LibraryProvider;
 import '../util/enumset.dart';
-
 import 'constant_serialization.dart';
 import 'element_serialization.dart';
 import 'json_serializer.dart';
diff --git a/pkg/compiler/lib/src/serialization/system.dart b/pkg/compiler/lib/src/serialization/system.dart
index 5e2a24b..9be7d6d 100644
--- a/pkg/compiler/lib/src/serialization/system.dart
+++ b/pkg/compiler/lib/src/serialization/system.dart
@@ -5,22 +5,18 @@
 library dart2js.serialization_system;
 
 import 'dart:async';
-import '../commandline_options.dart';
+
 import '../common.dart';
-import '../common/backend_api.dart';
-import '../common/names.dart';
 import '../common/resolution.dart';
 import '../compiler.dart';
 import '../elements/elements.dart';
-import '../io/source_file.dart';
 import '../scanner/scanner.dart';
 import '../script.dart';
 import '../serialization/impact_serialization.dart';
 import '../tokens/token.dart';
 import '../universe/call_structure.dart';
-import '../universe/world_impact.dart';
 import '../universe/use.dart';
-import 'json_serializer.dart';
+import '../universe/world_impact.dart';
 import 'modelz.dart';
 import 'resolved_ast_serialization.dart';
 import 'serialization.dart';
diff --git a/pkg/compiler/lib/src/serialization/task.dart b/pkg/compiler/lib/src/serialization/task.dart
index f57ade6..bfcd950 100644
--- a/pkg/compiler/lib/src/serialization/task.dart
+++ b/pkg/compiler/lib/src/serialization/task.dart
@@ -5,7 +5,7 @@
 library dart2js.serialization.task;
 
 import 'dart:async' show EventSink, Future;
-import '../common.dart';
+
 import '../common/resolution.dart' show ResolutionImpact, ResolutionWorkItem;
 import '../common/tasks.dart' show CompilerTask;
 import '../common/work.dart' show ItemCompilationContext;
diff --git a/pkg/compiler/lib/src/serialization/type_serialization.dart b/pkg/compiler/lib/src/serialization/type_serialization.dart
index ed94ade..96f659e 100644
--- a/pkg/compiler/lib/src/serialization/type_serialization.dart
+++ b/pkg/compiler/lib/src/serialization/type_serialization.dart
@@ -6,8 +6,8 @@
 
 import '../dart_types.dart';
 import '../elements/elements.dart';
-import 'serialization.dart';
 import 'keys.dart';
+import 'serialization.dart';
 
 /// Visitor that serializes a [DartType] by encoding it into an [ObjectEncoder].
 ///
diff --git a/pkg/compiler/lib/src/source_file_provider.dart b/pkg/compiler/lib/src/source_file_provider.dart
index 2e2c7aa..22273d4 100644
--- a/pkg/compiler/lib/src/source_file_provider.dart
+++ b/pkg/compiler/lib/src/source_file_provider.dart
@@ -19,16 +19,6 @@
 import 'io/source_file.dart';
 import 'util/uri_extras.dart';
 
-List<int> readAll(String filename) {
-  var file = (new File(filename)).openSync();
-  var length = file.lengthSync();
-  // +1 to have a 0 terminated list, see [Scanner].
-  var buffer = new Uint8List(length + 1);
-  file.readIntoSync(buffer, 0, length);
-  file.closeSync();
-  return buffer;
-}
-
 abstract class SourceFileProvider implements CompilerInput {
   bool isWindows = (Platform.operatingSystem == 'windows');
   Uri cwd = currentDirectory;
@@ -55,12 +45,10 @@
     try {
       source = readAll(resourceUri.toFilePath());
     } on FileSystemException catch (ex) {
-      OSError ose = ex.osError;
-      String detail =
-          (ose != null && ose.message != null) ? ' (${ose.message})' : '';
+      String message = ex.osError?.message;
+      String detail = message != null ? ' ($message)' : '';
       return new Future.error(
-          "Error reading '${relativize(cwd, resourceUri, isWindows)}'"
-          "$detail");
+          "Error reading '${relativizeUri(resourceUri)}' $detail");
     }
     dartCharactersRead += source.length;
     sourceFiles[resourceUri] = new CachingUtf8BytesSourceFile(
@@ -100,7 +88,7 @@
 
   // TODO(johnniwinther): Remove this when no longer needed for the old compiler
   // API.
-  Future/*<List<int> | String>*/ call(Uri resourceUri);
+  Future/*<List<int> | String>*/ call(Uri resourceUri) => throw "unimplemented";
 
   relativizeUri(Uri uri) => relativize(cwd, uri, isWindows);
 
@@ -109,6 +97,16 @@
   }
 }
 
+List<int> readAll(String filename) {
+  var file = (new File(filename)).openSync();
+  var length = file.lengthSync();
+  // +1 to have a 0 terminated list, see [Scanner].
+  var buffer = new Uint8List(length + 1);
+  file.readIntoSync(buffer, 0, length);
+  file.closeSync();
+  return buffer;
+}
+
 class CompilerSourceFileProvider extends SourceFileProvider {
   // TODO(johnniwinther): Remove this when no longer needed for the old compiler
   // API.
@@ -330,14 +328,14 @@
       }
     }
 
-    return new EventSinkWrapper(writeStringSync, onDone);
+    return new _EventSinkWrapper(writeStringSync, onDone);
   }
 }
 
-class EventSinkWrapper extends EventSink<String> {
+class _EventSinkWrapper extends EventSink<String> {
   var onAdd, onClose;
 
-  EventSinkWrapper(this.onAdd, this.onClose);
+  _EventSinkWrapper(this.onAdd, this.onClose);
 
   void add(String data) => onAdd(data);
 
@@ -345,3 +343,79 @@
 
   void close() => onClose();
 }
+
+/// Adapter to integrate dart2js in bazel.
+///
+/// To handle bazel's special layout:
+///
+///  * We specify a .packages configuration file that expands packages to their
+///    corresponding bazel location. This way there is no need to create a pub
+///    cache prior to invoking dart2js.
+///
+///  * We provide a mapping that can make all urls relative to the bazel root.
+///    To the compiler, URIs look like:
+///      file:///bazel-root/a/b/c.dart
+///
+///    even though in the file system the file is located at:
+///      file:///path/to/the/actual/bazel/root/a/b/c.dart
+///
+///    This mapping serves two purposes:
+///      - It makes compiler results independent of the machine layout, which
+///        enables us to share results across bazel runs and across machines.
+///
+///      - It hides the distinction between generated and source files. That way
+///      we can use the standard package-resolution mechanism and ignore the
+///      internals of how files are organized within bazel.
+///
+/// This class is initialized using a dart2js-bazel configuration file. The file
+/// follows the following custom format:
+///
+///     <generated-path-prefix>
+///     <file1-bazel-root-relative-path>
+///     <file2-bazel-root-relative-path>
+///     ...
+///     <fileN-bazel-root-relative-path>
+///
+/// For example:
+///
+///     bazel-bin/123/
+///     a/b/c.dart
+///     bazel-bin/123/a/b/d.dart
+///     a/b/e.dart
+///
+/// The current working directory will be used to resolve the bazel-root and
+/// when invoking the compiler, bazel will use `package:` and
+/// `file:///bazel-root/` URIs to specify entrypoints.
+class BazelInputProvider extends SourceFileProvider {
+  /// Anything above this root is treated as machine specific and will only be
+  /// used to locate files on disk, but otherwise it's abstracted away in the
+  /// representation of canonical uris in the compiler.
+  final Uri bazelRoot;
+
+  /// Path prefix where generated files are located.
+  final String genPath;
+
+  /// Mapping from bazel-root uris to relative paths on top of [bazelRoot].
+  final Map<Uri, Uri> mappings = <Uri, Uri>{};
+
+  factory BazelInputProvider(String configPath) {
+    var config = new File(configPath).readAsLinesSync();
+    var bazelRoot = currentDirectory;
+    var outPrefix = config[0];
+    var files = config.skip(1);
+    return new BazelInputProvider._(bazelRoot, outPrefix, files);
+  }
+
+  BazelInputProvider._(this.bazelRoot, this.genPath, Iterable<String> files) {
+    var fakeBazelRoot = Uri.parse('file:///bazel-root/');
+    for (var path in files) {
+      var absolute = currentDirectory.resolve(path);
+      var bazelRelativeUri = fakeBazelRoot.resolve(
+          path.startsWith(genPath) ? path.substring(genPath.length) : path);
+      mappings[bazelRelativeUri] = absolute;
+    }
+  }
+
+  @override
+  Future readFromUri(Uri uri) => readUtf8BytesFromUri(mappings[uri] ?? uri);
+}
diff --git a/pkg/compiler/lib/src/ssa/codegen_helpers.dart b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
index 681056f..5a0f558 100644
--- a/pkg/compiler/lib/src/ssa/codegen_helpers.dart
+++ b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
@@ -8,7 +8,6 @@
 import '../js_backend/js_backend.dart';
 import '../types/types.dart';
 import '../universe/selector.dart' show Selector;
-
 import 'nodes.dart';
 
 /**
diff --git a/pkg/compiler/lib/src/ssa/ssa_tracer.dart b/pkg/compiler/lib/src/ssa/ssa_tracer.dart
index 9a6f6c6..5591851 100644
--- a/pkg/compiler/lib/src/ssa/ssa_tracer.dart
+++ b/pkg/compiler/lib/src/ssa/ssa_tracer.dart
@@ -10,7 +10,6 @@
 import '../diagnostics/invariant.dart' show DEBUG_MODE;
 import '../js_backend/js_backend.dart';
 import '../tracer.dart';
-
 import 'nodes.dart';
 
 /**
diff --git a/pkg/compiler/lib/src/ssa/value_set.dart b/pkg/compiler/lib/src/ssa/value_set.dart
index c990014..89dbeca 100644
--- a/pkg/compiler/lib/src/ssa/value_set.dart
+++ b/pkg/compiler/lib/src/ssa/value_set.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import '../universe/side_effects.dart' show SideEffects;
-
 import 'nodes.dart';
 
 class ValueSet {
diff --git a/pkg/compiler/lib/src/ssa/variable_allocator.dart b/pkg/compiler/lib/src/ssa/variable_allocator.dart
index 2145d6d..5ea597d 100644
--- a/pkg/compiler/lib/src/ssa/variable_allocator.dart
+++ b/pkg/compiler/lib/src/ssa/variable_allocator.dart
@@ -5,7 +5,6 @@
 import '../common.dart';
 import '../compiler.dart' show Compiler;
 import '../js_backend/js_backend.dart';
-
 import 'nodes.dart';
 
 /**
diff --git a/pkg/compiler/lib/src/string_validator.dart b/pkg/compiler/lib/src/string_validator.dart
index 866d0f0..60c3c78 100644
--- a/pkg/compiler/lib/src/string_validator.dart
+++ b/pkg/compiler/lib/src/string_validator.dart
@@ -10,8 +10,8 @@
 
 import 'common.dart';
 import 'tokens/token.dart' show Token;
-import 'tree/nodes.dart' show StringQuoting;
 import 'tree/dartstring.dart' show DartString;
+import 'tree/nodes.dart' show StringQuoting;
 import 'util/characters.dart';
 
 class StringValidator {
diff --git a/pkg/compiler/lib/src/tokens/keyword.dart b/pkg/compiler/lib/src/tokens/keyword.dart
index ad22ee6..4d914bc 100644
--- a/pkg/compiler/lib/src/tokens/keyword.dart
+++ b/pkg/compiler/lib/src/tokens/keyword.dart
@@ -5,7 +5,6 @@
 library dart2js.tokens.keywords;
 
 import '../util/characters.dart' as Characters show $a;
-
 import 'precedence.dart' show PrecedenceInfo;
 import 'precedence_constants.dart' as Precedence
     show AS_INFO, IS_INFO, KEYWORD_INFO;
diff --git a/pkg/compiler/lib/src/tokens/token.dart b/pkg/compiler/lib/src/tokens/token.dart
index df66bd9..af31142 100644
--- a/pkg/compiler/lib/src/tokens/token.dart
+++ b/pkg/compiler/lib/src/tokens/token.dart
@@ -4,12 +4,11 @@
 
 library dart2js.tokens;
 
-import 'dart:convert' show UTF8;
 import 'dart:collection' show HashSet;
+import 'dart:convert' show UTF8;
 
 import '../common.dart';
 import '../util/util.dart' show computeHashCode;
-
 import 'keyword.dart' show Keyword;
 import 'precedence.dart' show PrecedenceInfo;
 import 'precedence_constants.dart' as Precedence show BAD_INPUT_INFO;
diff --git a/pkg/compiler/lib/src/tracer.dart b/pkg/compiler/lib/src/tracer.dart
index 359ea77..09b8b98 100644
--- a/pkg/compiler/lib/src/tracer.dart
+++ b/pkg/compiler/lib/src/tracer.dart
@@ -5,13 +5,14 @@
 library tracer;
 
 import 'dart:async' show EventSink;
+
 import '../compiler.dart' as api;
 import 'common/work.dart' show ItemCompilationContext;
 import 'compiler.dart' show Compiler;
-import 'ssa/nodes.dart' as ssa show HGraph;
-import 'ssa/ssa_tracer.dart' show HTracer;
 import 'cps_ir/cps_ir_nodes.dart' as cps_ir;
 import 'cps_ir/cps_ir_tracer.dart' show IRTracer;
+import 'ssa/nodes.dart' as ssa show HGraph;
+import 'ssa/ssa_tracer.dart' show HTracer;
 import 'tree_ir/tree_ir_nodes.dart' as tree_ir;
 import 'tree_ir/tree_ir_tracer.dart' show TreeTracer;
 import 'util/util.dart' show Indentation;
diff --git a/pkg/compiler/lib/src/tree/dartstring.dart b/pkg/compiler/lib/src/tree/dartstring.dart
index 684f55b..4ec773c 100644
--- a/pkg/compiler/lib/src/tree/dartstring.dart
+++ b/pkg/compiler/lib/src/tree/dartstring.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:collection';
+
 import '../util/characters.dart';
 
 /**
diff --git a/pkg/compiler/lib/src/tree_ir/optimization/logical_rewriter.dart b/pkg/compiler/lib/src/tree_ir/optimization/logical_rewriter.dart
index bfed37d..bdfadae 100644
--- a/pkg/compiler/lib/src/tree_ir/optimization/logical_rewriter.dart
+++ b/pkg/compiler/lib/src/tree_ir/optimization/logical_rewriter.dart
@@ -4,9 +4,9 @@
 
 library tree_ir.optimization.logical_rewriter;
 
+import '../../constants/values.dart' as values;
 import '../tree_ir_nodes.dart';
 import 'optimization.dart' show Pass;
-import '../../constants/values.dart' as values;
 
 /// Rewrites logical expressions to be more compact in the Tree IR.
 ///
diff --git a/pkg/compiler/lib/src/tree_ir/optimization/loop_rewriter.dart b/pkg/compiler/lib/src/tree_ir/optimization/loop_rewriter.dart
index e57c938..847d0ca 100644
--- a/pkg/compiler/lib/src/tree_ir/optimization/loop_rewriter.dart
+++ b/pkg/compiler/lib/src/tree_ir/optimization/loop_rewriter.dart
@@ -4,8 +4,8 @@
 
 library tree_ir.optimization.loop_rewriter;
 
-import 'optimization.dart' show Pass;
 import '../tree_ir_nodes.dart';
+import 'optimization.dart' show Pass;
 
 /// Rewrites [WhileTrue] statements into [For] statements.
 ///
diff --git a/pkg/compiler/lib/src/tree_ir/optimization/optimization.dart b/pkg/compiler/lib/src/tree_ir/optimization/optimization.dart
index 130e5e3..ebf201a 100644
--- a/pkg/compiler/lib/src/tree_ir/optimization/optimization.dart
+++ b/pkg/compiler/lib/src/tree_ir/optimization/optimization.dart
@@ -2,11 +2,11 @@
 
 import '../tree_ir_nodes.dart';
 
+export 'logical_rewriter.dart' show LogicalRewriter;
+export 'loop_rewriter.dart' show LoopRewriter;
+export 'pull_into_initializers.dart' show PullIntoInitializers;
 export 'statement_rewriter.dart' show StatementRewriter;
 export 'variable_merger.dart' show VariableMerger;
-export 'loop_rewriter.dart' show LoopRewriter;
-export 'logical_rewriter.dart' show LogicalRewriter;
-export 'pull_into_initializers.dart' show PullIntoInitializers;
 
 /// An optimization pass over the Tree IR.
 abstract class Pass {
diff --git a/pkg/compiler/lib/src/tree_ir/optimization/pull_into_initializers.dart b/pkg/compiler/lib/src/tree_ir/optimization/pull_into_initializers.dart
index 931368d..722230a 100644
--- a/pkg/compiler/lib/src/tree_ir/optimization/pull_into_initializers.dart
+++ b/pkg/compiler/lib/src/tree_ir/optimization/pull_into_initializers.dart
@@ -4,8 +4,8 @@
 
 library tree_ir.optimization.pull_into_initializers;
 
-import 'optimization.dart' show Pass;
 import '../tree_ir_nodes.dart';
+import 'optimization.dart' show Pass;
 
 /// Where a variable has been assigned.
 enum AssignArea {
diff --git a/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart b/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart
index 5db310a..cc2786e 100644
--- a/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart
+++ b/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart
@@ -4,11 +4,11 @@
 
 library tree_ir.optimization.statement_rewriter;
 
-import 'optimization.dart' show Pass;
-import '../tree_ir_nodes.dart';
-import '../../io/source_information.dart';
 import '../../elements/elements.dart';
+import '../../io/source_information.dart';
 import '../../js/placeholder_safety.dart';
+import '../tree_ir_nodes.dart';
+import 'optimization.dart' show Pass;
 
 /**
  * Translates to direct-style.
diff --git a/pkg/compiler/lib/src/tree_ir/optimization/variable_merger.dart b/pkg/compiler/lib/src/tree_ir/optimization/variable_merger.dart
index 273d7a4..d76bb31 100644
--- a/pkg/compiler/lib/src/tree_ir/optimization/variable_merger.dart
+++ b/pkg/compiler/lib/src/tree_ir/optimization/variable_merger.dart
@@ -4,8 +4,8 @@
 
 library tree_ir.optimization.variable_merger;
 
-import 'optimization.dart' show Pass;
 import '../tree_ir_nodes.dart';
+import 'optimization.dart' show Pass;
 
 /// Merges variables based on liveness and source variable information.
 ///
diff --git a/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart b/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart
index 000f610..a152f3b 100644
--- a/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart
+++ b/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart
@@ -10,7 +10,6 @@
 import '../elements/elements.dart';
 import '../io/source_information.dart';
 import '../js_backend/codegen/glue.dart';
-
 import 'tree_ir_nodes.dart';
 
 typedef Statement NodeCallback(Statement next);
diff --git a/pkg/compiler/lib/src/tree_ir/tree_ir_tracer.dart b/pkg/compiler/lib/src/tree_ir/tree_ir_tracer.dart
index 486ee13..e93ae0c 100644
--- a/pkg/compiler/lib/src/tree_ir/tree_ir_tracer.dart
+++ b/pkg/compiler/lib/src/tree_ir/tree_ir_tracer.dart
@@ -5,6 +5,7 @@
 library tree_ir_tracer;
 
 import 'dart:async' show EventSink;
+
 import '../tracer.dart';
 import 'tree_ir_nodes.dart';
 
diff --git a/pkg/compiler/lib/src/typechecker.dart b/pkg/compiler/lib/src/typechecker.dart
index be25edf..b4ad1f8 100644
--- a/pkg/compiler/lib/src/typechecker.dart
+++ b/pkg/compiler/lib/src/typechecker.dart
@@ -443,7 +443,7 @@
     if (result == null) {
       reporter.internalError(node, 'Type is null.');
     }
-    return _record(node, result);
+    return result;
   }
 
   void checkTypePromotion(Node node, TypePromotion typePromotion,
@@ -1151,24 +1151,6 @@
     return null;
   }
 
-  static bool _fyiShown = false;
-  DartType _record(Node node, DartType type) {
-    if (node is! Expression) return type;
-    if (const bool.fromEnvironment('send_stats') &&
-        executableContext != null &&
-        // TODO(sigmund): enable also in core libs.
-        !executableContext.library.isPlatformLibrary &&
-        !type.isDynamic) {
-      if (!_fyiShown) {
-        print('FYI experiment to collect send stats is on: '
-            'caching types of expressions');
-        _fyiShown = true;
-      }
-      elements.typesCache[node] = type;
-    }
-    return type;
-  }
-
   DartType visitSend(Send node) {
     Element element = elements[node];
 
diff --git a/pkg/compiler/lib/src/types/constants.dart b/pkg/compiler/lib/src/types/constants.dart
index d66a31c..219e6b1 100644
--- a/pkg/compiler/lib/src/types/constants.dart
+++ b/pkg/compiler/lib/src/types/constants.dart
@@ -48,7 +48,7 @@
 
   @override
   TypeMask visitSynthetic(SyntheticConstantValue constant, Compiler compiler) {
-    switch (constant.kind) {
+    switch (constant.valueKind) {
       case SyntheticConstantKind.DUMMY_INTERCEPTOR:
         return constant.payload;
       case SyntheticConstantKind.EMPTY_VALUE:
diff --git a/pkg/compiler/lib/src/types/types.dart b/pkg/compiler/lib/src/types/types.dart
index 61dbabf..d12b2bd 100644
--- a/pkg/compiler/lib/src/types/types.dart
+++ b/pkg/compiler/lib/src/types/types.dart
@@ -12,15 +12,14 @@
 import '../elements/elements.dart';
 import '../inferrer/type_graph_inferrer.dart' show TypeGraphInferrer;
 import '../tree/tree.dart';
-import '../util/util.dart';
 import '../universe/selector.dart' show Selector;
 import '../universe/universe.dart'
     show
         ReceiverConstraint,
         UniverseSelectorConstraints,
         SelectorConstraintsStrategy;
+import '../util/util.dart';
 import '../world.dart' show ClassWorld, World;
-
 import 'abstract_value_domain.dart' show AbstractValue;
 
 part 'container_type_mask.dart';
diff --git a/pkg/compiler/lib/src/universe/class_set.dart b/pkg/compiler/lib/src/universe/class_set.dart
index 038d757..4a7a035 100644
--- a/pkg/compiler/lib/src/universe/class_set.dart
+++ b/pkg/compiler/lib/src/universe/class_set.dart
@@ -5,6 +5,7 @@
 library dart2js.world.class_set;
 
 import 'dart:collection' show IterableBase;
+
 import '../elements/elements.dart' show ClassElement;
 import '../util/enumset.dart' show EnumSet;
 import '../util/util.dart' show Link;
diff --git a/pkg/compiler/lib/src/universe/function_set.dart b/pkg/compiler/lib/src/universe/function_set.dart
index c225b15..afa0951 100644
--- a/pkg/compiler/lib/src/universe/function_set.dart
+++ b/pkg/compiler/lib/src/universe/function_set.dart
@@ -10,7 +10,6 @@
 import '../types/types.dart';
 import '../util/util.dart' show Hashing, Setlet;
 import '../world.dart' show ClassWorld;
-
 import 'selector.dart' show Selector;
 import 'universe.dart' show ReceiverConstraint;
 
diff --git a/pkg/compiler/lib/src/universe/selector.dart b/pkg/compiler/lib/src/universe/selector.dart
index a76db34..19ce7c6 100644
--- a/pkg/compiler/lib/src/universe/selector.dart
+++ b/pkg/compiler/lib/src/universe/selector.dart
@@ -17,7 +17,6 @@
         PublicName;
 import '../util/util.dart' show Hashing;
 import '../world.dart' show World;
-
 import 'call_structure.dart' show CallStructure;
 
 class SelectorKind {
diff --git a/pkg/compiler/lib/src/universe/universe.dart b/pkg/compiler/lib/src/universe/universe.dart
index 8f08f6f..e2bba01 100644
--- a/pkg/compiler/lib/src/universe/universe.dart
+++ b/pkg/compiler/lib/src/universe/universe.dart
@@ -8,11 +8,10 @@
 
 import '../common.dart';
 import '../compiler.dart' show Compiler;
-import '../elements/elements.dart';
 import '../dart_types.dart';
+import '../elements/elements.dart';
 import '../util/util.dart';
 import '../world.dart' show ClassWorld, World;
-
 import 'selector.dart' show Selector;
 import 'use.dart' show DynamicUse, DynamicUseKind, StaticUse, StaticUseKind;
 
diff --git a/pkg/compiler/lib/src/universe/use.dart b/pkg/compiler/lib/src/universe/use.dart
index bb6b153..e795f02 100644
--- a/pkg/compiler/lib/src/universe/use.dart
+++ b/pkg/compiler/lib/src/universe/use.dart
@@ -11,9 +11,8 @@
 import '../common.dart';
 import '../dart_types.dart';
 import '../elements/elements.dart';
-import '../world.dart' show ClassWorld;
 import '../util/util.dart' show Hashing;
-
+import '../world.dart' show ClassWorld;
 import 'call_structure.dart' show CallStructure;
 import 'selector.dart' show Selector;
 import 'universe.dart' show ReceiverConstraint;
diff --git a/pkg/compiler/lib/src/use_unused_api.dart b/pkg/compiler/lib/src/use_unused_api.dart
index d3578f7..468fae3 100644
--- a/pkg/compiler/lib/src/use_unused_api.dart
+++ b/pkg/compiler/lib/src/use_unused_api.dart
@@ -9,7 +9,6 @@
 library dart2js.use_unused_api;
 
 import '../compiler.dart' as api;
-
 import 'colors.dart' as colors;
 import 'compiler.dart' as compiler;
 import 'constants/constant_system.dart' as constants;
@@ -19,9 +18,8 @@
 import 'constants/values.dart' as constants;
 import 'cps_ir/cps_ir_builder.dart' as ir_builder;
 import 'cps_ir/cps_ir_builder_task.dart' as ir_builder;
-import 'tree_ir/tree_ir_nodes.dart' as tree_ir;
-import 'dart_types.dart' as dart_types;
 import 'dart2js.dart' as dart2js;
+import 'dart_types.dart' as dart_types;
 import 'deferred_load.dart' as deferred;
 import 'diagnostics/source_span.dart' as diagnostics;
 import 'elements/elements.dart' as elements;
@@ -33,21 +31,21 @@
 import 'io/source_map_builder.dart' as io;
 import 'js/js.dart' as js;
 import 'js_backend/js_backend.dart' as js_backend;
-import 'js_emitter/js_emitter.dart' as js_emitter;
 import 'js_emitter/full_emitter/emitter.dart' as full;
+import 'js_emitter/js_emitter.dart' as js_emitter;
 import 'js_emitter/program_builder/program_builder.dart' as program_builder;
-import 'resolution/semantic_visitor.dart' as semantic_visitor;
+import 'parser/partial_elements.dart'
+    show PartialClassElement, PartialFunctionElement;
 import 'resolution/operators.dart' as operators;
+import 'resolution/semantic_visitor.dart' as semantic_visitor;
 import 'script.dart';
 import 'source_file_provider.dart' as source_file_provider;
 import 'ssa/nodes.dart' as ssa;
 import 'tree/tree.dart' as tree;
+import 'tree_ir/tree_ir_nodes.dart' as tree_ir;
 import 'util/util.dart' as util;
 import 'world.dart';
 
-import 'parser/partial_elements.dart'
-    show PartialClassElement, PartialFunctionElement;
-
 class ElementVisitor extends elements_visitor.BaseElementVisitor {
   visitElement(e, a) {}
 }
diff --git a/pkg/compiler/lib/src/util/util.dart b/pkg/compiler/lib/src/util/util.dart
index d9cc16c..397bd6c 100644
--- a/pkg/compiler/lib/src/util/util.dart
+++ b/pkg/compiler/lib/src/util/util.dart
@@ -4,12 +4,12 @@
 
 library dart2js.util;
 
-import 'util_implementation.dart';
 import 'characters.dart';
+import 'util_implementation.dart';
 
-export 'setlet.dart';
-export 'maplet.dart';
 export 'emptyset.dart';
+export 'maplet.dart';
+export 'setlet.dart';
 
 part 'indentation.dart';
 part 'link.dart';
diff --git a/pkg/compiler/lib/src/util/util_implementation.dart b/pkg/compiler/lib/src/util/util_implementation.dart
index c28b63f..bdb6b90 100644
--- a/pkg/compiler/lib/src/util/util_implementation.dart
+++ b/pkg/compiler/lib/src/util/util_implementation.dart
@@ -4,7 +4,8 @@
 
 library util_implementation;
 
-import 'util.dart';
 import 'dart:collection';
 
+import 'util.dart';
+
 part 'link_implementation.dart';
diff --git a/pkg/compiler/lib/src/world.dart b/pkg/compiler/lib/src/world.dart
index bfa2100..5bb3f52 100644
--- a/pkg/compiler/lib/src/world.dart
+++ b/pkg/compiler/lib/src/world.dart
@@ -5,8 +5,8 @@
 library dart2js.world;
 
 import 'closure.dart' show SynthesizedCallMethodElementX;
-import 'common.dart';
 import 'common/backend_api.dart' show Backend;
+import 'common.dart';
 import 'compiler.dart' show Compiler;
 import 'core_types.dart' show CoreClasses;
 import 'dart_types.dart';
diff --git a/pkg/compiler/samples/compile_loop/compile_loop.dart b/pkg/compiler/samples/compile_loop/compile_loop.dart
deleted file mode 100644
index 097d046..0000000
--- a/pkg/compiler/samples/compile_loop/compile_loop.dart
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// This sample demonstrates how to run the compiler in a loop reading
-// all sources from memory, instead of using dart:io.
-library sample.compile_loop;
-
-import 'dart:async';
-
-import '../../lib/compiler.dart' as compiler;
-
-// If this file is missing, generate it using ../jsonify/jsonify.dart.
-import 'sdk.dart';
-
-Future<String> compile(source) {
-  Future<String> inputProvider(Uri uri) {
-    if (uri.scheme == 'sdk') {
-      var value = SDK_SOURCES['$uri'];
-      if (value == null) {
-        // TODO(ahe): Use new Future.error.
-        throw new Exception('Error: Cannot read: $uri');
-      }
-      return new Future.value(value);
-    } else if ('$uri' == 'memory:/main.dart') {
-      return new Future.value(source);
-    }
-    // TODO(ahe): Use new Future.error.
-    throw new Exception('Error: Cannot read: $uri');
-  }
-  void handler(
-      Uri uri, int begin, int end, String message, compiler.Diagnostic kind) {
-    // TODO(ahe): Remove dart:io import from
-    // ../../lib/src/source_file_provider.dart and use
-    // FormattingDiagnosticHandler instead.
-    print({
-      'uri': '$uri',
-      'begin': begin,
-      'end': end,
-      'message': message,
-      'kind': kind.name
-    });
-    if (kind == compiler.Diagnostic.ERROR) {
-      throw new Exception('Unexpected error occurred.');
-    }
-  }
-  return compiler.compile(Uri.parse('memory:/main.dart'),
-      Uri.parse('sdk:/sdk/'), null, inputProvider, handler, []);
-}
-
-int iterations = 10;
-
-main() {
-  compile(EXAMPLE_HELLO_HTML).then((jsResult) {
-    if (jsResult == null) throw 'Compilation failed';
-    if (--iterations > 0) main();
-  });
-}
-
-const String EXAMPLE_HELLO_HTML = r'''
-// Go ahead and modify this example.
-
-import "dart:html";
-
-var greeting = "Hello, World!";
-
-// Displays a greeting.
-void main() {
-  // This example uses HTML to display the greeting and it will appear
-  // in a nested HTML frame (an iframe).
-  document.body.append(new HeadingElement.h1()..appendText(greeting));
-}
-''';
diff --git a/pkg/compiler/samples/darttags/darttags.dart b/pkg/compiler/samples/darttags/darttags.dart
deleted file mode 100644
index d77966d..0000000
--- a/pkg/compiler/samples/darttags/darttags.dart
+++ /dev/null
@@ -1,186 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// Usage: Add the following to your .gclient file (found in the parent
-// of the "dart" in a gclient checkout of the Dart repositor).
-//
-// hooks = [
-//   {
-//     "pattern": ".",
-//     "action": [
-//       "dart/sdk/bin/dart",
-//       # Replace "xcodebuild" with "out" on Linux, and "build" on Windows.
-//       "-pdart/xcodebuild/ReleaseIA32/packages/",
-//       "dart/pkg/compiler/samples/darttags/darttags.dart",
-//       "dart/TAGS",
-//       # Modify the following list to your preferences:
-//       "dart/tests/try/web/incremental_compilation_update_test.dart",
-//       "package:compiler/src/dart2js.dart",
-//     ],
-//   },
-// ]
-//
-// Modify .emacs to contain:
-//
-//      (setq tags-table-list
-//           '("DART_LOCATION/dart"))
-//
-// Where DART_LOCATION is the gclient directory where you found .gclient.
-
-import 'dart:io';
-import 'dart:mirrors';
-
-import 'package:compiler/src/filenames.dart';
-import 'package:compiler/src/io/source_file.dart';
-import 'package:compiler/src/mirrors/analyze.dart' show analyze;
-import 'package:compiler/src/mirrors/dart2js_mirrors.dart' show BackDoor;
-import 'package:compiler/src/mirrors/mirrors_util.dart' show nameOf;
-import 'package:compiler/src/source_file_provider.dart';
-import 'package:compiler/src/util/uri_extras.dart';
-import 'package:sdk_library_metadata/libraries.dart' show libraries;
-
-const DART2JS = 'package:compiler/src/dart2js.dart';
-const DART2JS_MIRROR = 'package:compiler/src/mirrors/dart2js_mirrors.dart';
-const SDK_ROOT = '../../../../sdk/';
-
-bool isPublicDart2jsLibrary(String name) {
-  return !name.startsWith('_') && libraries[name].isDart2jsLibrary;
-}
-
-var handler;
-RandomAccessFile output;
-Uri outputUri;
-
-main(List<String> arguments) {
-  handler = new FormattingDiagnosticHandler()..throwOnError = true;
-
-  outputUri = handler.provider.cwd.resolve(nativeToUriPath(arguments.first));
-  output = new File(arguments.first).openSync(mode: FileMode.WRITE);
-
-  Uri myLocation = handler.provider.cwd.resolveUri(Platform.script);
-
-  List<Uri> uris = <Uri>[];
-
-  if (arguments.length > 1) {
-    // Compute tags for libraries requested by the user.
-    uris.addAll(
-        arguments.skip(1).map((argument) => Uri.base.resolve(argument)));
-  } else {
-    // Compute tags for dart2js itself.
-    uris.add(myLocation.resolve(DART2JS));
-    uris.add(myLocation.resolve(DART2JS_MIRROR));
-  }
-
-  // Get the names of public dart2js libraries.
-  Iterable<String> names = libraries.keys.where(isPublicDart2jsLibrary);
-
-  // Prepend "dart:" to the names.
-  uris.addAll(names.map((String name) => Uri.parse('dart:$name')));
-
-  Uri platformConfigUri =
-      myLocation.resolve(SDK_ROOT).resolve("lib/dart2js_shared_sdk");
-  Uri packageRoot = Uri.base.resolve(Platform.packageRoot);
-
-  analyze(uris, platformConfigUri, packageRoot, handler.provider, handler)
-      .then(processMirrors);
-}
-
-processMirrors(MirrorSystem mirrors) {
-  mirrors.libraries.forEach((_, LibraryMirror library) {
-    BackDoor.compilationUnitsOf(library).forEach(emitTagsForCompilationUnit);
-  });
-
-  output.closeSync();
-}
-
-/**
- * From http://en.wikipedia.org/wiki/Ctags#Etags_2
- *
- * A section starts with a two line header, one line containing a
- * single <\x0c> character, followed by a line which consists of:
- *
- * {src_file},{size_of_tag_definition_data_in_bytes}
- *
- * The header is followed by tag definitions, one definition per line,
- * with the format:
- *
- * {tag_definition_text}<\x7f>{tagname}<\x01>{line_number},{byte_offset}
- */
-emitTagsForCompilationUnit(compilationUnit) {
-  // Certain variables in this method do not follow Dart naming
-  // conventions.  This is because the format as written on Wikipedia
-  // looks very similar to Dart string interpolation that the author
-  // felt it would make sense to keep the names.
-  Uri uri = compilationUnit.uri;
-  var buffer = new StringBuffer();
-  SourceFile file = handler.provider.sourceFiles[uri];
-  String src_file = relativize(outputUri, uri, false);
-
-  compilationUnit.declarations.forEach((_, DeclarationMirror mirror) {
-    Definition definition = new Definition.from(mirror, file);
-    String name = nameOf(mirror);
-    definition.writeOn(buffer, name);
-
-    if (mirror is ClassMirror) {
-      emitTagsForClass(mirror, file, buffer);
-    }
-  });
-
-  var tag_definition_data = '$buffer';
-  var size_of_tag_definition_data_in_bytes = tag_definition_data.length;
-
-  // The header.
-  output.writeStringSync(
-      '\x0c\n${src_file},${size_of_tag_definition_data_in_bytes}\n');
-  output.writeStringSync(tag_definition_data);
-}
-
-void emitTagsForClass(ClassMirror cls, SourceFile file, StringBuffer buffer) {
-  String className = nameOf(cls);
-
-  cls.declarations.forEach((_, DeclarationMirror mirror) {
-    Definition definition = new Definition.from(mirror, file);
-    String name = nameOf(mirror);
-    if (mirror is MethodMirror && mirror.isConstructor) {
-      if (name == '') {
-        name = className;
-        definition.writeOn(buffer, 'new $className');
-      } else {
-        definition.writeOn(buffer, 'new $className.$name');
-      }
-    } else {
-      definition.writeOn(buffer, '$className.$name');
-    }
-    definition.writeOn(buffer, name);
-  });
-}
-
-class Definition {
-  final int byte_offset;
-  final int line_number;
-  final String tag_definition_text;
-
-  Definition(this.byte_offset, this.line_number, this.tag_definition_text);
-
-  factory Definition.from(DeclarationMirror mirror, SourceFile file) {
-    var location = mirror.location;
-    int byte_offset = location.offset;
-    int line_number = file.getLine(byte_offset) + 1;
-
-    int lineStart = file.lineStarts[line_number - 1];
-
-    int lineEnd = file.lineStarts.length > line_number
-        // Subract 1 to remove trailing newline.
-        ? file.lineStarts[line_number] - 1
-        : null;
-    String tag_definition_text = file.slowText().substring(lineStart, lineEnd);
-
-    return new Definition(byte_offset, line_number, tag_definition_text);
-  }
-
-  void writeOn(StringBuffer buffer, String tagname) {
-    buffer.write('${tag_definition_text}\x7f${tagname}'
-        '\x01${line_number},${byte_offset}\n');
-  }
-}
diff --git a/pkg/pkg.gyp b/pkg/pkg.gyp
index 771152c..047607f 100644
--- a/pkg/pkg.gyp
+++ b/pkg/pkg.gyp
@@ -22,6 +22,7 @@
             '../sdk/lib/_internal/js_runtime/lib',
             '../sdk/lib/_internal/sdk_library_metadata/lib',
             '../site/try',
+            '../third_party/observatory_pub_packages/packages/charted/lib',
           ],
           'outputs': [
             '<(SHARED_INTERMEDIATE_DIR)/packages.stamp',
diff --git a/runtime/bin/common_patch.dart b/runtime/bin/common_patch.dart
index feaf552..aa6e1aa 100644
--- a/runtime/bin/common_patch.dart
+++ b/runtime/bin/common_patch.dart
@@ -2,8 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-patch class _IOCrypto {
-  /* patch */ static Uint8List getRandomBytes(int count)
+@patch class _IOCrypto {
+  /* @patch */ static Uint8List getRandomBytes(int count)
       native "Crypto_GetRandomBytes";
 }
 
diff --git a/runtime/bin/directory_patch.dart b/runtime/bin/directory_patch.dart
index 9f4a265..c503161 100644
--- a/runtime/bin/directory_patch.dart
+++ b/runtime/bin/directory_patch.dart
@@ -2,25 +2,25 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-patch class _Directory {
-  /* patch */ static _current() native "Directory_Current";
-  /* patch */ static _setCurrent(path) native "Directory_SetCurrent";
-  /* patch */ static _createTemp(String path) native "Directory_CreateTemp";
-  /* patch */ static String _systemTemp() native "Directory_SystemTemp";
-  /* patch */ static _exists(String path) native "Directory_Exists";
-  /* patch */ static _create(String path) native "Directory_Create";
-  /* patch */ static _deleteNative(String path, bool recursive)
+@patch class _Directory {
+  /* @patch */ static _current() native "Directory_Current";
+  /* @patch */ static _setCurrent(path) native "Directory_SetCurrent";
+  /* @patch */ static _createTemp(String path) native "Directory_CreateTemp";
+  /* @patch */ static String _systemTemp() native "Directory_SystemTemp";
+  /* @patch */ static _exists(String path) native "Directory_Exists";
+  /* @patch */ static _create(String path) native "Directory_Create";
+  /* @patch */ static _deleteNative(String path, bool recursive)
       native "Directory_Delete";
-  /* patch */ static _rename(String path, String newPath)
+  /* @patch */ static _rename(String path, String newPath)
       native "Directory_Rename";
-  /* patch */ static void _fillWithDirectoryListing(
+  /* @patch */ static void _fillWithDirectoryListing(
       List<FileSystemEntity> list, String path, bool recursive,
       bool followLinks)
       native "Directory_FillWithDirectoryListing";
 }
 
-patch class _AsyncDirectoryListerOps {
-  /* patch */ factory _AsyncDirectoryListerOps(int pointer) =>
+@patch class _AsyncDirectoryListerOps {
+  /* @patch */ factory _AsyncDirectoryListerOps(int pointer) =>
       new _AsyncDirectoryListerOpsImpl(pointer);
 }
 
diff --git a/runtime/bin/eventhandler_patch.dart b/runtime/bin/eventhandler_patch.dart
index d92271b..60be5e5 100644
--- a/runtime/bin/eventhandler_patch.dart
+++ b/runtime/bin/eventhandler_patch.dart
@@ -4,8 +4,8 @@
 
 import 'dart:nativewrappers';
 
-patch class _EventHandler {
-  /* patch */ static void _sendData(Object sender,
+@patch class _EventHandler {
+  /* @patch */ static void _sendData(Object sender,
                                     SendPort sendPort,
                                     int data)
       native "EventHandler_SendData";
diff --git a/runtime/bin/file_patch.dart b/runtime/bin/file_patch.dart
index a3d42e8..8795b9c 100644
--- a/runtime/bin/file_patch.dart
+++ b/runtime/bin/file_patch.dart
@@ -2,28 +2,28 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-patch class _File {
-  /* patch */ static _exists(String path) native "File_Exists";
-  /* patch */ static _create(String path) native "File_Create";
-  /* patch */ static _createLink(String path, String target)
+@patch class _File {
+  /* @patch */ static _exists(String path) native "File_Exists";
+  /* @patch */ static _create(String path) native "File_Create";
+  /* @patch */ static _createLink(String path, String target)
       native "File_CreateLink";
-  /* patch */ static _linkTarget(String path) native "File_LinkTarget";
-  /* patch */ static _deleteNative(String path) native "File_Delete";
-  /* patch */ static _deleteLinkNative(String path) native "File_DeleteLink";
-  /* patch */ static _rename(String oldPath, String newPath)
+  /* @patch */ static _linkTarget(String path) native "File_LinkTarget";
+  /* @patch */ static _deleteNative(String path) native "File_Delete";
+  /* @patch */ static _deleteLinkNative(String path) native "File_DeleteLink";
+  /* @patch */ static _rename(String oldPath, String newPath)
       native "File_Rename";
-  /* patch */ static _renameLink(String oldPath, String newPath)
+  /* @patch */ static _renameLink(String oldPath, String newPath)
       native "File_RenameLink";
-  /* patch */ static _copy(String oldPath, String newPath) native "File_Copy";
-  /* patch */ static _lengthFromPath(String path) native "File_LengthFromPath";
-  /* patch */ static _lastModified(String path) native "File_LastModified";
-  /* patch */ static _open(String path, int mode) native "File_Open";
-  /* patch */ static int _openStdio(int fd) native "File_OpenStdio";
+  /* @patch */ static _copy(String oldPath, String newPath) native "File_Copy";
+  /* @patch */ static _lengthFromPath(String path) native "File_LengthFromPath";
+  /* @patch */ static _lastModified(String path) native "File_LastModified";
+  /* @patch */ static _open(String path, int mode) native "File_Open";
+  /* @patch */ static int _openStdio(int fd) native "File_OpenStdio";
 }
 
 
-patch class _RandomAccessFileOps {
-  /* patch */ factory _RandomAccessFileOps(int pointer)
+@patch class _RandomAccessFileOps {
+  /* @patch */ factory _RandomAccessFileOps(int pointer)
       => new _RandomAccessFileOpsImpl(pointer);
 }
 
@@ -62,7 +62,7 @@
 }
 
 
-patch class _FileSystemWatcher {
+@patch class _FileSystemWatcher {
   static int _id;
   static final Map<int, _WatcherPath> _idMap = {};
 
@@ -74,7 +74,7 @@
 
   StreamController _broadcastController;
 
-  /* patch */ static Stream<FileSystemEvent> _watch(
+  /* @patch */ static Stream<FileSystemEvent> _watch(
       String path, int events, bool recursive) {
     if (Platform.isLinux) {
       return new _InotifyFileSystemWatcher(path, events, recursive).stream;
@@ -262,7 +262,7 @@
     });
   }
 
-  /* patch */ static bool get isSupported
+  /* @patch */ static bool get isSupported
       native "FileSystemWatcher_IsSupported";
 
   static int _initWatcher() native "FileSystemWatcher_InitWatcher";
diff --git a/runtime/bin/file_system_entity_patch.dart b/runtime/bin/file_system_entity_patch.dart
index 24782aa..dc2b346 100644
--- a/runtime/bin/file_system_entity_patch.dart
+++ b/runtime/bin/file_system_entity_patch.dart
@@ -2,16 +2,16 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-patch class FileStat {
-  /* patch */ static _statSync(String path) native "File_Stat";
+@patch class FileStat {
+  /* @patch */ static _statSync(String path) native "File_Stat";
 }
 
 
-patch class FileSystemEntity {
-  /* patch */ static _getType(String path, bool followLinks)
+@patch class FileSystemEntity {
+  /* @patch */ static _getType(String path, bool followLinks)
       native "File_GetType";
-  /* patch */ static _identical(String path1, String path2)
+  /* @patch */ static _identical(String path1, String path2)
       native "File_AreIdentical";
-  /* patch */ static _resolveSymbolicLinks(String path)
+  /* @patch */ static _resolveSymbolicLinks(String path)
       native "File_ResolveSymbolicLinks";
 }
diff --git a/runtime/bin/filter_patch.dart b/runtime/bin/filter_patch.dart
index a5626bb..11691e8 100644
--- a/runtime/bin/filter_patch.dart
+++ b/runtime/bin/filter_patch.dart
@@ -28,16 +28,16 @@
       native "Filter_CreateZLibDeflate";
 }
 
-patch class _Filter {
-  /* patch */ static _Filter _newZLibDeflateFilter(bool gzip, int level,
-                                                   int windowBits, int memLevel,
-                                                   int strategy,
-                                                   List<int> dictionary,
-                                                   bool raw) =>
+@patch class _Filter {
+  /* @patch */ static _Filter _newZLibDeflateFilter(bool gzip, int level,
+                                                    int windowBits, int memLevel,
+                                                    int strategy,
+                                                    List<int> dictionary,
+                                                    bool raw) =>
       new _ZLibDeflateFilter(gzip, level, windowBits, memLevel, strategy,
                              dictionary, raw);
-  /* patch */ static _Filter _newZLibInflateFilter(int windowBits,
-                                                   List<int> dictionary,
-                                                   bool raw) =>
+  /* @patch */ static _Filter _newZLibInflateFilter(int windowBits,
+                                                    List<int> dictionary,
+                                                    bool raw) =>
       new _ZLibInflateFilter(windowBits, dictionary, raw);
 }
diff --git a/runtime/bin/fuchsia_test.cc b/runtime/bin/fuchsia_test.cc
index 341f9c7..fef899a 100644
--- a/runtime/bin/fuchsia_test.cc
+++ b/runtime/bin/fuchsia_test.cc
@@ -148,16 +148,11 @@
     FATAL("Failed to set flags\n");
   }
   Log::Print("Calling Dart_Initialize\n");
-  char* error = Dart_Initialize(
-      vm_isolate_snapshot_buffer, NULL, NULL,
-      NULL, NULL, NULL, NULL,
-      NULL,
-      NULL,
-      NULL,
-      NULL,
-      NULL,
-      NULL,
-      NULL);
+  Dart_InitializeParams init_params;
+  memset(&init_params, 0, sizeof(init_params));
+  init_params.version = DART_INITIALIZE_PARAMS_CURRENT_VERSION;
+  init_params.vm_isolate_snapshot = vm_isolate_snapshot_buffer;
+  char* error = Dart_Initialize(&init_params);
   if (error != NULL) {
     FATAL1("VM initialization failed: %s\n", error);
   }
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index 8654e28..319a322 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -1231,21 +1231,20 @@
   // core library snapshot generation. However for the case when a full
   // snasphot is generated from a script (app_script_name != NULL) we will
   // need the service isolate to resolve URI and load code.
-  char* error = Dart_Initialize(
-      NULL,
-      NULL,
-      NULL,
-      (app_script_name != NULL) ? CreateServiceIsolate : NULL,
-      NULL,
-      NULL,
-      NULL,
-      NULL,
-      DartUtils::OpenFile,
-      DartUtils::ReadFile,
-      DartUtils::WriteFile,
-      DartUtils::CloseFile,
-      DartUtils::EntropySource,
-      NULL);
+
+  Dart_InitializeParams init_params;
+  memset(&init_params, 0, sizeof(init_params));
+  init_params.version = DART_INITIALIZE_PARAMS_CURRENT_VERSION;
+  if (app_script_name != NULL) {
+    init_params.create = CreateServiceIsolate;
+  }
+  init_params.file_open = DartUtils::OpenFile;
+  init_params.file_read = DartUtils::ReadFile;
+  init_params.file_write = DartUtils::WriteFile;
+  init_params.file_close = DartUtils::CloseFile;
+  init_params.entropy_source = DartUtils::EntropySource;
+
+  char* error = Dart_Initialize(&init_params);
   if (error != NULL) {
     Log::PrintErr("VM initialization failed: %s\n", error);
     free(error);
diff --git a/runtime/bin/io_service_patch.dart b/runtime/bin/io_service_patch.dart
index add622f..94b6346 100644
--- a/runtime/bin/io_service_patch.dart
+++ b/runtime/bin/io_service_patch.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-patch class _IOService {
+@patch class _IOService {
   // Lazy initialize service ports, 32 per isolate.
   static const int _SERVICE_PORT_COUNT = 32;
   static List<SendPort> _servicePort = new List(_SERVICE_PORT_COUNT);
@@ -11,7 +11,7 @@
   static Map<int, Completer> _messageMap = {};
   static int _id = 0;
 
-  /* patch */ static Future _dispatch(int request, List data) {
+  /* @patch */ static Future _dispatch(int request, List data) {
     int id;
     do {
       id = _getNextId();
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index a90c1a4..216b919 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -282,28 +282,32 @@
     environment = new HashMap(&HashMap::SameStringValue, 4);
   }
   // Split the name=value part of the -Dname=value argument.
-  char* name;
-  char* value = NULL;
   const char* equals_pos = strchr(arg, '=');
   if (equals_pos == NULL) {
     // No equal sign (name without value) currently not supported.
     Log::PrintErr("No value given to -D option\n");
     return false;
-  } else {
-    int name_len = equals_pos - arg;
-    if (name_len == 0) {
-      Log::PrintErr("No name given to -D option\n");
-      return false;
-    }
-    // Split name=value into name and value.
-    name = reinterpret_cast<char*>(malloc(name_len + 1));
-    strncpy(name, arg, name_len);
-    name[name_len] = '\0';
-    value = strdup(equals_pos + 1);
   }
+
+  char* name;
+  char* value = NULL;
+  int name_len = equals_pos - arg;
+  if (name_len == 0) {
+    Log::PrintErr("No name given to -D option\n");
+    return false;
+  }
+  // Split name=value into name and value.
+  name = reinterpret_cast<char*>(malloc(name_len + 1));
+  strncpy(name, arg, name_len);
+  name[name_len] = '\0';
+  value = strdup(equals_pos + 1);
   HashMap::Entry* entry = environment->Lookup(
       GetHashmapKeyFromString(name), HashMap::StringHash(name), true);
   ASSERT(entry != NULL);  // Lookup adds an entry if key not found.
+  if (entry->value != NULL) {
+    free(name);
+    free(entry->value);
+  }
   entry->value = value;
   return true;
 }
@@ -1727,16 +1731,22 @@
   }
 
   // Initialize the Dart VM.
-  char* error = Dart_Initialize(
-      vm_isolate_snapshot_buffer, instructions_snapshot, data_snapshot,
-      CreateIsolateAndSetup, NULL, NULL, ShutdownIsolate,
-      NULL,
-      DartUtils::OpenFile,
-      DartUtils::ReadFile,
-      DartUtils::WriteFile,
-      DartUtils::CloseFile,
-      DartUtils::EntropySource,
-      GetVMServiceAssetsArchiveCallback);
+  Dart_InitializeParams init_params;
+  memset(&init_params, 0, sizeof(init_params));
+  init_params.version = DART_INITIALIZE_PARAMS_CURRENT_VERSION;
+  init_params.vm_isolate_snapshot = vm_isolate_snapshot_buffer;
+  init_params.instructions_snapshot = instructions_snapshot;
+  init_params.data_snapshot = data_snapshot;
+  init_params.create = CreateIsolateAndSetup;
+  init_params.shutdown = ShutdownIsolate;
+  init_params.file_open = DartUtils::OpenFile;
+  init_params.file_read = DartUtils::ReadFile;
+  init_params.file_write = DartUtils::WriteFile;
+  init_params.file_close = DartUtils::CloseFile;
+  init_params.entropy_source = DartUtils::EntropySource;
+  init_params.get_service_assets = GetVMServiceAssetsArchiveCallback;
+
+  char* error = Dart_Initialize(&init_params);
   if (error != NULL) {
     EventHandler::Stop();
     fprintf(stderr, "VM initialization failed: %s\n", error);
diff --git a/runtime/bin/platform_patch.dart b/runtime/bin/platform_patch.dart
index 577bbb6..bbd353b 100644
--- a/runtime/bin/platform_patch.dart
+++ b/runtime/bin/platform_patch.dart
@@ -2,33 +2,33 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-patch class _Platform {
-  /* patch */ static int _numberOfProcessors()
+@patch class _Platform {
+  /* @patch */ static int _numberOfProcessors()
       native "Platform_NumberOfProcessors";
-  /* patch */ static String _pathSeparator()
+  /* @patch */ static String _pathSeparator()
       native "Platform_PathSeparator";
-  /* patch */ static String _operatingSystem()
+  /* @patch */ static String _operatingSystem()
       native "Platform_OperatingSystem";
-  /* patch */ static _localHostname()
+  /* @patch */ static _localHostname()
       native "Platform_LocalHostname";
-  /* patch */ static _executable()
+  /* @patch */ static _executable()
       native "Platform_ExecutableName";
-  /* patch */ static _resolvedExecutable()
+  /* @patch */ static _resolvedExecutable()
       native "Platform_ResolvedExecutableName";
-  /* patch */ static _environment()
+  /* @patch */ static _environment()
       native "Platform_Environment";
-  /* patch */ static List<String> _executableArguments()
+  /* @patch */ static List<String> _executableArguments()
       native "Platform_ExecutableArguments";
-  /* patch */ static String _version()
+  /* @patch */ static String _version()
       native "Platform_GetVersion";
 
-  /* patch */ static String _packageRoot()
+  /* @patch */ static String _packageRoot()
       => VMLibraryHooks.packageRootString;
-  /* patch */ static String _packageConfig()
+  /* @patch */ static String _packageConfig()
       => VMLibraryHooks.packageConfigString;
 
   // This script singleton is written to by the embedder if applicable.
-  /* patch */ static void set _nativeScript(String path) {
+  /* @patch */ static void set _nativeScript(String path) {
     if (path.startsWith('http:') ||
         path.startsWith('https:') ||
         path.startsWith('package:') ||
diff --git a/runtime/bin/process_patch.dart b/runtime/bin/process_patch.dart
index 60fb2b5..2e3d2fb 100644
--- a/runtime/bin/process_patch.dart
+++ b/runtime/bin/process_patch.dart
@@ -2,20 +2,20 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-patch class _WindowsCodePageDecoder {
-  /* patch */ static String _decodeBytes(List<int> bytes)
+@patch class _WindowsCodePageDecoder {
+  /* @patch */ static String _decodeBytes(List<int> bytes)
       native "SystemEncodingToString";
 }
 
 
-patch class _WindowsCodePageEncoder {
-  /* patch */ static List<int> _encodeString(String string)
+@patch class _WindowsCodePageEncoder {
+  /* @patch */ static List<int> _encodeString(String string)
       native "StringToSystemEncoding";
 }
 
 
-patch class Process {
-  /* patch */ static Future<Process> start(
+@patch class Process {
+  /* @patch */ static Future<Process> start(
       String executable,
       List<String> arguments,
       {String workingDirectory,
@@ -33,7 +33,7 @@
     return process._start();
   }
 
-  /* patch */ static Future<ProcessResult> run(
+  /* @patch */ static Future<ProcessResult> run(
       String executable,
       List<String> arguments,
       {String workingDirectory,
@@ -52,7 +52,7 @@
                                      stderrEncoding);
   }
 
-  /* patch */ static ProcessResult runSync(
+  /* @patch */ static ProcessResult runSync(
       String executable,
       List<String> arguments,
       {String workingDirectory,
@@ -71,7 +71,7 @@
                                          stderrEncoding);
   }
 
-  /* patch */ static bool killPid(
+  /* @patch */ static bool killPid(
       int pid, [ProcessSignal signal = ProcessSignal.SIGTERM]) {
     if (signal is! ProcessSignal) {
       throw new ArgumentError(
@@ -125,25 +125,25 @@
     }
   }
 
-  /* patch */ static _setSignalHandler(int signal)
+  /* @patch */ static _setSignalHandler(int signal)
       native "Process_SetSignalHandler";
-  /* patch */ static int _clearSignalHandler(int signal)
+  /* @patch */ static int _clearSignalHandler(int signal)
       native "Process_ClearSignalHandler";
 }
 
 Function _getWatchSignalInternal() => _ProcessUtils._watchSignalInternal;
 
 
-patch class _ProcessUtils {
-  /* patch */ static void _exit(int status) native "Process_Exit";
-  /* patch */ static void _setExitCode(int status)
+@patch class _ProcessUtils {
+  /* @patch */ static void _exit(int status) native "Process_Exit";
+  /* @patch */ static void _setExitCode(int status)
       native "Process_SetExitCode";
-  /* patch */ static int _getExitCode() native "Process_GetExitCode";
-  /* patch */ static void _sleep(int millis) native "Process_Sleep";
-  /* patch */ static int _pid(Process process) native "Process_Pid";
+  /* @patch */ static int _getExitCode() native "Process_GetExitCode";
+  /* @patch */ static void _sleep(int millis) native "Process_Sleep";
+  /* @patch */ static int _pid(Process process) native "Process_Pid";
   static bool _killPid(int pid, int signal)
       native "Process_KillPid";
-  /* patch */ static Stream<ProcessSignal> _watchSignal(ProcessSignal signal) {
+  /* @patch */ static Stream<ProcessSignal> _watchSignal(ProcessSignal signal) {
     if (signal != ProcessSignal.SIGHUP &&
         signal != ProcessSignal.SIGINT &&
         signal != ProcessSignal.SIGTERM &&
diff --git a/runtime/bin/run_vm_tests_fuchsia.cc b/runtime/bin/run_vm_tests_fuchsia.cc
index 43185ac..a7839a9 100644
--- a/runtime/bin/run_vm_tests_fuchsia.cc
+++ b/runtime/bin/run_vm_tests_fuchsia.cc
@@ -33,11 +33,11 @@
   "Read",
   "FileLength",
   "FilePosition",
-  // Hangs.
+  // Crash and then Hang.
   "ArrayLengthMaxElements",
   "Int8ListLengthMaxElements",
+  // Crashes in realloc.
   "LargeMap",
-  "CompileFunctionOnHelperThread",
   // The profiler is turned off.
   "Profiler_AllocationSampleTest",
   "Profiler_ArrayAllocation",
diff --git a/runtime/bin/secure_socket_patch.dart b/runtime/bin/secure_socket_patch.dart
index c47c941..b3fde05 100644
--- a/runtime/bin/secure_socket_patch.dart
+++ b/runtime/bin/secure_socket_patch.dart
@@ -2,18 +2,18 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-patch class SecureSocket {
-  /* patch */ factory SecureSocket._(RawSecureSocket rawSocket) =>
+@patch class SecureSocket {
+  /* @patch */ factory SecureSocket._(RawSecureSocket rawSocket) =>
       new _SecureSocket(rawSocket);
 }
 
 
-patch class _SecureFilter {
-  /* patch */ factory _SecureFilter() => new _SecureFilterImpl();
+@patch class _SecureFilter {
+  /* @patch */ factory _SecureFilter() => new _SecureFilterImpl();
 }
 
-patch class X509Certificate {
-  /* patch */ factory X509Certificate._() => new _X509CertificateImpl();
+@patch class X509Certificate {
+  /* @patch */ factory X509Certificate._() => new _X509CertificateImpl();
 }
 
 class _SecureSocket extends _Socket implements SecureSocket {
@@ -115,16 +115,16 @@
   List<_ExternalBuffer> buffers;
 }
 
-patch class SecurityContext {
-  /* patch */ factory SecurityContext() {
+@patch class SecurityContext {
+  /* @patch */ factory SecurityContext() {
     return new _SecurityContext();
   }
 
-  /* patch */ static SecurityContext get defaultContext {
+  /* @patch */ static SecurityContext get defaultContext {
     return _SecurityContext.defaultContext;
   }
 
-  /* patch */ static bool get alpnSupported {
+  /* @patch */ static bool get alpnSupported {
     return _SecurityContext.alpnSupported;
   }
 }
diff --git a/runtime/bin/socket_patch.dart b/runtime/bin/socket_patch.dart
index a8b60c3..e4bcb9f 100644
--- a/runtime/bin/socket_patch.dart
+++ b/runtime/bin/socket_patch.dart
@@ -2,8 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-patch class RawServerSocket {
-  /* patch */ static Future<RawServerSocket> bind(address,
+@patch class RawServerSocket {
+  /* @patch */ static Future<RawServerSocket> bind(address,
                                                   int port,
                                                   {int backlog: 0,
                                                    bool v6Only: false,
@@ -13,52 +13,52 @@
 }
 
 
-patch class RawSocket {
-  /* patch */ static Future<RawSocket> connect(
+@patch class RawSocket {
+  /* @patch */ static Future<RawSocket> connect(
       host, int port, {sourceAddress}) {
     return _RawSocket.connect(host, port, sourceAddress);
   }
 }
 
 
-patch class InternetAddress {
-  /* patch */ static InternetAddress get LOOPBACK_IP_V4 {
+@patch class InternetAddress {
+  /* @patch */ static InternetAddress get LOOPBACK_IP_V4 {
     return _InternetAddress.LOOPBACK_IP_V4;
   }
 
-  /* patch */ static InternetAddress get LOOPBACK_IP_V6 {
+  /* @patch */ static InternetAddress get LOOPBACK_IP_V6 {
     return _InternetAddress.LOOPBACK_IP_V6;
   }
 
-  /* patch */ static InternetAddress get ANY_IP_V4 {
+  /* @patch */ static InternetAddress get ANY_IP_V4 {
     return _InternetAddress.ANY_IP_V4;
   }
 
-  /* patch */ static InternetAddress get ANY_IP_V6 {
+  /* @patch */ static InternetAddress get ANY_IP_V6 {
     return _InternetAddress.ANY_IP_V6;
   }
 
-  /* patch */ factory InternetAddress(String address) {
+  /* @patch */ factory InternetAddress(String address) {
     return new _InternetAddress.parse(address);
   }
 
-  /* patch */ static Future<List<InternetAddress>> lookup(
+  /* @patch */ static Future<List<InternetAddress>> lookup(
       String host, {InternetAddressType type: InternetAddressType.ANY}) {
     return _NativeSocket.lookup(host, type: type);
   }
 
-  /* patch */ static InternetAddress _cloneWithNewHost(
+  /* @patch */ static InternetAddress _cloneWithNewHost(
       InternetAddress address, String host) {
     return (address as _InternetAddress)._cloneWithNewHost(host);
   }
 }
 
-patch class NetworkInterface {
-  /* patch */ static bool get listSupported {
+@patch class NetworkInterface {
+  /* @patch */ static bool get listSupported {
     return _listSupported();
   }
 
-  /* patch */ static Future<List<NetworkInterface>> list({
+  /* @patch */ static Future<List<NetworkInterface>> list({
       bool includeLoopback: false,
       bool includeLinkLocal: false,
       InternetAddressType type: InternetAddressType.ANY}) {
@@ -1095,7 +1095,7 @@
   nativeGetOption(int option, int protocol) native "Socket_GetOption";
   bool nativeSetOption(int option, int protocol, value)
       native "Socket_SetOption";
-  bool nativeJoinMulticast(
+  OSError nativeJoinMulticast(
       List<int> addr, List<int> interfaceAddr, int interfaceIndex)
           native "Socket_JoinMulticast";
   bool nativeLeaveMulticast(
@@ -1360,8 +1360,8 @@
 }
 
 
-patch class ServerSocket {
-  /* patch */ static Future<ServerSocket> bind(address,
+@patch class ServerSocket {
+  /* @patch */ static Future<ServerSocket> bind(address,
                                                int port,
                                                {int backlog: 0,
                                                 bool v6Only: false,
@@ -1407,8 +1407,8 @@
 }
 
 
-patch class Socket {
-  /* patch */ static Future<Socket> connect(host, int port, {sourceAddress}) {
+@patch class Socket {
+  /* @patch */ static Future<Socket> connect(host, int port, {sourceAddress}) {
     return RawSocket.connect(host, port, sourceAddress: sourceAddress).then(
         (socket) => new _Socket(socket));
   }
@@ -1720,8 +1720,8 @@
 }
 
 
-patch class RawDatagramSocket {
-  /* patch */ static Future<RawDatagramSocket> bind(
+@patch class RawDatagramSocket {
+  /* @patch */ static Future<RawDatagramSocket> bind(
       host, int port, {bool reuseAddress: true}) {
     return _RawDatagramSocket.bind(host, port, reuseAddress);
   }
diff --git a/runtime/bin/stdio_patch.dart b/runtime/bin/stdio_patch.dart
index cf02819..3c258c5 100644
--- a/runtime/bin/stdio_patch.dart
+++ b/runtime/bin/stdio_patch.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-patch class _StdIOUtils {
+@patch class _StdIOUtils {
   static Stdin _getStdioInputStream() {
     switch (_getStdioHandleType(0)) {
       case _STDIO_HANDLE_TYPE_TERMINAL:
@@ -46,14 +46,14 @@
   static _getStdioHandleType(int fd) native "File_GetStdioHandleType";
 }
 
-patch class Stdin {
-  /* patch */ int readByteSync() native "Stdin_ReadByte";
+@patch class Stdin {
+  /* @patch */ int readByteSync() native "Stdin_ReadByte";
 
-  /* patch */ bool get echoMode => _echoMode;
-  /* patch */ void set echoMode(bool enabled) { _echoMode = enabled; }
+  /* @patch */ bool get echoMode => _echoMode;
+  /* @patch */ void set echoMode(bool enabled) { _echoMode = enabled; }
 
-  /* patch */ bool get lineMode => _lineMode;
-  /* patch */ void set lineMode(bool enabled) { _lineMode = enabled; }
+  /* @patch */ bool get lineMode => _lineMode;
+  /* @patch */ void set lineMode(bool enabled) { _lineMode = enabled; }
 
   static bool get _echoMode native "Stdin_GetEchoMode";
   static void set _echoMode(bool enabled) native "Stdin_SetEchoMode";
@@ -61,8 +61,8 @@
   static void set _lineMode(bool enabled) native "Stdin_SetLineMode";
 }
 
-patch class Stdout {
-  /* patch */ bool _hasTerminal(int fd) {
+@patch class Stdout {
+  /* @patch */ bool _hasTerminal(int fd) {
     try {
       _terminalSize(fd);
       return true;
@@ -71,8 +71,8 @@
     }
   }
 
-  /* patch */ int _terminalColumns(int fd) => _terminalSize(fd)[0];
-  /* patch */ int _terminalLines(int fd) => _terminalSize(fd)[1];
+  /* @patch */ int _terminalColumns(int fd) => _terminalSize(fd)[0];
+  /* @patch */ int _terminalLines(int fd) => _terminalSize(fd)[1];
 
   static List _terminalSize(int fd) {
     var size = _getTerminalSize(fd);
diff --git a/runtime/bin/vmservice/server.dart b/runtime/bin/vmservice/server.dart
index 4e4c54a..4075e8d 100644
--- a/runtime/bin/vmservice/server.dart
+++ b/runtime/bin/vmservice/server.dart
@@ -157,12 +157,44 @@
     return false;
   }
 
-  void _requestHandler(HttpRequest request) {
+  Future _requestHandler(HttpRequest request) async {
     if (!_originCheck(request)) {
       // This is a cross origin attempt to connect
       request.response.close();
       return;
     }
+    if (request.method == 'PUT') {
+      // PUT requests are forwarded to DevFS for processing.
+
+      List fsNameList;
+      List fsPathList;
+      Object fsName;
+      Object fsPath;
+
+      try {
+        // Extract the fs name and fs path from the request headers.
+        fsNameList = request.headers['dev_fs_name'];
+        fsPathList = request.headers['dev_fs_path'];
+        fsName = fsNameList[0];
+        fsPath = fsPathList[0];
+      } catch (e) { /* ignore */ }
+
+      String result;
+      try {
+        result = await _service.devfs.handlePutStream(
+            fsName,
+            fsPath,
+            request.transform(GZIP.decoder));
+      } catch (e) { /* ignore */ }
+
+      if (result != null) {
+        request.response.headers.contentType =
+            HttpRequestClient.jsonContentType;
+        request.response.write(result);
+      }
+      request.response.close();
+      return;
+    }
     if (request.method != 'GET') {
       // Not a GET request. Do nothing.
       request.response.close();
diff --git a/runtime/bin/vmservice/vmservice_io.dart b/runtime/bin/vmservice/vmservice_io.dart
index 4e5ccab..49e8ad7 100644
--- a/runtime/bin/vmservice/vmservice_io.dart
+++ b/runtime/bin/vmservice/vmservice_io.dart
@@ -127,6 +127,15 @@
   return WriteLimiter.scheduleWrite(path, bytes);
 }
 
+Future writeStreamFileCallback(Uri path, Stream<List<int>> bytes) async {
+  var file = new File.fromUri(path);
+  var parent_directory = file.parent;
+  await parent_directory.create(recursive: true);
+  IOSink sink = await file.openWrite();
+  await sink.addStream(bytes);
+  await sink.close();
+}
+
 Future<List<int>> readFileCallback(Uri path) async {
   var file = new File.fromUri(path);
   return await file.readAsBytes();
@@ -191,6 +200,7 @@
   VMServiceEmbedderHooks.createTempDir = createTempDirCallback;
   VMServiceEmbedderHooks.deleteDir = deleteDirCallback;
   VMServiceEmbedderHooks.writeFile = writeFileCallback;
+  VMServiceEmbedderHooks.writeStreamFile = writeStreamFileCallback;
   VMServiceEmbedderHooks.readFile = readFileCallback;
   VMServiceEmbedderHooks.listFiles = listFilesCallback;
   // Always instantiate the vmservice object so that the exit message
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index 627e80f..3291dd0 100755
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -784,41 +784,54 @@
 typedef Dart_Handle (*Dart_GetVMServiceAssetsArchive)();
 
 /**
- * Initializes the VM.
+ * The current version of the Dart_InitializeFlags. Should be incremented every
+ * time Dart_InitializeFlags changes in a binary incompatible way.
+ */
+#define DART_INITIALIZE_PARAMS_CURRENT_VERSION (0x00000001)
+
+/**
+ * Describes how to initialize the VM. Used with Dart_Initialize.
  *
+ * \param version Identifies the version of the struct used by the client.
+ *   should be initialized to DART_INITIALIZE_PARAMS_CURRENT_VERSION.
  * \param vm_isolate_snapshot A buffer containing a snapshot of the VM isolate
  *   or NULL if no snapshot is provided.
  * \param instructions_snapshot A buffer containing a snapshot of precompiled
  *   instructions, or NULL if no snapshot is provided.
  * \param create A function to be called during isolate creation.
  *   See Dart_IsolateCreateCallback.
- * \param interrupt This parameter has been DEPRECATED.
- * \param unhandled_exception This parameter has been DEPRECATED.
  * \param shutdown A function to be called when an isolate is shutdown.
  *   See Dart_IsolateShutdownCallback.
- *
  * \param get_service_assets A function to be called by the service isolate when
  *    it requires the vmservice assets archive.
  *    See Dart_GetVMServiceAssetsArchive.
+ */
+typedef struct {
+    int32_t version;
+    const uint8_t* vm_isolate_snapshot;
+    const uint8_t* instructions_snapshot;
+    const uint8_t* data_snapshot;
+    Dart_IsolateCreateCallback create;
+    Dart_IsolateShutdownCallback shutdown;
+    Dart_ThreadExitCallback thread_exit;
+    Dart_FileOpenCallback file_open;
+    Dart_FileReadCallback file_read;
+    Dart_FileWriteCallback file_write;
+    Dart_FileCloseCallback file_close;
+    Dart_EntropySource entropy_source;
+    Dart_GetVMServiceAssetsArchive get_service_assets;
+} Dart_InitializeParams;
+
+/**
+ * Initializes the VM.
+ *
+ * \param flags A struct containing initialization information. The version
+ *   field of the struct must be DART_INITIALIZE_PARAMS_CURRENT_VERSION.
  *
  * \return NULL if initialization is successful. Returns an error message
  *   otherwise. The caller is responsible for freeing the error message.
  */
-DART_EXPORT char* Dart_Initialize(
-    const uint8_t* vm_isolate_snapshot,
-    const uint8_t* instructions_snapshot,
-    const uint8_t* data_snapshot,
-    Dart_IsolateCreateCallback create,
-    Dart_IsolateInterruptCallback interrupt,
-    Dart_IsolateUnhandledExceptionCallback unhandled_exception,
-    Dart_IsolateShutdownCallback shutdown,
-    Dart_ThreadExitCallback thread_exit,
-    Dart_FileOpenCallback file_open,
-    Dart_FileReadCallback file_read,
-    Dart_FileWriteCallback file_write,
-    Dart_FileCloseCallback file_close,
-    Dart_EntropySource entropy_source,
-    Dart_GetVMServiceAssetsArchive get_service_assets);
+DART_EXPORT char* Dart_Initialize(Dart_InitializeParams* params);
 
 /**
  * Cleanup state in the VM before process termination.
@@ -1178,6 +1191,23 @@
 
 
 /**
+ * Called when the embedder has caught a top level unhandled exception error
+ * in the current isolate. Also marks the isolate as paused at exit.
+ *
+ * NOTE: It is illegal to call this twice on the same isolate.
+ *
+ * \param error The unhandled exception error.
+ */
+DART_EXPORT void Dart_SetStickyError(Dart_Handle error);
+
+
+/**
+ * Does the current isolate have a sticky error?
+ */
+DART_EXPORT bool Dart_HasStickyError();
+
+
+/**
  * Handles the next pending message for the current isolate.
  *
  * May generate an unhandled exception error.
diff --git a/runtime/lib/array_patch.dart b/runtime/lib/array_patch.dart
index 94f29f1..95eeaa8 100644
--- a/runtime/lib/array_patch.dart
+++ b/runtime/lib/array_patch.dart
@@ -10,8 +10,8 @@
 
 const _GROWABLE_ARRAY_MARKER = const _GrowableArrayMarker();
 
-patch class List<E> {
-  /* patch */ factory List([int length = _GROWABLE_ARRAY_MARKER]) {
+@patch class List<E> {
+  /* @patch */ factory List([int length = _GROWABLE_ARRAY_MARKER]) {
     if (identical(length, _GROWABLE_ARRAY_MARKER)) {
       return new _GrowableList<E>(0);
     }
@@ -20,7 +20,7 @@
     return new _List<E>(length);
   }
 
-  /* patch */ factory List.filled(int length, E fill, {bool growable: false}) {
+  /* @patch */ factory List.filled(int length, E fill, {bool growable: false}) {
     // All error handling on the length parameter is done at the implementation
     // of new _List.
     var result = growable ? new _GrowableList<E>(length) : new _List<E>(length);
@@ -32,7 +32,7 @@
     return result;
   }
 
-  /* patch */ factory List.from(Iterable elements, { bool growable: true }) {
+  /* @patch */ factory List.from(Iterable elements, { bool growable: true }) {
     if (elements is EfficientLength) {
       int length = elements.length;
       var list = growable ? new _GrowableList<E>(length) : new _List<E>(length);
@@ -54,7 +54,7 @@
     return makeListFixedLength(list);
   }
 
-  /* patch */ factory List.unmodifiable(Iterable elements) {
+  /* @patch */ factory List.unmodifiable(Iterable elements) {
     List result = new List<E>.from(elements, growable: false);
     return makeFixedListUnmodifiable(result);
   }
diff --git a/runtime/lib/async_patch.dart b/runtime/lib/async_patch.dart
index 346e50d..c048ce8 100644
--- a/runtime/lib/async_patch.dart
+++ b/runtime/lib/async_patch.dart
@@ -188,4 +188,4 @@
   }
 }
 
-patch void _rethrow(Object error, StackTrace stackTrace) native "Async_rethrow";
+@patch void _rethrow(Object error, StackTrace stackTrace) native "Async_rethrow";
diff --git a/runtime/lib/bool_patch.dart b/runtime/lib/bool_patch.dart
index bbcbdb4..1a5eb6c 100644
--- a/runtime/lib/bool_patch.dart
+++ b/runtime/lib/bool_patch.dart
@@ -4,9 +4,9 @@
 
 // Dart core library.
 
-patch class bool {
+@patch class bool {
 
-  /* patch */ const factory bool.fromEnvironment(String name,
+  /* @patch */ const factory bool.fromEnvironment(String name,
                                                  {bool defaultValue: false})
       native "Bool_fromEnvironment";
 
diff --git a/runtime/lib/collection_patch.dart b/runtime/lib/collection_patch.dart
index ccb4190..000e0bc 100644
--- a/runtime/lib/collection_patch.dart
+++ b/runtime/lib/collection_patch.dart
@@ -2,10 +2,10 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-patch class HashMap<K, V> {
-  /* patch */ factory HashMap({ bool equals(K key1, K key2),
-                                int hashCode(K key),
-                                bool isValidKey(potentialKey) }) {
+@patch class HashMap<K, V> {
+  /* @patch */ factory HashMap({ bool equals(K key1, K key2),
+                                 int hashCode(K key),
+                                 bool isValidKey(potentialKey) }) {
     if (isValidKey == null) {
       if (hashCode == null) {
         if (equals == null) {
@@ -518,10 +518,10 @@
   }
 }
 
-patch class HashSet<E> {
-  /* patch */ factory HashSet({ bool equals(E e1, E e2),
-                                int hashCode(E e),
-                                bool isValidKey(potentialKey) }) {
+@patch class HashSet<E> {
+  /* @patch */ factory HashSet({ bool equals(E e1, E e2),
+                                 int hashCode(E e),
+                                 bool isValidKey(potentialKey) }) {
     if (isValidKey == null) {
       if (hashCode == null) {
         if (equals == null) {
@@ -548,7 +548,7 @@
     return new _CustomHashSet<E>(equals, hashCode, isValidKey);
   }
 
-  /* patch */ factory HashSet.identity() = _IdentityHashSet<E>;
+  /* @patch */ factory HashSet.identity() = _IdentityHashSet<E>;
 }
 
 class _HashSet<E> extends _HashSetBase<E> implements HashSet<E> {
@@ -901,7 +901,7 @@
 /**
  * A hash-based map that iterates keys and values in key insertion order.
  */
-patch class LinkedHashMap<K, V> {
+@patch class LinkedHashMap<K, V> {
   /// Holds a double-linked list of entries in insertion order.
   /// The fields have the same name as the ones in [_LinkedHashMapEntry],
   /// and this map is itself used as the head entry of the list.
@@ -910,9 +910,9 @@
   var _nextEntry;
   var _previousEntry;
 
-  /* patch */ factory LinkedHashMap({ bool equals(K key1, K key2),
-                                      int hashCode(K key),
-                                      bool isValidKey(potentialKey) }) {
+  /* @patch */ factory LinkedHashMap({ bool equals(K key1, K key2),
+                                       int hashCode(K key),
+                                       bool isValidKey(potentialKey) }) {
     if (isValidKey == null) {
       if (hashCode == null) {
         if (equals == null) {
@@ -939,14 +939,14 @@
     return new _CompactLinkedCustomHashMap<K, V>(equals, hashCode, isValidKey);
   }
 
-  /* patch */ factory LinkedHashMap.identity() =
+  /* @patch */ factory LinkedHashMap.identity() =
       _CompactLinkedIdentityHashMap<K, V>;
 }
 
-patch class LinkedHashSet<E> {
-  /* patch */ factory LinkedHashSet({ bool equals(E e1, E e2),
-                                      int hashCode(E e),
-                                      bool isValidKey(potentialKey) }) {
+@patch class LinkedHashSet<E> {
+  /* @patch */ factory LinkedHashSet({ bool equals(E e1, E e2),
+                                       int hashCode(E e),
+                                       bool isValidKey(potentialKey) }) {
     if (isValidKey == null) {
       if (hashCode == null) {
         if (equals == null) {
@@ -973,6 +973,6 @@
     return new _CompactLinkedCustomHashSet<E>(equals, hashCode, isValidKey);
   }
 
-  /* patch */ factory LinkedHashSet.identity() =
+  /* @patch */ factory LinkedHashSet.identity() =
       _CompactLinkedIdentityHashSet<E>;
 }
diff --git a/runtime/lib/convert_patch.dart b/runtime/lib/convert_patch.dart
index d4acc18a..6bf0a2c 100644
--- a/runtime/lib/convert_patch.dart
+++ b/runtime/lib/convert_patch.dart
@@ -6,7 +6,7 @@
 
 // JSON conversion.
 
-patch _parseJson(String json, reviver(var key, var value)) {
+@patch _parseJson(String json, reviver(var key, var value)) {
   _BuildJsonListener listener;
   if (reviver == null) {
     listener = new _BuildJsonListener();
@@ -21,8 +21,8 @@
   return listener.result;
 }
 
-patch class Utf8Decoder {
-  /* patch */
+@patch class Utf8Decoder {
+  /* @patch */
   Converter<List<int>, dynamic/*=T*/> fuse/*<T>*/(
       Converter<String, dynamic/*=T*/> next) {
     if (next is JsonDecoder) {
@@ -34,7 +34,7 @@
   }
 
   // Allow intercepting of UTF-8 decoding when built-in lists are passed.
-  /* patch */
+  /* @patch */
   static String _convertIntercepted(
       bool allowMalformed, List<int> codeUnits, int start, int end) {
     return null;  // This call was not intercepted.
@@ -1376,8 +1376,8 @@
   }
 }
 
-patch class JsonDecoder {
-  /* patch */ StringConversionSink startChunkedConversion(Sink<Object> sink) {
+@patch class JsonDecoder {
+  /* @patch */ StringConversionSink startChunkedConversion(Sink<Object> sink) {
     return new _JsonStringDecoderSink(this._reviver, sink);
   }
 }
diff --git a/runtime/lib/core_patch.dart b/runtime/lib/core_patch.dart
index 6c792d2..5fd883e 100644
--- a/runtime/lib/core_patch.dart
+++ b/runtime/lib/core_patch.dart
@@ -75,6 +75,6 @@
   }
 }
 
-patch class StackTrace {
-  /* patch */ static StackTrace get current native "StackTrace_current";
+@patch class StackTrace {
+  /* @patch */ static StackTrace get current native "StackTrace_current";
 }
diff --git a/runtime/lib/date_patch.dart b/runtime/lib/date_patch.dart
index 1ecf812..0f7837e 100644
--- a/runtime/lib/date_patch.dart
+++ b/runtime/lib/date_patch.dart
@@ -4,7 +4,7 @@
 // Dart core library.
 
 // VM implementation of DateTime.
-patch class DateTime {
+@patch class DateTime {
   // Natives.
   // The natives have been moved up here to work around Issue 10401.
   static int _getCurrentMicros() native "DateTime_currentTimeMicros";
@@ -30,17 +30,17 @@
 
   List __parts;
 
-  /* patch */ DateTime.fromMillisecondsSinceEpoch(int millisecondsSinceEpoch,
+  /* @patch */ DateTime.fromMillisecondsSinceEpoch(int millisecondsSinceEpoch,
                                                   {bool isUtc: false})
       : this._withValue(
           millisecondsSinceEpoch * Duration.MICROSECONDS_PER_MILLISECOND,
           isUtc: isUtc);
 
-  /* patch */ DateTime.fromMicrosecondsSinceEpoch(int microsecondsSinceEpoch,
+  /* @patch */ DateTime.fromMicrosecondsSinceEpoch(int microsecondsSinceEpoch,
                                                   {bool isUtc: false})
       : this._withValue(microsecondsSinceEpoch, isUtc: isUtc);
 
-  /* patch */ DateTime._internal(int year,
+  /* @patch */ DateTime._internal(int year,
                                  int month,
                                  int day,
                                  int hour,
@@ -57,17 +57,17 @@
     if (isUtc == null) throw new ArgumentError();
   }
 
-  /* patch */ DateTime._now()
+  /* @patch */ DateTime._now()
       : isUtc = false,
         _value = _getCurrentMicros() {
   }
 
-  /* patch */ String get timeZoneName {
+  /* @patch */ String get timeZoneName {
     if (isUtc) return "UTC";
     return _timeZoneName(microsecondsSinceEpoch);
   }
 
-  /* patch */ Duration get timeZoneOffset {
+  /* @patch */ Duration get timeZoneOffset {
     if (isUtc) return new Duration();
     int offsetInSeconds = _timeZoneOffsetInSeconds(microsecondsSinceEpoch);
     return new Duration(seconds: offsetInSeconds);
@@ -165,42 +165,42 @@
     return __parts;
   }
 
-  /* patch */ DateTime add(Duration duration) {
+  /* @patch */ DateTime add(Duration duration) {
     return new DateTime._withValue(
         _value + duration.inMicroseconds, isUtc: isUtc);
   }
 
-  /* patch */ DateTime subtract(Duration duration) {
+  /* @patch */ DateTime subtract(Duration duration) {
     return new DateTime._withValue(
         _value - duration.inMicroseconds, isUtc: isUtc);
   }
 
-  /* patch */ Duration difference(DateTime other) {
+  /* @patch */ Duration difference(DateTime other) {
     return new Duration(microseconds: _value - other._value);
   }
 
-  /* patch */ int get millisecondsSinceEpoch =>
+  /* @patch */ int get millisecondsSinceEpoch =>
       _value ~/ Duration.MICROSECONDS_PER_MILLISECOND;
 
-  /* patch */ int get microsecondsSinceEpoch => _value;
+  /* @patch */ int get microsecondsSinceEpoch => _value;
 
-  /* patch */ int get microsecond => _parts[_MICROSECOND_INDEX];
+  /* @patch */ int get microsecond => _parts[_MICROSECOND_INDEX];
 
-  /* patch */ int get millisecond => _parts[_MILLISECOND_INDEX];
+  /* @patch */ int get millisecond => _parts[_MILLISECOND_INDEX];
 
-  /* patch */ int get second => _parts[_SECOND_INDEX];
+  /* @patch */ int get second => _parts[_SECOND_INDEX];
 
-  /* patch */ int get minute => _parts[_MINUTE_INDEX];
+  /* @patch */ int get minute => _parts[_MINUTE_INDEX];
 
-  /* patch */ int get hour => _parts[_HOUR_INDEX];
+  /* @patch */ int get hour => _parts[_HOUR_INDEX];
 
-  /* patch */ int get day => _parts[_DAY_INDEX];
+  /* @patch */ int get day => _parts[_DAY_INDEX];
 
-  /* patch */ int get weekday => _parts[_WEEKDAY_INDEX];
+  /* @patch */ int get weekday => _parts[_WEEKDAY_INDEX];
 
-  /* patch */ int get month => _parts[_MONTH_INDEX];
+  /* @patch */ int get month => _parts[_MONTH_INDEX];
 
-  /* patch */ int get year => _parts[_YEAR_INDEX];
+  /* @patch */ int get year => _parts[_YEAR_INDEX];
 
   /**
    * Returns the amount of microseconds in UTC that represent the same values
@@ -244,7 +244,7 @@
   }
 
   /// Converts the given broken down date to microseconds.
-  /* patch */ static int _brokenDownDateToValue(
+  /* @patch */ static int _brokenDownDateToValue(
       int year, int month, int day,
       int hour, int minute, int second, int millisecond, int microsecond,
       bool isUtc) {
diff --git a/runtime/lib/deferred_load_patch.dart b/runtime/lib/deferred_load_patch.dart
index 800fdef..32f233b 100644
--- a/runtime/lib/deferred_load_patch.dart
+++ b/runtime/lib/deferred_load_patch.dart
@@ -4,8 +4,8 @@
 
 final Set<String> _loadedLibraries = new Set<String>();
 
-patch class DeferredLibrary {
-  /* patch */ Future<Null> load() {
+@patch class DeferredLibrary {
+  /* @patch */ Future<Null> load() {
     // Dummy implementation that should eventually be replaced by real
     // implementation.
     Future future =
diff --git a/runtime/lib/developer.dart b/runtime/lib/developer.dart
index f7b45f0..ec3d38b 100644
--- a/runtime/lib/developer.dart
+++ b/runtime/lib/developer.dart
@@ -4,19 +4,19 @@
 
 import 'dart:isolate';
 
-patch bool debugger({bool when: true,
+@patch bool debugger({bool when: true,
                      String message}) native "Developer_debugger";
 
-patch Object inspect(Object object) native "Developer_inspect";
+@patch Object inspect(Object object) native "Developer_inspect";
 
-patch void log(String message,
-               {DateTime time,
-                int sequenceNumber,
-                int level: 0,
-                String name: '',
-                Zone zone,
-                Object error,
-                StackTrace stackTrace}) {
+@patch void log(String message,
+                {DateTime time,
+                 int sequenceNumber,
+                 int level: 0,
+                 String name: '',
+                 Zone zone,
+                 Object error,
+                 StackTrace stackTrace}) {
   if (message is! String) {
     throw new ArgumentError(message, "message", "Must be a String");
   }
@@ -52,13 +52,13 @@
      Object error,
      StackTrace stackTrace) native "Developer_log";
 
-patch void _postEvent(String eventKind, String eventData)
+@patch void _postEvent(String eventKind, String eventData)
     native "Developer_postEvent";
 
-patch ServiceExtensionHandler _lookupExtension(String method)
+@patch ServiceExtensionHandler _lookupExtension(String method)
     native "Developer_lookupExtension";
 
-patch _registerExtension(String method, ServiceExtensionHandler handler)
+@patch _registerExtension(String method, ServiceExtensionHandler handler)
     native "Developer_registerExtension";
 
 // This code is only invoked when there is no other Dart code on the stack.
diff --git a/runtime/lib/double_patch.dart b/runtime/lib/double_patch.dart
index f33122a..cc3c605 100644
--- a/runtime/lib/double_patch.dart
+++ b/runtime/lib/double_patch.dart
@@ -5,7 +5,7 @@
 
 // VM implementation of double.
 
-patch class double {
+@patch class double {
 
   static double _nativeParse(String str,
                              int start, int end) native "Double_parse";
@@ -101,8 +101,8 @@
     return _nativeParse(str, start, end);
   }
 
-  /* patch */ static double parse(String str,
-                                  [double onError(String str)]) {
+  /* @patch */ static double parse(String str,
+                                   [double onError(String str)]) {
     var result = _parse(str);
     if (result == null) {
       if (onError == null) throw new FormatException("Invalid double", str);
diff --git a/runtime/lib/errors_patch.dart b/runtime/lib/errors_patch.dart
index faf342b..2deb7f9 100644
--- a/runtime/lib/errors_patch.dart
+++ b/runtime/lib/errors_patch.dart
@@ -5,16 +5,16 @@
 import 'dart:_internal' as internal;
 import 'dart:convert' show JSON;
 
-patch class Error {
-  /* patch */ static String _objectToString(Object object) {
+@patch class Error {
+  /* @patch */ static String _objectToString(Object object) {
     return Object._toString(object);
   }
 
-  /* patch */ static String _stringToSafeString(String string) {
+  /* @patch */ static String _stringToSafeString(String string) {
     return JSON.encode(string);
   }
 
-  /* patch */ StackTrace get stackTrace => _stackTrace;
+  /* @patch */ StackTrace get stackTrace => _stackTrace;
 
   StackTrace _stackTrace;
 }
@@ -95,12 +95,12 @@
   final String _errorMsg;
 }
 
-patch class FallThroughError {
+@patch class FallThroughError {
   FallThroughError._create(this._url, this._line);
 
   static _throwNew(int case_clause_pos) native "FallThroughError_throwNew";
 
-  /* patch */ String toString() {
+  /* @patch */ String toString() {
     return "'$_url': Switch case fall-through at line $_line.";
   }
 
@@ -116,26 +116,26 @@
   final String _msg;
 }
 
-patch class UnsupportedError {
+@patch class UnsupportedError {
   static _throwNew(String msg) {
     throw new UnsupportedError(msg);
   }
 }
 
-patch class CyclicInitializationError {
+@patch class CyclicInitializationError {
   static _throwNew(String variableName) {
     throw new CyclicInitializationError(variableName);
   }
 }
 
-patch class AbstractClassInstantiationError {
+@patch class AbstractClassInstantiationError {
   AbstractClassInstantiationError._create(
       this._className, this._url, this._line);
 
   static _throwNew(int case_clause_pos, String className)
       native "AbstractClassInstantiationError_throwNew";
 
-  /* patch */ String toString() {
+  /* @patch */ String toString() {
     return "Cannot instantiate abstract class $_className: "
            "_url '$_url' line $_line";
   }
@@ -146,7 +146,7 @@
   int _line;
 }
 
-patch class NoSuchMethodError {
+@patch class NoSuchMethodError {
   // The compiler emits a call to _throwNew when it cannot resolve a static
   // method at compile time. The receiver is actually the literal class of the
   // unresolved method.
@@ -284,7 +284,7 @@
     return "$msg\n\n";
   }
 
-  /* patch */ String toString() {
+  /* @patch */ String toString() {
     StringBuffer actual_buf = new StringBuffer();
     int i = 0;
     if (_arguments == null) {
diff --git a/runtime/lib/expando_patch.dart b/runtime/lib/expando_patch.dart
index df0234d..abdefab 100644
--- a/runtime/lib/expando_patch.dart
+++ b/runtime/lib/expando_patch.dart
@@ -2,15 +2,15 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-patch class Expando<T> {
-  /* patch */ Expando([String this.name])
+@patch class Expando<T> {
+  /* @patch */ Expando([String this.name])
       : _data = new List(_minSize),
         _used = 0;
 
   static const _minSize = 8;
   static final _deletedEntry = new _WeakProperty(null, null);
 
-  /* patch */ T operator[](Object object) {
+  /* @patch */ T operator[](Object object) {
     _checkType(object);
 
     var mask = _size - 1;
@@ -31,7 +31,7 @@
     return null;
   }
 
-  /* patch */ void operator[]=(Object object, T value) {
+  /* @patch */ void operator[]=(Object object, T value) {
     _checkType(object);
 
     var mask = _size - 1;
diff --git a/runtime/lib/function_patch.dart b/runtime/lib/function_patch.dart
index c94c78b..7ed74c8 100644
--- a/runtime/lib/function_patch.dart
+++ b/runtime/lib/function_patch.dart
@@ -2,13 +2,13 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-patch class Function {
+@patch class Function {
   static _apply(List arguments, List names)
       native "Function_apply";
 
-  /* patch */ static apply(Function function,
-                           List positionalArguments,
-                           [Map<Symbol, dynamic> namedArguments]) {
+  /* @patch */ static apply(Function function,
+                            List positionalArguments,
+                            [Map<Symbol, dynamic> namedArguments]) {
     int numPositionalArguments = 1 +  // Function is first implicit argument.
         (positionalArguments != null ? positionalArguments.length : 0);
     int numNamedArguments = namedArguments != null ? namedArguments.length : 0;
diff --git a/runtime/lib/identical_patch.dart b/runtime/lib/identical_patch.dart
index 172478f..6aaa1fc 100644
--- a/runtime/lib/identical_patch.dart
+++ b/runtime/lib/identical_patch.dart
@@ -2,6 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-patch bool identical(Object a, Object b) native "Identical_comparison";
+@patch bool identical(Object a, Object b) native "Identical_comparison";
 
-patch int identityHashCode(Object object) => object._identityHashCode;
+@patch int identityHashCode(Object object) => object._identityHashCode;
diff --git a/runtime/lib/integers_patch.dart b/runtime/lib/integers_patch.dart
index 19cc787..6aa072b 100644
--- a/runtime/lib/integers_patch.dart
+++ b/runtime/lib/integers_patch.dart
@@ -7,9 +7,9 @@
 
 import 'dart:_internal' as internal;
 
-patch class int {
+@patch class int {
 
-  /* patch */ const factory int.fromEnvironment(String name,
+  /* @patch */ const factory int.fromEnvironment(String name,
                                                 {int defaultValue})
       native "Integer_fromEnvironment";
 
@@ -42,7 +42,7 @@
     return sign * result;
   }
 
-  /* patch */ static int parse(String source,
+  /* @patch */ static int parse(String source,
                                { int radix,
                                  int onError(String str) }) {
     if (source == null) throw new ArgumentError("The source must not be null");
diff --git a/runtime/lib/internal_patch.dart b/runtime/lib/internal_patch.dart
index 3089830..24f31de 100644
--- a/runtime/lib/internal_patch.dart
+++ b/runtime/lib/internal_patch.dart
@@ -2,10 +2,10 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-patch List makeListFixedLength(List growableList)
+@patch List makeListFixedLength(List growableList)
     native "Internal_makeListFixedLength";
 
-patch List makeFixedListUnmodifiable(List fixedLengthList)
+@patch List makeFixedListUnmodifiable(List fixedLengthList)
     native "Internal_makeFixedListUnmodifiable";
 
 class VMLibraryHooks {
@@ -32,7 +32,7 @@
   static var platformScript;
 }
 
-patch class CodeUnits {
+@patch class CodeUnits {
   static final int cid = ClassID.getID(new CodeUnits(""));
 }
 
diff --git a/runtime/lib/isolate_patch.dart b/runtime/lib/isolate_patch.dart
index 4dd89c0..6ea2ef5 100644
--- a/runtime/lib/isolate_patch.dart
+++ b/runtime/lib/isolate_patch.dart
@@ -5,15 +5,15 @@
 import "dart:collection" show HashMap;
 import "dart:_internal";
 
-patch class ReceivePort {
-  /* patch */ factory ReceivePort() = _ReceivePortImpl;
+@patch class ReceivePort {
+  /* @patch */ factory ReceivePort() = _ReceivePortImpl;
 
-  /* patch */ factory ReceivePort.fromRawReceivePort(RawReceivePort rawPort) =
+  /* @patch */ factory ReceivePort.fromRawReceivePort(RawReceivePort rawPort) =
       _ReceivePortImpl.fromRawReceivePort;
 }
 
-patch class Capability {
-  /* patch */ factory Capability() = _CapabilityImpl;
+@patch class Capability {
+  /* @patch */ factory Capability() = _CapabilityImpl;
 }
 
 class _CapabilityImpl implements Capability {
@@ -31,7 +31,7 @@
   _get_hashcode() native "CapabilityImpl_get_hashcode";
 }
 
-patch class RawReceivePort {
+@patch class RawReceivePort {
   /**
    * Opens a long-lived port for receiving messages.
    *
@@ -39,7 +39,7 @@
    * can not be paused. The data-handler must be set before the first
    * event is received.
    */
-  /* patch */ factory RawReceivePort([void handler(event)]) {
+  /* @patch */ factory RawReceivePort([void handler(event)]) {
     _RawReceivePortImpl result = new _RawReceivePortImpl();
     result.handler = handler;
     return result;
@@ -268,13 +268,13 @@
   port.sendPort.send(null);
 }
 
-patch class Isolate {
+@patch class Isolate {
   static final _currentIsolate = _getCurrentIsolate();
   static final _rootUri = _getCurrentRootUri();
 
-  /* patch */ static Isolate get current => _currentIsolate;
+  /* @patch */ static Isolate get current => _currentIsolate;
 
-  /* patch */ static Future<Uri> get packageRoot {
+  /* @patch */ static Future<Uri> get packageRoot {
     var hook = VMLibraryHooks.packageRootUriFuture;
     if (hook == null) {
       throw new UnsupportedError("Isolate.packageRoot");
@@ -282,7 +282,7 @@
     return hook();
   }
 
-  /* patch */ static Future<Uri> get packageConfig {
+  /* @patch */ static Future<Uri> get packageConfig {
     var hook = VMLibraryHooks.packageConfigUriFuture;
     if (hook == null) {
       throw new UnsupportedError("Isolate.packageConfig");
@@ -290,7 +290,7 @@
     return hook();
   }
 
-  /* patch */ static Future<Uri> resolvePackageUri(Uri packageUri) {
+  /* @patch */ static Future<Uri> resolvePackageUri(Uri packageUri) {
     var hook = VMLibraryHooks.resolvePackageUriFuture;
     if (hook == null) {
       throw new UnsupportedError("Isolate.resolvePackageUri");
@@ -303,7 +303,7 @@
       (VMLibraryHooks.packageConfigUriFuture != null) &&
       (VMLibraryHooks.resolvePackageUriFuture != null);
 
-  /* patch */ static Future<Isolate> spawn(
+  /* @patch */ static Future<Isolate> spawn(
       void entryPoint(message), var message,
       {bool paused: false, bool errorsAreFatal,
        SendPort onExit, SendPort onError}) async {
@@ -340,7 +340,7 @@
     }
   }
 
-  /* patch */ static Future<Isolate> spawnUri(
+  /* @patch */ static Future<Isolate> spawnUri(
       Uri uri, List<String> args, var message,
       {bool paused: false,
        SendPort onExit,
@@ -478,7 +478,7 @@
 
   static void _sendOOB(port, msg) native "Isolate_sendOOB";
 
-  /* patch */ void _pause(Capability resumeCapability) {
+  /* @patch */ void _pause(Capability resumeCapability) {
     var msg = new List(4)
         ..[0] = 0  // Make room for OOB message type.
         ..[1] = _PAUSE
@@ -487,7 +487,7 @@
     _sendOOB(controlPort, msg);
   }
 
-  /* patch */ void resume(Capability resumeCapability) {
+  /* @patch */ void resume(Capability resumeCapability) {
     var msg = new List(4)
         ..[0] = 0  // Make room for OOB message type.
         ..[1] = _RESUME
@@ -496,7 +496,7 @@
     _sendOOB(controlPort, msg);
   }
 
-  /* patch */ void addOnExitListener(SendPort responsePort,
+  /* @patch */ void addOnExitListener(SendPort responsePort,
                                      {Object response}) {
     var msg = new List(4)
         ..[0] = 0  // Make room for OOB message type.
@@ -506,7 +506,7 @@
     _sendOOB(controlPort, msg);
   }
 
-  /* patch */ void removeOnExitListener(SendPort responsePort) {
+  /* @patch */ void removeOnExitListener(SendPort responsePort) {
     var msg = new List(3)
         ..[0] = 0  // Make room for OOB message type.
         ..[1] = _DEL_EXIT
@@ -514,7 +514,7 @@
     _sendOOB(controlPort, msg);
   }
 
-  /* patch */ void setErrorsFatal(bool errorsAreFatal) {
+  /* @patch */ void setErrorsFatal(bool errorsAreFatal) {
     var msg = new List(4)
       ..[0] = 0  // Make room for OOB message type.
       ..[1] = _ERROR_FATAL
@@ -523,7 +523,7 @@
     _sendOOB(controlPort, msg);
   }
 
-  /* patch */ void kill({int priority: BEFORE_NEXT_EVENT}) {
+  /* @patch */ void kill({int priority: BEFORE_NEXT_EVENT}) {
     var msg = new List(4)
         ..[0] = 0  // Make room for OOB message type.
         ..[1] = _KILL
@@ -532,7 +532,7 @@
     _sendOOB(controlPort, msg);
   }
 
-  /* patch */ void ping(SendPort responsePort, {Object response,
+  /* @patch */ void ping(SendPort responsePort, {Object response,
                                                 int priority: IMMEDIATE}) {
     var msg = new List(5)
         ..[0] = 0  // Make room for OOM message type.
@@ -543,7 +543,7 @@
     _sendOOB(controlPort, msg);
   }
 
-  /* patch */ void addErrorListener(SendPort port) {
+  /* @patch */ void addErrorListener(SendPort port) {
     var msg = new List(3)
         ..[0] = 0  // Make room for OOB message type.
         ..[1] = _ADD_ERROR
@@ -551,7 +551,7 @@
     _sendOOB(controlPort, msg);
   }
 
-  /* patch */ void removeErrorListener(SendPort port) {
+  /* @patch */ void removeErrorListener(SendPort port) {
     var msg = new List(3)
         ..[0] = 0  // Make room for OOB message type.
         ..[1] = _DEL_ERROR
diff --git a/runtime/lib/map_patch.dart b/runtime/lib/map_patch.dart
index 8a8359a..333f62a 100644
--- a/runtime/lib/map_patch.dart
+++ b/runtime/lib/map_patch.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-patch class Map<K, V> {
+@patch class Map<K, V> {
   // Factory constructing a Map from a parser generated Map literal.
   // [elements] contains n key-value pairs.
   // The keys are at position 2*n and are already type checked by the parser
@@ -17,9 +17,9 @@
     return map;
   }
 
-  /* patch */ factory Map.unmodifiable(Map other) {
+  /* @patch */ factory Map.unmodifiable(Map other) {
     return new UnmodifiableMapView<K, V>(new Map.from(other));
   }
 
-  /* patch */ factory Map() = LinkedHashMap<K, V>;
+  /* @patch */ factory Map() = LinkedHashMap<K, V>;
 }
diff --git a/runtime/lib/math_patch.dart b/runtime/lib/math_patch.dart
index 4f0b852..5cf80c9 100644
--- a/runtime/lib/math_patch.dart
+++ b/runtime/lib/math_patch.dart
@@ -8,7 +8,7 @@
 
 // If [x] is an [int] and [exponent] is a non-negative [int], the result is
 // an [int], otherwise the result is a [double].
-patch num pow(num x, num exponent) {
+@patch num pow(num x, num exponent) {
   if ((x is int) && (exponent is int) && (exponent >= 0)) {
     return _intPow(x, exponent);
   }
@@ -23,7 +23,7 @@
   if (exponent == 1.0) return base;
   if (exponent == 2.0) return base * base;
   if (exponent == 3.0) return base * base * base;
-  
+
   if (base == 1.0) return 1.0;
 
   if (base.isNaN || exponent.isNaN) {
@@ -56,16 +56,16 @@
   return result;
 }
 
-patch double atan2(num a, num b) => _atan2(a.toDouble(), b.toDouble());
-patch double sin(num value) => _sin(value.toDouble());
-patch double cos(num value) => _cos(value.toDouble());
-patch double tan(num value) => _tan(value.toDouble());
-patch double acos(num value) => _acos(value.toDouble());
-patch double asin(num value) => _asin(value.toDouble());
-patch double atan(num value) => _atan(value.toDouble());
-patch double sqrt(num value) => _sqrt(value.toDouble());
-patch double exp(num value) => _exp(value.toDouble());
-patch double log(num value) => _log(value.toDouble());
+@patch double atan2(num a, num b) => _atan2(a.toDouble(), b.toDouble());
+@patch double sin(num value) => _sin(value.toDouble());
+@patch double cos(num value) => _cos(value.toDouble());
+@patch double tan(num value) => _tan(value.toDouble());
+@patch double acos(num value) => _acos(value.toDouble());
+@patch double asin(num value) => _asin(value.toDouble());
+@patch double atan(num value) => _atan(value.toDouble());
+@patch double sqrt(num value) => _sqrt(value.toDouble());
+@patch double exp(num value) => _exp(value.toDouble());
+@patch double log(num value) => _log(value.toDouble());
 
 double _atan2(double a, double b) native "Math_atan2";
 double _sin(double x) native "Math_sin";
@@ -80,9 +80,9 @@
 
 
 // TODO(iposva): Handle patch methods within a patch class correctly.
-patch class Random {
+@patch class Random {
 
-  /*patch*/ factory Random([int seed]) {
+  /*@patch*/ factory Random([int seed]) {
     var state = _Random._setupSeed((seed == null) ? _Random._nextSeed() : seed);
     // Crank a couple of times to distribute the seed bits a bit further.
     return new _Random._withState(state).._nextState()
@@ -91,7 +91,7 @@
                                         .._nextState();
   }
 
-  /*patch*/ factory Random.secure() {
+  /*@patch*/ factory Random.secure() {
     return new _SecureRandom();
   }
 }
diff --git a/runtime/lib/mirrors_patch.dart b/runtime/lib/mirrors_patch.dart
index e80dd47..d66ce82 100644
--- a/runtime/lib/mirrors_patch.dart
+++ b/runtime/lib/mirrors_patch.dart
@@ -7,7 +7,7 @@
 /**
  * Returns a [MirrorSystem] for the current isolate.
  */
-patch MirrorSystem currentMirrorSystem() {
+@patch MirrorSystem currentMirrorSystem() {
   return _Mirrors.currentMirrorSystem();
 }
 
@@ -17,7 +17,7 @@
  * This only works if this mirror system is associated with the
  * current running isolate.
  */
-patch InstanceMirror reflect(Object reflectee) {
+@patch InstanceMirror reflect(Object reflectee) {
   return _Mirrors.reflect(reflectee);
 }
 
@@ -27,16 +27,16 @@
  *
  * This only works with objects local to the current isolate.
  */
-patch ClassMirror reflectClass(Type key) {
+@patch ClassMirror reflectClass(Type key) {
   return _Mirrors.reflectClass(key);
 }
 
-patch TypeMirror reflectType(Type key) {
+@patch TypeMirror reflectType(Type key) {
   return _Mirrors.reflectType(key);
 }
 
-patch class MirrorSystem {
-  /* patch */ LibraryMirror findLibrary(Symbol libraryName) {
+@patch class MirrorSystem {
+  /* @patch */ LibraryMirror findLibrary(Symbol libraryName) {
     var candidates =
         libraries.values.where((lib) => lib.simpleName == libraryName);
     if (candidates.length == 1) {
@@ -50,11 +50,11 @@
     throw new Exception("There is no library named '${getName(libraryName)}'");
   }
 
-  /* patch */ static String getName(Symbol symbol) {
+  /* @patch */ static String getName(Symbol symbol) {
     return internal.Symbol.getUnmangledName(symbol);
   }
 
-  /* patch */ static Symbol getSymbol(String name, [LibraryMirror library]) {
+  /* @patch */ static Symbol getSymbol(String name, [LibraryMirror library]) {
     if ((library != null && library is! _LocalLibraryMirror) ||
         ((name.length > 0) && (name[0] == '_') && (library == null))) {
       throw new ArgumentError(library);
diff --git a/runtime/lib/null_patch.dart b/runtime/lib/null_patch.dart
index 047039b..312804e 100644
--- a/runtime/lib/null_patch.dart
+++ b/runtime/lib/null_patch.dart
@@ -4,7 +4,7 @@
 
 // Dart core library.
 
-patch class Null {
+@patch class Null {
 
   factory Null._uninstantiable() {
     throw new UnsupportedError("class Null cannot be instantiated");
diff --git a/runtime/lib/object_patch.dart b/runtime/lib/object_patch.dart
index 719e592..7de335b 100644
--- a/runtime/lib/object_patch.dart
+++ b/runtime/lib/object_patch.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-patch class Object {
+@patch class Object {
 
   // The VM has its own implementation of equals.
   bool operator ==(other) native "Object_equals";
@@ -29,10 +29,10 @@
     return result;
   }
 
-  /* patch */ int get hashCode => _objectHashCode(this);
+  /* @patch */ int get hashCode => _objectHashCode(this);
   int get _identityHashCode => _objectHashCode(this);
 
-  /* patch */ String toString() native "Object_toString";
+  /* @patch */ String toString() native "Object_toString";
   // A statically dispatched version of Object.toString.
   static String _toString(obj) native "Object_toString";
 
@@ -43,7 +43,7 @@
                 Map<String, dynamic> namedArguments)
       native "Object_noSuchMethod";
 
-  /* patch */ noSuchMethod(Invocation invocation) {
+  /* @patch */ noSuchMethod(Invocation invocation) {
     return _noSuchMethod(invocation.isMethod,
                          internal.Symbol.getName(invocation.memberName),
                          invocation._type,
@@ -51,7 +51,7 @@
                          _symbolMapToStringMap(invocation.namedArguments));
   }
 
-  /* patch */ Type get runtimeType native "Object_runtimeType";
+  /* @patch */ Type get runtimeType native "Object_runtimeType";
 
   // Call this function instead of inlining instanceof, thus collecting
   // type feedback and reducing code size of unoptimized code.
@@ -62,7 +62,7 @@
   bool _simpleInstanceOf(type) native "Object_simpleInstanceOf";
   bool _simpleInstanceOfTrue(type) => true;
   bool _simpleInstanceOfFalse(type) => false;
-  
+
   bool _instanceOfDouble(bool negate) native "Object_instanceOfDouble";
   bool _instanceOfNum(bool negate) native "Object_instanceOfNum";
   bool _instanceOfInt(bool negate) native "Object_instanceOfInt";
diff --git a/runtime/lib/print_patch.dart b/runtime/lib/print_patch.dart
index 539294a..3df38d1 100644
--- a/runtime/lib/print_patch.dart
+++ b/runtime/lib/print_patch.dart
@@ -6,7 +6,7 @@
 // string is a line, but it may contain "\n" characters.
 typedef void _PrintClosure(String line);
 
-patch void printToConsole(String line) {
+@patch void printToConsole(String line) {
   _printClosure(line);
 }
 
diff --git a/runtime/lib/profiler.dart b/runtime/lib/profiler.dart
index 94d11ef..9b4ce97 100644
--- a/runtime/lib/profiler.dart
+++ b/runtime/lib/profiler.dart
@@ -4,11 +4,11 @@
 
 import 'dart:_internal';
 
-patch class UserTag {
-  /* patch */ factory UserTag(String label) {
+@patch class UserTag {
+  /* @patch */ factory UserTag(String label) {
     return new _UserTag(label);
   }
-  /* patch */ static UserTag get defaultTag => _getDefaultTag();
+  /* @patch */ static UserTag get defaultTag => _getDefaultTag();
 }
 
 
@@ -18,7 +18,7 @@
   UserTag makeCurrent() native "UserTag_makeCurrent";
 }
 
-patch UserTag getCurrentTag() => _getCurrentTag();
+@patch UserTag getCurrentTag() => _getCurrentTag();
 UserTag _getCurrentTag() native "Profiler_getCurrentTag";
 
 UserTag _getDefaultTag() native "UserTag_defaultTag";
diff --git a/runtime/lib/regexp_patch.dart b/runtime/lib/regexp_patch.dart
index d8e622a..9b23430 100644
--- a/runtime/lib/regexp_patch.dart
+++ b/runtime/lib/regexp_patch.dart
@@ -4,10 +4,10 @@
 
 import "dart:collection" show LinkedList, LinkedListEntry;
 
-patch class RegExp {
-  /* patch */ factory RegExp(String source,
-                             {bool multiLine: false,
-                              bool caseSensitive: true}) {
+@patch class RegExp {
+  /* @patch */ factory RegExp(String source,
+                              {bool multiLine: false,
+                               bool caseSensitive: true}) {
     _RegExpHashKey key = new _RegExpHashKey(
         source, multiLine, caseSensitive);
     _RegExpHashValue value = _cache[key];
diff --git a/runtime/lib/resource_patch.dart b/runtime/lib/resource_patch.dart
index 0643516..e0db212 100644
--- a/runtime/lib/resource_patch.dart
+++ b/runtime/lib/resource_patch.dart
@@ -2,8 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-patch class Resource {
-  /* patch */ const factory Resource(String uri) = _Resource;
+@patch class Resource {
+  /* @patch */ const factory Resource(String uri) = _Resource;
 }
 
 class _Resource implements Resource {
diff --git a/runtime/lib/schedule_microtask_patch.dart b/runtime/lib/schedule_microtask_patch.dart
index f08de2b..9384c1e 100644
--- a/runtime/lib/schedule_microtask_patch.dart
+++ b/runtime/lib/schedule_microtask_patch.dart
@@ -2,8 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-patch class _AsyncRun {
-  /* patch */ static void _scheduleImmediate(void callback()) {
+@patch class _AsyncRun {
+  /* @patch */ static void _scheduleImmediate(void callback()) {
     if (_ScheduleImmediate._closure == null) {
       throw new UnsupportedError("Microtasks are not supported");
     }
diff --git a/runtime/lib/stopwatch_patch.dart b/runtime/lib/stopwatch_patch.dart
index e16005c..e3749e8 100644
--- a/runtime/lib/stopwatch_patch.dart
+++ b/runtime/lib/stopwatch_patch.dart
@@ -4,15 +4,15 @@
 
 // A VM patch of the stopwatch part of dart:core.
 
-patch class Stopwatch {
-  /* patch */ static void _initTicker() {
+@patch class Stopwatch {
+  /* @patch */ static void _initTicker() {
     if (_frequency == null) {
       _frequency = _computeFrequency();
     }
   }
 
   // Returns the current clock tick.
-  /* patch */ static int _now() native "Stopwatch_now";
+  /* @patch */ static int _now() native "Stopwatch_now";
 
   // Returns the frequency of clock ticks in Hz.
   static int _computeFrequency() native "Stopwatch_frequency";
diff --git a/runtime/lib/string_buffer_patch.dart b/runtime/lib/string_buffer_patch.dart
index 401d258..c4fab5c 100644
--- a/runtime/lib/string_buffer_patch.dart
+++ b/runtime/lib/string_buffer_patch.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-patch class StringBuffer {
+@patch class StringBuffer {
   static const int _BUFFER_SIZE = 64;
   static const int _PARTS_TO_COMPACT = 128;
   static const int _PARTS_TO_COMPACT_SIZE_LIMIT = _PARTS_TO_COMPACT * 8;
@@ -48,20 +48,20 @@
   int _bufferCodeUnitMagnitude = 0;
 
   /// Creates the string buffer with an initial content.
-  /* patch */ StringBuffer([Object content = ""]) {
+  /* @patch */ StringBuffer([Object content = ""]) {
     write(content);
   }
 
-  /* patch */ int get length => _partsCodeUnits + _bufferPosition;
+  /* @patch */ int get length => _partsCodeUnits + _bufferPosition;
 
-  /* patch */ void write(Object obj) {
+  /* @patch */ void write(Object obj) {
     String str = '$obj';
     if (str.isEmpty) return;
     _consumeBuffer();
     _addPart(str);
   }
 
-  /* patch */ void writeCharCode(int charCode) {
+  /* @patch */ void writeCharCode(int charCode) {
     if (charCode <= 0xFFFF) {
       if (charCode < 0) {
         throw new RangeError.range(charCode, 0, 0x10FFFF);
@@ -81,7 +81,7 @@
     }
   }
 
-  /* patch */ void writeAll(Iterable objects, [String separator = ""]) {
+  /* @patch */ void writeAll(Iterable objects, [String separator = ""]) {
     Iterator iterator = objects.iterator;
     if (!iterator.moveNext()) return;
     if (separator.isEmpty) {
@@ -97,19 +97,19 @@
     }
   }
 
-  /* patch */ void writeln([Object obj = ""]) {
+  /* @patch */ void writeln([Object obj = ""]) {
     write(obj);
     write("\n");
   }
 
   /** Makes the buffer empty. */
-  /* patch */ void clear() {
+  /* @patch */ void clear() {
     _parts = null;
     _partsCodeUnits = _bufferPosition = _bufferCodeUnitMagnitude = 0;
   }
 
   /** Returns the contents of buffer as a string. */
-  /* patch */ String toString() {
+  /* @patch */ String toString() {
     _consumeBuffer();
     return (_partsCodeUnits == 0) ?
         "" :
diff --git a/runtime/lib/string_patch.dart b/runtime/lib/string_patch.dart
index 4352245..e8b3642 100644
--- a/runtime/lib/string_patch.dart
+++ b/runtime/lib/string_patch.dart
@@ -7,16 +7,16 @@
 const int _maxUtf16 = 0xffff;
 const int _maxUnicode = 0x10ffff;
 
-patch class String {
-  /* patch */ factory String.fromCharCodes(Iterable<int> charCodes,
-                                           [int start = 0, int end]) {
+@patch class String {
+  /* @patch */ factory String.fromCharCodes(Iterable<int> charCodes,
+                                            [int start = 0, int end]) {
     if (charCodes is! Iterable) throw new ArgumentError.value(charCodes, "charCodes");
     if (start is! int) throw new ArgumentError.value(start, "start");
     if (end != null && end is! int) throw new ArgumentError.value(end, "end");
     return _StringBase.createFromCharCodes(charCodes, start, end, null);
   }
 
-  /* patch */ factory String.fromCharCode(int charCode) {
+  /* @patch */ factory String.fromCharCode(int charCode) {
     if (charCode >= 0) {
       if (charCode <= 0xff) {
         return _OneByteString._allocate(1).._setAt(0, charCode);
@@ -37,8 +37,8 @@
     throw new RangeError.range(charCode, 0, 0x10ffff);
   }
 
-  /* patch */ const factory String.fromEnvironment(String name,
-                                                   {String defaultValue})
+  /* @patch */ const factory String.fromEnvironment(String name,
+                                                    {String defaultValue})
       native "String_fromEnvironment";
 }
 
diff --git a/runtime/lib/symbol_patch.dart b/runtime/lib/symbol_patch.dart
index 1a1b2bc..4c70daa 100644
--- a/runtime/lib/symbol_patch.dart
+++ b/runtime/lib/symbol_patch.dart
@@ -2,11 +2,11 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-patch class Symbol {
-  /* patch */ const Symbol(String name)
+@patch class Symbol {
+  /* @patch */ const Symbol(String name)
       : this._name = name;
 
-  /* patch */ toString() => 'Symbol("${getUnmangledName(this)}")';
+  /* @patch */ toString() => 'Symbol("${getUnmangledName(this)}")';
 
   static getUnmangledName(Symbol symbol) {
     String string = Symbol.getName(symbol);
@@ -52,7 +52,7 @@
     return result.toString();
   }
 
-  /* patch */ int get hashCode {
+  /* @patch */ int get hashCode {
     const arbitraryPrime = 664597;
     return 0x1fffffff & (arbitraryPrime * _name.hashCode);
   }
diff --git a/runtime/lib/timeline.dart b/runtime/lib/timeline.dart
index df43dec..da5760e 100644
--- a/runtime/lib/timeline.dart
+++ b/runtime/lib/timeline.dart
@@ -4,33 +4,33 @@
 
 import 'dart:_internal';
 
-patch bool _isDartStreamEnabled() native "Timeline_isDartStreamEnabled";
+@patch bool _isDartStreamEnabled() native "Timeline_isDartStreamEnabled";
 
-patch int _getTraceClock() native "Timeline_getTraceClock";
+@patch int _getTraceClock() native "Timeline_getTraceClock";
 
-patch int _getThreadCpuClock() native "Timeline_getThreadCpuClock";
+@patch int _getThreadCpuClock() native "Timeline_getThreadCpuClock";
 
-patch int _getNextAsyncId() native "Timeline_getNextAsyncId";
+@patch int _getNextAsyncId() native "Timeline_getNextAsyncId";
 
-patch int _getIsolateNum() native "Timeline_getIsolateNum";
+@patch int _getIsolateNum() native "Timeline_getIsolateNum";
 
-patch void _reportTaskEvent(
-    int start,
-    int taskId,
-    String phase,
-    String category,
-    String name,
-    String argumentsAsJson) native "Timeline_reportTaskEvent";
+@patch void _reportTaskEvent(
+     int start,
+     int taskId,
+     String phase,
+     String category,
+     String name,
+     String argumentsAsJson) native "Timeline_reportTaskEvent";
 
-patch void _reportCompleteEvent(
-    int start,
-    int end,
-    String category,
-    String name,
-    String argumentsAsJson) native "Timeline_reportCompleteEvent";
+@patch void _reportCompleteEvent(
+     int start,
+     int end,
+     String category,
+     String name,
+     String argumentsAsJson) native "Timeline_reportCompleteEvent";
 
-patch void _reportInstantEvent(
-    int start,
-    String category,
-    String name,
-    String argumentsAsJson) native "Timeline_reportInstantEvent";
+@patch void _reportInstantEvent(
+     int start,
+     String category,
+     String name,
+     String argumentsAsJson) native "Timeline_reportInstantEvent";
diff --git a/runtime/lib/timer_patch.dart b/runtime/lib/timer_patch.dart
index f975daa..a92db40 100644
--- a/runtime/lib/timer_patch.dart
+++ b/runtime/lib/timer_patch.dart
@@ -2,8 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-patch class Timer {
-  /*patch*/ static Timer _createTimer(Duration duration, void callback()) {
+@patch class Timer {
+  /*@patch*/ static Timer _createTimer(Duration duration, void callback()) {
     // TODO(iposva): Remove _TimerFactory and use VMLibraryHooks exclusively.
     if (_TimerFactory._factory == null) {
       _TimerFactory._factory = VMLibraryHooks.timerFactory;
@@ -16,7 +16,7 @@
     return _TimerFactory._factory(milliseconds, (_) { callback(); }, false);
   }
 
-  /*patch*/ static Timer _createPeriodicTimer(Duration duration,
+  /*@patch*/ static Timer _createPeriodicTimer(Duration duration,
                                               void callback(Timer timer)) {
     // TODO(iposva): Remove _TimerFactory and use VMLibraryHooks exclusively.
     if (_TimerFactory._factory == null) {
diff --git a/runtime/lib/uri_patch.dart b/runtime/lib/uri_patch.dart
index 2664b9b..d4eb712 100644
--- a/runtime/lib/uri_patch.dart
+++ b/runtime/lib/uri_patch.dart
@@ -15,19 +15,19 @@
 // value for Uri.base.
 _UriBaseClosure _uriBaseClosure = _unsupportedUriBase;
 
-patch class Uri {
+@patch class Uri {
   static final bool _isWindowsCached = _isWindowsPlatform;
 
-  /* patch */ static bool get _isWindows => _isWindowsCached;
+  /* @patch */ static bool get _isWindows => _isWindowsCached;
 
-  /* patch */ static Uri get base => _uriBaseClosure();
+  /* @patch */ static Uri get base => _uriBaseClosure();
 
   static bool get _isWindowsPlatform native "Uri_isWindowsPlatform";
 
-  /* patch */ static String _uriEncode(List<int> canonicalTable,
-                                       String text,
-                                       Encoding encoding,
-                                       bool spaceToPlus) {
+  /* @patch */ static String _uriEncode(List<int> canonicalTable,
+                                        String text,
+                                        Encoding encoding,
+                                        bool spaceToPlus) {
     // First check if the text will be changed by encoding.
     int i = 0;
     if (identical(encoding, UTF8) ||
diff --git a/runtime/lib/vmservice_patch.dart b/runtime/lib/vmservice_patch.dart
index 498bda2..e0a2e02 100644
--- a/runtime/lib/vmservice_patch.dart
+++ b/runtime/lib/vmservice_patch.dart
@@ -2,9 +2,9 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-patch class Asset {
+@patch class Asset {
   /// Call to request assets from the embedder.
-  /* patch */ static HashMap<String, Asset> request() {
+  /* @patch */ static HashMap<String, Asset> request() {
     HashMap<String, Asset> assets = new HashMap<String, Asset>();
     Uint8List tarBytes = _requestAssets();
     if (tarBytes == null) {
@@ -21,18 +21,18 @@
 
 List _decodeAssets(Uint8List data) native "VMService_DecodeAssets";
 
-patch bool sendIsolateServiceMessage(SendPort sp, List m)
+@patch bool sendIsolateServiceMessage(SendPort sp, List m)
     native "VMService_SendIsolateServiceMessage";
-patch void sendRootServiceMessage(List m)
+@patch void sendRootServiceMessage(List m)
     native "VMService_SendRootServiceMessage";
-patch void sendObjectRootServiceMessage(List m)
+@patch void sendObjectRootServiceMessage(List m)
     native "VMService_SendObjectRootServiceMessage";
-patch void _onStart() native "VMService_OnStart";
-patch void _onExit() native "VMService_OnExit";
-patch void onServerAddressChange(String address)
+@patch void _onStart() native "VMService_OnStart";
+@patch void _onExit() native "VMService_OnExit";
+@patch void onServerAddressChange(String address)
     native "VMService_OnServerAddressChange";
-patch bool _vmListenStream(String streamId) native "VMService_ListenStream";
-patch void _vmCancelStream(String streamId) native "VMService_CancelStream";
-patch Uint8List _requestAssets() native "VMService_RequestAssets";
-patch void _spawnUriNotify(obj, String token)
+@patch bool _vmListenStream(String streamId) native "VMService_ListenStream";
+@patch void _vmCancelStream(String streamId) native "VMService_CancelStream";
+@patch Uint8List _requestAssets() native "VMService_RequestAssets";
+@patch void _spawnUriNotify(obj, String token)
     native "VMService_spawnUriNotify";
diff --git a/runtime/observatory/lib/app.dart b/runtime/observatory/lib/app.dart
index 4856448..0b85c8b 100644
--- a/runtime/observatory/lib/app.dart
+++ b/runtime/observatory/lib/app.dart
@@ -7,7 +7,6 @@
 import 'dart:async';
 import 'dart:convert';
 import 'dart:html';
-import 'dart:math' as math;
 
 import 'package:logging/logging.dart';
 import 'package:observatory/service_html.dart';
diff --git a/runtime/observatory/lib/cpu_profile.dart b/runtime/observatory/lib/cpu_profile.dart
index 5ebd9a5..ccc53c5 100644
--- a/runtime/observatory/lib/cpu_profile.dart
+++ b/runtime/observatory/lib/cpu_profile.dart
@@ -4,6 +4,7 @@
 
 library cpu_profiler;
 
+import 'dart:async';
 import 'dart:typed_data';
 import 'package:observatory/models.dart' as M;
 import 'package:observatory/service.dart';
diff --git a/runtime/observatory/lib/elements.dart b/runtime/observatory/lib/elements.dart
index ecc32ac..8f72b4d 100644
--- a/runtime/observatory/lib/elements.dart
+++ b/runtime/observatory/lib/elements.dart
@@ -7,7 +7,7 @@
 export 'package:observatory/src/elements/code_view.dart';
 export 'package:observatory/src/elements/context_ref.dart';
 export 'package:observatory/src/elements/context_view.dart';
-export 'package:observatory/src/elements/cpu_profile.dart';
+export 'package:observatory/src/elements/cpu_profile_table.dart';
 export 'package:observatory/src/elements/debugger.dart';
 export 'package:observatory/src/elements/error_view.dart';
 export 'package:observatory/src/elements/eval_box.dart';
@@ -36,7 +36,6 @@
 export 'package:observatory/src/elements/object_view.dart';
 export 'package:observatory/src/elements/objectpool_view.dart';
 export 'package:observatory/src/elements/objectstore_view.dart';
-export 'package:observatory/src/elements/observatory_application.dart';
 export 'package:observatory/src/elements/observatory_element.dart';
 export 'package:observatory/src/elements/persistent_handles.dart';
 export 'package:observatory/src/elements/ports.dart';
@@ -57,6 +56,8 @@
 import 'package:observatory/src/elements/code_ref_wrapper.dart';
 import 'package:observatory/src/elements/containers/virtual_collection.dart';
 import 'package:observatory/src/elements/containers/virtual_tree.dart';
+import 'package:observatory/src/elements/cpu_profile.dart';
+import 'package:observatory/src/elements/cpu_profile/virtual_tree.dart';
 import 'package:observatory/src/elements/curly_block.dart';
 import 'package:observatory/src/elements/curly_block_wrapper.dart';
 import 'package:observatory/src/elements/error_ref.dart';
@@ -65,8 +66,12 @@
 import 'package:observatory/src/elements/function_ref.dart';
 import 'package:observatory/src/elements/function_ref_wrapper.dart';
 import 'package:observatory/src/elements/general_error.dart';
+import 'package:observatory/src/elements/isolate_reconnect.dart';
 import 'package:observatory/src/elements/isolate_ref.dart';
 import 'package:observatory/src/elements/isolate_ref_wrapper.dart';
+import 'package:observatory/src/elements/isolate/counter_chart.dart';
+import 'package:observatory/src/elements/isolate/shared_summary.dart';
+import 'package:observatory/src/elements/isolate/shared_summary_wrapper.dart';
 import 'package:observatory/src/elements/library_ref.dart';
 import 'package:observatory/src/elements/library_ref_wrapper.dart';
 import 'package:observatory/src/elements/nav/bar.dart';
@@ -90,10 +95,13 @@
 import 'package:observatory/src/elements/nav/top_menu_wrapper.dart';
 import 'package:observatory/src/elements/nav/vm_menu.dart';
 import 'package:observatory/src/elements/nav/vm_menu_wrapper.dart';
+import 'package:observatory/src/elements/observatory_application.dart';
+import 'package:observatory/src/elements/sample_buffer_control.dart';
 import 'package:observatory/src/elements/script_ref.dart';
 import 'package:observatory/src/elements/script_ref_wrapper.dart';
 import 'package:observatory/src/elements/source_link.dart';
 import 'package:observatory/src/elements/source_link_wrapper.dart';
+import 'package:observatory/src/elements/stack_trace_tree_config.dart';
 import 'package:observatory/src/elements/view_footer.dart';
 import 'package:observatory/src/elements/vm_connect_target.dart';
 import 'package:observatory/src/elements/vm_connect.dart';
@@ -105,12 +113,17 @@
 export 'package:observatory/src/elements/code_ref.dart';
 export 'package:observatory/src/elements/containers/virtual_collection.dart';
 export 'package:observatory/src/elements/containers/virtual_tree.dart';
+export 'package:observatory/src/elements/cpu_profile.dart';
+export 'package:observatory/src/elements/cpu_profile/virtual_tree.dart';
 export 'package:observatory/src/elements/curly_block.dart';
 export 'package:observatory/src/elements/error_ref.dart';
 export 'package:observatory/src/elements/flag_list.dart';
 export 'package:observatory/src/elements/function_ref.dart';
 export 'package:observatory/src/elements/general_error.dart';
+export 'package:observatory/src/elements/isolate_reconnect.dart';
 export 'package:observatory/src/elements/isolate_ref.dart';
+export 'package:observatory/src/elements/isolate/counter_chart.dart';
+export 'package:observatory/src/elements/isolate/shared_summary.dart';
 export 'package:observatory/src/elements/library_ref.dart';
 export 'package:observatory/src/elements/nav/bar.dart';
 export 'package:observatory/src/elements/nav/class_menu.dart';
@@ -124,8 +137,11 @@
 export 'package:observatory/src/elements/nav/refresh.dart';
 export 'package:observatory/src/elements/nav/top_menu.dart';
 export 'package:observatory/src/elements/nav/vm_menu.dart';
+export 'package:observatory/src/elements/observatory_application.dart';
+export 'package:observatory/src/elements/sample_buffer_control.dart';
 export 'package:observatory/src/elements/script_ref.dart';
 export 'package:observatory/src/elements/source_link.dart';
+export 'package:observatory/src/elements/stack_trace_tree_config.dart';
 export 'package:observatory/src/elements/view_footer.dart';
 export 'package:observatory/src/elements/vm_connect_target.dart';
 export 'package:observatory/src/elements/vm_connect.dart';
@@ -138,6 +154,8 @@
   ClassTreeElement.tag.ensureRegistration();
   CodeRefElement.tag.ensureRegistration();
   CodeRefElementWrapper.tag.ensureRegistration();
+  CpuProfileElement.tag.ensureRegistration();
+  CpuProfileVirtualTreeElement.tag.ensureRegistration();
   CurlyBlockElement.tag.ensureRegistration();
   CurlyBlockElementWrapper.tag.ensureRegistration();
   ErrorRefElement.tag.ensureRegistration();
@@ -146,8 +164,12 @@
   FunctionRefElement.tag.ensureRegistration();
   FunctionRefElementWrapper.tag.ensureRegistration();
   GeneralErrorElement.tag.ensureRegistration();
+  IsolateCounterChartElement.tag.ensureRegistration();
+  IsolateReconnectElement.tag.ensureRegistration();
   IsolateRefElement.tag.ensureRegistration();
   IsolateRefElementWrapper.tag.ensureRegistration();
+  IsolateSharedSummaryElement.tag.ensureRegistration();
+  IsolateSharedSummaryElementWrapper.tag.ensureRegistration();
   LibraryRefElement.tag.ensureRegistration();
   LibraryRefElementWrapper.tag.ensureRegistration();
   NavBarElement.tag.ensureRegistration();
@@ -171,13 +193,19 @@
   NavTopMenuElementWrapper.tag.ensureRegistration();
   NavVMMenuElement.tag.ensureRegistration();
   NavVMMenuElementWrapper.tag.ensureRegistration();
+  ObservatoryApplicationElement.tag.ensureRegistration();
+  ScriptRefElement.tag.ensureRegistration();
+  SampleBufferControlElement.tag.ensureRegistration();
   ScriptRefElement.tag.ensureRegistration();
   ScriptRefElementWrapper.tag.ensureRegistration();
   SourceLinkElement.tag.ensureRegistration();
   SourceLinkElementWrapper.tag.ensureRegistration();
+  StackTraceTreeConfigElement.tag.ensureRegistration();
   ViewFooterElement.tag.ensureRegistration();
   VirtualCollectionElement.tag.ensureRegistration();
   VirtualTreeElement.tag.ensureRegistration();
   VMConnectElement.tag.ensureRegistration();
+  VirtualCollectionElement.tag.ensureRegistration();
+  VirtualTreeElement.tag.ensureRegistration();
   VMConnectTargetElement.tag.ensureRegistration();
 }
diff --git a/runtime/observatory/lib/elements.html b/runtime/observatory/lib/elements.html
index 2b42d47..5c34c60 100644
--- a/runtime/observatory/lib/elements.html
+++ b/runtime/observatory/lib/elements.html
@@ -2,7 +2,7 @@
 <link rel="import" href="src/elements/class_ref_as_value.html">
 <link rel="import" href="src/elements/class_view.html">
 <link rel="import" href="src/elements/code_view.html">
-<link rel="import" href="src/elements/cpu_profile.html">
+<link rel="import" href="src/elements/cpu_profile_table.html">
 <link rel="import" href="src/elements/debugger.html">
 <link rel="import" href="src/elements/error_view.html">
 <link rel="import" href="src/elements/eval_box.html">
@@ -16,7 +16,6 @@
 <link rel="import" href="src/elements/io_view.html">
 <link rel="import" href="src/elements/icdata_view.html">
 <link rel="import" href="src/elements/instructions_view.html">
-<link rel="import" href="src/elements/isolate_reconnect.html">
 <link rel="import" href="src/elements/isolate_summary.html">
 <link rel="import" href="src/elements/isolate_view.html">
 <link rel="import" href="src/elements/json_view.html">
@@ -29,11 +28,11 @@
 <link rel="import" href="src/elements/object_view.html">
 <link rel="import" href="src/elements/objectpool_view.html">
 <link rel="import" href="src/elements/objectstore_view.html">
-<link rel="import" href="src/elements/observatory_application.html">
 <link rel="import" href="src/elements/persistent_handles.html">
 <link rel="import" href="src/elements/ports.html">
 <link rel="import" href="src/elements/script_inset.html">
 <link rel="import" href="src/elements/script_view.html">
 <link rel="import" href="src/elements/service_ref.html">
+<link rel="import" href="src/elements/service_view.html">
 <link rel="import" href="src/elements/timeline_page.html">
 <link rel="import" href="src/elements/vm_view.html">
diff --git a/runtime/observatory/lib/models.dart b/runtime/observatory/lib/models.dart
index ded6d78..943592f 100644
--- a/runtime/observatory/lib/models.dart
+++ b/runtime/observatory/lib/models.dart
@@ -17,11 +17,13 @@
 part 'src/models/objects/flag.dart';
 part 'src/models/objects/frame.dart';
 part 'src/models/objects/function.dart';
+part 'src/models/objects/heap_space.dart';
 part 'src/models/objects/instance.dart';
 part 'src/models/objects/isolate.dart';
 part 'src/models/objects/library.dart';
 part 'src/models/objects/notification.dart';
 part 'src/models/objects/object.dart';
+part 'src/models/objects/sample_profile.dart';
 part 'src/models/objects/script.dart';
 part 'src/models/objects/source_location.dart';
 part 'src/models/objects/target.dart';
@@ -33,5 +35,6 @@
 part 'src/models/repositories/flag.dart';
 part 'src/models/repositories/instance.dart';
 part 'src/models/repositories/notification.dart';
+part 'src/models/repositories/sample_profile.dart';
 part 'src/models/repositories/script.dart';
 part 'src/models/repositories/target.dart';
diff --git a/runtime/observatory/lib/repositories.dart b/runtime/observatory/lib/repositories.dart
index 9f3c340..b3938b1 100644
--- a/runtime/observatory/lib/repositories.dart
+++ b/runtime/observatory/lib/repositories.dart
@@ -7,6 +7,7 @@
 import 'dart:async';
 import 'dart:convert';
 import 'dart:html';
+import 'package:observatory/cpu_profile.dart';
 import 'package:observatory/models.dart' as M;
 import 'package:observatory/service.dart' as S;
 import 'package:observatory/service_common.dart' as SC;
@@ -17,6 +18,7 @@
 part 'src/repositories/flag.dart';
 part 'src/repositories/instance.dart';
 part 'src/repositories/notification.dart';
+part 'src/repositories/sample_profile.dart';
 part 'src/repositories/script.dart';
 part 'src/repositories/settings.dart';
 part 'src/repositories/target.dart';
diff --git a/runtime/observatory/lib/src/app/location_manager.dart b/runtime/observatory/lib/src/app/location_manager.dart
index 64ea764..aadf653 100644
--- a/runtime/observatory/lib/src/app/location_manager.dart
+++ b/runtime/observatory/lib/src/app/location_manager.dart
@@ -98,8 +98,8 @@
                        ? '/vm-connect' : '/isolate-reconnect');
         var parameters = {};
         parameters.addAll(_uri.queryParameters);
-        parameters['originalPath'] = _uri.path;
-        parameters['originalIsolateId'] = parameters['isolateId'];
+        parameters['originalUri'] = _uri.toString();
+        parameters['isolateId'] = parameters['isolateId'];
         var generatedUri = new Uri(path: newPath, queryParameters: parameters);
         go(makeLink(generatedUri.toString()), true);
         return;
diff --git a/runtime/observatory/lib/src/app/page.dart b/runtime/observatory/lib/src/app/page.dart
index 9d624c1..e5d0b1f 100644
--- a/runtime/observatory/lib/src/app/page.dart
+++ b/runtime/observatory/lib/src/app/page.dart
@@ -4,6 +4,9 @@
 
 part of app;
 
+IsolateSampleProfileRepository _isolateSampleProfileRepository
+    = new IsolateSampleProfileRepository();
+
 class IsolateNotFound implements Exception {
   String isolateId;
   IsolateNotFound(this.isolateId);
@@ -47,17 +50,10 @@
   bool canVisit(Uri uri);
 }
 
-/// A [SimplePage] matches a single uri path and displays a single element.
-class SimplePage extends Page {
+/// A [MatchingPage] matches a single uri path.
+abstract class MatchingPage extends Page {
   final String path;
-  final String elementTagName;
-  SimplePage(this.path, this.elementTagName, app) : super(app);
-
-  void onInstall() {
-    if (element == null) {
-      element = new Element.tag(elementTagName);
-    }
-  }
+  MatchingPage(this.path, app) : super(app);
 
   void _visit(Uri uri) {
     assert(uri != null);
@@ -77,6 +73,18 @@
   bool canVisit(Uri uri) => uri.path == path;
 }
 
+/// A [SimplePage] matches a single uri path and displays a single element.
+class SimplePage extends MatchingPage {
+  final String elementTagName;
+  SimplePage(String path, this.elementTagName, app) : super(path, app);
+
+  void onInstall() {
+    if (element == null) {
+      element = new Element.tag(elementTagName);
+    }
+  }
+}
+
 /// Error page for unrecognized paths.
 class ErrorPage extends Page {
   ErrorPage(app) : super(app);
@@ -216,19 +224,28 @@
   }
 }
 
-class CpuProfilerPage extends SimplePage {
-  CpuProfilerPage(app) : super('profiler', 'cpu-profile', app);
+class CpuProfilerPage extends MatchingPage {
+  CpuProfilerPage(app) : super('profiler', app);
+
+  DivElement container = new DivElement();
 
   void _visit(Uri uri) {
     super._visit(uri);
     getIsolate(uri).then((isolate) {
-      if (element != null) {
-        /// Update the page.
-        CpuProfileElement page = element;
-        page.isolate = isolate;
-      }
+      container.children = [
+        new CpuProfileElement(isolate.vm, isolate, app.events,
+                              app.notifications,
+                              _isolateSampleProfileRepository)
+      ];
     });
   }
+
+  void onInstall() {
+    if (element == null) {
+      element = container;
+    }
+    assert(element != null);
+  }
 }
 
 class TableCpuProfilerPage extends SimplePage {
@@ -389,15 +406,19 @@
 class IsolateReconnectPage extends Page {
   IsolateReconnectPage(app) : super(app);
 
+  DivElement container = new DivElement();
+
   void onInstall() {
-    if (element == null) {
-      element = new Element.tag('isolate-reconnect');
-    }
-    assert(element != null);
+    element = container;
   }
 
   void _visit(Uri uri) {
     app.vm.reload();
+    container.children = [
+      new IsolateReconnectElement(app.vm, app.events, app.notifications,
+                                  uri.queryParameters['isolateId'],
+                                  Uri.parse(uri.queryParameters['originalUri']))
+    ];
     assert(element != null);
     assert(canVisit(uri));
   }
diff --git a/runtime/observatory/lib/src/app/view_model.dart b/runtime/observatory/lib/src/app/view_model.dart
index 76033eb..94edb49 100644
--- a/runtime/observatory/lib/src/app/view_model.dart
+++ b/runtime/observatory/lib/src/app/view_model.dart
@@ -4,389 +4,6 @@
 
 part of app;
 
-abstract class VirtualTreeRow {
-  // Number of ems each subtree is indented.
-  static const subtreeIndent = 2.0;
-
-  static const redColor = '#F44336';
-  static const blueColor = '#3F51B5';
-  static const purpleColor = '#673AB7';
-  static const greenColor = '#4CAF50';
-  static const orangeColor = '#FF9800';
-  static const lightGrayColor = '#FAFAFA';
-
-  List backgroundColors = const [
-    purpleColor,
-    redColor,
-    greenColor,
-    blueColor,
-    orangeColor,
-  ];
-
-  final VirtualTree tree;
-  final List<VirtualTreeRow> children = [];
-  final List<StreamSubscription> _listeners = [];
-  final int depth;
-  bool _expanded = false;
-
-  VirtualTreeRow(this.tree, this.depth);
-
-  bool get expanded => _expanded;
-
-  set expanded(bool expanded) {
-    var changed = _expanded != expanded;
-    _expanded = expanded;
-    if (!changed) {
-      return;
-    }
-    if (_expanded) {
-      _expand();
-    } else {
-      _collapse();
-    }
-  }
-
-  Element makeColorBar(int depth) {
-    var element = new SpanElement();
-    element.style.paddingLeft = '2px';
-    element.style.paddingRight = '2px';
-    element.style.flexBasis = '2px';
-    element.style.height = '${tree.rowHeight}px';
-    element.style.minHeight = '${tree.rowHeight}px';
-    if (depth > 0) {
-      var colorIndex = (depth - 1) % backgroundColors.length;
-      element.style.backgroundColor = backgroundColors[colorIndex];
-    }
-    return element;
-  }
-
-  Element makeExpander() {
-    SpanElement element = new SpanElement();
-    element.style.flexBasis = '2em';
-    if (!hasChildren()) {
-      element.style.visibility = 'hidden';
-    } else {
-      element.style.visibility = 'visible';
-      element.children.add(expanded ?
-          new Element.tag('icon-expand-more') :
-          new Element.tag('icon-chevron-right'));
-    }
-    _listeners.add(element.onClick.listen((e) {
-      e.stopPropagation();
-      toggle();
-    }));
-    return element;
-  }
-
-  Element makeIndenter(int depth, {colored: true}) {
-    SpanElement element = new SpanElement();
-    element.style.paddingLeft = '${subtreeIndent * depth}em';
-    element.style.flexBasis = '${subtreeIndent * depth}em';
-    element.style.height = '${tree.rowHeight}px';
-    element.style.minHeight = '${tree.rowHeight}px';
-    if (colored) {
-      if (depth > 0) {
-        var colorIndex = (depth - 1) % backgroundColors.length;
-        element.style.backgroundColor = backgroundColors[colorIndex];
-      }
-    }
-    return element;
-  }
-
-  Element makeText(String text, {String toolTip,
-                                 String flexBasis: '4.5em',
-                                 String cssClass}) {
-    SpanElement element = new SpanElement();
-    element.text = text;
-    if (toolTip != null) {
-      element.title = toolTip;
-    }
-    if (flexBasis != null) {
-      element.style.flexBasis = flexBasis;
-    }
-    if (cssClass != null) {
-      element.classes.add(cssClass);
-    }
-    return element;
-  }
-
-  Element makeGap({double ems: 0.5}) {
-    SpanElement element = new SpanElement();
-    var flexBasis = '${ems}em';
-    element.style.flexBasis = flexBasis;
-    return element;
-  }
-
-  void _cleanupListeners() {
-    for (var listener in _listeners) {
-      listener.cancel();
-    }
-    _listeners.clear();
-  }
-
-  void _expand() {
-    onShow();
-    tree._onExpand(this);
-    if (children.length == 1) {
-      children[0]._expand();
-    }
-    _expanded = true;
-  }
-
-  void _collapse() {
-    _expanded = false;
-    for (var i = 0; i < children.length; i++) {
-      if (children[i].expanded) {
-        children[i]._collapse();
-      }
-    }
-    tree._onCollapse(this);
-  }
-
-  void toggle() {
-    expanded = !expanded;
-  }
-
-  void _render(DivElement rowDiv) {
-    rowDiv.style.display = 'flex';
-    rowDiv.style.alignItems = 'center';
-    _cleanupListeners();
-    onShow();
-    onRender(rowDiv);
-  }
-
-  /// Called when you should render into [rowDiv].
-  void onRender(DivElement rowDiv);
-
-  // Called when this row is visible.
-  void onShow();
-
-  // Return the number of children this node has.
-  int get childCount => 0;
-
-  // Return true if this node can be expanded.
-  bool hasChildren() => childCount > 0;
-
-  // Called when this row is not visible.
-  void onHide() {
-    _cleanupListeners();
-  }
-}
-
-class VirtualTree {
-  final int rowHeight;
-  final List<VirtualTreeRow> rows = [];
-  final DivElement root;
-  final Stopwatch _clock = new Stopwatch();
-
-  DivElement _treeHeightElement;
-  DivElement _tree;
-
-  StreamSubscription _scrollSubscription;
-  StreamSubscription _resizeSubscription;
-
-  // Height of [root] in pixels.
-  int viewHeight;
-
-  // Number of pixels view can be scrolled before a redraw occurs.
-  int redrawThresholdPixels;
-
-  // Number of rows visible at any given time.
-  int numVisibleRows;
-  // Number of rows above the current view that are in the dom.
-  int extraRowsAbove;
-  // Number of rows below the current view that are in the dom.
-  int extraRowsBelow;
-
-  // The scroll top of the last scroll event.
-  int lastPaintScrollTop;
-
-  // The starting row of the last paint.
-  int lastPaintStartingRow = 0;
-
-  bool paintScheduled = false;
-
-  bool scrolled = false;
-
-  static const scrollStopThresholdMilliseconds = 100;
-
-  VirtualTree(this.rowHeight, this.root) {
-    _clock.start();
-    _install();
-    _resize();
-    _schedulePaint(0);
-  }
-
-  void uninstall() => _uninstall();
-
-  void refresh() {
-    _resize();
-    _schedulePaint(lastPaintStartingRow);
-  }
-
-  // Clear the tree.
-  void clear() {
-    rows.clear();
-    _resize();
-  }
-
-  void _onExpand(VirtualTreeRow parent) {
-    int index = rows.indexOf(parent);
-    if (index == -1) {
-      return;
-    }
-    rows.insertAll(index + 1, parent.children);
-    refresh();
-  }
-
-  void _onCollapse(VirtualTreeRow parent) {
-    int index = rows.indexOf(parent);
-    if (index == -1) {
-      return;
-    }
-    int start = index + 1;
-    int end = start + parent.children.length;
-    rows.removeRange(start, end);
-    refresh();
-  }
-
-  void _resize() {
-    if (viewHeight != root.offsetHeight) {
-      viewHeight = root.offsetHeight;
-      numVisibleRows = (viewHeight ~/ rowHeight) + 1;
-      extraRowsAbove = numVisibleRows ~/ 2;
-      extraRowsBelow = numVisibleRows - extraRowsAbove;
-      redrawThresholdPixels =
-          math.min(extraRowsAbove, extraRowsBelow) * rowHeight;
-    }
-    _treeHeightElement.style.height = '${_treeHeight()}px';
-  }
-
-  int _treeHeight() {
-    return rows.length * rowHeight;
-  }
-
-  int _pixelsFromLastScroll(int currentScrollTop) {
-    if (lastPaintScrollTop == null) {
-      return currentScrollTop;
-    }
-
-    return (currentScrollTop - lastPaintScrollTop).abs();
-  }
-
-  int _pixelToRow(int pixelY) {
-    int result = pixelY ~/ rowHeight;
-    return result;
-  }
-
-  void _install() {
-    // This element controls the height of the tree's scrollable region.
-    // It is one pixel wide and the height is set to rowHeight * numRows.
-    _treeHeightElement = new DivElement();
-    _treeHeightElement.style.position = 'absolute';
-    _treeHeightElement.style.top = '0';
-    _treeHeightElement.style.left = '0';
-    _treeHeightElement.style.width = '1px';
-
-    // This element holds the visible tree rows and the height controlling
-    // element. It takes the full width and height of its parent element.
-    _tree = new DivElement();
-    _tree.children.add(_treeHeightElement);
-    _tree.style.width = '100%';
-    _tree.style.height = '100%';
-    _tree.style.position = 'relative';
-    _tree.style.overflow = 'auto';
-
-    // Listen for scroll events on the tree.
-    _scrollSubscription = _tree.onScroll.listen(_onScroll);
-
-    root.children.add(_tree);
-
-    // Listen for resize events.
-    _resizeSubscription = window.onResize.listen((_) {
-      _resize();
-      _schedulePaint(lastPaintStartingRow);
-    });
-  }
-
-  void _uninstall() {
-    root.children.clear();
-    _scrollSubscription?.cancel();
-    _scrollSubscription = null;
-    _resizeSubscription?.cancel();
-    _resizeSubscription = null;
-  }
-
-  void _onScroll(Event scrollEvent) {
-    Element target = scrollEvent.target;
-    int scrollTop = target.scrollTop;
-    if (_pixelsFromLastScroll(scrollTop) > redrawThresholdPixels) {
-      _schedulePaint(lastPaintStartingRow);
-      scrolled = true;
-    }
-    scrollEvent.preventDefault();
-  }
-
-  void _schedulePaint(int startingRow) {
-    if (paintScheduled) {
-      return;
-    }
-    paintScheduled = true;
-    window.requestAnimationFrame(
-        (timestamp) => _onRenderFrame(timestamp, startingRow));
-  }
-
-  void _onRenderFrame(int timestamp, int startingRow) {
-    paintScheduled = false;
-    _paint(startingRow);
-  }
-
-  void _paint(int startingRow) {
-    if (scrolled) {
-      startingRow = math.max(_pixelToRow(_tree.scrollTop), 0);
-      scrolled = false;
-    }
-    lastPaintScrollTop = _tree.scrollTop;
-    lastPaintStartingRow = startingRow;
-
-    int endingRow =
-        math.min(rows.length, startingRow + numVisibleRows + extraRowsBelow);
-
-    startingRow =
-        math.max(0, startingRow - extraRowsAbove);
-
-    print('PAINT $startingRow $endingRow');
-
-    for (int i = startingRow; i < endingRow; i++) {
-      // We add 1 because _tree.children[0] contains the height control element.
-      int cacheIndex = (i - startingRow) + 1;
-      DivElement row;
-      if (cacheIndex < _tree.children.length) {
-        // re-use existing row.
-        row = _tree.children[cacheIndex];
-        row.children.clear();
-      } else {
-        // Allocate a new row.
-        row = new DivElement();
-        row.style.position = 'absolute';
-        row.style.height = '${rowHeight}px';
-        row.style.maxHeight = '${rowHeight}px';
-        row.style.margin = '0';
-        row.style.width = '100%';
-        row.style.left = '0';
-        _tree.children.add(row);
-      }
-      row.style.top = '${(i * rowHeight)}px';
-      // Render the row.
-      rows[i]._render(row);
-    }
-    int necessaryChildren = (endingRow - startingRow) + 1;
-    while (_tree.children.length > necessaryChildren) {
-      _tree.children.removeLast();
-    }
-  }
-}
-
 abstract class TableTreeRow extends Observable {
   static const arrowRight = '\u2192';
   static const arrowDownRight = '\u21b3';
diff --git a/runtime/observatory/lib/src/cpu_profile/cpu_profile.dart b/runtime/observatory/lib/src/cpu_profile/cpu_profile.dart
index a572279..f96f5db 100644
--- a/runtime/observatory/lib/src/cpu_profile/cpu_profile.dart
+++ b/runtime/observatory/lib/src/cpu_profile/cpu_profile.dart
@@ -4,8 +4,9 @@
 
 part of cpu_profiler;
 
-abstract class CallTreeNode {
-  final List<CallTreeNode> children;
+abstract class CallTreeNode<NodeT extends M.CallTreeNode>
+    implements M.CallTreeNode {
+  final List<NodeT> children;
   final int count;
   double get percentage => _percentage;
   double _percentage = 0.0;
@@ -18,7 +19,8 @@
   CallTreeNode(this.children, this.count);
 }
 
-class CodeCallTreeNode extends CallTreeNode {
+class CodeCallTreeNode extends CallTreeNode<CodeCallTreeNode>
+    implements M.CodeCallTreeNode {
   final ProfileCode profileCode;
 
   Object get profileData => profileCode;
@@ -32,14 +34,15 @@
   }
 }
 
-class CallTree {
+class CallTree<NodeT extends CallTreeNode> {
   final bool inclusive;
-  final CallTreeNode root;
+  final NodeT root;
 
   CallTree(this.inclusive, this.root);
 }
 
-class CodeCallTree extends CallTree {
+class CodeCallTree extends CallTree<CodeCallTreeNode>
+    implements M.CodeCallTree {
   CodeCallTree(bool inclusive, CodeCallTreeNode root)
       : super(inclusive, root) {
     _setCodePercentage(null, root);
@@ -305,7 +308,7 @@
   }
 }
 
-class FunctionCallTree extends CallTree {
+class FunctionCallTree extends CallTree implements M.FunctionCallTree {
   FunctionCallTree(bool inclusive, FunctionCallTreeNode root)
       : super(inclusive, root) {
     _setFunctionPercentage(null, root);
@@ -370,7 +373,7 @@
   InlineIntervalTick(this.startAddress);
 }
 
-class ProfileCode {
+class ProfileCode implements M.ProfileCode {
   final CpuProfile profile;
   final Code code;
   int exclusiveTicks;
@@ -488,7 +491,7 @@
   }
 }
 
-class ProfileFunction {
+class ProfileFunction implements M.ProfileFunction {
   final CpuProfile profile;
   final ServiceFunction function;
   // List of compiled code objects containing this function.
@@ -640,9 +643,7 @@
 
 
 // TODO(johnmccutchan): Rename to SampleProfile
-class CpuProfile {
-  final double MICROSECONDS_PER_SECOND = 1000000.0;
-  final double displayThreshold = 0.0002; // 0.02%.
+class CpuProfile extends M.SampleProfile {
 
   Isolate isolate;
 
@@ -660,20 +661,24 @@
   final List<ProfileFunction> functions = new List<ProfileFunction>();
   bool _builtFunctionCalls = false;
 
-  CodeCallTree loadCodeTree(String name) {
-    if (name == 'inclusive') {
-      return _loadCodeTree(true, tries['inclusiveCodeTrie']);
-    } else {
-      return _loadCodeTree(false, tries['exclusiveCodeTrie']);
+  CodeCallTree loadCodeTree(M.ProfileTreeDirection direction) {
+    switch (direction) {
+      case M.ProfileTreeDirection.inclusive:
+        return _loadCodeTree(true, tries['inclusiveCodeTrie']);
+      case M.ProfileTreeDirection.exclusive:
+        return _loadCodeTree(false, tries['exclusiveCodeTrie']);
     }
+    throw new Exception('Unknown ProfileTreeDirection');
   }
 
-  FunctionCallTree loadFunctionTree(String name) {
-    if (name == 'inclusive') {
-      return _loadFunctionTree(true, tries['inclusiveFunctionTrie']);
-    } else {
-      return _loadFunctionTree(false, tries['exclusiveFunctionTrie']);
+  FunctionCallTree loadFunctionTree(M.ProfileTreeDirection direction) {
+    switch (direction) {
+      case M.ProfileTreeDirection.inclusive:
+        return _loadFunctionTree(true, tries['inclusiveFunctionTrie']);
+      case M.ProfileTreeDirection.exclusive:
+        return _loadFunctionTree(false, tries['exclusiveFunctionTrie']);
     }
+    throw new Exception('Unknown ProfileTreeDirection');
   }
 
   buildCodeCallerAndCallees() {
@@ -681,7 +686,7 @@
       return;
     }
     _builtCodeCalls = true;
-    var tree = loadCodeTree('inclusive');
+    var tree = loadCodeTree(M.ProfileTreeDirection.inclusive);
     tree._recordCallerAndCallees();
   }
 
@@ -690,7 +695,7 @@
       return;
     }
     _builtFunctionCalls = true;
-    var tree = loadFunctionTree('inclusive');
+    var tree = loadFunctionTree(M.ProfileTreeDirection.inclusive);
     tree._markFunctionCalls();
   }
 
@@ -707,44 +712,87 @@
     _builtFunctionCalls = false;
   }
 
-  load(Isolate isolate, ServiceMap profile) {
-    clear();
-    if ((isolate == null) || (profile == null)) {
-      return;
-    }
+  Future load(Isolate isolate, ServiceMap profile) async {
+    await loadProgress(isolate, profile).last;
+  }
 
-    this.isolate = isolate;
-    isolate.resetCachedProfileData();
+  static Future sleep([Duration duration = const Duration(microseconds: 0)]) {
+    final Completer completer = new Completer();
+    new Timer(duration, () => completer.complete() );
+    return completer.future;
+  }
 
-    sampleCount = profile['sampleCount'];
-    samplePeriod = profile['samplePeriod'];
-    sampleRate = (MICROSECONDS_PER_SECOND / samplePeriod);
-    stackDepth = profile['stackDepth'];
-    timeSpan = profile['timeSpan'];
+  Stream<double> loadProgress(Isolate isolate, ServiceMap profile) {
+    var progress = new StreamController<double>.broadcast();
 
-    // Process code table.
-    for (var codeRegion in profile['codes']) {
-      Code code = codeRegion['code'];
-      assert(code != null);
-      codes.add(new ProfileCode.fromMap(this, code, codeRegion));
-    }
+    (() async {
+      final Stopwatch watch = new Stopwatch();
+      watch.start();
+      int count = 0;
+      var needToUpdate = () {
+        count++;
+        if (((count % 256) == 0) && (watch.elapsedMilliseconds > 16)) {
+          watch.reset();
+          return true;
+        }
+        return false;
+      };
+      var signal = (double p) {
+        progress.add(p);
+        return sleep();
+      };
+      try {
+        clear();
+        progress.add(0.0);
+        if ((isolate == null) || (profile == null)) {
+          return;
+        }
 
-    // Process function table.
-    for (var profileFunction in profile['functions']) {
-      ServiceFunction function = profileFunction['function'];
-      assert(function != null);
-      functions.add(
-          new ProfileFunction.fromMap(this, function, profileFunction));
-    }
+        this.isolate = isolate;
+        isolate.resetCachedProfileData();
 
-    tries['exclusiveCodeTrie'] =
-        new Uint32List.fromList(profile['exclusiveCodeTrie']);
-    tries['inclusiveCodeTrie'] =
-        new Uint32List.fromList(profile['inclusiveCodeTrie']);
-    tries['exclusiveFunctionTrie'] =
-        new Uint32List.fromList(profile['exclusiveFunctionTrie']);
-    tries['inclusiveFunctionTrie'] =
-        new Uint32List.fromList(profile['inclusiveFunctionTrie']);
+        sampleCount = profile['sampleCount'];
+        samplePeriod = profile['samplePeriod'];
+        sampleRate = (Duration.MICROSECONDS_PER_SECOND / samplePeriod);
+        stackDepth = profile['stackDepth'];
+        timeSpan = profile['timeSpan'];
+
+        num length = profile['codes'].length +
+                        profile['functions'].length;
+
+        // Process code table.
+        for (var codeRegion in profile['codes']) {
+          if (needToUpdate()) {
+            await signal(count * 100.0 / length);
+          }
+          Code code = codeRegion['code'];
+          assert(code != null);
+          codes.add(new ProfileCode.fromMap(this, code, codeRegion));
+        }
+        // Process function table.
+        for (var profileFunction in profile['functions']) {
+          if (needToUpdate()) {
+            await signal(count * 100 / length);
+          }
+          ServiceFunction function = profileFunction['function'];
+          assert(function != null);
+          functions.add(
+              new ProfileFunction.fromMap(this, function, profileFunction));
+        }
+
+        tries['exclusiveCodeTrie'] =
+            new Uint32List.fromList(profile['exclusiveCodeTrie']);
+        tries['inclusiveCodeTrie'] =
+            new Uint32List.fromList(profile['inclusiveCodeTrie']);
+        tries['exclusiveFunctionTrie'] =
+            new Uint32List.fromList(profile['exclusiveFunctionTrie']);
+        tries['inclusiveFunctionTrie'] =
+            new Uint32List.fromList(profile['inclusiveFunctionTrie']);
+      } finally {
+        progress.close();
+      }
+    }());
+    return progress.stream;
   }
 
   // Data shared across calls to _read*TrieNode.
@@ -918,12 +966,10 @@
   }
 
   int approximateMillisecondsForCount(count) {
-    var MICROSECONDS_PER_MILLISECOND = 1000.0;
-    return (count * samplePeriod) ~/ MICROSECONDS_PER_MILLISECOND;
+    return (count * samplePeriod) ~/ Duration.MICROSECONDS_PER_MILLISECOND;
   }
 
   double approximateSecondsForCount(count) {
-    var MICROSECONDS_PER_SECOND = 1000000.0;
-    return (count * samplePeriod) / MICROSECONDS_PER_SECOND;
+    return (count * samplePeriod) / Duration.MICROSECONDS_PER_SECOND;
   }
 }
diff --git a/runtime/observatory/lib/src/elements/class_tree.dart b/runtime/observatory/lib/src/elements/class_tree.dart
index f17f27b..6fefdfd 100644
--- a/runtime/observatory/lib/src/elements/class_tree.dart
+++ b/runtime/observatory/lib/src/elements/class_tree.dart
@@ -147,7 +147,7 @@
     return new DivElement()..classes = ['class-tree-item']
         ..children = [
           new SpanElement()..classes = ['lines'],
-          new SpanElement()..classes = ['expander']
+          new ButtonElement()..classes = ['expander']
             ..onClick.listen((_) => toggle(autoToggleSingleChildNodes: true)),
           new SpanElement()..classes = ['name']
         ];
diff --git a/runtime/observatory/lib/src/elements/class_view.dart b/runtime/observatory/lib/src/elements/class_view.dart
index b1ac3fc..9f860a9 100644
--- a/runtime/observatory/lib/src/elements/class_view.dart
+++ b/runtime/observatory/lib/src/elements/class_view.dart
@@ -6,9 +6,13 @@
 
 import 'dart:async';
 import 'observatory_element.dart';
-import 'package:observatory/cpu_profile.dart';
+import 'sample_buffer_control.dart';
+import 'stack_trace_tree_config.dart';
+import 'cpu_profile/virtual_tree.dart';
 import 'package:observatory/elements.dart';
+import 'package:observatory/models.dart' as M;
 import 'package:observatory/service.dart';
+import 'package:observatory/repositories.dart';
 import 'package:polymer/polymer.dart';
 
 @CustomTag('class-view')
@@ -21,6 +25,8 @@
   SampleBufferControlElement sampleBufferControlElement;
   StackTraceTreeConfigElement stackTraceTreeConfigElement;
   CpuProfileVirtualTreeElement cpuProfileTreeElement;
+  ClassSampleProfileRepository repository = new ClassSampleProfileRepository();
+
 
   ClassViewElement.created() : super.created();
 
@@ -59,66 +65,62 @@
 
   void attached() {
     super.attached();
-    sampleBufferControlElement =
-        shadowRoot.querySelector('#sampleBufferControl');
-    assert(sampleBufferControlElement != null);
-    sampleBufferControlElement.onSampleBufferUpdate = onSampleBufferChange;
-    sampleBufferControlElement.state =
-        SampleBufferControlElement.kNotLoadedState;
-    stackTraceTreeConfigElement =
-        shadowRoot.querySelector('#stackTraceTreeConfig');
-    assert(stackTraceTreeConfigElement != null);
-    stackTraceTreeConfigElement.onTreeConfigChange = onTreeConfigChange;
-    stackTraceTreeConfigElement.show = false;
-    stackTraceTreeConfigElement.showFilter = false;
-    cpuProfileTreeElement = shadowRoot.querySelector('#cpuProfileTree');
-    assert(cpuProfileTreeElement != null);
-    cpuProfileTreeElement.profile = sampleBufferControlElement.profile;
-    cpuProfileTreeElement.show = false;
     cls.fields.forEach((field) => field.reload());
-    sampleBufferControlElement.allocationProfileClass = cls;
   }
 
-  Future refresh() {
+  Future refresh() async {
     instances = null;
     retainedBytes = null;
     mostRetained = null;
-    var loads = [];
-    loads.add(cls.reload());
-    cls.fields.forEach((field) => loads.add(field.reload()));
-    return Future.wait(loads);
+    await cls.reload();
+    await Future.wait(cls.fields.map((field) => field.reload()));
   }
 
-  onSampleBufferChange(CpuProfile sampleBuffer) {
-    stackTraceTreeConfigElement.show = sampleBuffer.sampleCount > 0;
-    cpuProfileTreeElement.show = sampleBuffer.sampleCount > 0;
-    cpuProfileTreeElement.render();
-  }
-
-  onTreeConfigChange(String modeSelector,
-                     String directionSelector,
-                     String filter) {
-    ProfileTreeDirection direction = ProfileTreeDirection.Exclusive;
-    if (directionSelector != 'Up') {
-      direction = ProfileTreeDirection.Inclusive;
-    }
-    ProfileTreeMode mode = ProfileTreeMode.Function;
-    if (modeSelector == 'Code') {
-      mode = ProfileTreeMode.Code;
-    }
-    cpuProfileTreeElement.direction = direction;
-    cpuProfileTreeElement.mode = mode;
-    cpuProfileTreeElement.render();
-  }
+  M.SampleProfileTag _tag = M.SampleProfileTag.none;
 
   Future refreshAllocationProfile() async {
-    return sampleBufferControlElement.reload(cls.isolate);
+    shadowRoot.querySelector('#sampleBufferControl').children = const [];
+    shadowRoot.querySelector('#stackTraceTreeConfig').children = const [];
+    shadowRoot.querySelector('#cpuProfileTree').children = const [];
+    final stream = repository.get(cls, _tag);
+    var progress = (await stream.first).progress;
+    shadowRoot.querySelector('#sampleBufferControl')..children = [
+      new SampleBufferControlElement(progress, stream, queue: app.queue,
+          selectedTag: _tag)
+        ..onTagChange.listen((e) {
+          _tag = e.element.selectedTag;
+          refreshAllocationProfile();
+        })
+    ];
+    if (M.isSampleProcessRunning(progress.status)) {
+      progress = await stream.last;
+    }
+    if (progress.status == M.SampleProfileLoadingStatus.loaded) {
+      shadowRoot.querySelector('#stackTraceTreeConfig')..children = [
+        new StackTraceTreeConfigElement(
+          queue: app.queue)
+          ..showFilter = false
+          ..onModeChange.listen((e) {
+            cpuProfileTreeElement.mode = e.element.mode;
+          })
+          ..onDirectionChange.listen((e) {
+            cpuProfileTreeElement.direction = e.element.direction;
+          })
+      ];
+      shadowRoot.querySelector('#cpuProfileTree')..children = [
+        cpuProfileTreeElement = new CpuProfileVirtualTreeElement(cls.isolate,
+          progress.profile, queue: app.queue)
+      ];
+    }
   }
 
   Future toggleAllocationTrace() {
     if (cls == null) {
       return new Future(refresh);
     }
+    if (cls.traceAllocations) {
+      refreshAllocationProfile();
+    }
     return cls.setTraceAllocations(!cls.traceAllocations).whenComplete(refresh);
   }
 }
diff --git a/runtime/observatory/lib/src/elements/class_view.html b/runtime/observatory/lib/src/elements/class_view.html
index 94efab1..60e9e3e 100644
--- a/runtime/observatory/lib/src/elements/class_view.html
+++ b/runtime/observatory/lib/src/elements/class_view.html
@@ -1,6 +1,5 @@
 <link rel="import" href="../../../../packages/polymer/polymer.html">
 <link rel="import" href="action_link.html">
-<link rel="import" href="cpu_profile.html">
 <link rel="import" href="eval_box.html">
 <link rel="import" href="eval_link.html">
 <link rel="import" href="field_ref.html">
@@ -258,15 +257,11 @@
           </div>
         </template>
       </div>
-      <sample-buffer-control id="sampleBufferControl"></sample-buffer-control>
+      <div id="sampleBufferControl"></div>
       <br>
-      <stack-trace-tree-config id="stackTraceTreeConfig"></stack-trace-tree-config>
+      <div id="stackTraceTreeConfig"></div>
       <br>
-      <div class="flex-row centered">
-        <div class="flex-item-90-percent outlined" style="margin: 16px; margin-left: 8px; margin-right: 8px">
-          <cpu-profile-virtual-tree id="cpuProfileTree"></cpu-profile-virtual-tree>
-        </div>
-      </div>
+      <div id="cpuProfileTree"></div>
     </div>
 
     <div class="content-centered-big">
diff --git a/runtime/observatory/lib/src/elements/cpu_profile.dart b/runtime/observatory/lib/src/elements/cpu_profile.dart
index 82f479d..0b24b07 100644
--- a/runtime/observatory/lib/src/elements/cpu_profile.dart
+++ b/runtime/observatory/lib/src/elements/cpu_profile.dart
@@ -6,1571 +6,168 @@
 
 import 'dart:async';
 import 'dart:html';
-import 'observatory_element.dart';
 import 'package:observatory/models.dart' as M;
-import 'package:observatory/service.dart';
-import 'package:observatory/app.dart';
-import 'package:observatory/cpu_profile.dart';
-import 'package:observatory/elements.dart';
-import 'package:polymer/polymer.dart';
+import 'package:observatory/src/elements/cpu_profile/virtual_tree.dart';
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/helpers/uris.dart';
+import 'package:observatory/src/elements/nav/bar.dart';
+import 'package:observatory/src/elements/nav/isolate_menu.dart';
+import 'package:observatory/src/elements/nav/menu.dart';
+import 'package:observatory/src/elements/nav/notify.dart';
+import 'package:observatory/src/elements/nav/refresh.dart';
+import 'package:observatory/src/elements/nav/top_menu.dart';
+import 'package:observatory/src/elements/nav/vm_menu.dart';
+import 'package:observatory/src/elements/sample_buffer_control.dart';
+import 'package:observatory/src/elements/stack_trace_tree_config.dart';
 
-List<String> sorted(Set<String> attributes) {
-  var list = attributes.toList();
-  list.sort();
-  return list;
-}
+class CpuProfileElement  extends HtmlElement implements Renderable {
+  static const tag = const Tag<CpuProfileElement>('cpu-profile',
+                                            dependencies: const [
+                                              NavBarElement.tag,
+                                              NavTopMenuElement.tag,
+                                              NavVMMenuElement.tag,
+                                              NavIsolateMenuElement.tag,
+                                              NavMenuElement.tag,
+                                              NavMenuElement.tag,
+                                              NavRefreshElement.tag,
+                                              NavNotifyElement.tag,
+                                              SampleBufferControlElement.tag,
+                                              StackTraceTreeConfigElement.tag,
+                                              CpuProfileVirtualTreeElement.tag,
+                                            ]);
 
-abstract class ProfileTreeRow<T> extends TableTreeRow {
-  final CpuProfile profile;
-  final T node;
-  final String selfPercent;
-  final String percent;
-  bool _infoBoxShown = false;
-  HtmlElement infoBox;
-  HtmlElement infoButton;
+  RenderingScheduler<CpuProfileElement> _r;
 
-  ProfileTreeRow(TableTree tree, TableTreeRow parent,
-                 this.profile, this.node, double selfPercent, double percent)
-      : super(tree, parent),
-        selfPercent = Utils.formatPercentNormalized(selfPercent),
-        percent = Utils.formatPercentNormalized(percent);
+  Stream<RenderedEvent<CpuProfileElement>> get onRendered => _r.onRendered;
 
-  static _addToMemberList(DivElement memberList, Map<String, String> items) {
-    items.forEach((k, v) {
-      var item = new DivElement();
-      item.classes.add('memberItem');
-      var name = new DivElement();
-      name.classes.add('memberName');
-      name.text = k;
-      var value = new DivElement();
-      value.classes.add('memberValue');
-      value.text = v;
-      item.children.add(name);
-      item.children.add(value);
-      memberList.children.add(item);
-    });
+  M.VM _vm;
+  M.IsolateRef _isolate;
+  M.EventRepository _events;
+  M.NotificationRepository _notifications;
+  M.IsolateSampleProfileRepository _profiles;
+  Stream<M.SampleProfileLoadingProgressEvent> _progressStream;
+  M.SampleProfileLoadingProgress _progress;
+  M.SampleProfileTag _tag = M.SampleProfileTag.none;
+  ProfileTreeMode _mode = ProfileTreeMode.function;
+  M.ProfileTreeDirection _direction = M.ProfileTreeDirection.exclusive;
+  String _filter = '';
+
+
+  M.IsolateRef get isolate => _isolate;
+  M.NotificationRepository get notifications => _notifications;
+  M.IsolateSampleProfileRepository get profiles => _profiles;
+  M.VMRef get vm => _vm;
+
+  factory CpuProfileElement(M.VM vm, M.IsolateRef isolate,
+                            M.EventRepository events,
+                            M.NotificationRepository notifications,
+                            M.IsolateSampleProfileRepository profiles,
+                            {RenderingQueue queue}) {
+    assert(vm != null);
+    assert(isolate != null);
+    assert(events != null);
+    assert(notifications != null);
+    assert(profiles != null);
+    CpuProfileElement e = document.createElement(tag.name);
+    e._r = new RenderingScheduler(e, queue: queue);
+    e._vm = vm;
+    e._isolate = isolate;
+    e._events = events;
+    e._notifications = notifications;
+    e._profiles = profiles;
+    return e;
   }
 
-  makeInfoBox() {
-    if (infoBox != null) {
-      return;
-    }
-    infoBox = new DivElement();
-    infoBox.classes.add('infoBox');
-    infoBox.classes.add('shadow');
-    infoBox.style.display = 'none';
-    listeners.add(infoBox.onClick.listen((e) => e.stopPropagation()));
-  }
-
-  makeInfoButton() {
-    infoButton = new SpanElement();
-    infoButton.style.marginLeft = 'auto';
-    infoButton.style.marginRight = '1em';
-    infoButton.children.add(new Element.tag('icon-info-outline'));
-    listeners.add(infoButton.onClick.listen((event) {
-      event.stopPropagation();
-      toggleInfoBox();
-    }));
-  }
-
-  static const attributes = const {
-    'optimized' : const ['O', null, 'Optimized'],
-    'unoptimized' : const ['U', null, 'Unoptimized'],
-    'inlined' : const ['I', null, 'Inlined'],
-    'intrinsic' : const ['It', null, 'Intrinsic'],
-    'ffi' : const ['F', null, 'FFI'],
-    'dart' : const ['D', null, 'Dart'],
-    'tag' : const ['T', null, 'Tag'],
-    'native' : const ['N', null, 'Native'],
-    'stub': const ['S', null, 'Stub'],
-    'synthetic' : const ['?', null, 'Synthetic'],
-  };
-
-  HtmlElement newAttributeBox(String attribute) {
-    List attributeDetails = attributes[attribute];
-    if (attributeDetails == null) {
-      print('could not find attribute $attribute');
-      return null;
-    }
-    var element = new SpanElement();
-    element.style.border = 'solid 2px #ECECEC';
-    element.style.height = '100%';
-    element.style.display = 'inline-block';
-    element.style.textAlign = 'center';
-    element.style.minWidth = '1.5em';
-    element.style.fontWeight = 'bold';
-    if (attributeDetails[1] != null) {
-      element.style.backgroundColor = attributeDetails[1];
-    }
-    element.text = attributeDetails[0];
-    element.title = attributeDetails[2];
-    return element;
-  }
-
-  onHide() {
-    super.onHide();
-    infoBox = null;
-    infoButton = null;
-  }
-
-  showInfoBox() {
-    if ((infoButton == null) || (infoBox == null)) {
-      return;
-    }
-    _infoBoxShown = true;
-    infoBox.style.display = 'block';
-    infoButton.children.clear();
-    infoButton.children.add(new Element.tag('icon-info'));
-  }
-
-  hideInfoBox() {
-    _infoBoxShown = false;
-    if ((infoButton == null) || (infoBox == null)) {
-      return;
-    }
-    infoBox.style.display = 'none';
-    infoButton.children.clear();
-    infoButton.children.add(new Element.tag('icon-info-outline'));
-  }
-
-  toggleInfoBox() {
-   if (_infoBoxShown) {
-     hideInfoBox();
-   } else {
-     showInfoBox();
-   }
-  }
-
-  hideAllInfoBoxes() {
-    final List<ProfileTreeRow> rows = tree.rows;
-    for (var row in rows) {
-      row.hideInfoBox();
-    }
-  }
-
-  onClick(MouseEvent e) {
-    e.stopPropagation();
-    if (e.altKey) {
-      bool show = !_infoBoxShown;
-      hideAllInfoBoxes();
-      if (show) {
-        showInfoBox();
-      }
-      return;
-    }
-    super.onClick(e);
-  }
-
-  HtmlElement newCodeRef(ProfileCode code) {
-    var codeRef = new Element.tag('code-ref');
-    codeRef.ref = code.code;
-    return codeRef;
-  }
-
-  HtmlElement newFunctionRef(ProfileFunction function) {
-    var ref = new Element.tag('function-ref');
-    ref.ref = function.function;
-    return ref;
-  }
-
-  HtmlElement hr() {
-    var element = new HRElement();
-    return element;
-  }
-
-  HtmlElement div(String text) {
-    var element = new DivElement();
-    element.text = text;
-    return element;
-  }
-
-  HtmlElement br() {
-    return new BRElement();
-  }
-
-  HtmlElement span(String text) {
-    var element = new SpanElement();
-    element.style.minWidth = '1em';
-    element.text = text;
-    return element;
-  }
-}
-
-class CodeProfileTreeRow extends ProfileTreeRow<CodeCallTreeNode> {
-  CodeProfileTreeRow(TableTree tree, CodeProfileTreeRow parent,
-                     CpuProfile profile, CodeCallTreeNode node)
-      : super(tree, parent, profile, node,
-              node.profileCode.normalizedExclusiveTicks,
-              node.percentage) {
-    // fill out attributes.
-  }
-
-  bool hasChildren() => node.children.length > 0;
-
-  void onShow() {
-    super.onShow();
-
-    if (children.length == 0) {
-      for (var childNode in node.children) {
-        var row = new CodeProfileTreeRow(tree, this, profile, childNode);
-        children.add(row);
-      }
-    }
-
-    // Fill in method column.
-    var methodColumn = flexColumns[0];
-    methodColumn.style.justifyContent = 'flex-start';
-    methodColumn.style.position = 'relative';
-
-    // Percent.
-    var percentNode = new DivElement();
-    percentNode.text = percent;
-    percentNode.style.minWidth = '5em';
-    percentNode.style.textAlign = 'right';
-    percentNode.title = 'Executing: $selfPercent';
-    methodColumn.children.add(percentNode);
-
-    // Gap.
-    var gap = new SpanElement();
-    gap.style.minWidth = '1em';
-    methodColumn.children.add(gap);
-
-    // Code link.
-    var codeRef = newCodeRef(node.profileCode);
-    codeRef.style.alignSelf = 'center';
-    methodColumn.children.add(codeRef);
-
-    gap = new SpanElement();
-    gap.style.minWidth = '1em';
-    methodColumn.children.add(gap);
-
-    for (var attribute in sorted(node.attributes)) {
-      methodColumn.children.add(newAttributeBox(attribute));
-    }
-
-    makeInfoBox();
-    methodColumn.children.add(infoBox);
-
-    infoBox.children.add(span('Code '));
-    infoBox.children.add(newCodeRef(node.profileCode));
-    infoBox.children.add(span(' '));
-    for (var attribute in sorted(node.profileCode.attributes)) {
-      infoBox.children.add(newAttributeBox(attribute));
-    }
-    infoBox.children.add(br());
-    infoBox.children.add(br());
-    var memberList = new DivElement();
-    memberList.classes.add('memberList');
-    infoBox.children.add(br());
-    infoBox.children.add(memberList);
-    ProfileTreeRow._addToMemberList(memberList, {
-        'Exclusive ticks' : node.profileCode.formattedExclusiveTicks,
-        'Cpu time' : node.profileCode.formattedCpuTime,
-        'Inclusive ticks' : node.profileCode.formattedInclusiveTicks,
-        'Call stack time' : node.profileCode.formattedOnStackTime,
-    });
-
-    makeInfoButton();
-    methodColumn.children.add(infoButton);
-
-    // Fill in self column.
-    var selfColumn = flexColumns[1];
-    selfColumn.style.position = 'relative';
-    selfColumn.style.alignItems = 'center';
-    selfColumn.text = selfPercent;
-  }
-}
-
-class FunctionProfileTreeRow extends ProfileTreeRow<FunctionCallTreeNode> {
-  FunctionProfileTreeRow(TableTree tree, FunctionProfileTreeRow parent,
-                         CpuProfile profile, FunctionCallTreeNode node)
-      : super(tree, parent, profile, node,
-              node.profileFunction.normalizedExclusiveTicks,
-              node.percentage) {
-    // fill out attributes.
-  }
-
-  bool hasChildren() => node.children.length > 0;
-
-  onShow() {
-    super.onShow();
-    if (children.length == 0) {
-      for (var childNode in node.children) {
-        var row = new FunctionProfileTreeRow(tree, this, profile, childNode);
-        children.add(row);
-      }
-    }
-
-    var methodColumn = flexColumns[0];
-    methodColumn.style.justifyContent = 'flex-start';
-
-    var codeAndFunctionColumn = new DivElement();
-    codeAndFunctionColumn.classes.add('flex-column');
-    codeAndFunctionColumn.style.justifyContent = 'center';
-    codeAndFunctionColumn.style.width = '100%';
-    methodColumn.children.add(codeAndFunctionColumn);
-
-    var functionRow = new DivElement();
-    functionRow.classes.add('flex-row');
-    functionRow.style.position = 'relative';
-    functionRow.style.justifyContent = 'flex-start';
-    codeAndFunctionColumn.children.add(functionRow);
-
-    // Insert the parent percentage
-    var parentPercent = new SpanElement();
-    parentPercent.text = percent;
-    parentPercent.style.minWidth = '4em';
-    parentPercent.style.alignSelf = 'center';
-    parentPercent.style.textAlign = 'right';
-    parentPercent.title = 'Executing: $selfPercent';
-    functionRow.children.add(parentPercent);
-
-    // Gap.
-    var gap = new SpanElement();
-    gap.style.minWidth = '1em';
-    gap.text = ' ';
-    functionRow.children.add(gap);
-
-    var functionRef = new Element.tag('function-ref');
-    functionRef.ref = node.profileFunction.function;
-    functionRef.style.alignSelf = 'center';
-    functionRow.children.add(functionRef);
-
-    gap = new SpanElement();
-    gap.style.minWidth = '1em';
-    gap.text = ' ';
-    functionRow.children.add(gap);
-
-    for (var attribute in sorted(node.attributes)) {
-      functionRow.children.add(newAttributeBox(attribute));
-    }
-
-    makeInfoBox();
-    functionRow.children.add(infoBox);
-
-    if (M.hasDartCode(node.profileFunction.function.kind)) {
-      infoBox.children.add(div('Code for current node'));
-      infoBox.children.add(br());
-      var totalTicks = node.totalCodesTicks;
-      var numCodes = node.codes.length;
-      for (var i = 0; i < numCodes; i++) {
-        var codeRowSpan = new DivElement();
-        codeRowSpan.style.paddingLeft = '1em';
-        infoBox.children.add(codeRowSpan);
-        var nodeCode = node.codes[i];
-        var ticks = nodeCode.ticks;
-        var percentage = Utils.formatPercent(ticks, totalTicks);
-        var percentageSpan = new SpanElement();
-        percentageSpan.style.display = 'inline-block';
-        percentageSpan.text = '$percentage';
-        percentageSpan.style.minWidth = '5em';
-        percentageSpan.style.textAlign = 'right';
-        codeRowSpan.children.add(percentageSpan);
-        var codeRef = new Element.tag('code-ref');
-        codeRef.ref = nodeCode.code.code;
-        codeRef.style.marginLeft = '1em';
-        codeRef.style.marginRight = 'auto';
-        codeRef.style.width = '100%';
-        codeRowSpan.children.add(codeRef);
-      }
-      infoBox.children.add(hr());
-    }
-    infoBox.children.add(span('Function '));
-    infoBox.children.add(newFunctionRef(node.profileFunction));
-    infoBox.children.add(span(' '));
-    for (var attribute in sorted(node.profileFunction.attributes)) {
-      infoBox.children.add(newAttributeBox(attribute));
-    }
-    var memberList = new DivElement();
-    memberList.classes.add('memberList');
-    infoBox.children.add(br());
-    infoBox.children.add(br());
-    infoBox.children.add(memberList);
-    infoBox.children.add(br());
-    ProfileTreeRow._addToMemberList(memberList, {
-        'Exclusive ticks' : node.profileFunction.formattedExclusiveTicks,
-        'Cpu time' : node.profileFunction.formattedCpuTime,
-        'Inclusive ticks' : node.profileFunction.formattedInclusiveTicks,
-        'Call stack time' : node.profileFunction.formattedOnStackTime,
-    });
-
-    if (M.hasDartCode(node.profileFunction.function.kind)) {
-      infoBox.children.add(div('Code containing function'));
-      infoBox.children.add(br());
-      var totalTicks = profile.sampleCount;
-      var codes = node.profileFunction.profileCodes;
-      var numCodes = codes.length;
-      for (var i = 0; i < numCodes; i++) {
-        var codeRowSpan = new DivElement();
-        codeRowSpan.style.paddingLeft = '1em';
-        infoBox.children.add(codeRowSpan);
-        var profileCode = codes[i];
-        var code = profileCode.code;
-        var ticks = profileCode.inclusiveTicks;
-        var percentage = Utils.formatPercent(ticks, totalTicks);
-        var percentageSpan = new SpanElement();
-        percentageSpan.style.display = 'inline-block';
-        percentageSpan.text = '$percentage';
-        percentageSpan.style.minWidth = '5em';
-        percentageSpan.style.textAlign = 'right';
-        percentageSpan.title = 'Inclusive ticks';
-        codeRowSpan.children.add(percentageSpan);
-        var codeRef = new Element.tag('code-ref');
-        codeRef.ref = code;
-        codeRef.style.marginLeft = '1em';
-        codeRef.style.marginRight = 'auto';
-        codeRef.style.width = '100%';
-        codeRowSpan.children.add(codeRef);
-      }
-    }
-
-    makeInfoButton();
-    methodColumn.children.add(infoButton);
-
-    // Fill in self column.
-    var selfColumn = flexColumns[1];
-    selfColumn.style.position = 'relative';
-    selfColumn.style.alignItems = 'center';
-    selfColumn.text = selfPercent;
-  }
-}
-
-@CustomTag('sample-buffer-control')
-class SampleBufferControlElement extends ObservatoryElement {
-  SampleBufferControlElement.created() : super.created() {
-    _stopWatch.start();
-  }
-
-  Future<CpuProfile> reload(Isolate isolate) async {
-    profile.clear();
-    if (isolate == null) {
-      _update(profile);
-      // Notify listener.
-      onSampleBufferUpdate(profile);
-      return profile;
-    }
-    profileVM = isolate.vm.profileVM;
-    if (tagSelector == null) {
-      // Set default value.
-      tagSelector = profileVM ? 'UserVM' : 'None';
-    }
-    await _changeState(kFetchingState);
-    try {
-      var response;
-      if (allocationProfileClass != null) {
-        response =
-            await allocationProfileClass.getAllocationSamples(tagSelector);
-      } else {
-        var params = { 'tags': tagSelector };
-        response = await isolate.invokeRpc('_getCpuProfile', params);
-      }
-      await _changeState(kLoadingState);
-      profile.load(isolate, response);
-      profile.buildFunctionCallerAndCallees();
-      _update(profile);
-      await _changeState(kLoadedState);
-      // Notify listener.
-      onSampleBufferUpdate(profile);
-      return profile;
-    } catch (e, st) {
-      if (e is ServerRpcException) {
-        ServerRpcException se = e;
-        if (se.code == ServerRpcException.kFeatureDisabled) {
-          await _changeState(kDisabledState);
-          return profile;
-        }
-      }
-      await _changeState(kExceptionState, e, st);
-      rethrow;
-    }
-  }
-
-  Future _changeState(String newState, [exception, stackTrace]) {
-    if ((newState == kDisabledState) ||
-        (newState == kFetchingState) ||
-        (newState == kExceptionState)) {
-      loadTime = '';
-      fetchTime = '';
-    } else if (newState == kLoadingState) {
-      fetchTime = formatTimeMilliseconds(_stopWatch.elapsedMilliseconds);
-      loadTime = '';
-    } else if (newState == kLoadedState) {
-      loadTime = formatTimeMilliseconds(_stopWatch.elapsedMilliseconds);
-    }
-    state = newState;
-    this.exception = exception;
-    this.stackTrace = stackTrace;
-    _stopWatch.reset();
-    return window.animationFrame;
-  }
-
-  _update(CpuProfile sampleBuffer) {
-    sampleCount = profile.sampleCount.toString();
-    refreshTime = new DateTime.now().toString();
-    stackDepth = profile.stackDepth.toString();
-    sampleRate = profile.sampleRate.toStringAsFixed(0);
-    if (profile.sampleCount == 0) {
-      timeSpan = '0s';
-    } else {
-      timeSpan = formatTime(profile.timeSpan);
-    }
-  }
-
-  void tagSelectorChanged(oldValue) {
-    reload(profile.isolate);
-  }
-
-  Function onSampleBufferUpdate;
-  @observable bool showTagSelector = true;
-  @observable bool profileVM = false;
-  @observable String sampleCount = '';
-  @observable String refreshTime = '';
-  @observable String sampleRate = '';
-  @observable String stackDepth = '';
-  @observable String timeSpan = '';
-  @observable String fetchTime = '';
-  @observable String loadTime = '';
-  @observable String tagSelector;
-  @observable String state = kFetchingState;
-  @observable var exception;
-  @observable var stackTrace;
-
-  static const kDisabledState = 'kDisabled';
-  static const kExceptionState = 'Exception';
-  static const kFetchingState = 'kFetching';
-  static const kLoadedState = 'kLoaded';
-  static const kLoadingState = 'kLoading';
-  static const kNotLoadedState = 'kNotLoaded';
-
-  Isolate isolate;
-  Class allocationProfileClass;
-
-  final CpuProfile profile = new CpuProfile();
-  final Stopwatch _stopWatch = new Stopwatch();
-}
-
-@CustomTag('stack-trace-tree-config')
-class StackTraceTreeConfigElement extends ObservatoryElement {
-  StackTraceTreeConfigElement.created() : super.created();
-
-  attached() {
-    super.attached();
-    var filterElement = shadowRoot.querySelector('#filterInput');
-    keyDownSubscription = filterElement.onKeyDown.listen(_onKeyDown);
-    blurSubscription = filterElement.onBlur.listen(_onBlur);
-  }
-
-  detached() {
-    super.detached();
-    keyDownSubscription?.cancel();
-    blurSubscription?.cancel();
-  }
-
-  void _onKeyDown(KeyboardEvent keyEvent) {
-    if (keyEvent.keyCode == 13) {
-      // On enter, update the filter string.
-      filterString =
-          (shadowRoot.querySelector('#filterInput') as InputElement).value;
-      if (onTreeConfigChange == null) {
-        return;
-      }
-      onTreeConfigChange(modeSelector, directionSelector, filterString);
-    }
-  }
-
-  void _onBlur(Event event) {
-    // Input box has lost focus, update the display to match the active
-    // filter string.
-    (shadowRoot.querySelector('#filterInput') as InputElement).value =
-        filterString;
-  }
-
-  void modeSelectorChanged(oldValue) {
-    if (onTreeConfigChange == null) {
-      return;
-    }
-    onTreeConfigChange(modeSelector, directionSelector, filterString);
-  }
-
-  void directionSelectorChanged(oldValue) {
-    if (onTreeConfigChange == null) {
-      return;
-    }
-    onTreeConfigChange(modeSelector, directionSelector, filterString);
-  }
-
-  Function onTreeConfigChange;
-  StreamSubscription keyDownSubscription;
-  StreamSubscription blurSubscription;
-  @observable bool show = true;
-  @observable bool showModeSelector = true;
-  @observable bool showDirectionSelector = true;
-  @observable bool showFilter = true;
-  @observable String modeSelector = 'Function';
-  @observable String directionSelector = 'Up';
-  @observable String filterString;
-}
-
-class FunctionCallTreeNodeRow extends VirtualTreeRow {
-  final CpuProfile profile;
-  final FunctionCallTreeNode node;
-  String selfPercent;
-  String totalPercent;
-  String percent;
-
-  static const kHotThreshold = 0.05;  // 5%.
-  static const kMediumThreshold = 0.02;  // 2%.
-
-  double _percent(bool self) {
-    if (self) {
-      return node.profileFunction.normalizedExclusiveTicks;
-    } else {
-      return node.profileFunction.normalizedInclusiveTicks;
-    }
-  }
-
-  bool isHot(bool self) => _percent(self) > kHotThreshold;
-  bool isMedium(bool self) => _percent(self) > kMediumThreshold;
-
-  String rowClass(bool self) {
-    if (isHot(self)) {
-      return 'hotProfile';
-    } else if (isMedium(self)) {
-      return 'mediumProfile';
-    } else {
-      return 'coldProfile';
-    }
-  }
-
-  FunctionCallTreeNodeRow(VirtualTree tree,
-                          int depth,
-                          this.profile,
-                          FunctionCallTreeNode node)
-      : node = node,
-        super(tree, depth) {
-    if ((node.profileFunction.function.kind == M.FunctionKind.tag) &&
-        (node.profileFunction.normalizedExclusiveTicks == 0) &&
-        (node.profileFunction.normalizedInclusiveTicks == 0)) {
-    selfPercent = '';
-    totalPercent = '';
-    } else {
-      selfPercent = Utils.formatPercentNormalized(
-          node.profileFunction.normalizedExclusiveTicks);
-      totalPercent = Utils.formatPercentNormalized(
-          node.profileFunction.normalizedInclusiveTicks);
-    }
-    percent = Utils.formatPercentNormalized(node.percentage);
-  }
-
-  void onRender(DivElement rowDiv) {
-    rowDiv.children.add(makeGap(ems:0.1));
-    rowDiv.children.add(
-        makeText(totalPercent,
-                 toolTip: 'global % on stack'));
-    rowDiv.children.add(makeGap());
-    rowDiv.children.add(
-        makeText(selfPercent,
-                 toolTip: 'global % executing'));
-    rowDiv.children.add(makeGap());
-    rowDiv.children.add(makeIndenter(depth, colored: false));
-    rowDiv.children.add(makeColorBar(depth));
-    rowDiv.children.add(makeGap(ems: 1.0));
-    rowDiv.children.add(makeExpander());
-    rowDiv.children.add(
-        makeText(percent, toolTip: 'tree node %', flexBasis: null));
-    rowDiv.children.add(makeGap(ems: 0.5));
-    functionRef.ref = node.profileFunction.function;
-    rowDiv.children.add(functionRef);
-  }
-
-  var functionRef = new Element.tag('function-ref');
-
-  int get childCount => node.children.length;
-
-  void onShow() {
-    if (children.length > 0) {
-      return;
-    }
-    for (var childNode in node.children) {
-      var row = new FunctionCallTreeNodeRow(tree, depth + 1, profile, childNode);
-      children.add(row);
-    }
-  }
-}
-
-
-class CodeCallTreeNodeRow extends VirtualTreeRow {
-  final CpuProfile profile;
-  final CodeCallTreeNode node;
-  String selfPercent;
-  String totalPercent;
-  String percent;
-
-  static const kHotThreshold = 0.05;  // 5%.
-  static const kMediumThreshold = 0.02;  // 2%.
-
-  double _percent(bool self) {
-    if (self) {
-      return node.profileCode.normalizedExclusiveTicks;
-    } else {
-      return node.profileCode.normalizedInclusiveTicks;
-    }
-  }
-
-  bool isHot(bool self) => _percent(self) > kHotThreshold;
-  bool isMedium(bool self) => _percent(self) > kMediumThreshold;
-
-  String rowClass(bool self) {
-    if (isHot(self)) {
-      return 'hotProfile';
-    } else if (isMedium(self)) {
-      return 'mediumProfile';
-    } else {
-      return 'coldProfile';
-    }
-  }
-
-  CodeCallTreeNodeRow(VirtualTree tree,
-                      int depth,
-                      this.profile,
-                      CodeCallTreeNode node)
-      : node = node,
-        super(tree, depth) {
-    if ((node.profileCode.code.kind == M.CodeKind.tag) &&
-        (node.profileCode.normalizedExclusiveTicks == 0) &&
-        (node.profileCode.normalizedInclusiveTicks == 0)) {
-      selfPercent = '';
-      totalPercent = '';
-    } else {
-      selfPercent = Utils.formatPercentNormalized(
-          node.profileCode.normalizedExclusiveTicks);
-      totalPercent = Utils.formatPercentNormalized(
-          node.profileCode.normalizedInclusiveTicks);
-    }
-    percent = Utils.formatPercentNormalized(node.percentage);
-  }
-
-  void onRender(DivElement rowDiv) {
-    rowDiv.children.add(makeGap(ems:0.1));
-    rowDiv.children.add(
-        makeText(totalPercent,
-                 toolTip: 'global % on stack'));
-    rowDiv.children.add(makeGap());
-    rowDiv.children.add(
-        makeText(selfPercent,
-                 toolTip: 'global % executing'));
-    rowDiv.children.add(makeGap());
-    rowDiv.children.add(makeIndenter(depth, colored: false));
-    rowDiv.children.add(makeColorBar(depth));
-    rowDiv.children.add(makeGap(ems: 1.0));
-    rowDiv.children.add(makeExpander());
-    rowDiv.children.add(
-        makeText(percent, toolTip: 'tree node %', flexBasis: null));
-    rowDiv.children.add(makeGap(ems: 0.5));
-    codeRef.ref = node.profileCode.code;
-    rowDiv.children.add(codeRef);
-  }
-
-  var codeRef = new Element.tag('code-ref');
-
-  int get childCount => node.children.length;
-
-  void onShow() {
-    if (children.length > 0) {
-      return;
-    }
-    for (var childNode in node.children) {
-      var row = new CodeCallTreeNodeRow(tree, depth + 1, profile, childNode);
-      children.add(row);
-    }
-  }
-}
-
-/// Displays a CpuProfile
-@CustomTag('cpu-profile')
-class CpuProfileElement extends ObservatoryElement {
-  CpuProfileElement.created() : super.created() {
-    _updateTask = new Task(update);
-    _renderTask = new Task(render);
-  }
-
-  attached() {
-    super.attached();
-    sampleBufferControlElement =
-        shadowRoot.querySelector('#sampleBufferControl');
-    assert(sampleBufferControlElement != null);
-    sampleBufferControlElement.onSampleBufferUpdate = onSampleBufferChange;
-    stackTraceTreeConfigElement =
-        shadowRoot.querySelector('#stackTraceTreeConfig');
-    assert(stackTraceTreeConfigElement != null);
-    stackTraceTreeConfigElement.onTreeConfigChange = onTreeConfigChange;
-    cpuProfileVirtualTreeElement = shadowRoot.querySelector('#cpuProfileVirtualTree');
-    assert(cpuProfileVirtualTreeElement != null);
-    cpuProfileVirtualTreeElement.profile = sampleBufferControlElement.profile;
-    _resizeSubscription = window.onResize.listen((_) => _updateSize());
-    _updateTask.queue();
-    _updateSize();
-  }
-
-  detached() {
-    super.detached();
-    if (_resizeSubscription != null) {
-      _resizeSubscription.cancel();
-    }
-  }
-
-  _updateSize() {
-    var applySize = (e) {
-      Rectangle rect = e.getBoundingClientRect();
-      final totalHeight = window.innerHeight;
-      final bottomMargin = 200;
-      final mainHeight = totalHeight - bottomMargin;
-      e.style.setProperty('height', '${mainHeight}px');
-    };
-    HtmlElement e2 = $['cpuProfileVirtualTree'];
-    applySize(e2);
-  }
-
-  isolateChanged(oldValue) {
-    _updateTask.queue();
-  }
-
-  update() {
-    if (sampleBufferControlElement != null) {
-      sampleBufferControlElement.reload(isolate);
-    }
-  }
-
-  onSampleBufferChange(CpuProfile sampleBuffer) {
-    _renderTask.queue();
-  }
-
-  onTreeConfigChange(String modeSelector,
-                     String directionSelector,
-                     String filterString) {
-    ProfileTreeDirection direction = ProfileTreeDirection.Exclusive;
-    if (directionSelector != 'Up') {
-      direction = ProfileTreeDirection.Inclusive;
-    }
-    ProfileTreeMode mode = ProfileTreeMode.Function;
-    if (modeSelector == 'Code') {
-      mode = ProfileTreeMode.Code;
-    }
-    // Clear the filter.
-    cpuProfileVirtualTreeElement.filter = null;
-    if (filterString != null) {
-      filterString = filterString.trim();
-      if (filterString.isNotEmpty) {
-        cpuProfileVirtualTreeElement.filter = (CallTreeNode node) {
-          return node.name.contains(filterString);
-        };
-      }
-    }
-    cpuProfileVirtualTreeElement.direction = direction;
-    cpuProfileVirtualTreeElement.mode = mode;
-    _renderTask.queue();
-  }
-
-  Future clearCpuProfile() async {
-    await isolate.invokeRpc('_clearCpuProfile', { });
-    _updateTask.queue();
-    return new Future.value(null);
-  }
-
-  Future refresh() {
-    _updateTask.queue();
-    return new Future.value(null);
-  }
-
-  render() {
-    cpuProfileVirtualTreeElement.render();
-  }
-
-  @published Isolate isolate;
-
-  StreamSubscription _resizeSubscription;
-  Task _updateTask;
-  Task _renderTask;
-  SampleBufferControlElement sampleBufferControlElement;
-  StackTraceTreeConfigElement stackTraceTreeConfigElement;
-  CpuProfileVirtualTreeElement cpuProfileVirtualTreeElement;
-}
+  CpuProfileElement.created() : super.created();
 
-class NameSortedTable extends SortedTable {
-  NameSortedTable(columns) : super(columns);
   @override
-  dynamic getSortKeyFor(int row, int col) {
-    if (col == FUNCTION_COLUMN) {
-      // Use name as sort key.
-      return rows[row].values[col].name;
-    }
-    return super.getSortKeyFor(row, col);
-  }
-
-  SortedTableRow rowFromIndex(int tableIndex) {
-    final modelIndex = sortedRows[tableIndex];
-    return rows[modelIndex];
-  }
-
-  static const FUNCTION_SPACER_COLUMNS = const [];
-  static const FUNCTION_COLUMN = 2;
-  TableRowElement _makeFunctionRow() {
-    var tr = new TableRowElement();
-    var cell;
-
-    // Add percentage.
-    cell = tr.insertCell(-1);
-    cell = tr.insertCell(-1);
-
-    // Add function ref.
-    cell = tr.insertCell(-1);
-    var functionRef = new Element.tag('function-ref');
-    cell.children.add(functionRef);
-
-    return tr;
-  }
-
-  static const CALL_SPACER_COLUMNS = const [];
-  static const CALL_FUNCTION_COLUMN = 1;
-  TableRowElement _makeCallRow() {
-    var tr = new TableRowElement();
-    var cell;
-
-    // Add percentage.
-    cell = tr.insertCell(-1);
-    // Add function ref.
-    cell = tr.insertCell(-1);
-    var functionRef = new Element.tag('function-ref');
-    cell.children.add(functionRef);
-    return tr;
-  }
-
-  _updateRow(TableRowElement tr,
-             int rowIndex,
-             List spacerColumns,
-             int refColumn) {
-    var row = rows[rowIndex];
-    // Set reference
-    var ref = tr.children[refColumn].children[0];
-    ref.ref = row.values[refColumn];
-
-    for (var i = 0; i < row.values.length; i++) {
-      if (spacerColumns.contains(i) || (i == refColumn)) {
-        // Skip spacer columns.
-        continue;
-      }
-      var cell = tr.children[i];
-      cell.title = row.values[i].toString();
-      cell.text = getFormattedValue(rowIndex, i);
-    }
-  }
-
-  _updateTableView(HtmlElement table,
-                   HtmlElement makeEmptyRow(),
-                   void onRowClick(TableRowElement tr),
-                   List spacerColumns,
-                   int refColumn) {
-    assert(table != null);
-
-    // Resize DOM table.
-    if (table.children.length > sortedRows.length) {
-      // Shrink the table.
-      var deadRows = table.children.length - sortedRows.length;
-      for (var i = 0; i < deadRows; i++) {
-        table.children.removeLast();
-      }
-    } else if (table.children.length < sortedRows.length) {
-      // Grow table.
-      var newRows = sortedRows.length - table.children.length;
-      for (var i = 0; i < newRows; i++) {
-        var row = makeEmptyRow();
-        row.onClick.listen((e) {
-          e.stopPropagation();
-          e.preventDefault();
-          onRowClick(row);
-        });
-        table.children.add(row);
-      }
-    }
-
-    assert(table.children.length == sortedRows.length);
-
-    // Fill table.
-    for (var i = 0; i < sortedRows.length; i++) {
-      var rowIndex = sortedRows[i];
-      var tr = table.children[i];
-      _updateRow(tr, rowIndex, spacerColumns, refColumn);
-    }
-  }
-}
-
-@CustomTag('cpu-profile-table')
-class CpuProfileTableElement extends ObservatoryElement {
-  CpuProfileTableElement.created() : super.created() {
-    _updateTask = new Task(update);
-    _renderTask = new Task(render);
-    var columns = [
-        new SortedTableColumn.withFormatter('Executing (%)',
-                                            Utils.formatPercentNormalized),
-        new SortedTableColumn.withFormatter('In stack (%)',
-                                            Utils.formatPercentNormalized),
-        new SortedTableColumn('Method'),
-    ];
-    profileTable = new NameSortedTable(columns);
-    profileTable.sortColumnIndex = 0;
-
-    columns = [
-        new SortedTableColumn.withFormatter('Callees (%)',
-                                            Utils.formatPercentNormalized),
-        new SortedTableColumn('Method')
-    ];
-    profileCalleesTable = new NameSortedTable(columns);
-    profileCalleesTable.sortColumnIndex = 0;
-
-    columns = [
-        new SortedTableColumn.withFormatter('Callers (%)',
-                                            Utils.formatPercentNormalized),
-        new SortedTableColumn('Method')
-    ];
-    profileCallersTable = new NameSortedTable(columns);
-    profileCallersTable.sortColumnIndex = 0;
-  }
-
   attached() {
     super.attached();
-    sampleBufferControlElement =
-        shadowRoot.querySelector('#sampleBufferControl');
-    assert(sampleBufferControlElement != null);
-    sampleBufferControlElement.onSampleBufferUpdate = onSampleBufferChange;
-    // Disable the tag selector- we always want no tags.
-    sampleBufferControlElement.tagSelector = 'None';
-    sampleBufferControlElement.showTagSelector = false;
-    stackTraceTreeConfigElement =
-        shadowRoot.querySelector('#stackTraceTreeConfig');
-    assert(stackTraceTreeConfigElement != null);
-    stackTraceTreeConfigElement.onTreeConfigChange = onTreeConfigChange;
-    stackTraceTreeConfigElement.modeSelector = 'Function';
-    stackTraceTreeConfigElement.showModeSelector = false;
-    stackTraceTreeConfigElement.directionSelector = 'Down';
-    stackTraceTreeConfigElement.showDirectionSelector = false;
-    cpuProfileTreeElement = shadowRoot.querySelector('#cpuProfileTree');
-    assert(cpuProfileTreeElement != null);
-    cpuProfileTreeElement.profile = sampleBufferControlElement.profile;
-    _updateTask.queue();
-    _resizeSubscription = window.onResize.listen((_) => _updateSize());
-    _updateSize();
+    _r.enable();
+    _request();
   }
 
+  @override
   detached() {
-    super.detached();
-    if (_resizeSubscription != null) {
-      _resizeSubscription.cancel();
-    }
-  }
-
-  _updateSize() {
-    HtmlElement e = $['main'];
-    final totalHeight = window.innerHeight;
-    final top = e.offset.top;
-    final bottomMargin = 32;
-    final mainHeight = totalHeight - top - bottomMargin;
-    e.style.setProperty('height', '${mainHeight}px');
-  }
-
-  isolateChanged(oldValue) {
-    _updateTask.queue();
-  }
-
-  update() {
-    _clearView();
-    if (sampleBufferControlElement != null) {
-      sampleBufferControlElement.reload(isolate).whenComplete(checkParameters);
-    }
-  }
-
-  onSampleBufferChange(CpuProfile sampleBuffer) {
-    _renderTask.queue();
-  }
-
-  onTreeConfigChange(String modeSelector,
-                     String directionSelector,
-                     String filterString) {
-    ProfileTreeDirection direction = ProfileTreeDirection.Exclusive;
-    if (directionSelector != 'Up') {
-      direction = ProfileTreeDirection.Inclusive;
-    }
-    ProfileTreeMode mode = ProfileTreeMode.Function;
-    if (modeSelector == 'Code') {
-      mode = ProfileTreeMode.Code;
-    }
-    cpuProfileTreeElement.direction = direction;
-    cpuProfileTreeElement.mode = mode;
-    _renderTask.queue();
-  }
-
-  Future clearCpuProfile() async {
-    await isolate.invokeRpc('_clearCpuProfile', { });
-    _updateTask.queue();
-    return new Future.value(null);
-  }
-
-  Future refresh() {
-    _updateTask.queue();
-    return new Future.value(null);
-  }
-
-  render() {
-    _updateView();
-  }
-
-  checkParameters() {
-    if (isolate == null) {
-      return;
-    }
-    var functionId = app.locationManager.uri.queryParameters['functionId'];
-    var functionName =
-        app.locationManager.uri.queryParameters['functionName'];
-    if (functionId == '') {
-      // Fallback to searching by name.
-      _focusOnFunction(_findFunction(functionName));
-    } else {
-      if (functionId == null) {
-        _focusOnFunction(null);
-        return;
-      }
-      isolate.getObject(functionId).then((func) => _focusOnFunction(func));
-    }
-  }
-
-  _clearView() {
-    profileTable.clearRows();
-    _renderTable();
-  }
-
-  _updateView() {
-    _buildFunctionTable();
-    _renderTable();
-    _updateFunctionTreeView();
-  }
-
-  int _findFunctionRow(ServiceFunction function) {
-    for (var i = 0; i < profileTable.sortedRows.length; i++) {
-      var rowIndex = profileTable.sortedRows[i];
-      var row = profileTable.rows[rowIndex];
-      if (row.values[NameSortedTable.FUNCTION_COLUMN] == function) {
-        return i;
-      }
-    }
-    return -1;
-  }
-
-  _scrollToFunction(ServiceFunction function) {
-    TableSectionElement tableBody = $['profile-table'];
-    var row = _findFunctionRow(function);
-    if (row == -1) {
-      return;
-    }
-    tableBody.children[row].classes.remove('shake');
-    // trigger reflow.
-    tableBody.children[row].offsetHeight;
-    tableBody.children[row].scrollIntoView(ScrollAlignment.CENTER);
-    tableBody.children[row].classes.add('shake');
-    // Focus on clicked function.
-    _focusOnFunction(function);
-  }
-
-  _clearFocusedFunction() {
-    TableSectionElement tableBody = $['profile-table'];
-    // Clear current focus.
-    if (focusedRow != null) {
-      tableBody.children[focusedRow].classes.remove('focused');
-    }
-    focusedRow = null;
-    focusedFunction = null;
-  }
-
-  ServiceFunction _findFunction(String functionName) {
-    for (var func in profile.functions) {
-      if (func.function.name == functionName) {
-        return func.function;
-      }
-    }
-    return null;
-  }
-
-  _focusOnFunction(ServiceFunction function) {
-    if (focusedFunction == function) {
-      // Do nothing.
-      return;
-    }
-
-    _clearFocusedFunction();
-
-    if (function == null) {
-      _updateFunctionTreeView();
-      _clearCallTables();
-      return;
-    }
-
-    var row = _findFunctionRow(function);
-    if (row == -1) {
-      _updateFunctionTreeView();
-      _clearCallTables();
-      return;
-    }
-
-    focusedRow = row;
-    focusedFunction = function;
-
-    TableSectionElement tableBody = $['profile-table'];
-    tableBody.children[focusedRow].classes.add('focused');
-    _updateFunctionTreeView();
-    _buildCallersTable(focusedFunction);
-    _buildCalleesTable(focusedFunction);
-  }
-
-  _onRowClick(TableRowElement tr) {
-    var tableBody = $['profile-table'];
-    var row = profileTable.rowFromIndex(tableBody.children.indexOf(tr));
-    var function = row.values[NameSortedTable.FUNCTION_COLUMN];
-    app.locationManager.goReplacingParameters(
-        {
-          'functionId': function.id,
-          'functionName': function.vmName
-        }
-    );
-  }
-
-  _renderTable() {
-    profileTable._updateTableView($['profile-table'],
-                                  profileTable._makeFunctionRow,
-                                  _onRowClick,
-                                  NameSortedTable.FUNCTION_SPACER_COLUMNS,
-                                  NameSortedTable.FUNCTION_COLUMN);
-  }
-
-  _buildFunctionTable() {
-    for (var func in profile.functions) {
-      if ((func.exclusiveTicks == 0) && (func.inclusiveTicks == 0)) {
-        // Skip.
-        continue;
-      }
-      var row = [
-        func.normalizedExclusiveTicks,
-        func.normalizedInclusiveTicks,
-        func.function,
-      ];
-      profileTable.addRow(new SortedTableRow(row));
-    }
-    profileTable.sort();
-  }
-
-  _renderCallTable(TableSectionElement view,
-                   NameSortedTable model,
-                   void onRowClick(TableRowElement tr)) {
-    model._updateTableView(view,
-                           model._makeCallRow,
-                           onRowClick,
-                           NameSortedTable.CALL_SPACER_COLUMNS,
-                           NameSortedTable.CALL_FUNCTION_COLUMN);
-  }
-
-  _buildCallTable(Map<ProfileFunction, int> calls,
-                  NameSortedTable model) {
-    model.clearRows();
-    if (calls == null) {
-      return;
-    }
-    var sum = 0;
-    calls.values.forEach((i) => sum += i);
-    calls.forEach((func, count) {
-      var row = [
-          count / sum,
-          func.function,
-      ];
-      model.addRow(new SortedTableRow(row));
-    });
-    model.sort();
-  }
-
-  _clearCallTables() {
-    _buildCallersTable(null);
-    _buildCalleesTable(null);
-  }
-
-  _onCallersClick(TableRowElement tr) {
-    var table = $['callers-table'];
-    final row = profileCallersTable.rowFromIndex(table.children.indexOf(tr));
-    var function = row.values[NameSortedTable.CALL_FUNCTION_COLUMN];
-    _scrollToFunction(function);
-  }
-
-  _buildCallersTable(ServiceFunction function) {
-    var calls = (function != null) ? function.profile.callers : null;
-    var table = $['callers-table'];
-    _buildCallTable(calls, profileCallersTable);
-    _renderCallTable(table, profileCallersTable, _onCallersClick);
-  }
-
-  _onCalleesClick(TableRowElement tr) {
-    var table = $['callees-table'];
-    final row = profileCalleesTable.rowFromIndex(table.children.indexOf(tr));
-    var function = row.values[NameSortedTable.CALL_FUNCTION_COLUMN];
-    _scrollToFunction(function);
-  }
-
-  _buildCalleesTable(ServiceFunction function) {
-    var calls = (function != null) ? function.profile.callees : null;
-    var table = $['callees-table'];
-    _buildCallTable(calls, profileCalleesTable);
-    _renderCallTable(table, profileCalleesTable, _onCalleesClick);
-  }
-
-  _changeSort(Element target, NameSortedTable table) {
-    if (target is TableCellElement) {
-      if (table.sortColumnIndex != target.cellIndex) {
-        table.sortColumnIndex = target.cellIndex;
-        table.sortDescending = true;
-      } else {
-        table.sortDescending = !profileTable.sortDescending;
-      }
-      table.sort();
-    }
-  }
-
-  changeSortProfile(Event e, var detail, Element target) {
-    _changeSort(target, profileTable);
-    _renderTable();
-  }
-
-  changeSortCallers(Event e, var detail, Element target) {
-    _changeSort(target, profileCallersTable);
-    _renderCallTable($['callers-table'], profileCallersTable, _onCallersClick);
-  }
-
-  changeSortCallees(Event e, var detail, Element target) {
-    _changeSort(target, profileCalleesTable);
-    _renderCallTable($['callees-table'], profileCalleesTable, _onCalleesClick);
-  }
-
-  //////
-  ///
-  /// Function tree.
-  ///
-  TableTree functionTree;
-  _updateFunctionTreeView() {
-    cpuProfileTreeElement.filter = (FunctionCallTreeNode node) {
-      return node.profileFunction.function == focusedFunction;
-    };
-    cpuProfileTreeElement.render();
-  }
-
-  @published Isolate isolate;
-  @observable NameSortedTable profileTable;
-  @observable NameSortedTable profileCallersTable;
-  @observable NameSortedTable profileCalleesTable;
-  @observable ServiceFunction focusedFunction;
-  @observable int focusedRow;
-
-
-  StreamSubscription _resizeSubscription;
-  Task _updateTask;
-  Task _renderTask;
-
-  CpuProfile get profile => sampleBufferControlElement.profile;
-  SampleBufferControlElement sampleBufferControlElement;
-  StackTraceTreeConfigElement stackTraceTreeConfigElement;
-  CpuProfileVirtualTreeElement cpuProfileTreeElement;
-}
-
-enum ProfileTreeDirection {
-  Exclusive,
-  Inclusive
-}
-
-enum ProfileTreeMode {
-  Code,
-  Function,
-}
-
-@CustomTag('cpu-profile-virtual-tree')
-class CpuProfileVirtualTreeElement extends ObservatoryElement {
-  ProfileTreeDirection direction = ProfileTreeDirection.Exclusive;
-  ProfileTreeMode mode = ProfileTreeMode.Function;
-  CpuProfile profile;
-  VirtualTree virtualTree;
-  CallTreeNodeFilter filter;
-  StreamSubscription _resizeSubscription;
-  @observable bool show = true;
-
-  CpuProfileVirtualTreeElement.created() : super.created();
-
-  attached() {
-    super.attached();
-    _resizeSubscription = window.onResize.listen((_) => _updateSize());
-  }
-
-  detached() {
-    super.detached();
-    _resizeSubscription?.cancel();
+    super.detached(); _r.disable(notify: true);
+    children = [];
   }
 
   void render() {
-    _updateView();
-  }
-
-  showChanged(oldValue) {
-    if (show) {
-      virtualTree?.root?.style?.display = 'block';
-    } else {
-      virtualTree?.root?.style?.display = 'none';
-    }
-  }
-
-  void _updateView() {
-    _updateSize();
-    virtualTree?.clear();
-    virtualTree?.uninstall();
-    virtualTree = null;
-    bool exclusive = direction == ProfileTreeDirection.Exclusive;
-    if (mode == ProfileTreeMode.Code) {
-      _buildCodeTree(exclusive);
-    } else {
-      assert(mode == ProfileTreeMode.Function);
-      _buildFunctionTree(exclusive);
-    }
-    virtualTree?.refresh();
-  }
-
-  void _updateSize() {
-    var treeBody = shadowRoot.querySelector('#tree');
-    assert(treeBody != null);
-    int windowHeight = window.innerHeight - 32;
-    treeBody.style.height = '${windowHeight}px';
-  }
-
-  void _buildFunctionTree(bool exclusive) {
-    var treeBody = shadowRoot.querySelector('#tree');
-    assert(treeBody != null);
-    virtualTree = new VirtualTree(32, treeBody);
-    if (profile == null) {
+    var content = [
+      new NavBarElement(queue: _r.queue)
+        ..children = [
+          new NavTopMenuElement(queue: _r.queue),
+          new NavVMMenuElement(_vm, _events, queue: _r.queue),
+          new NavIsolateMenuElement(_isolate, _events, queue: _r.queue),
+          new NavMenuElement('cpu profile', link: Uris.profiler(_isolate),
+              last: true, queue: _r.queue),
+          new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen(_refresh),
+          new NavRefreshElement(label: 'Clear', queue: _r.queue)
+              ..onRefresh.listen(_clearCpuProfile),
+          new NavNotifyElement(_notifications, queue: _r.queue)
+        ],
+    ];
+    if (_progress == null) {
+      children = content;
       return;
     }
-    var tree = profile.loadFunctionTree(exclusive ? 'exclusive' : 'inclusive');
-    if (tree == null) {
-      return;
+    content.add(new SampleBufferControlElement(_progress, _progressStream,
+      selectedTag: _tag, queue: _r.queue)
+      ..onTagChange.listen((e) {
+        _tag = e.element.selectedTag;
+        _request();
+    }));
+    if (_progress.status == M.SampleProfileLoadingStatus.loaded) {
+      CpuProfileVirtualTreeElement tree;
+      content.addAll([
+        new BRElement(),
+        new StackTraceTreeConfigElement(mode: _mode, direction: _direction,
+          filter: _filter, queue: _r.queue)
+            ..onModeChange.listen((e) {
+              _mode = tree.mode = e.element.mode;
+            })
+            ..onFilterChange.listen((e) {
+              _filter = e.element.filter.trim();
+              tree.filter = _filter.isNotEmpty
+                ? (node) { return node.name.contains(_filter); }
+                : null;
+            })
+            ..onDirectionChange.listen((e) {
+              _direction = tree.direction = e.element.direction;
+            }),
+        new BRElement(),
+        tree = new CpuProfileVirtualTreeElement(_isolate, _progress.profile,
+            queue: _r.queue)
+      ]);
     }
-    if (filter != null) {
-      tree = tree.filtered(filter);
-    }
-    for (var child in tree.root.children) {
-      virtualTree.rows.add(
-          new FunctionCallTreeNodeRow(virtualTree, 0, profile, child));
-    }
-    if (virtualTree.rows.length == 1) {
-      virtualTree.rows[0].expanded = true;
+    children = content;
+  }
+
+  Future _request({bool clear: false, bool forceFetch: false}) async {
+    _progress = null;
+    _progressStream = _profiles.get(isolate, _tag, clear: clear,
+        forceFetch: forceFetch);
+    _r.dirty();
+    _progress = (await _progressStream.first).progress;
+    _r.dirty();
+    if (M.isSampleProcessRunning(_progress.status)) {
+      _progress = (await _progressStream.last).progress;
+      _r.dirty();
     }
   }
 
-  void _buildCodeTree(bool exclusive) {
-    var treeBody = shadowRoot.querySelector('#tree');
-    assert(treeBody != null);
-    virtualTree = new VirtualTree(32, treeBody);
-    if (profile == null) {
-      return;
-    }
-    var tree = profile.loadCodeTree(exclusive ? 'exclusive' : 'inclusive');
-    if (tree == null) {
-      return;
-    }
-    if (filter != null) {
-      tree = tree.filtered(filter);
-    }
-    for (var child in tree.root.children) {
-      virtualTree.rows.add(
-          new CodeCallTreeNodeRow(virtualTree, 0, profile, child));
-    }
-    if (virtualTree.rows.length == 1) {
-      virtualTree.rows[0].expanded = true;
-    }
-  }
-}
-
-@CustomTag('cpu-profile-tree')
-class CpuProfileTreeElement extends ObservatoryElement {
-  ProfileTreeDirection direction = ProfileTreeDirection.Exclusive;
-  ProfileTreeMode mode = ProfileTreeMode.Function;
-  CpuProfile profile;
-  TableTree codeTree;
-  TableTree functionTree;
-  CallTreeNodeFilter functionFilter;
-  @observable bool show = true;
-
-  CpuProfileTreeElement.created() : super.created();
-
-  void render() {
-    _updateView();
+  Future _clearCpuProfile(RefreshEvent e) async {
+    e.element.disabled = true;
+    await _request(clear: true);
+    e.element.disabled = false;
   }
 
-  showChanged(oldValue) {
-    var treeTable = shadowRoot.querySelector('#treeTable');
-    assert(treeTable != null);
-    treeTable.style.display = show ? 'table' : 'none';
-  }
-
-  void _updateView() {
-    if (functionTree != null) {
-      functionTree.clear();
-      functionTree = null;
-    }
-    if (codeTree != null) {
-      codeTree.clear();
-      codeTree = null;
-    }
-    bool exclusive = direction == ProfileTreeDirection.Exclusive;
-    if (mode == ProfileTreeMode.Code) {
-      _buildCodeTree(exclusive);
-    } else {
-      assert(mode == ProfileTreeMode.Function);
-      _buildFunctionTree(exclusive);
-    }
-  }
-
-  void _buildFunctionTree(bool exclusive) {
-    if (functionTree == null) {
-      var tableBody = shadowRoot.querySelector('#treeBody');
-      assert(tableBody != null);
-      functionTree = new TableTree(tableBody, 2);
-    }
-    if (profile == null) {
-      return;
-    }
-    var tree = profile.loadFunctionTree(exclusive ? 'exclusive' : 'inclusive');
-    if (tree == null) {
-      return;
-    }
-    if (functionFilter != null) {
-      tree = tree.filtered(functionFilter);
-    }
-    var rootRow =
-        new FunctionProfileTreeRow(functionTree, null, profile, tree.root);
-    functionTree.initialize(rootRow);
-  }
-
-  void _buildCodeTree(bool exclusive) {
-    if (codeTree == null) {
-      var tableBody = shadowRoot.querySelector('#treeBody');
-      assert(tableBody != null);
-      codeTree = new TableTree(tableBody, 2);
-    }
-    if (profile == null) {
-      return;
-    }
-    var tree = profile.loadCodeTree(exclusive ? 'exclusive' : 'inclusive');
-    if (tree == null) {
-      return;
-    }
-    var rootRow = new CodeProfileTreeRow(codeTree, null, profile, tree.root);
-    codeTree.initialize(rootRow);
+  Future _refresh(e) async {
+    e.element.disabled = true;
+    await _request(forceFetch: true);
+    e.element.disabled = false;
   }
 }
diff --git a/runtime/observatory/lib/src/elements/cpu_profile.html b/runtime/observatory/lib/src/elements/cpu_profile.html
deleted file mode 100644
index 32363c7..0000000
--- a/runtime/observatory/lib/src/elements/cpu_profile.html
+++ /dev/null
@@ -1,515 +0,0 @@
-<link rel="import" href="../../../../packages/polymer/polymer.html">
-
-<polymer-element name="sample-buffer-control">
-  <template>
-    <link rel="stylesheet" href="css/shared.css">
-    <style>
-    .statusMessage {
-      font-size: 150%;
-      font-weight: bold;
-    }
-
-    .statusBox {
-      height: 100%;
-      padding: 1em;
-    }
-
-    .center {
-      align-items: center;
-      justify-content: center;
-    }
-
-    .notice {
-      background-color: #fcf8e3;
-    }
-
-    .red {
-      background-color: #f2dede;
-    }
-    </style>
-    <div class="content-centered-big">
-      <template if="{{ state != 'kNotLoaded' }}">
-        <h2>Sample buffer</h2>
-        <hr>
-      </template>
-      <template if="{{ state == 'kFetching' }}">
-        <div class="statusBox shadow center">
-          <div class="statusMessage">Fetching profile from VM...</div>
-        </div>
-      </template>
-      <template if="{{ state == 'kLoading' }}">
-        <div class="statusBox shadow center">
-          <div class="statusMessage">Loading profile...</div>
-        </div>
-      </template>
-      <template if="{{ state == 'kDisabled' }}">
-        <div class="statusBox shadow center">
-          <div>
-            <h1>Profiling is disabled</h1>
-            <br>
-            Perhaps the <b>profile</b> flag has been disabled for this VM.
-            <br><br>
-            See all
-            <a on-click="{{ goto }}" _href="{{ gotoLink('/flags') }}">vm flags</a>
-          </div>
-        </div>
-      </template>
-      <template if="{{ state == 'kException' }}">
-        <div class="statusBox shadow center">
-          <div class="statusMessage">
-            <h1>Profiling is disabled due to unexpected exception:</h1>
-            <br>
-            <pre>{{ exception.toString() }}</pre>
-            <br>
-            <h1>Stack trace:</h1>
-            <br>
-            <pre>{{ stackTrace.toString() }}</pre>
-          </div>
-        </div>
-      </template>
-      <template if="{{ state == 'kLoaded' }}">
-        <div class="memberList">
-          <div class="memberItem">
-            <div class="memberName">Refreshed at </div>
-            <div class="memberValue">{{ refreshTime }} (fetched in {{ fetchTime  }}) (loaded in {{ loadTime }})</div>
-          </div>
-          <div class="memberItem">
-            <div class="memberName">Profile contains</div>
-            <div class="memberValue">{{ sampleCount }} samples (spanning {{ timeSpan }})</div>
-          </div>
-          <div class="memberItem">
-            <div class="memberName">Sampling</div>
-            <div class="memberValue">{{ stackDepth }} stack frames @ {{ sampleRate }} Hz</div>
-          </div>
-          <template if="{{ showTagSelector }}">
-            <div class="memberItem">
-              <div class="memberName">Tag Order</div>
-              <div class="memberValue">
-                <template if="{{ profileVM }}">
-                  <select value="{{tagSelector}}">
-                    <option value="UserVM">User &gt; VM</option>
-                    <option value="UserOnly">User</option>
-                    <option value="VMUser">VM &gt; User</option>
-                    <option value="VMOnly">VM</option>
-                    <option value="None">None</option>
-                  </select>
-                </template>
-                <template if="{{ !profileVM }}">
-                  <select value="{{tagSelector}}">
-                    <option value="UserOnly">User</option>
-                    <option value="None">None</option>
-                  </select>
-                </template>
-              </div>
-            </div>
-          </template>
-        </div>
-      </template>
-    </div>
-  </template>
-</polymer-element>
-
-<polymer-element name="stack-trace-tree-config">
-  <template>
-    <link rel="stylesheet" href="css/shared.css">
-    <style>
-    .statusBox {
-      height: 100%;
-      padding: 0.5em;
-    }
-    .row {
-      display: flex;
-    }
-    </style>
-    <div class="content-centered-big">
-      <template if="{{ show }}">
-        <h2>Tree display</h2>
-        <hr>
-        <div class="row">
-          <div>
-            <div class="memberList">
-              <template if="{{ showModeSelector }}">
-                <div class="memberItem">
-                  <div class="memberName">Mode</div>
-                  <div class="memberValue">
-                    <select value="{{modeSelector}}">
-                      <option value="Code">Code</option>
-                      <option value="Function">Function</option>
-                    </select>
-                  </div>
-                </div>
-              </template>
-              <template if="{{ showDirectionSelector }}">
-                <div class="memberItem">
-                  <div class="memberName">Call Tree Direction</div>
-                  <span class="memberValue">
-                    <select value="{{directionSelector}}">
-                      <option value="Down">Top down</option>
-                      <option value="Up">Bottom up</option>
-                    </select>
-                    <template if="{{ directionSelector == 'Down' }}">
-                      <span>
-                        Tree is rooted at "main". Child nodes are callees.
-                      </span>
-                    </template>
-                    <template if="{{ directionSelector == 'Up' }}">
-                      <span>
-                        Tree is rooted at executing function / code. Child nodes are callers.
-                      </span>
-                    </template>
-                  </span>
-                </div>
-              </template>
-              <template if="{{ showFilter }}">
-                <div class="memberItem">
-                  <div title="case-sensitive substring match" class="memberName">Call Tree Filter</div>
-                  <span class="memberValue">
-                    <input type="text" placeholder="Search filter" id="filterInput">
-                  </span>
-                </div>
-              </template>
-            </div>
-          </div>
-        </div>
-      </template>
-    </div>
-  </template>
-</polymer-element>
-
-<polymer-element name="cpu-profile-tree">
-  <template>
-    <link rel="stylesheet" href="css/shared.css">
-    <style>
-    .infoBox {
-      position: absolute;
-      top: 100%;
-      left: 0%;
-      z-index: 999;
-      opacity: 1;
-      padding: 1em;
-      background-color: #ffffff;
-      border-left: solid 2px #ECECEC;
-      border-bottom: solid 2px #ECECEC;
-      border-right: solid 2px #ECECEC;
-    }
-    .full-width {
-      width: 100%;
-    }
-    .tree {
-      border-spacing: 0px;
-      width: 100%;
-      margin-bottom: 20px
-      vertical-align: middle;
-    }
-    .tree tbody tr {
-      animation: fadeIn 0.5s;
-      -moz-animation: fadeIn 0.5s;
-      -webkit-animation: fadeIn 0.5s;
-    }
-    .tree tbody tr:hover {
-      background-color: #FAFAFA;
-    }
-    .tree tr td:first-child,
-    .tree tr th:first-child {
-      width: 100%;
-    }
-    .tree thead > tr > th {
-      padding: 8px;
-      vertical-align: bottom;
-      text-align: left;
-      border-bottom: 1px solid #ddd;
-    }
-    tr {
-      background-color: #FFFFFF;
-    }
-    tbody tr {
-      animation: fadeIn 0.5s;
-      -moz-animation: fadeIn 0.5s;
-      -webkit-animation: fadeIn 0.5s;
-    }
-    tbody tr:hover {
-      background-color: #FAFAFA;
-    }
-    tr td:first-child,
-    tr th:first-child {
-      width: 100%;
-    }
-    </style>
-    <table id="treeTable" class="full-width tree">
-      <thead id="treeHeader">
-      <tr>
-        <th>Method</th>
-        <th>Executing</th>
-      </tr>
-      </thead>
-      <tbody id="treeBody">
-      </tbody>
-    </table>
-  </template>
-</polymer-element>
-
-<polymer-element name="cpu-profile-virtual-tree">
-  <template>
-    <link rel="stylesheet" href="css/shared.css">
-    <style>
-    .full {
-      height: 50%;
-      width: 100%;
-    }
-    .coldProfile {
-      background-color: #aea;
-    }
-    .mediumProfile {
-      background-color: #fe9;
-    }
-    .hotProfile {
-      background-color: #faa;
-    }
-    </style>
-    <div id="tree" class="full"></div>
-  </template>
-</polymer-element>
-
-
-<polymer-element name="cpu-profile-table">
-  <template>
-    <link rel="stylesheet" href="css/shared.css">
-    <nav-bar>
-      <top-nav-menu></top-nav-menu>
-      <vm-nav-menu vm="{{ isolate.vm }}"></vm-nav-menu>
-      <isolate-nav-menu isolate="{{ isolate }}"></isolate-nav-menu>
-      <nav-menu link="{{ makeLink('/profiler-table', isolate) }}" anchor="cpu profile (table)" last="{{ true }}"></nav-menu>
-      <nav-refresh callback="{{ refresh }}"></nav-refresh>
-      <nav-refresh callback="{{ clearCpuProfile }}" label="Clear"></nav-refresh>
-      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
-    </nav-bar>
-    <style>
-      /* general */
-      .well {
-        background-color: #ECECEC;
-        padding: 0.2em;
-      }
-      .center {
-        align-items: center;
-        justify-content: center;
-      }
-
-      /* status messages */
-      .statusMessage {
-        font-size: 150%;
-        font-weight: bold;
-      }
-      .statusBox {
-        height: 100%;
-        padding: 1em;
-      }
-
-      /* tables */
-      .table {
-        border-collapse: collapse!important;
-        table-layout: fixed;
-        height: 100%;
-      }
-      .th, .td {
-        padding: 8px;
-        vertical-align: top;
-      }
-      .table thead > tr > th {
-        vertical-align: bottom;
-        text-align: left;
-        border-bottom:2px solid #ddd;
-      }
-      .spacer {
-        width: 16px;
-      }
-      .left-border-spacer {
-        width: 16px;
-        border-left: 1px solid;
-      }
-      .clickable {
-        color: #0489c3;
-        text-decoration: none;
-        cursor: pointer;
-        min-width: 8em;
-      }
-      .clickable:hover {
-        text-decoration: underline;
-        cursor: pointer;
-      }
-      tr:hover:not(.focused) > td {
-        background-color: #FAFAFA;
-      }
-      .focused {
-        background-color: #F4C7C3;
-      }
-      .scroll {
-        overflow: scroll;
-      }
-      .outlined {
-        -webkit-box-shadow: 0px 0px 2px 1px rgba(0,0,0,0.75);
-        -moz-box-shadow: 0px 0px 2px 1px rgba(0,0,0,0.75);
-        box-shadow: 0px 0px 2px 1px rgba(0,0,0,0.75);
-        margin: 4px;
-      }
-      .centered {
-        margin-left: auto;
-        margin-right: auto;
-        justify-content: center;
-      }
-      .full-height {
-        height: 100%;
-      }
-      .mostly-full-height {
-        height: 80%;
-      }
-      .full-width {
-        width: 100%;
-      }
-      .focused-function-label {
-        flex: 0 1 auto;
-        margin-left: auto;
-        margin-right: auto;
-        justify-content: center;
-      }
-      .call-table {
-        flex: 1 1 auto;
-      }
-
-      .tree {
-        border-spacing: 0px;
-        width: 100%;
-        margin-bottom: 20px
-        vertical-align: middle;
-      }
-
-      .tree tbody tr {
-        animation: fadeIn 0.5s;
-        -moz-animation: fadeIn 0.5s;
-        -webkit-animation: fadeIn 0.5s;
-      }
-
-      .tree tbody tr:hover {
-        background-color: #FAFAFA;
-      }
-
-      .tree tr td:first-child,
-      .tree tr th:first-child {
-        width: 100%;
-      }
-
-      .tree thead > tr > th {
-        padding: 8px;
-        vertical-align: bottom;
-        text-align: left;
-        border-bottom: 1px solid #ddd;
-      }
-
-    </style>
-    <sample-buffer-control id="sampleBufferControl"></sample-buffer-control>
-    <br>
-    <hr>
-    <div id="main" class="flex-row centered">
-      <div class="flex-item-45-percent full-height outlined scroll">
-        <table id="main-table" class="flex-item-100-percent table">
-          <thead>
-          <tr>
-            <th on-click="{{changeSortProfile}}" class="clickable" title="Executing (%)">{{ profileTable.getColumnLabel(0) }}</th>
-            <th on-click="{{changeSortProfile}}" class="clickable" title="In stack (%)">{{ profileTable.getColumnLabel(1) }}</th>
-            <th on-click="{{changeSortProfile}}" class="clickable" title="Method">{{ profileTable.getColumnLabel(2) }}</th>
-          </tr>
-          </thead>
-          <tbody id="profile-table">
-          </tbody>
-        </table>
-      </div>
-      <div class="flex-item-45-percent full-height outlined">
-        <div class="flex-column full-height">
-          <div class="focused-function-label">
-            <template if="{{ focusedFunction != null }}">
-              <span>Focused on: </span>
-              <function-ref ref="{{ focusedFunction }}"></function-ref>
-            </template>
-            <template if="{{ focusedFunction == null }}">
-              <span>No focused function</span>
-            </template>
-          </div>
-          <hr>
-          <div class="call-table scroll">
-            <table class="full-width table">
-              <thead>
-              <tr>
-                <th on-click="{{changeSortCallers}}" class="clickable" title="Callers (%)">{{ profileCallersTable.getColumnLabel(0) }}</th>
-                <th on-click="{{changeSortCallers}}" class="clickable" title="Method">{{ profileCallersTable.getColumnLabel(1) }}</th>
-              </tr>
-              </thead>
-              <tbody id="callers-table">
-              </tbody>
-            </table>
-          </div>
-          <hr>
-          <div class="call-table scroll">
-            <table class="full-width table">
-              <thead>
-              <tr>
-                <th on-click="{{changeSortCallees}}" class="clickable" title="Callees (%)">{{ profileCalleesTable.getColumnLabel(0) }}</th>
-                <th on-click="{{changeSortCallees}}" class="clickable" title="Method">{{ profileCalleesTable.getColumnLabel(1) }}</th>
-              </tr>
-              </thead>
-              <tbody id="callees-table">
-              </tbody>
-            </table>
-          </div>
-        </div>
-      </div>
-    </div>
-    <br>
-    <stack-trace-tree-config id="stackTraceTreeConfig"></stack-trace-tree-config>
-    <br>
-    <div class="content-centered-big">
-      <div class="focused-function-label">
-        <template if="{{ focusedFunction != null }}">
-          <span>Filtered tree: </span>
-          <function-ref ref="{{ focusedFunction }}"></function-ref>
-        </template>
-        <template if="{{ focusedFunction == null }}">
-          <span>No focused function</span>
-        </template>
-      </div>
-    </div>
-    <br>
-    <br>
-    <div class="flex-row centered">
-      <div class="flex-item-90-percent outlined" style="margin: 16px; margin-left: 8px; margin-right: 8px">
-        <cpu-profile-virtual-tree id="cpuProfileTree"></cpu-profile-virtual-tree>
-      </div>
-    </div>
-  </template>
-</polymer-element>
-
-<polymer-element name="cpu-profile">
-  <template>
-    <link rel="stylesheet" href="css/shared.css">
-    <nav-bar>
-      <top-nav-menu></top-nav-menu>
-      <vm-nav-menu vm="{{ isolate.vm }}"></vm-nav-menu>
-      <isolate-nav-menu isolate="{{ isolate }}"></isolate-nav-menu>
-      <nav-menu link="{{ makeLink('/profiler', isolate) }}" anchor="cpu profile" last="{{ true }}"></nav-menu>
-      <nav-refresh callback="{{ refresh }}"></nav-refresh>
-      <nav-refresh callback="{{ clearCpuProfile }}" label="Clear"></nav-refresh>
-      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
-    </nav-bar>
-    <style>
-      .tableWell {
-        background-color: #ECECEC;
-        padding: 0.2em;
-      }
-    </style>
-    <sample-buffer-control id="sampleBufferControl"></sample-buffer-control>
-    <br>
-    <stack-trace-tree-config id="stackTraceTreeConfig"></stack-trace-tree-config>
-    <br>
-    <cpu-profile-virtual-tree id="cpuProfileVirtualTree"></cpu-profile-virtual-tree>
-  </template>
-</polymer-element>
-
-<script type="application/dart" src="cpu_profile.dart"></script>
diff --git a/runtime/observatory/lib/src/elements/cpu_profile/virtual_tree.dart b/runtime/observatory/lib/src/elements/cpu_profile/virtual_tree.dart
new file mode 100644
index 0000000..236b395
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/cpu_profile/virtual_tree.dart
@@ -0,0 +1,179 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:html';
+import 'dart:math' as Math;
+import 'package:observatory/models.dart' as M;
+import 'package:observatory/src/elements/stack_trace_tree_config.dart'
+  show ProfileTreeMode;
+import 'package:observatory/src/elements/code_ref.dart';
+import 'package:observatory/src/elements/containers/virtual_tree.dart';
+import 'package:observatory/src/elements/function_ref.dart';
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/utils.dart';
+
+export 'package:observatory/src/elements/stack_trace_tree_config.dart'
+  show ProfileTreeMode;
+
+class CpuProfileVirtualTreeElement extends HtmlElement implements Renderable {
+  static const tag =
+      const Tag<CpuProfileVirtualTreeElement>('cpu-profile-virtual-tree');
+
+  RenderingScheduler<CpuProfileVirtualTreeElement> _r;
+
+  Stream<RenderedEvent<CpuProfileVirtualTreeElement>> get onRendered =>
+                                                                  _r.onRendered;
+
+  M.ProfileTreeDirection _direction;
+  ProfileTreeMode _mode;
+  M.IsolateRef _isolate;
+  M.SampleProfile _profile;
+  M.CallTreeNodeFilter _filter;
+
+  M.ProfileTreeDirection get direction => _direction;
+  ProfileTreeMode get mode => _mode;
+  M.IsolateRef get isolate => _isolate;
+  M.SampleProfile get profile => _profile;
+  M.CallTreeNodeFilter get filter => _filter;
+
+  set direction(M.ProfileTreeDirection value) =>
+      _direction = _r.checkAndReact(_direction, value);
+  set mode(ProfileTreeMode value) => _mode = _r.checkAndReact(_mode, value);
+  set filter(M.CallTreeNodeFilter value) =>
+      _filter = _r.checkAndReact(_filter, value);
+
+  factory CpuProfileVirtualTreeElement(M.IsolateRef isolate,
+      M.SampleProfile profile, {ProfileTreeMode mode: ProfileTreeMode.function,
+      M.ProfileTreeDirection direction: M.ProfileTreeDirection.exclusive,
+      RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(profile != null);
+    assert(mode != null);
+    assert(direction != null);
+    CpuProfileVirtualTreeElement e = document.createElement(tag.name);
+    e._r = new RenderingScheduler(e, queue: queue);
+    e._isolate = isolate;
+    e._profile = profile;
+    e._mode = mode;
+    e._direction = direction;
+    return e;
+  }
+
+  CpuProfileVirtualTreeElement.created() : super.created();
+
+  @override
+  attached() {
+    super.attached();
+    _r.enable();
+  }
+
+ @override
+  detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = [];
+  }
+
+  VirtualTreeElement _tree;
+
+  void render() {
+    var tree;
+    var update;
+    switch (mode) {
+      case ProfileTreeMode.code:
+        tree = _profile.loadCodeTree(_direction);
+        update = _updateCodeRow;
+        break;
+      case ProfileTreeMode.function:
+        tree = _profile.loadFunctionTree(_direction);
+        update = _updateFunctionRow;
+        break;
+      default:
+        throw new Exception('Unknown ProfileTreeMode: $mode');
+    }
+    if (tree == null) {
+      children = [
+        new HeadingElement.h1()..text = 'No Results'
+      ];
+      return;
+    }
+    if (filter != null) {
+      tree = tree.filtered(filter);
+    }
+    _tree = new VirtualTreeElement(_createRow, update, _getChildren,
+      items: tree.root.children, queue: _r.queue);
+    if (tree.root.children.length == 1) {
+      _tree.expand(tree.root.children.first, autoExpandSingleChildNodes: true);
+    }
+    children = [_tree];
+  }
+
+  static Element _createRow(toggle) {
+    return new DivElement()
+      ..classes = const ['tree-item']
+      ..children = [
+        new SpanElement()..classes = const ['inclusive']
+          ..title = 'global % on stack',
+        new SpanElement()..classes = const ['exclusive']
+          ..title = 'global % executing',
+        new SpanElement()..classes = const ['lines'],
+        new ButtonElement()..classes = const ['expander']
+          ..onClick.listen((_) => toggle(autoToggleSingleChildNodes: true)),
+        new SpanElement()..classes = const ['percentage']
+          ..title = 'tree node %',
+        new SpanElement()..classes = const ['name']
+      ];
+  }
+
+  static _getChildren(M.CallTreeNode node) => node.children;
+
+  void _updateFunctionRow(HtmlElement element, M.FunctionCallTreeNode item,
+      int depth) {
+    element.children[0].text = Utils.formatPercentNormalized(
+        item.profileFunction.normalizedInclusiveTicks);
+    element.children[1].text = Utils.formatPercentNormalized(
+        item.profileFunction.normalizedExclusiveTicks);
+    _updateLines(element.children[2].children, depth);
+    if (item.children.isNotEmpty) {
+      element.children[3].text = _tree.isExpanded(item) ? 'â–¼' : 'â–º';
+    } else {
+      element.children[3].text = '';
+    }
+    element.children[4].text = Utils.formatPercentNormalized(
+        item.percentage);
+    element.children[5] = new FunctionRefElement(_isolate,
+            item.profileFunction.function, queue: _r.queue)
+            ..classes = const ['name'];
+  }
+
+  void _updateCodeRow(HtmlElement element, M.CodeCallTreeNode item, int depth) {
+    element.children[0].text = Utils.formatPercentNormalized(
+        item.profileCode.normalizedInclusiveTicks);
+    element.children[1].text = Utils.formatPercentNormalized(
+        item.profileCode.normalizedExclusiveTicks);
+    _updateLines(element.children[2].children, depth);
+    if (item.children.isNotEmpty) {
+      element.children[3].text = _tree.isExpanded(item) ? 'â–¼' : 'â–º';
+    } else {
+      element.children[3].text = '';
+    }
+    element.children[4].text = Utils.formatPercentNormalized(
+        item.percentage);
+    element.children[5] = new CodeRefElement(_isolate,
+        item.profileCode.code, queue: _r.queue)
+        ..classes = const ['name'];
+  }
+
+  static _updateLines(List<Element> lines, int n) {
+    n = Math.max(0, n);
+    while (lines.length > n) {
+      lines.removeLast();
+    }
+    while (lines.length < n) {
+      lines.add(new SpanElement());
+    }
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/cpu_profile_table.dart b/runtime/observatory/lib/src/elements/cpu_profile_table.dart
new file mode 100644
index 0000000..2a76e17
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/cpu_profile_table.dart
@@ -0,0 +1,929 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library cpu_profile_table_element;
+
+import 'dart:async';
+import 'dart:html';
+import 'observatory_element.dart';
+import 'sample_buffer_control.dart';
+import 'stack_trace_tree_config.dart';
+import 'cpu_profile/virtual_tree.dart';
+import 'package:observatory/service.dart';
+import 'package:observatory/app.dart';
+import 'package:observatory/cpu_profile.dart';
+import 'package:observatory/elements.dart';
+import 'package:observatory/models.dart' as M;
+import 'package:observatory/repositories.dart';
+import 'package:polymer/polymer.dart';
+
+List<String> sorted(Set<String> attributes) {
+  var list = attributes.toList();
+  list.sort();
+  return list;
+}
+
+abstract class ProfileTreeRow<T> extends TableTreeRow {
+  final CpuProfile profile;
+  final T node;
+  final String selfPercent;
+  final String percent;
+  bool _infoBoxShown = false;
+  HtmlElement infoBox;
+  HtmlElement infoButton;
+
+  ProfileTreeRow(TableTree tree, TableTreeRow parent,
+                 this.profile, this.node, double selfPercent, double percent)
+      : super(tree, parent),
+        selfPercent = Utils.formatPercentNormalized(selfPercent),
+        percent = Utils.formatPercentNormalized(percent);
+
+  static _addToMemberList(DivElement memberList, Map<String, String> items) {
+    items.forEach((k, v) {
+      var item = new DivElement();
+      item.classes.add('memberItem');
+      var name = new DivElement();
+      name.classes.add('memberName');
+      name.text = k;
+      var value = new DivElement();
+      value.classes.add('memberValue');
+      value.text = v;
+      item.children.add(name);
+      item.children.add(value);
+      memberList.children.add(item);
+    });
+  }
+
+  makeInfoBox() {
+    if (infoBox != null) {
+      return;
+    }
+    infoBox = new DivElement();
+    infoBox.classes.add('infoBox');
+    infoBox.classes.add('shadow');
+    infoBox.style.display = 'none';
+    listeners.add(infoBox.onClick.listen((e) => e.stopPropagation()));
+  }
+
+  makeInfoButton() {
+    infoButton = new SpanElement();
+    infoButton.style.marginLeft = 'auto';
+    infoButton.style.marginRight = '1em';
+    infoButton.children.add(new Element.tag('icon-info-outline'));
+    listeners.add(infoButton.onClick.listen((event) {
+      event.stopPropagation();
+      toggleInfoBox();
+    }));
+  }
+
+  static const attributes = const {
+    'optimized' : const ['O', null, 'Optimized'],
+    'unoptimized' : const ['U', null, 'Unoptimized'],
+    'inlined' : const ['I', null, 'Inlined'],
+    'intrinsic' : const ['It', null, 'Intrinsic'],
+    'ffi' : const ['F', null, 'FFI'],
+    'dart' : const ['D', null, 'Dart'],
+    'tag' : const ['T', null, 'Tag'],
+    'native' : const ['N', null, 'Native'],
+    'stub': const ['S', null, 'Stub'],
+    'synthetic' : const ['?', null, 'Synthetic'],
+  };
+
+  HtmlElement newAttributeBox(String attribute) {
+    List attributeDetails = attributes[attribute];
+    if (attributeDetails == null) {
+      print('could not find attribute $attribute');
+      return null;
+    }
+    var element = new SpanElement();
+    element.style.border = 'solid 2px #ECECEC';
+    element.style.height = '100%';
+    element.style.display = 'inline-block';
+    element.style.textAlign = 'center';
+    element.style.minWidth = '1.5em';
+    element.style.fontWeight = 'bold';
+    if (attributeDetails[1] != null) {
+      element.style.backgroundColor = attributeDetails[1];
+    }
+    element.text = attributeDetails[0];
+    element.title = attributeDetails[2];
+    return element;
+  }
+
+  onHide() {
+    super.onHide();
+    infoBox = null;
+    infoButton = null;
+  }
+
+  showInfoBox() {
+    if ((infoButton == null) || (infoBox == null)) {
+      return;
+    }
+    _infoBoxShown = true;
+    infoBox.style.display = 'block';
+    infoButton.children.clear();
+    infoButton.children.add(new Element.tag('icon-info'));
+  }
+
+  hideInfoBox() {
+    _infoBoxShown = false;
+    if ((infoButton == null) || (infoBox == null)) {
+      return;
+    }
+    infoBox.style.display = 'none';
+    infoButton.children.clear();
+    infoButton.children.add(new Element.tag('icon-info-outline'));
+  }
+
+  toggleInfoBox() {
+   if (_infoBoxShown) {
+     hideInfoBox();
+   } else {
+     showInfoBox();
+   }
+  }
+
+  hideAllInfoBoxes() {
+    final List<ProfileTreeRow> rows = tree.rows;
+    for (var row in rows) {
+      row.hideInfoBox();
+    }
+  }
+
+  onClick(MouseEvent e) {
+    e.stopPropagation();
+    if (e.altKey) {
+      bool show = !_infoBoxShown;
+      hideAllInfoBoxes();
+      if (show) {
+        showInfoBox();
+      }
+      return;
+    }
+    super.onClick(e);
+  }
+
+  HtmlElement newCodeRef(ProfileCode code) {
+    var codeRef = new Element.tag('code-ref');
+    codeRef.ref = code.code;
+    return codeRef;
+  }
+
+  HtmlElement newFunctionRef(ProfileFunction function) {
+    var ref = new Element.tag('function-ref');
+    ref.ref = function.function;
+    return ref;
+  }
+
+  HtmlElement hr() {
+    var element = new HRElement();
+    return element;
+  }
+
+  HtmlElement div(String text) {
+    var element = new DivElement();
+    element.text = text;
+    return element;
+  }
+
+  HtmlElement br() {
+    return new BRElement();
+  }
+
+  HtmlElement span(String text) {
+    var element = new SpanElement();
+    element.style.minWidth = '1em';
+    element.text = text;
+    return element;
+  }
+}
+
+class CodeProfileTreeRow extends ProfileTreeRow<CodeCallTreeNode> {
+  CodeProfileTreeRow(TableTree tree, CodeProfileTreeRow parent,
+                     CpuProfile profile, CodeCallTreeNode node)
+      : super(tree, parent, profile, node,
+              node.profileCode.normalizedExclusiveTicks,
+              node.percentage) {
+    // fill out attributes.
+  }
+
+  bool hasChildren() => node.children.length > 0;
+
+  void onShow() {
+    super.onShow();
+
+    if (children.length == 0) {
+      for (var childNode in node.children) {
+        var row = new CodeProfileTreeRow(tree, this, profile, childNode);
+        children.add(row);
+      }
+    }
+
+    // Fill in method column.
+    var methodColumn = flexColumns[0];
+    methodColumn.style.justifyContent = 'flex-start';
+    methodColumn.style.position = 'relative';
+
+    // Percent.
+    var percentNode = new DivElement();
+    percentNode.text = percent;
+    percentNode.style.minWidth = '5em';
+    percentNode.style.textAlign = 'right';
+    percentNode.title = 'Executing: $selfPercent';
+    methodColumn.children.add(percentNode);
+
+    // Gap.
+    var gap = new SpanElement();
+    gap.style.minWidth = '1em';
+    methodColumn.children.add(gap);
+
+    // Code link.
+    var codeRef = newCodeRef(node.profileCode);
+    codeRef.style.alignSelf = 'center';
+    methodColumn.children.add(codeRef);
+
+    gap = new SpanElement();
+    gap.style.minWidth = '1em';
+    methodColumn.children.add(gap);
+
+    for (var attribute in sorted(node.attributes)) {
+      methodColumn.children.add(newAttributeBox(attribute));
+    }
+
+    makeInfoBox();
+    methodColumn.children.add(infoBox);
+
+    infoBox.children.add(span('Code '));
+    infoBox.children.add(newCodeRef(node.profileCode));
+    infoBox.children.add(span(' '));
+    for (var attribute in sorted(node.profileCode.attributes)) {
+      infoBox.children.add(newAttributeBox(attribute));
+    }
+    infoBox.children.add(br());
+    infoBox.children.add(br());
+    var memberList = new DivElement();
+    memberList.classes.add('memberList');
+    infoBox.children.add(br());
+    infoBox.children.add(memberList);
+    ProfileTreeRow._addToMemberList(memberList, {
+        'Exclusive ticks' : node.profileCode.formattedExclusiveTicks,
+        'Cpu time' : node.profileCode.formattedCpuTime,
+        'Inclusive ticks' : node.profileCode.formattedInclusiveTicks,
+        'Call stack time' : node.profileCode.formattedOnStackTime,
+    });
+
+    makeInfoButton();
+    methodColumn.children.add(infoButton);
+
+    // Fill in self column.
+    var selfColumn = flexColumns[1];
+    selfColumn.style.position = 'relative';
+    selfColumn.style.alignItems = 'center';
+    selfColumn.text = selfPercent;
+  }
+}
+
+class FunctionProfileTreeRow extends ProfileTreeRow<FunctionCallTreeNode> {
+  FunctionProfileTreeRow(TableTree tree, FunctionProfileTreeRow parent,
+                         CpuProfile profile, FunctionCallTreeNode node)
+      : super(tree, parent, profile, node,
+              node.profileFunction.normalizedExclusiveTicks,
+              node.percentage) {
+    // fill out attributes.
+  }
+
+  bool hasChildren() => node.children.length > 0;
+
+  onShow() {
+    super.onShow();
+    if (children.length == 0) {
+      for (var childNode in node.children) {
+        var row = new FunctionProfileTreeRow(tree, this, profile, childNode);
+        children.add(row);
+      }
+    }
+
+    var methodColumn = flexColumns[0];
+    methodColumn.style.justifyContent = 'flex-start';
+
+    var codeAndFunctionColumn = new DivElement();
+    codeAndFunctionColumn.classes.add('flex-column');
+    codeAndFunctionColumn.style.justifyContent = 'center';
+    codeAndFunctionColumn.style.width = '100%';
+    methodColumn.children.add(codeAndFunctionColumn);
+
+    var functionRow = new DivElement();
+    functionRow.classes.add('flex-row');
+    functionRow.style.position = 'relative';
+    functionRow.style.justifyContent = 'flex-start';
+    codeAndFunctionColumn.children.add(functionRow);
+
+    // Insert the parent percentage
+    var parentPercent = new SpanElement();
+    parentPercent.text = percent;
+    parentPercent.style.minWidth = '4em';
+    parentPercent.style.alignSelf = 'center';
+    parentPercent.style.textAlign = 'right';
+    parentPercent.title = 'Executing: $selfPercent';
+    functionRow.children.add(parentPercent);
+
+    // Gap.
+    var gap = new SpanElement();
+    gap.style.minWidth = '1em';
+    gap.text = ' ';
+    functionRow.children.add(gap);
+
+    var functionRef = new Element.tag('function-ref');
+    functionRef.ref = node.profileFunction.function;
+    functionRef.style.alignSelf = 'center';
+    functionRow.children.add(functionRef);
+
+    gap = new SpanElement();
+    gap.style.minWidth = '1em';
+    gap.text = ' ';
+    functionRow.children.add(gap);
+
+    for (var attribute in sorted(node.attributes)) {
+      functionRow.children.add(newAttributeBox(attribute));
+    }
+
+    makeInfoBox();
+    functionRow.children.add(infoBox);
+
+    if (M.hasDartCode(node.profileFunction.function.kind)) {
+      infoBox.children.add(div('Code for current node'));
+      infoBox.children.add(br());
+      var totalTicks = node.totalCodesTicks;
+      var numCodes = node.codes.length;
+      for (var i = 0; i < numCodes; i++) {
+        var codeRowSpan = new DivElement();
+        codeRowSpan.style.paddingLeft = '1em';
+        infoBox.children.add(codeRowSpan);
+        var nodeCode = node.codes[i];
+        var ticks = nodeCode.ticks;
+        var percentage = Utils.formatPercent(ticks, totalTicks);
+        var percentageSpan = new SpanElement();
+        percentageSpan.style.display = 'inline-block';
+        percentageSpan.text = '$percentage';
+        percentageSpan.style.minWidth = '5em';
+        percentageSpan.style.textAlign = 'right';
+        codeRowSpan.children.add(percentageSpan);
+        var codeRef = new Element.tag('code-ref');
+        codeRef.ref = nodeCode.code.code;
+        codeRef.style.marginLeft = '1em';
+        codeRef.style.marginRight = 'auto';
+        codeRef.style.width = '100%';
+        codeRowSpan.children.add(codeRef);
+      }
+      infoBox.children.add(hr());
+    }
+    infoBox.children.add(span('Function '));
+    infoBox.children.add(newFunctionRef(node.profileFunction));
+    infoBox.children.add(span(' '));
+    for (var attribute in sorted(node.profileFunction.attributes)) {
+      infoBox.children.add(newAttributeBox(attribute));
+    }
+    var memberList = new DivElement();
+    memberList.classes.add('memberList');
+    infoBox.children.add(br());
+    infoBox.children.add(br());
+    infoBox.children.add(memberList);
+    infoBox.children.add(br());
+    ProfileTreeRow._addToMemberList(memberList, {
+        'Exclusive ticks' : node.profileFunction.formattedExclusiveTicks,
+        'Cpu time' : node.profileFunction.formattedCpuTime,
+        'Inclusive ticks' : node.profileFunction.formattedInclusiveTicks,
+        'Call stack time' : node.profileFunction.formattedOnStackTime,
+    });
+
+    if (M.hasDartCode(node.profileFunction.function.kind)) {
+      infoBox.children.add(div('Code containing function'));
+      infoBox.children.add(br());
+      var totalTicks = profile.sampleCount;
+      var codes = node.profileFunction.profileCodes;
+      var numCodes = codes.length;
+      for (var i = 0; i < numCodes; i++) {
+        var codeRowSpan = new DivElement();
+        codeRowSpan.style.paddingLeft = '1em';
+        infoBox.children.add(codeRowSpan);
+        var profileCode = codes[i];
+        var code = profileCode.code;
+        var ticks = profileCode.inclusiveTicks;
+        var percentage = Utils.formatPercent(ticks, totalTicks);
+        var percentageSpan = new SpanElement();
+        percentageSpan.style.display = 'inline-block';
+        percentageSpan.text = '$percentage';
+        percentageSpan.style.minWidth = '5em';
+        percentageSpan.style.textAlign = 'right';
+        percentageSpan.title = 'Inclusive ticks';
+        codeRowSpan.children.add(percentageSpan);
+        var codeRef = new Element.tag('code-ref');
+        codeRef.ref = code;
+        codeRef.style.marginLeft = '1em';
+        codeRef.style.marginRight = 'auto';
+        codeRef.style.width = '100%';
+        codeRowSpan.children.add(codeRef);
+      }
+    }
+
+    makeInfoButton();
+    methodColumn.children.add(infoButton);
+
+    // Fill in self column.
+    var selfColumn = flexColumns[1];
+    selfColumn.style.position = 'relative';
+    selfColumn.style.alignItems = 'center';
+    selfColumn.text = selfPercent;
+  }
+}
+
+class NameSortedTable extends SortedTable {
+  NameSortedTable(columns) : super(columns);
+  @override
+  dynamic getSortKeyFor(int row, int col) {
+    if (col == FUNCTION_COLUMN) {
+      // Use name as sort key.
+      return rows[row].values[col].name;
+    }
+    return super.getSortKeyFor(row, col);
+  }
+
+  SortedTableRow rowFromIndex(int tableIndex) {
+    final modelIndex = sortedRows[tableIndex];
+    return rows[modelIndex];
+  }
+
+  static const FUNCTION_SPACER_COLUMNS = const [];
+  static const FUNCTION_COLUMN = 2;
+  TableRowElement _makeFunctionRow() {
+    var tr = new TableRowElement();
+    var cell;
+
+    // Add percentage.
+    cell = tr.insertCell(-1);
+    cell = tr.insertCell(-1);
+
+    // Add function ref.
+    cell = tr.insertCell(-1);
+    var functionRef = new Element.tag('function-ref');
+    cell.children.add(functionRef);
+
+    return tr;
+  }
+
+  static const CALL_SPACER_COLUMNS = const [];
+  static const CALL_FUNCTION_COLUMN = 1;
+  TableRowElement _makeCallRow() {
+    var tr = new TableRowElement();
+    var cell;
+
+    // Add percentage.
+    cell = tr.insertCell(-1);
+    // Add function ref.
+    cell = tr.insertCell(-1);
+    var functionRef = new Element.tag('function-ref');
+    cell.children.add(functionRef);
+    return tr;
+  }
+
+  _updateRow(TableRowElement tr,
+             int rowIndex,
+             List spacerColumns,
+             int refColumn) {
+    var row = rows[rowIndex];
+    // Set reference
+    var ref = tr.children[refColumn].children[0];
+    ref.ref = row.values[refColumn];
+
+    for (var i = 0; i < row.values.length; i++) {
+      if (spacerColumns.contains(i) || (i == refColumn)) {
+        // Skip spacer columns.
+        continue;
+      }
+      var cell = tr.children[i];
+      cell.title = row.values[i].toString();
+      cell.text = getFormattedValue(rowIndex, i);
+    }
+  }
+
+  _updateTableView(HtmlElement table,
+                   HtmlElement makeEmptyRow(),
+                   void onRowClick(TableRowElement tr),
+                   List spacerColumns,
+                   int refColumn) {
+    assert(table != null);
+
+    // Resize DOM table.
+    if (table.children.length > sortedRows.length) {
+      // Shrink the table.
+      var deadRows = table.children.length - sortedRows.length;
+      for (var i = 0; i < deadRows; i++) {
+        table.children.removeLast();
+      }
+    } else if (table.children.length < sortedRows.length) {
+      // Grow table.
+      var newRows = sortedRows.length - table.children.length;
+      for (var i = 0; i < newRows; i++) {
+        var row = makeEmptyRow();
+        row.onClick.listen((e) {
+          e.stopPropagation();
+          e.preventDefault();
+          onRowClick(row);
+        });
+        table.children.add(row);
+      }
+    }
+
+    assert(table.children.length == sortedRows.length);
+
+    // Fill table.
+    for (var i = 0; i < sortedRows.length; i++) {
+      var rowIndex = sortedRows[i];
+      var tr = table.children[i];
+      _updateRow(tr, rowIndex, spacerColumns, refColumn);
+    }
+  }
+}
+
+@CustomTag('cpu-profile-table')
+class CpuProfileTableElement extends ObservatoryElement {
+
+
+  CpuProfileTableElement.created() : super.created() {
+    _updateTask = new Task(update);
+    _renderTask = new Task(render);
+    var columns = [
+        new SortedTableColumn.withFormatter('Executing (%)',
+                                            Utils.formatPercentNormalized),
+        new SortedTableColumn.withFormatter('In stack (%)',
+                                            Utils.formatPercentNormalized),
+        new SortedTableColumn('Method'),
+    ];
+    profileTable = new NameSortedTable(columns);
+    profileTable.sortColumnIndex = 0;
+
+    columns = [
+        new SortedTableColumn.withFormatter('Callees (%)',
+                                            Utils.formatPercentNormalized),
+        new SortedTableColumn('Method')
+    ];
+    profileCalleesTable = new NameSortedTable(columns);
+    profileCalleesTable.sortColumnIndex = 0;
+
+    columns = [
+        new SortedTableColumn.withFormatter('Callers (%)',
+                                            Utils.formatPercentNormalized),
+        new SortedTableColumn('Method')
+    ];
+    profileCallersTable = new NameSortedTable(columns);
+    profileCallersTable.sortColumnIndex = 0;
+  }
+
+  attached() {
+    super.attached();
+    _updateTask.queue();
+    _resizeSubscription = window.onResize.listen((_) => _updateSize());
+    _updateSize();
+  }
+
+  detached() {
+    super.detached();
+    if (_resizeSubscription != null) {
+      _resizeSubscription.cancel();
+    }
+  }
+
+  _updateSize() {
+    HtmlElement e = $['main'];
+    final totalHeight = window.innerHeight;
+    final top = e.offset.top;
+    final bottomMargin = 32;
+    final mainHeight = totalHeight - top - bottomMargin;
+    e.style.setProperty('height', '${mainHeight}px');
+  }
+
+  isolateChanged(oldValue) {
+    _updateTask.queue();
+  }
+
+  update() async {
+    _clearView();
+    if (isolate == null) {
+      return;
+    }
+    final stream = _repository.get(isolate, M.SampleProfileTag.none);
+    var progress = (await stream.first).progress;
+    shadowRoot.querySelector('#sampleBufferControl').children = [
+      sampleBufferControlElement =
+        new SampleBufferControlElement(progress, stream, showTag: false,
+          selectedTag: M.SampleProfileTag.none, queue: app.queue)
+    ];
+    if (M.isSampleProcessRunning(progress.status)) {
+      progress = (await stream.last).progress;
+    }
+    if (progress.status == M.SampleProfileLoadingStatus.loaded) {
+      _profile = progress.profile;
+      shadowRoot.querySelector('#stackTraceTreeConfig').children = [
+        stackTraceTreeConfigElement =
+            new StackTraceTreeConfigElement(showMode: false,
+                showDirection: false, mode: ProfileTreeMode.function,
+                direction: M.ProfileTreeDirection.exclusive, queue: app.queue)
+              ..onModeChange.listen((e) {
+                cpuProfileTreeElement.mode = e.element.mode;
+                _renderTask.queue();
+              })
+              ..onDirectionChange.listen((e) {
+                cpuProfileTreeElement.direction = e.element.direction;
+                _renderTask.queue();
+              })
+              ..onFilterChange.listen((e) =>_renderTask.queue())
+      ];
+      shadowRoot.querySelector('#cpuProfileTree').children = [
+        cpuProfileTreeElement =
+            new CpuProfileVirtualTreeElement(isolate, _profile,
+                queue: app.queue)
+      ];
+    }
+    _renderTask.queue();
+  }
+
+  Future clearCpuProfile() async {
+    await isolate.invokeRpc('_clearCpuProfile', { });
+    _updateTask.queue();
+    return new Future.value(null);
+  }
+
+  Future refresh() {
+    _updateTask.queue();
+    return new Future.value(null);
+  }
+
+  render() {
+    _updateView();
+  }
+
+  checkParameters() {
+    if (isolate == null) {
+      return;
+    }
+    var functionId = app.locationManager.uri.queryParameters['functionId'];
+    var functionName =
+        app.locationManager.uri.queryParameters['functionName'];
+    if (functionId == '') {
+      // Fallback to searching by name.
+      _focusOnFunction(_findFunction(functionName));
+    } else {
+      if (functionId == null) {
+        _focusOnFunction(null);
+        return;
+      }
+      isolate.getObject(functionId).then((func) => _focusOnFunction(func));
+    }
+  }
+
+  _clearView() {
+    profileTable.clearRows();
+    _renderTable();
+  }
+
+  _updateView() {
+    _buildFunctionTable();
+    _renderTable();
+    _updateFunctionTreeView();
+  }
+
+  int _findFunctionRow(ServiceFunction function) {
+    for (var i = 0; i < profileTable.sortedRows.length; i++) {
+      var rowIndex = profileTable.sortedRows[i];
+      var row = profileTable.rows[rowIndex];
+      if (row.values[NameSortedTable.FUNCTION_COLUMN] == function) {
+        return i;
+      }
+    }
+    return -1;
+  }
+
+  _scrollToFunction(ServiceFunction function) {
+    TableSectionElement tableBody = $['profile-table'];
+    var row = _findFunctionRow(function);
+    if (row == -1) {
+      return;
+    }
+    tableBody.children[row].classes.remove('shake');
+    // trigger reflow.
+    tableBody.children[row].offsetHeight;
+    tableBody.children[row].scrollIntoView(ScrollAlignment.CENTER);
+    tableBody.children[row].classes.add('shake');
+    // Focus on clicked function.
+    _focusOnFunction(function);
+  }
+
+  _clearFocusedFunction() {
+    TableSectionElement tableBody = $['profile-table'];
+    // Clear current focus.
+    if (focusedRow != null) {
+      tableBody.children[focusedRow].classes.remove('focused');
+    }
+    focusedRow = null;
+    focusedFunction = null;
+  }
+
+  ServiceFunction _findFunction(String functionName) {
+    for (var func in _profile.functions) {
+      if (func.function.name == functionName) {
+        return func.function;
+      }
+    }
+    return null;
+  }
+
+  _focusOnFunction(ServiceFunction function) {
+    if (focusedFunction == function) {
+      // Do nothing.
+      return;
+    }
+
+    _clearFocusedFunction();
+
+    if (function == null) {
+      _updateFunctionTreeView();
+      _clearCallTables();
+      return;
+    }
+
+    var row = _findFunctionRow(function);
+    if (row == -1) {
+      _updateFunctionTreeView();
+      _clearCallTables();
+      return;
+    }
+
+    focusedRow = row;
+    focusedFunction = function;
+
+    TableSectionElement tableBody = $['profile-table'];
+    tableBody.children[focusedRow].classes.add('focused');
+    _updateFunctionTreeView();
+    _buildCallersTable(focusedFunction);
+    _buildCalleesTable(focusedFunction);
+  }
+
+  _onRowClick(TableRowElement tr) {
+    var tableBody = $['profile-table'];
+    var row = profileTable.rowFromIndex(tableBody.children.indexOf(tr));
+    var function = row.values[NameSortedTable.FUNCTION_COLUMN];
+    app.locationManager.goReplacingParameters(
+        {
+          'functionId': function.id,
+          'functionName': function.vmName
+        }
+    );
+  }
+
+  _renderTable() {
+    profileTable._updateTableView($['profile-table'],
+                                  profileTable._makeFunctionRow,
+                                  _onRowClick,
+                                  NameSortedTable.FUNCTION_SPACER_COLUMNS,
+                                  NameSortedTable.FUNCTION_COLUMN);
+  }
+
+  _buildFunctionTable() {
+    for (var func in _profile.functions) {
+      if ((func.exclusiveTicks == 0) && (func.inclusiveTicks == 0)) {
+        // Skip.
+        continue;
+      }
+      var row = [
+        func.normalizedExclusiveTicks,
+        func.normalizedInclusiveTicks,
+        func.function,
+      ];
+      profileTable.addRow(new SortedTableRow(row));
+    }
+    profileTable.sort();
+  }
+
+  _renderCallTable(TableSectionElement view,
+                   NameSortedTable model,
+                   void onRowClick(TableRowElement tr)) {
+    model._updateTableView(view,
+                           model._makeCallRow,
+                           onRowClick,
+                           NameSortedTable.CALL_SPACER_COLUMNS,
+                           NameSortedTable.CALL_FUNCTION_COLUMN);
+  }
+
+  _buildCallTable(Map<ProfileFunction, int> calls,
+                  NameSortedTable model) {
+    model.clearRows();
+    if (calls == null) {
+      return;
+    }
+    var sum = 0;
+    calls.values.forEach((i) => sum += i);
+    calls.forEach((func, count) {
+      var row = [
+          count / sum,
+          func.function,
+      ];
+      model.addRow(new SortedTableRow(row));
+    });
+    model.sort();
+  }
+
+  _clearCallTables() {
+    _buildCallersTable(null);
+    _buildCalleesTable(null);
+  }
+
+  _onCallersClick(TableRowElement tr) {
+    var table = $['callers-table'];
+    final row = profileCallersTable.rowFromIndex(table.children.indexOf(tr));
+    var function = row.values[NameSortedTable.CALL_FUNCTION_COLUMN];
+    _scrollToFunction(function);
+  }
+
+  _buildCallersTable(ServiceFunction function) {
+    var calls = (function != null) ? function.profile.callers : null;
+    var table = $['callers-table'];
+    _buildCallTable(calls, profileCallersTable);
+    _renderCallTable(table, profileCallersTable, _onCallersClick);
+  }
+
+  _onCalleesClick(TableRowElement tr) {
+    var table = $['callees-table'];
+    final row = profileCalleesTable.rowFromIndex(table.children.indexOf(tr));
+    var function = row.values[NameSortedTable.CALL_FUNCTION_COLUMN];
+    _scrollToFunction(function);
+  }
+
+  _buildCalleesTable(ServiceFunction function) {
+    var calls = (function != null) ? function.profile.callees : null;
+    var table = $['callees-table'];
+    _buildCallTable(calls, profileCalleesTable);
+    _renderCallTable(table, profileCalleesTable, _onCalleesClick);
+  }
+
+  _changeSort(Element target, NameSortedTable table) {
+    if (target is TableCellElement) {
+      if (table.sortColumnIndex != target.cellIndex) {
+        table.sortColumnIndex = target.cellIndex;
+        table.sortDescending = true;
+      } else {
+        table.sortDescending = !profileTable.sortDescending;
+      }
+      table.sort();
+    }
+  }
+
+  changeSortProfile(Event e, var detail, Element target) {
+    _changeSort(target, profileTable);
+    _renderTable();
+  }
+
+  changeSortCallers(Event e, var detail, Element target) {
+    _changeSort(target, profileCallersTable);
+    _renderCallTable($['callers-table'], profileCallersTable, _onCallersClick);
+  }
+
+  changeSortCallees(Event e, var detail, Element target) {
+    _changeSort(target, profileCalleesTable);
+    _renderCallTable($['callees-table'], profileCalleesTable, _onCalleesClick);
+  }
+
+  //////
+  ///
+  /// Function tree.
+  ///
+  TableTree functionTree;
+  _updateFunctionTreeView() {
+    if (cpuProfileTreeElement == null) {
+      return;
+    }
+    cpuProfileTreeElement.filter = (FunctionCallTreeNode node) {
+      return node.profileFunction.function == focusedFunction;
+    };
+  }
+
+  @published Isolate isolate;
+  @observable NameSortedTable profileTable;
+  @observable NameSortedTable profileCallersTable;
+  @observable NameSortedTable profileCalleesTable;
+  @observable ServiceFunction focusedFunction;
+  @observable int focusedRow;
+
+
+  StreamSubscription _resizeSubscription;
+  Task _updateTask;
+  Task _renderTask;
+
+  IsolateSampleProfileRepository _repository =
+      new IsolateSampleProfileRepository();
+  CpuProfile _profile;
+  SampleBufferControlElement sampleBufferControlElement;
+  StackTraceTreeConfigElement stackTraceTreeConfigElement;
+  CpuProfileVirtualTreeElement cpuProfileTreeElement;
+}
diff --git a/runtime/observatory/lib/src/elements/cpu_profile_table.html b/runtime/observatory/lib/src/elements/cpu_profile_table.html
new file mode 100644
index 0000000..b95c0bc
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/cpu_profile_table.html
@@ -0,0 +1,218 @@
+<link rel="import" href="../../../../packages/polymer/polymer.html">
+
+<polymer-element name="cpu-profile-table">
+  <template>
+    <link rel="stylesheet" href="css/shared.css">
+    <nav-bar>
+      <top-nav-menu></top-nav-menu>
+      <vm-nav-menu vm="{{ isolate.vm }}"></vm-nav-menu>
+      <isolate-nav-menu isolate="{{ isolate }}"></isolate-nav-menu>
+      <nav-menu link="{{ makeLink('/profiler-table', isolate) }}" anchor="cpu profile (table)" last="{{ true }}"></nav-menu>
+      <nav-refresh callback="{{ refresh }}"></nav-refresh>
+      <nav-refresh callback="{{ clearCpuProfile }}" label="Clear"></nav-refresh>
+      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
+    </nav-bar>
+    <style>
+      /* general */
+      .well {
+        background-color: #ECECEC;
+        padding: 0.2em;
+      }
+      .center {
+        align-items: center;
+        justify-content: center;
+      }
+
+      /* status messages */
+      .statusMessage {
+        font-size: 150%;
+        font-weight: bold;
+      }
+      .statusBox {
+        height: 100%;
+        padding: 1em;
+      }
+
+      /* tables */
+      .table {
+        border-collapse: collapse!important;
+        table-layout: fixed;
+        height: 100%;
+      }
+      .th, .td {
+        padding: 8px;
+        vertical-align: top;
+      }
+      .table thead > tr > th {
+        vertical-align: bottom;
+        text-align: left;
+        border-bottom:2px solid #ddd;
+      }
+      .spacer {
+        width: 16px;
+      }
+      .left-border-spacer {
+        width: 16px;
+        border-left: 1px solid;
+      }
+      .clickable {
+        color: #0489c3;
+        text-decoration: none;
+        cursor: pointer;
+        min-width: 8em;
+      }
+      .clickable:hover {
+        text-decoration: underline;
+        cursor: pointer;
+      }
+      tr:hover:not(.focused) > td {
+        background-color: #FAFAFA;
+      }
+      .focused {
+        background-color: #F4C7C3;
+      }
+      .scroll {
+        overflow: scroll;
+      }
+      .outlined {
+        -webkit-box-shadow: 0px 0px 2px 1px rgba(0,0,0,0.75);
+        -moz-box-shadow: 0px 0px 2px 1px rgba(0,0,0,0.75);
+        box-shadow: 0px 0px 2px 1px rgba(0,0,0,0.75);
+        margin: 4px;
+      }
+      .centered {
+        margin-left: auto;
+        margin-right: auto;
+        justify-content: center;
+      }
+      .full-height {
+        height: 100%;
+      }
+      .mostly-full-height {
+        height: 80%;
+      }
+      .full-width {
+        width: 100%;
+      }
+      .focused-function-label {
+        flex: 0 1 auto;
+        margin-left: auto;
+        margin-right: auto;
+        justify-content: center;
+      }
+      .call-table {
+        flex: 1 1 auto;
+      }
+
+      .tree {
+        border-spacing: 0px;
+        width: 100%;
+        margin-bottom: 20px
+        vertical-align: middle;
+      }
+
+      .tree tbody tr {
+        animation: fadeIn 0.5s;
+        -moz-animation: fadeIn 0.5s;
+        -webkit-animation: fadeIn 0.5s;
+      }
+
+      .tree tbody tr:hover {
+        background-color: #FAFAFA;
+      }
+
+      .tree tr td:first-child,
+      .tree tr th:first-child {
+        width: 100%;
+      }
+
+      .tree thead > tr > th {
+        padding: 8px;
+        vertical-align: bottom;
+        text-align: left;
+        border-bottom: 1px solid #ddd;
+      }
+
+    </style>
+    <div id="sampleBufferControl"></div>
+    <br>
+    <hr>
+    <div id="main" class="flex-row centered">
+      <div class="flex-item-45-percent full-height outlined scroll">
+        <table id="main-table" class="flex-item-100-percent table">
+          <thead>
+          <tr>
+            <th on-click="{{changeSortProfile}}" class="clickable" title="Executing (%)">{{ profileTable.getColumnLabel(0) }}</th>
+            <th on-click="{{changeSortProfile}}" class="clickable" title="In stack (%)">{{ profileTable.getColumnLabel(1) }}</th>
+            <th on-click="{{changeSortProfile}}" class="clickable" title="Method">{{ profileTable.getColumnLabel(2) }}</th>
+          </tr>
+          </thead>
+          <tbody id="profile-table">
+          </tbody>
+        </table>
+      </div>
+      <div class="flex-item-45-percent full-height outlined">
+        <div class="flex-column full-height">
+          <div class="focused-function-label">
+            <template if="{{ focusedFunction != null }}">
+              <span>Focused on: </span>
+              <function-ref ref="{{ focusedFunction }}"></function-ref>
+            </template>
+            <template if="{{ focusedFunction == null }}">
+              <span>No focused function</span>
+            </template>
+          </div>
+          <hr>
+          <div class="call-table scroll">
+            <table class="full-width table">
+              <thead>
+              <tr>
+                <th on-click="{{changeSortCallers}}" class="clickable" title="Callers (%)">{{ profileCallersTable.getColumnLabel(0) }}</th>
+                <th on-click="{{changeSortCallers}}" class="clickable" title="Method">{{ profileCallersTable.getColumnLabel(1) }}</th>
+              </tr>
+              </thead>
+              <tbody id="callers-table">
+              </tbody>
+            </table>
+          </div>
+          <hr>
+          <div class="call-table scroll">
+            <table class="full-width table">
+              <thead>
+              <tr>
+                <th on-click="{{changeSortCallees}}" class="clickable" title="Callees (%)">{{ profileCalleesTable.getColumnLabel(0) }}</th>
+                <th on-click="{{changeSortCallees}}" class="clickable" title="Method">{{ profileCalleesTable.getColumnLabel(1) }}</th>
+              </tr>
+              </thead>
+              <tbody id="callees-table">
+              </tbody>
+            </table>
+          </div>
+        </div>
+      </div>
+    </div>
+    <br>
+    <div id="stackTraceTreeConfig"></div>
+    <br>
+    <div class="content-centered-big">
+      <div class="focused-function-label">
+        <template if="{{ focusedFunction != null }}">
+          <span>Filtered tree: </span>
+          <function-ref ref="{{ focusedFunction }}"></function-ref>
+        </template>
+        <template if="{{ focusedFunction == null }}">
+          <span>No focused function</span>
+        </template>
+      </div>
+    </div>
+    <br>
+    <br>
+    <div class="flex-row centered">
+      <div class="flex-item-90-percent outlined" style="margin: 16px; margin-left: 8px; margin-right: 8px">
+        <div id="cpuProfileTree"></div>
+      </div>
+    </div>
+  </template>
+</polymer-element>
+
+<script type="application/dart" src="cpu_profile.dart"></script>
diff --git a/runtime/observatory/lib/src/elements/css/shared.css b/runtime/observatory/lib/src/elements/css/shared.css
index e468fc8..9e4a0f5 100644
--- a/runtime/observatory/lib/src/elements/css/shared.css
+++ b/runtime/observatory/lib/src/elements/css/shared.css
@@ -61,12 +61,12 @@
   white-space: nowrap;
 }
 
-a {
+a[href] {
   color: #0489c3;
   text-decoration: none;
 }
 
-a:hover {
+a[href]:hover {
   text-decoration: underline;
 }
 
@@ -307,6 +307,12 @@
   font: 400 16px 'Montserrat', sans-serif;
 }
 
+select, button, input {
+  border-radius: 0px;
+  border-style: solid;
+  border-width: 1px;
+}
+
 @-webkit-keyframes fadeIn {
   0%   { opacity: 0; }
   100% { opacity: 1; }
@@ -416,6 +422,56 @@
   margin-left: 0.5em;
 }
 
+/* cpu-profile */
+
+cpu-profile {
+  position: relative;
+  display: block;
+  height: 100%;
+}
+
+cpu-profile > cpu-profile-virtual-tree {
+  position: absolute;
+  height: auto;
+  top: 320px;
+  bottom: 0;
+  left: 0;
+  right: 0;
+}
+
+/* cpu-profile-virtual-tree */
+
+cpu-profile-virtual-tree {
+  display: block;
+  height: 600px;
+}
+
+cpu-profile-virtual-tree .tree-item {
+  line-height: 30px;
+  height: 30px;
+  padding-left: 5%;
+  padding-right: 5%;
+}
+
+cpu-profile-virtual-tree .tree-item > .inclusive,
+cpu-profile-virtual-tree .tree-item > .exclusive,
+cpu-profile-virtual-tree .tree-item > .percentage {
+  display: inline-block;
+  text-align: right;
+  width: 4em;
+  margin-left: 0.25em;
+  margin-right: 0.25em;
+}
+
+cpu-profile-virtual-tree .tree-item > .exclusive {
+  margin-right: 1.5em;
+}
+
+cpu-profile-virtual-tree .tree-item > .name {
+  display: inline;
+  margin-left: 0.5em;
+}
+
 /* error-ref */
 /* TODO(cbernaschina) fix error-ref-wrapped to error-ref when wrapper
 removed */
@@ -461,6 +517,36 @@
   text-decoration: none;
 }
 
+/* isolate-counter-chart */
+
+isolate-counter-chart {
+  display: block;
+  position: relative;
+  height: 300px;
+  min-width: 350px;
+}
+isolate-counter-chart > div.host {
+  position: absolute;
+  left: 0;
+  bottom: 20px;
+  top: 5px;
+  right: 250px;
+}
+isolate-counter-chart > div.legend {
+  position: absolute;
+  width: 250px;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  overflow-y: auto;
+}
+
+/* isolate-reconnect */
+
+isolate-reconnect div.doubleSpaced {
+  line-height: 2em;
+}
+
 /* isolate-ref */
 /* TODO(cbernaschina) fix isolate-ref-wrapped to isolate-ref when wrapper
 removed */
@@ -473,6 +559,38 @@
   text-decoration: none;
 }
 
+/* isolate-shared-summary */
+/* TODO(cbernaschina) fix isolate-shared-summary-wrapped
+to isolate-shared-summary when wrapper removed */
+
+isolate-shared-summary,
+isolate-shared-summary-wrapped {
+  display: block;
+  height: 300px;
+  position: relative;
+}
+isolate-shared-summary-wrapped > .menu {
+  float: right;
+  top: 0;
+  right: 0;
+}
+isolate-shared-summary-wrapped > isolate-counter-chart {
+  position: absolute;
+  left: 0;
+  top: 0;
+  right: 230px;
+  clear: both;
+}
+isolate-shared-summary-wrapped .errorBox {
+  background-color: #f5f5f5;
+  border: 1px solid #ccc;
+  padding: 2em;
+  font-family: consolas, courier, monospace;
+  font-size: 1em;
+  line-height: 1.2em;
+  white-space: pre;
+}
+
 /* library-ref */
 /* TODO(cbernaschina) fix library-ref-wrapped to library-ref when wrapper
 removed */
@@ -621,6 +739,47 @@
 }
 
 
+/* observatory-application */
+
+observatory-application {
+  display: block;
+  height: 100%;
+}
+
+observatory-application > div {
+  display: block;
+  height: 100%;
+}
+
+/* sample-buffer-control */
+
+sample-buffer-control .statusMessage {
+  font-size: 150%;
+  font-weight: bold;
+}
+
+sample-buffer-control .statusBox {
+  height: 100%;
+  padding: 1em;
+}
+
+sample-buffer-control .center {
+  align-items: center;
+  justify-content: center;
+}
+
+sample-buffer-control .notice {
+  background-color: #fcf8e3;
+}
+
+sample-buffer-control .red {
+  background-color: #f2dede;
+}
+
+sample-buffer-control .shadow {
+  box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.16),
+              0 2px 5px 0 rgba(0, 0, 0, 0.26);
+}
 
 /* view-footer */
 
@@ -681,6 +840,12 @@
   font-weight: bold;
   font-size: 18px;
   width: 19px;
+  border: none;
+  background-color: transparent;
+}
+
+virtual-tree .expander:focus {
+  outline: none;
 }
 
 virtual-tree .lines,
diff --git a/runtime/observatory/lib/src/elements/helpers/rendering_scheduler.dart b/runtime/observatory/lib/src/elements/helpers/rendering_scheduler.dart
index a2ab155..d5ba83d 100644
--- a/runtime/observatory/lib/src/elements/helpers/rendering_scheduler.dart
+++ b/runtime/observatory/lib/src/elements/helpers/rendering_scheduler.dart
@@ -13,7 +13,7 @@
 }
 
 /// Event related to a Renderable rendering phase.
-class RenderedEvent<T extends Renderable> {
+class RenderedEvent<T> {
   /// Renderable to which the event is related
   final T element;
   /// Is another rendering scheduled for this element.
diff --git a/runtime/observatory/lib/src/elements/helpers/uris.dart b/runtime/observatory/lib/src/elements/helpers/uris.dart
index a099bbf..b243f78 100644
--- a/runtime/observatory/lib/src/elements/helpers/uris.dart
+++ b/runtime/observatory/lib/src/elements/helpers/uris.dart
@@ -13,35 +13,37 @@
     return '#' + new Uri(path: path, queryParameters: parameters).toString();
   }
 
-  static String inspect(M.IsolateRef isolate, {M.ObjectRef object, int pos}) {
-    if (pos == null) {
-      return _isolatePage('/inspect', isolate, object: object);
-    }
-    return _isolatePage('/inspect', isolate, object: object) + '---pos=${pos}';
-  }
-  static String debugger(M.IsolateRef isolate)
-      => _isolatePage('/debugger', isolate);
+  static String allocationProfiler(M.IsolateRef isolate)
+      => _isolatePage('/allocation-profiler', isolate);
   static String classTree(M.IsolateRef isolate)
       => _isolatePage('/class-tree', isolate);
   static String cpuProfiler(M.IsolateRef isolate)
       => _isolatePage('/profiler', isolate);
   static String cpuProfilerTable(M.IsolateRef isolate)
       => _isolatePage('/profiler-table', isolate);
-  static String allocationProfiler(M.IsolateRef isolate)
-      => _isolatePage('/allocation-profiler', isolate);
+  static String debugger(M.IsolateRef isolate)
+      => _isolatePage('/debugger', isolate);
+  static String flags() => '#/flags';
   static String heapMap(M.IsolateRef isolate)
       => _isolatePage('/heap-map', isolate);
-  static String metrics(M.IsolateRef isolate)
-      => _isolatePage('/metrics', isolate);
   static String heapSnapshot(M.IsolateRef isolate)
       => _isolatePage('/heap-snapshot', isolate);
+  static String inspect(M.IsolateRef isolate, {M.ObjectRef object, int pos}) {
+    if (pos == null) {
+      return _isolatePage('/inspect', isolate, object: object);
+    }
+    return _isolatePage('/inspect', isolate, object: object) + '---pos=${pos}';
+  }
+  static String logging(M.IsolateRef isolate)
+      => _isolatePage('/logging', isolate);
+  static String metrics(M.IsolateRef isolate)
+      => _isolatePage('/metrics', isolate);
   static String persistentHandles(M.IsolateRef isolate)
       => _isolatePage('/persistent-handles', isolate);
   static String ports(M.IsolateRef isolate)
       => _isolatePage('/ports', isolate);
-  static String logging(M.IsolateRef isolate)
-      => _isolatePage('/logging', isolate);
+  static String profiler(M.IsolateRef isolate)
+      => _isolatePage('/profiler', isolate);
   static String vm() => '#/vm';
   static String vmConnect() => '#/vm-connect';
-  static String flags() => '#/flags';
 }
diff --git a/runtime/observatory/lib/src/elements/isolate/counter_chart.dart b/runtime/observatory/lib/src/elements/isolate/counter_chart.dart
new file mode 100644
index 0000000..3c7b3bc
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/isolate/counter_chart.dart
@@ -0,0 +1,77 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:charted/charted.dart';
+import "package:charted/charts/charts.dart";
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+
+class IsolateCounterChartElement extends HtmlElement implements Renderable {
+  static const tag =
+    const Tag<IsolateCounterChartElement>('isolate-counter-chart');
+
+  RenderingScheduler<IsolateCounterChartElement> _r;
+
+  Stream<RenderedEvent<IsolateCounterChartElement>> get onRendered =>
+      _r.onRendered;
+
+  Map _counters;
+  StreamSubscription _subscription;
+
+  factory IsolateCounterChartElement(Map counters, {RenderingQueue queue}) {
+    assert(counters != null);
+    IsolateCounterChartElement e = document.createElement(tag.name);
+    e._r = new RenderingScheduler(e, queue: queue);
+    e._counters = counters;
+    return e;
+  }
+
+  IsolateCounterChartElement.created() : super.created();
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+    _subscription = window.onResize.listen((_) => _r.dirty());
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = [];
+    _r.disable(notify: true);
+    _subscription.cancel();
+  }
+
+  void render() {
+    var areaHost;
+    var legendHost;
+    children = [
+      areaHost = new DivElement()..classes = ['host'],
+      legendHost = new DivElement()..classes = ['legend']
+    ];
+    final series = new ChartSeries("Work", [1], new PieChartRenderer(
+      sortDataByValue: false
+    ));
+    var rect = areaHost.getBoundingClientRect();
+    var minSize = new Rect.size(rect.width, rect.height);
+    final config = new ChartConfig([series], [0])
+        ..minimumSize = minSize
+        ..legend = new ChartLegend(legendHost, showValues: true);
+    final data = new ChartData([
+        new ChartColumnSpec(label: 'Type', type: ChartColumnSpec.TYPE_STRING),
+        new ChartColumnSpec(label: 'Percent', formatter: (v) => v.toString())
+      ], _counters.keys
+          .map((key) => [key, double.parse(_counters[key].split('%')[0])])
+          .toList());
+
+    new LayoutArea(areaHost, data, config, state: new ChartState(),
+        autoUpdate: true)
+      ..addChartBehavior(new Hovercard())
+      ..addChartBehavior(new AxisLabelTooltip())
+      ..draw();
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/isolate/shared_summary.dart b/runtime/observatory/lib/src/elements/isolate/shared_summary.dart
new file mode 100644
index 0000000..51fdc28
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/isolate/shared_summary.dart
@@ -0,0 +1,155 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory/models.dart' as M;
+import 'package:observatory/utils.dart';
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/helpers/uris.dart';
+import 'package:observatory/src/elements/isolate/counter_chart.dart';
+
+class IsolateSharedSummaryElement extends HtmlElement implements Renderable {
+  static const tag =
+    const Tag<IsolateSharedSummaryElement>('isolate-shared-summary-wrapped',
+                                           dependencies: const [
+                                             IsolateCounterChartElement.tag
+                                           ]);
+
+  RenderingScheduler<IsolateSharedSummaryElement> _r;
+
+  Stream<RenderedEvent<IsolateSharedSummaryElement>> get onRendered =>
+      _r.onRendered;
+
+  M.Isolate _isolate;
+
+  factory IsolateSharedSummaryElement(M.Isolate isolate,
+                                      {RenderingQueue queue}) {
+    assert(isolate != null);
+    IsolateSharedSummaryElement e = document.createElement(tag.name);
+    e._r = new RenderingScheduler(e, queue: queue);
+    e._isolate = isolate;
+    return e;
+  }
+
+  IsolateSharedSummaryElement.created() : super.created();
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = [];
+    _r.disable(notify: true);
+  }
+
+  void render() {
+    children = [];
+    if (_isolate.error != null) {
+      children = [
+        new PreElement()..classes = const ["errorBox"]
+          ..text = _isolate.error.message
+      ];
+    }
+    final newHeapUsed = Utils.formatSize(_isolate.newSpace.used);
+    final newHeapCapacity = Utils.formatSize(_isolate.newSpace.capacity);
+    final oldHeapUsed = Utils.formatSize(_isolate.oldSpace.used);
+    final oldHeapCapacity = Utils.formatSize(_isolate.oldSpace.capacity);
+    children.addAll([
+      new DivElement()..classes = ['menu']
+        ..children = [
+          new DivElement()..classes = const ['memberList']
+            ..children = [
+              new DivElement()..classes = const ['memberItem']
+                ..children = [
+                  new DivElement()..classes = const ['memberName']
+                    ..text = 'new heap',
+                  new DivElement()..classes = const ['memberValue']
+                    ..text = '$newHeapUsed of $newHeapCapacity',
+                ],
+              new DivElement()..classes = const ['memberItem']
+                ..children = [
+                  new DivElement()..classes = const ['memberName']
+                    ..text = 'old heap',
+                  new DivElement()..classes = const ['memberValue']
+                    ..text = '$oldHeapUsed of $oldHeapCapacity',
+                ]
+            ],
+          new BRElement(),
+          new DivElement()
+            ..children = [
+              new SpanElement()..text = 'see ',
+              new AnchorElement(href: Uris.debugger(_isolate))
+                ..text = 'debug'
+            ],
+          new DivElement()
+            ..children = [
+              new SpanElement()..text = 'see ',
+              new AnchorElement(href: Uris.classTree(_isolate))
+                ..text = 'class hierarchy'
+            ],
+          new DivElement()
+            ..children = [
+              new SpanElement()..text = 'see ',
+              new AnchorElement(href: Uris.cpuProfiler(_isolate))
+                ..text = 'cpu profile'
+            ],
+          new DivElement()
+            ..children = [
+              new SpanElement()..text = 'see ',
+              new AnchorElement(href: Uris.cpuProfilerTable(_isolate))
+                ..text = 'cpu profile (table)'
+            ],
+          new DivElement()
+            ..children = [
+              new SpanElement()..text = 'see ',
+              new AnchorElement(href: Uris.allocationProfiler(_isolate))
+                ..text = 'allocation profile'
+            ],
+          new DivElement()
+            ..children = [
+              new SpanElement()..text = 'see ',
+              new AnchorElement(href: Uris.heapMap(_isolate))
+                ..text = 'heap map'
+            ],
+          new DivElement()
+            ..children = [
+              new SpanElement()..text = 'see ',
+              new AnchorElement(href: Uris.metrics(_isolate))
+                ..text = 'metrics'
+            ],
+          new DivElement()
+            ..children = [
+              new SpanElement()..text = 'see ',
+              new AnchorElement(href: Uris.heapSnapshot(_isolate))
+                ..text = 'heap snapshot'
+            ],
+          new DivElement()
+            ..children = [
+              new SpanElement()..text = 'see ',
+              new AnchorElement(href: Uris.persistentHandles(_isolate))
+                ..text = 'persistent handles'
+            ],
+          new DivElement()
+            ..children = [
+              new SpanElement()..text = 'see ',
+              new AnchorElement(href: Uris.ports(_isolate))
+                ..text = 'ports'
+            ],
+          new DivElement()
+            ..children = [
+              new SpanElement()..text = 'see ',
+              new AnchorElement(href: Uris.logging(_isolate))
+                ..text = 'logging'
+            ]
+      ],
+      new IsolateCounterChartElement(_isolate.counters, queue: _r.queue)
+    ]);
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/isolate/shared_summary_wrapper.dart b/runtime/observatory/lib/src/elements/isolate/shared_summary_wrapper.dart
new file mode 100644
index 0000000..72b86c2
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/isolate/shared_summary_wrapper.dart
@@ -0,0 +1,167 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory/app.dart';
+import 'package:observatory/service.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/shims/binding.dart';
+import 'package:observatory/src/elements/isolate/shared_summary.dart';
+
+@bindable
+class IsolateSharedSummaryElementWrapper extends HtmlElement {
+  static const binder = const Binder<IsolateSharedSummaryElementWrapper>(const {
+      'isolate': #isolate
+    });
+
+  static const tag =
+      const Tag<IsolateSharedSummaryElementWrapper>('isolate-shared-summary');
+
+  IsolateSharedSummaryElementWrapper.created() : super.created() {
+    binder.registerCallback(this);
+    createShadowRoot();
+    render();
+  }
+
+  Isolate _isolate;
+  StreamSubscription _subscription;
+
+  Isolate get isolate => _isolate;
+
+  void set isolate(Isolate value) {
+    _isolate = value;
+    _detached();
+    _attached();
+  }
+
+  @override
+  void attached() {
+    super.attached();
+    _attached();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    _detached();
+  }
+
+  void _attached() {
+    if (_isolate != null) {
+      _subscription = _isolate.changes.listen((_) { render(); });
+    }
+    render();
+  }
+
+  void _detached() {
+    _subscription?.cancel();
+    _subscription = null;
+  }
+
+  void render() {
+    if (_isolate == null) {
+      return;
+    }
+    shadowRoot.children = [
+      new StyleElement()
+        ..text = '''
+        a[href] {
+          color: #0489c3;
+          text-decoration: none;
+        }
+        a[href]:hover {
+          text-decoration: underline;
+        }
+        .memberList {
+          display: table;
+        }
+        .memberItem {
+          display: table-row;
+        }
+        .memberName, .memberValue {
+          display: table-cell;
+          vertical-align: top;
+          padding: 3px 0 3px 1em;
+          font: 400 14px 'Montserrat', sans-serif;
+        }
+        isolate-shared-summary-wrapped {
+          display: block;
+          height: 300px;
+          position: relative;
+        }
+        isolate-shared-summary-wrapped > .menu {
+          float: right;
+          top: 0;
+          right: 0;
+        }
+        isolate-shared-summary-wrapped > isolate-counter-chart {
+          position: absolute;
+          left: 0;
+          top: 0;
+          right: 230px;
+          clear: both;
+        }
+        isolate-shared-summary-wrapped .errorBox {
+          background-color: #f5f5f5;
+          border: 1px solid #ccc;
+          padding: 2em;
+          font-family: consolas, courier, monospace;
+          font-size: 1em;
+          line-height: 1.2em;
+          white-space: pre;
+        }
+        isolate-counter-chart {
+          display: block;
+          position: relative;
+          height: 300px;
+          min-width: 350px;
+        }
+        isolate-counter-chart > div.host {
+          position: absolute;
+          left: 0;
+          bottom: 20px;
+          top: 5px;
+          right: 250px;
+        }
+        isolate-counter-chart > div.legend {
+          position: absolute;
+          width: 250px;
+          top: 0;
+          right: 0;
+          bottom: 0;
+          overflow-y: auto;
+        }
+        .type-pie-rdr > .chart-legend-color {
+          border-radius: 6px;
+        }
+        .chart-legend-row, .chart-legend-more {
+          width: 100%;
+          display: flex;
+          font-size: 14px;
+          margin-bottom: 16px;
+          position: relative;
+          cursor: default;
+        }
+        .chart-legend-row:hover, .chart-legend-more:hover {
+          font-weight: bold;
+        }
+        .chart-legend-color, .chart-legend-more-color {
+          width: 12px;
+          height: 12px;
+          margin: auto 8px;
+          border-radius: 2px;
+        }
+        .chart-legend-label {
+          overflow: hidden;
+          text-overflow: ellipsis;
+          max-width: 120px;
+          flex: 1;
+        }
+        ''',
+      new IsolateSharedSummaryElement(_isolate,
+                                      queue: ObservatoryApplication.app.queue)
+    ];
+  }
+}
diff --git a/runtime/observatory/lib/src/elements/isolate_reconnect.dart b/runtime/observatory/lib/src/elements/isolate_reconnect.dart
index 01edf8f..465bc0c 100644
--- a/runtime/observatory/lib/src/elements/isolate_reconnect.dart
+++ b/runtime/observatory/lib/src/elements/isolate_reconnect.dart
@@ -4,24 +4,111 @@
 
 library isolate_reconnect_element;
 
-import 'package:polymer/polymer.dart';
-import 'observatory_element.dart';
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory/models.dart' as M;
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/helpers/uris.dart';
+import 'package:observatory/src/elements/nav/bar.dart';
+import 'package:observatory/src/elements/nav/notify.dart';
+import 'package:observatory/src/elements/nav/top_menu.dart';
+import 'package:observatory/src/elements/view_footer.dart';
 
-@CustomTag('isolate-reconnect')
-class IsolateReconnectElement extends ObservatoryElement {
-  IsolateReconnectElement.created() : super.created();
+class IsolateReconnectElement extends HtmlElement implements Renderable{
+  static const tag = const Tag<IsolateReconnectElement>('isolate-reconnect',
+                     dependencies: const [NavBarElement.tag,
+                                          NavTopMenuElement.tag,
+                                          NavNotifyElement.tag,
+                                          ViewFooterElement.tag]);
 
-  get missingIsolateId {
-    return app.locationManager.uri.queryParameters['originalIsolateId'];
+  RenderingScheduler _r;
+
+  Stream<RenderedEvent<IsolateReconnectElement>> get onRendered =>
+      _r.onRendered;
+
+  M.VM _vm;
+  String _missing;
+  Uri _uri;
+  M.EventRepository _events;
+  StreamSubscription _subscription;
+
+  M.VM get vm  => _vm;
+  String get missing => _missing;
+  Uri get uri => _uri;
+
+  M.NotificationRepository _notifications;
+  factory IsolateReconnectElement(M.VM vm, M.EventRepository events,
+      M.NotificationRepository notifications, String missing, Uri uri,
+      {RenderingQueue queue}) {
+    assert(vm != null);
+    assert(events != null);
+    assert(missing != null);
+    assert(uri != null);
+    assert(notifications != null);
+    IsolateReconnectElement e = document.createElement(tag.name);
+    e._r = new RenderingScheduler(e, queue: queue);
+    e._vm = vm;
+    e._events = events;
+    e._missing = missing;
+    e._uri = uri;
+    e._notifications = notifications;
+    return e;
   }
 
-  linkToContinueIn(isolate) {
-    var parameters = new Map.from(app.locationManager.uri.queryParameters);
-    parameters['isolateId'] = isolate.id;
-    parameters.remove('originalIsolateId');
-    var path = parameters.remove('originalPath');
-    path = "/$path";
-    var generatedUri = new Uri(path: path, queryParameters: parameters);
-    return app.locationManager.makeLink(generatedUri.toString());
+  IsolateReconnectElement.created() : super.created();
+
+  @override
+  void attached() {
+    super.attached();
+    _subscription = _events.onVMUpdate.listen((e) {
+      _vm = e.vm;
+      _r.dirty();
+    });
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = [];
+    _r.disable(notify: true);
+    _subscription.cancel();
+  }
+
+  void render() {
+    children = [
+      new NavBarElement(queue: _r.queue)
+        ..children = [
+          new NavTopMenuElement(last: true, queue: _r.queue),
+          new NavNotifyElement(_notifications, queue: _r.queue)
+        ],
+      new DivElement()
+        ..classes = ['content-centered']
+        ..children = [
+          new HeadingElement.h1()..text = 'Isolate $_missing no longer exists',
+          new BRElement(), new HRElement(),
+          new DivElement()..classes = ['memberList']
+            ..children = (_vm.isolates.map((isolate) {
+              final query = new Map.from(_uri.queryParameters);
+              query['isolateId'] = isolate.id;
+              final href = new Uri(path: _uri.path, queryParameters: query);
+              return new DivElement()..classes = ['memberItem', 'doubleSpaced']
+                ..children = [
+                  new SpanElement()..text = 'Continue in ',
+                  new AnchorElement(href: '#$href')..classes = ['isolate-link']
+                    ..text = '${isolate.id} (${isolate.name})'
+                ];
+            }).toList()..add(
+              new DivElement()..classes = ['memberItem', 'doubleSpaced']
+                ..children = [
+                  new SpanElement()..text = 'Go to ',
+                  new AnchorElement(href: Uris.vm())
+                    ..text = 'isolates summary',
+                ]
+            ))
+        ],
+      new ViewFooterElement(queue: _r.queue)
+    ];
   }
 }
diff --git a/runtime/observatory/lib/src/elements/isolate_reconnect.html b/runtime/observatory/lib/src/elements/isolate_reconnect.html
deleted file mode 100644
index 1f678f5..0000000
--- a/runtime/observatory/lib/src/elements/isolate_reconnect.html
+++ /dev/null
@@ -1,33 +0,0 @@
-<link rel="import" href="../../../../packages/polymer/polymer.html">
-
-<polymer-element name="isolate-reconnect">
-  <template>
-    <link rel="stylesheet" href="css/shared.css">
-    <style>
-      .doubleSpaced {
-	line-height: 2em;
-      }
-    </style>
-
-    <nav-bar>
-      <top-nav-menu last="{{ true }}"></top-nav-menu>
-      <nav-notify notifications="{{ app.notifications }}"></nav-notify>
-    </nav-bar>
-
-    <div class="content-centered">
-      <h1 class="doubleSpaced">Isolate {{ missingIsolateId }} no longer exists</h1>
-      <div class="memberList">
-         <template repeat="{{ i in app.vm.isolates }}">
-           <div class="memberItem doubleSpaced">
-             Continue in <a _href="{{ linkToContinueIn(i) }}">{{ i.id }} ({{ i.name }})</a>
-           </div>
-         </template>
-         <div class="memberItem doubleSpaced">
-           Go to <a _href="{{ gotoLink('/vm') }}">isolates summary</a>
-         </div>
-      </div>
-    </div>
-  </template>
-</polymer-element>
-
-<script type="application/dart" src="isolate_reconnect.dart"></script>
diff --git a/runtime/observatory/lib/src/elements/isolate_summary.dart b/runtime/observatory/lib/src/elements/isolate_summary.dart
index b0b2e06..b41befd 100644
--- a/runtime/observatory/lib/src/elements/isolate_summary.dart
+++ b/runtime/observatory/lib/src/elements/isolate_summary.dart
@@ -4,10 +4,7 @@
 
 library isolate_summary_element;
 
-import 'dart:html';
 import 'observatory_element.dart';
-import 'package:charted/charted.dart';
-import "package:charted/charts/charts.dart";
 import 'package:observatory/service.dart';
 import 'package:polymer/polymer.dart';
 
@@ -31,88 +28,3 @@
 
   @published Isolate isolate;
 }
-
-@CustomTag('isolate-shared-summary')
-class IsolateSharedSummaryElement extends ObservatoryElement {
-  IsolateSharedSummaryElement.created() : super.created();
-
-  @published Isolate isolate;
-}
-
-class CounterChart {
-  final HtmlElement _wrapper;
-  HtmlElement _areaHost;
-  HtmlElement _legendHost;
-  LayoutArea _area;
-  ChartData _data;
-  final _columns = [
-      new ChartColumnSpec(label: 'Type', type: ChartColumnSpec.TYPE_STRING),
-      new ChartColumnSpec(label: 'Percent', formatter: (v) => v.toString())
-  ];
-
-  CounterChart(this._wrapper) {
-    assert(_wrapper != null);
-    _areaHost = _wrapper.querySelector('.chart-host');
-    assert(_areaHost != null);
-    _areaHost.clientWidth;
-    _legendHost = _wrapper.querySelector('.chart-legend-host');
-    assert(_legendHost != null);
-    var series = new ChartSeries("Work", [1], new PieChartRenderer(
-      sortDataByValue: false
-    ));
-    var config = new ChartConfig([series], [0]);
-    config.minimumSize = new Rect(200, 200);
-    config.legend = new ChartLegend(_legendHost, showValues: true);
-    _data = new ChartData(_columns, []);
-    _area = new LayoutArea(_areaHost,
-                           _data,
-                           config,
-                           state: new ChartState(),
-                           autoUpdate: false);
-    _area.addChartBehavior(new Hovercard());
-    _area.addChartBehavior(new AxisLabelTooltip());
-  }
-
-  void update(Map counters) {
-    var rows = [];
-    for (var key in counters.keys) {
-      var value = double.parse(counters[key].split('%')[0]);
-      rows.add([key, value]);
-    }
-    _area.data = new ChartData(_columns, rows);
-    _area.draw();
-  }
-}
-
-@CustomTag('isolate-counter-chart')
-class IsolateCounterChartElement extends ObservatoryElement {
-  IsolateCounterChartElement.created() : super.created();
-
-  @published ObservableMap counters;
-  CounterChart chart;
-
-  attached() {
-    super.attached();
-    chart =
-        new CounterChart(shadowRoot.querySelector('#isolate-counter-chart'));
-  }
-
-  detached() {
-    super.detached();
-    var host = shadowRoot.querySelector('#isolate-counter-chart-host');
-    host.children.clear();
-    var legendHost =
-        shadowRoot.querySelector('#isolate-counter-chart-legend-host');
-    legendHost.children.clear();
-  }
-
-  void countersChanged(oldValue) {
-    if (counters == null) {
-      return;
-    }
-    if (chart == null) {
-      return;
-    }
-    chart.update(counters);
-  }
-}
diff --git a/runtime/observatory/lib/src/elements/isolate_summary.html b/runtime/observatory/lib/src/elements/isolate_summary.html
index 1a0c0a1..3c4924d 100644
--- a/runtime/observatory/lib/src/elements/isolate_summary.html
+++ b/runtime/observatory/lib/src/elements/isolate_summary.html
@@ -85,146 +85,4 @@
   </template>
 </polymer-element>
 
-<polymer-element name="isolate-shared-summary">
-  <template>
-    <style>
-      .errorBox {
-        background-color: #f5f5f5;
-        border: 1px solid #ccc;
-        padding: 2em;
-        font-family: consolas, courier, monospace;
-        font-size: 1em;
-        line-height: 1.2em;
-        white-space: pre;
-      }
-    </style>
-    <link rel="stylesheet" href="css/shared.css">
-    <template if="{{ isolate.error != null }}">
-      <div class="content-centered">
-        <pre class="errorBox">{{ isolate.error.message }}</pre>
-        <br>
-      </div>
-    </template>
-    <div class="flex-row">
-      <div style="flex:2">
-        <isolate-counter-chart counters="{{ isolate.counters }}"></isolate-counter-chart>
-      </div>
-      <div style="flex:1">
-        <div class="memberList">
-          <div class="memberItem">
-            <div class="memberName">new heap</div>
-            <div class="memberValue">
-              {{ isolate.newSpace.used | formatSize }}
-              of
-              {{ isolate.newSpace.capacity | formatSize }}
-            </div>
-          </div>
-          <div class="memberItem">
-            <div class="memberName">old heap</div>
-            <div class="memberValue">
-              {{ isolate.oldSpace.used | formatSize }}
-              of
-              {{ isolate.oldSpace.capacity | formatSize }}
-            </div>
-          </div>
-        </div>
-        <br>
-        <div class="memberItem">
-          <div class="memberValue">
-            See <a on-click="{{ goto }}" _href="{{ gotoLink('/debugger', isolate) }}">debugger</a>
-          </div>
-        </div>
-        <div class="memberItem">
-          <div class="memberValue">
-            See <a on-click="{{ goto }}" _href="{{ gotoLink('/class-tree', isolate) }}">class hierarchy</a>
-          </div>
-        </div>
-        <div class="memberItem">
-          <div class="memberValue">
-            See <a on-click="{{ goto }}" _href="{{ gotoLink('/profiler', isolate) }}">cpu profile</a>
-          </div>
-        </div>
-        <div class="memberItem">
-          <div class="memberValue">
-            See <a on-click="{{ goto }}" _href="{{ gotoLink('/profiler-table', isolate) }}">cpu profile (table)</a>
-          </div>
-        </div>
-        <div class="memberItem">
-          <div class="memberValue">
-            See <a on-click="{{ goto }}" _href="{{ gotoLink('/allocation-profiler', isolate) }}">allocation profile</a>
-          </div>
-        </div>
-        <div class="memberItem">
-          <div class="memberValue">
-            See <a on-click="{{ goto }}" _href="{{ gotoLink('/heap-map', isolate) }}">heap map</a>
-          </div>
-        </div>
-        <div class="memberItem">
-          <div class="memberValue">
-            See <a on-click="{{ goto }}" _href="{{ gotoLink('/metrics', isolate) }}">metrics</a>
-          </div>
-        </div>
-        <div class="memberItem">
-          <div class="memberValue">
-            See <a on-click="{{ goto }}" _href="{{ gotoLink('/heap-snapshot', isolate) }}">heap snapshot</a>
-          </div>
-        </div>
-        <div class="memberItem">
-          <div class="memberValue">
-            See <a on-click="{{ goto }}" _href="{{ gotoLink('/persistent-handles', isolate) }}">persistent handles</a>
-          </div>
-        </div>
-        <div class="memberItem">
-          <div class="memberValue">
-            See <a on-click="{{ goto }}" _href="{{ gotoLink('/ports', isolate) }}">ports</a>
-          </div>
-        </div>
-        <div class="memberItem">
-          <div class="memberValue">
-            See <a on-click="{{ goto }}" _href="{{ gotoLink('/logging', isolate) }}">logging</a>
-          </div>
-        </div>
-        <!-- Temporarily disabled until UI for dart:io is acceptable.
-        <template if="{{ isolate.ioEnabled }}">
-          <div class="memberItem">
-            <div class="memberValue">
-              See <a on-click="{{ goto }}" href="{{ gotoLink('/io', isolate) }}">dart:io</a>
-            </div>
-          </div>
-        </template>
-        -->
-      </div>
-    </div>
-  </template>
-</polymer-element>
-
-<polymer-element name="isolate-counter-chart">
-  <template>
-    <link rel="stylesheet" href="../../../../packages/charted/charts/themes/quantum_theme.css">
-    <style>
-.chart-wrapper {
-}
-.chart-host-wrapper {
-  display: flex;
-  flex-direction: row;
-  max-height: 250px;
-}
-.chart-host {
-  flex: 1;
-}
-.chart-legend-host {
-  flex: 1;
-  overflow-x: auto;
-  overflow-y: auto;
-}
-    </style>
-    <div class="chart-wrapper" id="isolate-counter-chart">
-      <div class="chart-host-wrapper">
-        <div class="chart-host" id="isolate-counter-chart-host"></div>
-        <div class="chart-legend-host" id="isolate-counter-chart-legend-host"></div>
-      </div>
-  </div>
-  </template>
-</polymer-element>
-
 <script type="application/dart" src="isolate_summary.dart"></script>
diff --git a/runtime/observatory/lib/src/elements/observatory_application.dart b/runtime/observatory/lib/src/elements/observatory_application.dart
index 4acdc65..0e85692 100644
--- a/runtime/observatory/lib/src/elements/observatory_application.dart
+++ b/runtime/observatory/lib/src/elements/observatory_application.dart
@@ -4,22 +4,24 @@
 
 library observatory_application_element;
 
-import 'observatory_element.dart';
+import 'dart:html';
 import 'package:observatory/app.dart';
-import 'package:polymer/polymer.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
 
 /// Main application tag. Responsible for instantiating an instance of
 /// [ObservatoryApplication] which is passed declaratively to all child
 /// elements.
-@CustomTag('observatory-application')
-class ObservatoryApplicationElement extends ObservatoryElement {
+class ObservatoryApplicationElement extends HtmlElement {
+  static const tag =
+      const Tag<ObservatoryApplicationElement>('observatory-application');
+
   ObservatoryApplication app;
 
   ObservatoryApplicationElement.created() : super.created();
 
   @override
-  void domReady() {
-    super.domReady();
+  void attached() {
+    super.attached();
     app = new ObservatoryApplication(this);
   }
 }
diff --git a/runtime/observatory/lib/src/elements/observatory_application.html b/runtime/observatory/lib/src/elements/observatory_application.html
deleted file mode 100644
index d91819f..0000000
--- a/runtime/observatory/lib/src/elements/observatory_application.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<link rel="import" href="../../../../packages/polymer/polymer.html">
-
-<link rel="import" href="service_view.html">
-<polymer-element name="observatory-application">
-  <!-- This element explicitly manages its child elements -->
-</polymer-element>
-
-<script type="application/dart" src="observatory_application.dart"></script>
\ No newline at end of file
diff --git a/runtime/observatory/lib/src/elements/sample_buffer_control.dart b/runtime/observatory/lib/src/elements/sample_buffer_control.dart
new file mode 100644
index 0000000..dde5eb8
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/sample_buffer_control.dart
@@ -0,0 +1,232 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:html';
+import 'package:observatory/models.dart' as M;
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/helpers/uris.dart';
+import 'package:observatory/utils.dart';
+
+class SampleBufferControlChangedElement {
+  final SampleBufferControlElement element;
+  SampleBufferControlChangedElement(this.element);
+}
+
+class SampleBufferControlElement extends HtmlElement implements Renderable {
+  static const tag =
+      const Tag<SampleBufferControlElement>('sample-buffer-control');
+
+  RenderingScheduler<SampleBufferControlElement> _r;
+
+  Stream<RenderedEvent<SampleBufferControlElement>> get onRendered =>
+                                                                  _r.onRendered;
+
+  StreamController<SampleBufferControlChangedElement> _onTagChange =
+      new StreamController<SampleBufferControlChangedElement>.broadcast();
+  Stream<SampleBufferControlChangedElement> get onTagChange =>
+      _onTagChange.stream;
+
+  Stream<M.SampleProfileLoadingProgressEvent> _progressStream;
+  M.SampleProfileLoadingProgress _progress;
+  M.SampleProfileTag _tag;
+  bool _showTag = false;
+  bool _profileVM = false;
+  StreamSubscription _subscription;
+
+  M.SampleProfileLoadingProgress get progress => _progress;
+  M.SampleProfileTag get selectedTag => _tag;
+  bool get showTag => _showTag;
+  bool get profileVM => _profileVM;
+
+  set selectedTag(M.SampleProfileTag value) =>
+      _tag = _r.checkAndReact(_tag, value);
+  set showTag(bool value) => _showTag = _r.checkAndReact(_showTag, value);
+  set profileVM(bool value) => _profileVM = _r.checkAndReact(_profileVM, value);
+
+
+  factory SampleBufferControlElement(M.SampleProfileLoadingProgress progress,
+      Stream<M.SampleProfileLoadingProgressEvent> progressStream,
+      {M.SampleProfileTag selectedTag: M.SampleProfileTag.none,
+      bool showTag: true, RenderingQueue queue}) {
+    assert(progress != null);
+    assert(progressStream != null);
+    assert(selectedTag != null);
+    assert(showTag != null);
+    SampleBufferControlElement e = document.createElement(tag.name);
+    e._r = new RenderingScheduler(e, queue: queue);
+    e._progress = progress;
+    e._progressStream = progressStream;
+    e._tag = selectedTag;
+    e._showTag = showTag;
+    return e;
+  }
+
+  SampleBufferControlElement.created() : super.created();
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+    _subscription = _progressStream.listen((e) {
+      _progress = e.progress;
+      _r.dirty();
+    });
+  }
+
+  @override
+  void detached() {
+    super.detached(); _r.disable(notify: true);
+    children = const [];
+    _subscription.cancel();
+  }
+
+  void render() {
+    var content = <Element>[
+      new HeadingElement.h2()..text = 'Sample buffer',
+      new HRElement()
+    ];
+    switch (_progress.status) {
+      case M.SampleProfileLoadingStatus.fetching :
+        content.addAll(_createStatusMessage('Fetching profile from VM...'));
+        break;
+      case M.SampleProfileLoadingStatus.loading :
+        content.addAll(_createStatusMessage('Loading profile...',
+            progress: _progress.progress));
+        break;
+      case M.SampleProfileLoadingStatus.disabled :
+        content.addAll(_createDisabledMessage());
+        break;
+      case M.SampleProfileLoadingStatus.loaded:
+        content.addAll(_createStatusReport());
+        break;
+    }
+    children = [
+      new DivElement()..classes = ['content-centered-big']
+        ..children = content
+    ];
+  }
+
+  static List<Element> _createStatusMessage(String message,
+      {double progress: 0.0}) {
+    return [new DivElement()..classes = ['statusBox', 'shadow', 'center']
+      ..children = [
+        new DivElement()..classes = ['statusMessage']
+          ..text = message,
+        new DivElement()..style.background = '#0489c3'
+          ..style.width = '$progress%'
+          ..style.height = '15px'
+          ..style.borderRadius = '4px'
+      ]
+    ];
+  }
+
+  static List<Element> _createDisabledMessage() {
+    return [new DivElement()..classes = ['statusBox' 'shadow' 'center']
+      ..children = [
+        new DivElement()
+          ..children = [
+            new HeadingElement.h1()
+            ..text = 'Profiling is disabled',
+            new BRElement(),
+            new DivElement()
+              ..innerHtml = 'Perhaps the <b>profile</b> '
+                            'flag has been disabled for this VM.',
+            new BRElement(),
+            new SpanElement()..text = 'See all',
+            new AnchorElement(href: Uris.flags())..text = 'vm flags'
+          ]
+      ]
+    ];
+  }
+
+  List<Element> _createStatusReport() {
+    final fetchT = Utils.formatDurationInSeconds(_progress.fetchingTime);
+    final loadT = Utils.formatDurationInSeconds(_progress.loadingTime);
+    final sampleCount = _progress.profile.sampleCount;
+    final refreshT = new DateTime.now();
+    final stackDepth = _progress.profile.stackDepth;
+    final sampleRate = _progress.profile.sampleRate.toStringAsFixed(0);
+    final timeSpan = _progress.profile.sampleCount == 0 ? '0s'
+        : Utils.formatTimePrecise(_progress.profile.timeSpan);
+
+    var content = <Element>[
+      new DivElement()..classes = ['memberItem']
+        ..children = [
+          new DivElement()..classes = ['memberName']
+            ..text = 'Refreshed at',
+          new DivElement()..classes = ['memberValue']
+            ..text = '$refreshT (fetched in ${fetchT}s) (loaded in ${loadT}s)'
+        ],
+      new DivElement()..classes = ['memberItem']
+        ..children = [
+          new DivElement()..classes = ['memberName']
+            ..text = 'Profile contains ',
+          new DivElement()..classes = ['memberValue']
+            ..text = '$sampleCount samples (spanning $timeSpan)'
+        ],
+      new DivElement()..classes = ['memberItem']
+        ..children = [
+          new DivElement()..classes = ['memberName']
+            ..text = 'Sampling',
+          new DivElement()..classes = ['memberValue']
+            ..text = '$stackDepth stack frames @ ${sampleRate}Hz'
+        ],
+    ];
+    if (_showTag) {
+      content.add(
+        new DivElement()..classes = ['memberItem']
+          ..children = [
+            new DivElement()..classes = ['memberName']
+              ..text = 'Tag Order',
+            new DivElement()..classes = ['memberValue']
+              ..children = _createTagSelect()
+          ]
+      );
+    }
+    return [
+      new DivElement()..classes = ['memberList']
+        ..children = content
+    ];
+  }
+
+  List<Element> _createTagSelect() {
+    var values = M.SampleProfileTag.values;
+    if (!_profileVM) {
+      values = const [M.SampleProfileTag.userOnly, M.SampleProfileTag.none];
+    }
+    var s;
+    return [
+      s = new SelectElement()..classes = ['tag-select']
+        ..value = tagToString(_tag)
+        ..children = values.map((tag) {
+            return new OptionElement(value : tagToString(tag),
+                selected: _tag == tag)
+              ..text = tagToString(tag);
+          }).toList(growable: false)
+        ..onChange.listen((_) {
+            _tag = values[s.selectedIndex];
+          })
+        ..onChange.map(_toEvent).listen(_triggerModeChange),
+    ];
+  }
+
+  static String tagToString(M.SampleProfileTag tag) {
+    switch (tag) {
+      case M.SampleProfileTag.userVM: return 'User > VM';
+      case M.SampleProfileTag.userOnly: return 'User';
+      case M.SampleProfileTag.vmUser: return 'VM > User';
+      case M.SampleProfileTag.vmOnly: return 'VM';
+      case M.SampleProfileTag.none: return 'None';
+    }
+    throw new Exception('Unknown tagToString');
+  }
+
+  SampleBufferControlChangedElement _toEvent(_) {
+    return new SampleBufferControlChangedElement(this);
+  }
+
+  void _triggerModeChange(e) => _onTagChange.add(e);
+}
diff --git a/runtime/observatory/lib/src/elements/service_view.html b/runtime/observatory/lib/src/elements/service_view.html
index 3ddbbe4..52f6d07 100644
--- a/runtime/observatory/lib/src/elements/service_view.html
+++ b/runtime/observatory/lib/src/elements/service_view.html
@@ -2,7 +2,6 @@
 <link rel="import" href="class_view.html">
 <link rel="import" href="code_view.html">
 <link rel="import" href="context_view.html">
-<link rel="import" href="cpu_profile.html">
 <link rel="import" href="error_view.html">
 <link rel="import" href="field_view.html">
 <link rel="import" href="function_view.html">
diff --git a/runtime/observatory/lib/src/elements/stack_trace_tree_config.dart b/runtime/observatory/lib/src/elements/stack_trace_tree_config.dart
new file mode 100644
index 0000000..b1f2f4e
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/stack_trace_tree_config.dart
@@ -0,0 +1,228 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:html';
+import 'package:observatory/models.dart' as M;
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+
+enum ProfileTreeMode {
+  code,
+  function,
+}
+
+class StackTraceTreeConfigChangedEvent {
+  final StackTraceTreeConfigElement element;
+  StackTraceTreeConfigChangedEvent(this.element);
+}
+
+class StackTraceTreeConfigElement extends HtmlElement implements Renderable {
+  static const tag =
+      const Tag<StackTraceTreeConfigElement>('stack-trace-tree-config');
+
+  RenderingScheduler<StackTraceTreeConfigElement> _r;
+
+  Stream<RenderedEvent<StackTraceTreeConfigElement>> get onRendered =>
+                                                                  _r.onRendered;
+
+  StreamController<StackTraceTreeConfigChangedEvent> _onModeChange =
+      new StreamController<StackTraceTreeConfigChangedEvent>.broadcast();
+  StreamController<StackTraceTreeConfigChangedEvent> _onDirectionChange =
+      new StreamController<StackTraceTreeConfigChangedEvent>.broadcast();
+  StreamController<StackTraceTreeConfigChangedEvent> _onFilterChange =
+      new StreamController<StackTraceTreeConfigChangedEvent>.broadcast();
+  Stream<StackTraceTreeConfigChangedEvent> get onModeChange =>
+      _onModeChange.stream;
+  Stream<StackTraceTreeConfigChangedEvent> get onDirectionChange =>
+      _onDirectionChange.stream;
+  Stream<StackTraceTreeConfigChangedEvent> get onFilterChange =>
+      _onFilterChange.stream;
+
+  bool _showMode;
+  bool _showDirection;
+  bool _showFilter;
+  ProfileTreeMode _mode;
+  M.ProfileTreeDirection _direction;
+  String _filter;
+
+  bool get showMode => _showMode;
+  bool get showDirection => _showDirection;
+  bool get showFilter => _showFilter;
+  ProfileTreeMode get mode => _mode;
+  M.ProfileTreeDirection get direction => _direction;
+  String get filter => _filter;
+
+  set showMode(bool value) => _showMode = _r.checkAndReact(_showMode, value);
+  set showDirection(bool value) =>
+      _showDirection = _r.checkAndReact(_showDirection, value);
+  set showFilter(bool value) =>
+      _showFilter = _r.checkAndReact(_showFilter, value);
+  set mode(ProfileTreeMode value) => _mode = _r.checkAndReact(_mode, value);
+  set direction(M.ProfileTreeDirection value) =>
+      _direction = _r.checkAndReact(_direction, value);
+  set filter(String value) => _filter = _r.checkAndReact(_filter, value);
+
+  factory StackTraceTreeConfigElement({bool showMode: true,
+      bool showDirection: true, bool showFilter: true, String filter: '',
+      ProfileTreeMode mode: ProfileTreeMode.function,
+      M.ProfileTreeDirection direction: M.ProfileTreeDirection.exclusive,
+      RenderingQueue queue}) {
+    assert(showMode != null);
+    assert(showDirection != null);
+    assert(showFilter != null);
+    assert(mode != null);
+    assert(direction != null);
+    assert(filter != null);
+    StackTraceTreeConfigElement e = document.createElement(tag.name);
+    e._r = new RenderingScheduler(e, queue: queue);
+    e._showMode = showMode;
+    e._showDirection = showDirection;
+    e._showFilter = showFilter;
+    e._mode = mode;
+    e._direction = direction;
+    e._filter = filter;
+    return e;
+  }
+
+  StackTraceTreeConfigElement.created() : super.created();
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached(); _r.disable(notify: true);
+    children = const [];
+  }
+
+  void render() {
+    children = [
+      new DivElement()..classes = ['content-centered-big']
+        ..children = [
+          new HeadingElement.h2()..text = 'Tree display',
+          new HRElement(),
+          new DivElement()..classes = ['row']
+            ..children = [
+              new DivElement()..classes = ['memberList']
+                ..children = _createMembers()
+            ]
+        ]
+    ];
+  }
+
+  List<Element> _createMembers() {
+    var members = <Element>[];
+    if (_showMode) {
+      members.add(
+        new DivElement()..classes = ['memberItem']
+          ..children = [
+            new DivElement()..classes = ['memberName']..text = 'Mode',
+            new DivElement()..classes = ['memberValue']
+              ..children = _createModeSelect()
+          ]
+      );
+    }
+    if (_showDirection) {
+      members.add(
+        new DivElement()..classes = ['memberItem']
+          ..children = [
+            new DivElement()..classes = ['memberName']
+              ..text = 'Call Tree Direction',
+            new SpanElement()..classes = ['memberValue']
+              ..children = _createDirectionSelect()
+          ]
+      );
+    }
+    if (showFilter) {
+      members.add(
+        new DivElement()..classes = ['memberItem']
+          ..children = [
+            new DivElement()..classes = ['memberName']
+              ..text = 'Call Tree Filter'
+              ..title = 'case-sensitive substring match',
+            new SpanElement()..classes = ['memberValue']
+              ..children = _createFilter()
+          ]
+      );
+    }
+    return members;
+  }
+
+  List<Element> _createModeSelect() {
+    var s;
+    return [
+      s = new SelectElement()..classes = ['mode-select']
+        ..value = modeToString(_mode)
+        ..children = ProfileTreeMode.values.map((mode) {
+            return new OptionElement(value : modeToString(mode),
+                selected: _mode == mode)
+              ..text = modeToString(mode);
+          }).toList(growable: false)
+        ..onChange.listen((_) {
+            _mode = ProfileTreeMode.values[s.selectedIndex];
+          })
+        ..onChange.map(_toEvent).listen(_triggerModeChange),
+    ];
+  }
+
+  List<Element> _createDirectionSelect() {
+    var s;
+    return [
+      s = new SelectElement()..classes = ['direction-select']
+        ..value = directionToString(_direction)
+        ..children = M.ProfileTreeDirection.values.map((direction) {
+            return new OptionElement(value: directionToString(direction),
+                selected: _direction == direction)
+              ..text = directionToString(direction);
+          }).toList(growable: false)
+        ..onChange.listen((_) {
+            _direction = M.ProfileTreeDirection.values[s.selectedIndex];
+          })
+        ..onChange.map(_toEvent).listen(_triggerDirectionChange),
+      new SpanElement()..text = 'Tree is rooted at ' +
+          (_direction == 'Down' ? '"main"' : 'function / code') +
+          '. Child nodes are callers.'
+    ];
+  }
+
+  List<Element> _createFilter(){
+    var t;
+    return [
+      t = new TextInputElement()..placeholder = 'Search filter'
+          ..value = filter
+          ..onChange.listen((_) { _filter = t.value; })
+          ..onChange.map(_toEvent).listen(_triggerFilterChange)
+    ];
+  }
+
+  static String modeToString(ProfileTreeMode mode) {
+    switch (mode) {
+      case ProfileTreeMode.code: return 'Code';
+      case ProfileTreeMode.function: return 'Function';
+    }
+    throw new Exception('Unknown ProfileTreeMode');
+  }
+
+  static String directionToString(M.ProfileTreeDirection direction) {
+    switch (direction) {
+      case M.ProfileTreeDirection.inclusive: return 'Top down';
+      case M.ProfileTreeDirection.exclusive: return 'Bottom up';
+    }
+    throw new Exception('Unknown ProfileTreeDirection');
+  }
+
+  StackTraceTreeConfigChangedEvent _toEvent(_) {
+    return new StackTraceTreeConfigChangedEvent(this);
+  }
+
+  void _triggerModeChange(e) => _onModeChange.add(e);
+  void _triggerDirectionChange(e) => _onDirectionChange.add(e);
+  void _triggerFilterChange(e) => _onFilterChange.add(e);
+
+
+}
diff --git a/runtime/observatory/lib/src/models/objects/error.dart b/runtime/observatory/lib/src/models/objects/error.dart
index 23de456..8b36aed 100644
--- a/runtime/observatory/lib/src/models/objects/error.dart
+++ b/runtime/observatory/lib/src/models/objects/error.dart
@@ -6,14 +6,14 @@
 
 enum ErrorKind {
   /// The isolate has encountered an unhandled Dart exception.
-  UnhandledException,
+  unhandledException,
   /// The isolate has encountered a Dart language error in the program.
-  LanguageError,
+  languageError,
   /// The isolate has encounted an internal error. These errors should be
   /// reported as bugs.
-  InternalError,
+  internalError,
   /// The isolate has been terminated by an external source.
-  TerminationError
+  terminationError
 }
 
 abstract class ErrorRef extends ObjectRef {
diff --git a/runtime/observatory/lib/src/models/objects/heap_space.dart b/runtime/observatory/lib/src/models/objects/heap_space.dart
new file mode 100644
index 0000000..29c55ce
--- /dev/null
+++ b/runtime/observatory/lib/src/models/objects/heap_space.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class HeapSpace {
+  int get used;
+  int get capacity;
+}
diff --git a/runtime/observatory/lib/src/models/objects/isolate.dart b/runtime/observatory/lib/src/models/objects/isolate.dart
index 81d54c5..45f5524 100644
--- a/runtime/observatory/lib/src/models/objects/isolate.dart
+++ b/runtime/observatory/lib/src/models/objects/isolate.dart
@@ -5,12 +5,58 @@
 part of models;
 
 abstract class IsolateRef {
+  /// The id which is passed to the getIsolate RPC to reload this
+  /// isolate.
   String get id;
+
+  /// A numeric id for this isolate, represented as a string. Unique.
   int get number;
+
+  /// A name identifying this isolate. Not guaranteed to be unique.
   String get name;
 }
 
 abstract class Isolate extends IsolateRef {
+  /// The time that the VM started in milliseconds since the epoch.
   DateTime get startTime;
+
+  /// Is the isolate in a runnable state?
   bool get runnable;
+
+  /// The number of live ports for this isolate.
+  //int get livePorts;
+
+  /// Will this isolate pause when exiting?
+  //bool get pauseOnExit;
+
+  /// The last pause event delivered to the isolate. If the isolate is
+  /// running, this will be a resume event.
+  //Event get pauseEvent;
+
+  /// [optional] The root library for this isolate.
+  ///
+  /// Guaranteed to be initialized when the IsolateRunnable event fires.
+  //LibraryRef get rootLib;
+
+  /// A list of all libraries for this isolate.
+  ///
+  /// Guaranteed to be initialized when the IsolateRunnable event fires.
+  Iterable<LibraryRef> get libraries;
+
+  /// A list of all breakpoints for this isolate.
+  //Iterable<Breakpoint> get breakpoints;
+
+  /// [optional] The error that is causing this isolate to exit, if applicable.
+  Error get error;
+
+  /// The current pause on exception mode for this isolate.
+  //ExceptionPauseMode get exceptionPauseMode;
+
+  /// [optional]The list of service extension RPCs that are registered for this
+  /// isolate, if any.
+  Iterable<String> get extensionRPCs;
+
+  Map get counters;
+  HeapSpace get newSpace;
+  HeapSpace get oldSpace;
 }
diff --git a/runtime/observatory/lib/src/models/objects/sample_profile.dart b/runtime/observatory/lib/src/models/objects/sample_profile.dart
new file mode 100644
index 0000000..5c5a983
--- /dev/null
+++ b/runtime/observatory/lib/src/models/objects/sample_profile.dart
@@ -0,0 +1,64 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+enum ProfileTreeDirection {
+  inclusive,
+  exclusive
+}
+
+abstract class SampleProfile {
+  int get sampleCount;
+  int get stackDepth;
+  double get sampleRate;
+  double get timeSpan;
+
+  FunctionCallTree loadFunctionTree(ProfileTreeDirection direction);
+  CodeCallTree loadCodeTree(ProfileTreeDirection direction);
+}
+
+abstract class Profile {
+  double get normalizedExclusiveTicks;
+  double get normalizedInclusiveTicks;
+}
+
+abstract class ProfileCode extends Profile {
+  CodeRef get code;
+}
+
+abstract class ProfileFunction extends Profile {
+  FunctionRef get function;
+}
+
+typedef bool CallTreeNodeFilter(CallTreeNode);
+
+abstract class CallTree {
+  CallTree filtered(CallTreeNodeFilter filter);
+}
+
+abstract class CodeCallTree extends CallTree {
+  CodeCallTreeNode get root;
+  CodeCallTree filtered(CallTreeNodeFilter filter);
+}
+
+abstract class FunctionCallTree extends CallTree {
+  FunctionCallTreeNode get root;
+  FunctionCallTree filtered(CallTreeNodeFilter filter);
+}
+
+abstract class CallTreeNode {
+  double get percentage;
+  Iterable<CallTreeNode> get children;
+}
+
+abstract class CodeCallTreeNode extends CallTreeNode {
+  ProfileCode get profileCode;
+  Iterable<CodeCallTreeNode> get children;
+}
+
+abstract class FunctionCallTreeNode extends CallTreeNode {
+  ProfileFunction get profileFunction;
+  Iterable<FunctionCallTreeNode> get children;
+}
diff --git a/runtime/observatory/lib/src/models/repositories/sample_profile.dart b/runtime/observatory/lib/src/models/repositories/sample_profile.dart
new file mode 100644
index 0000000..3ec7cfd
--- /dev/null
+++ b/runtime/observatory/lib/src/models/repositories/sample_profile.dart
@@ -0,0 +1,52 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+enum SampleProfileTag {
+  userVM,
+  userOnly,
+  vmUser,
+  vmOnly,
+  none
+}
+
+enum SampleProfileLoadingStatus {
+  disabled,
+  fetching,
+  loading,
+  loaded
+}
+
+bool isSampleProcessRunning(SampleProfileLoadingStatus status) {
+  switch (status) {
+    case SampleProfileLoadingStatus.fetching:
+    case SampleProfileLoadingStatus.loading:
+      return true;
+    default:
+      return false;
+  }
+}
+
+abstract class SampleProfileLoadingProgressEvent {
+  SampleProfileLoadingProgress get progress;
+}
+
+abstract class SampleProfileLoadingProgress {
+  SampleProfileLoadingStatus get status;
+  double get progress;
+  Duration get fetchingTime;
+  Duration get loadingTime;
+  SampleProfile get profile;
+}
+
+abstract class ClassSampleProfileRepository {
+  Stream<SampleProfileLoadingProgressEvent> get(ClassRef cls,
+      SampleProfileTag tag, {bool clear: false});
+}
+
+abstract class IsolateSampleProfileRepository {
+  Stream<SampleProfileLoadingProgressEvent> get(IsolateRef cls,
+      SampleProfileTag tag, {bool clear: false, bool forceFetch: false});
+}
diff --git a/runtime/observatory/lib/src/repositories/sample_profile.dart b/runtime/observatory/lib/src/repositories/sample_profile.dart
new file mode 100644
index 0000000..5752139
--- /dev/null
+++ b/runtime/observatory/lib/src/repositories/sample_profile.dart
@@ -0,0 +1,137 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of repositories;
+
+String _tagToString(M.SampleProfileTag tag) {
+  switch (tag) {
+    case M.SampleProfileTag.userVM: return 'UserVM';
+    case M.SampleProfileTag.userOnly: return 'UserOnly';
+    case M.SampleProfileTag.vmUser: return 'VMUser';
+    case M.SampleProfileTag.vmOnly: return 'VMOnly';
+    case M.SampleProfileTag.none: return 'None';
+  }
+  throw new Exception('Unknown SampleProfileTag: $tag');
+}
+
+class SampleProfileLoadingProgressEvent
+  implements M.SampleProfileLoadingProgressEvent {
+  final SampleProfileLoadingProgress progress;
+  SampleProfileLoadingProgressEvent(this.progress);
+}
+
+class SampleProfileLoadingProgress extends M.SampleProfileLoadingProgress {
+  StreamController<SampleProfileLoadingProgressEvent> _onProgress =
+      new StreamController<SampleProfileLoadingProgressEvent>.broadcast();
+  Stream<SampleProfileLoadingProgressEvent> get onProgress =>
+      _onProgress.stream;
+
+  final S.Isolate isolate;
+  final S.Class cls;
+  final M.SampleProfileTag tag;
+  final bool clear;
+
+  M.SampleProfileLoadingStatus _status = M.SampleProfileLoadingStatus.fetching;
+  double _progress = 0.0;
+  final Stopwatch _fetchingTime = new Stopwatch();
+  final Stopwatch  _loadingTime = new Stopwatch();
+  CpuProfile _profile;
+
+  M.SampleProfileLoadingStatus get status => _status;
+  double get progress => _progress;
+  Duration get fetchingTime => _fetchingTime.elapsed;
+  Duration get loadingTime => _loadingTime.elapsed;
+  CpuProfile get profile => _profile;
+
+  SampleProfileLoadingProgress(this.isolate, this.tag,
+      this.clear, {this.cls}) {
+      _run();
+  }
+
+  Future _run() async {
+    _fetchingTime.start();
+    try {
+      if (clear) {
+        await isolate.invokeRpc('_clearCpuProfile', { });
+      }
+
+      final response = cls != null
+        ? await cls.getAllocationSamples(_tagToString(tag))
+        : await isolate.invokeRpc('_getCpuProfile',
+            { 'tags': _tagToString(tag) });
+
+      _fetchingTime.stop();
+      _loadingTime.start();
+      _status = M.SampleProfileLoadingStatus.loading;
+      _triggerOnProgress();
+
+      CpuProfile profile = new CpuProfile();
+
+      Stream<double> progress = profile.loadProgress(isolate, response);
+      progress.listen((value) { _progress = value; _triggerOnProgress(); });
+
+      await progress.drain();
+
+      profile.buildFunctionCallerAndCallees();
+      _profile = profile;
+
+      _loadingTime.stop();
+      _status = M.SampleProfileLoadingStatus.loaded;
+      _triggerOnProgress();
+    } catch (e) {
+      if (e is S.ServerRpcException) {
+        if (e.code == S.ServerRpcException.kFeatureDisabled) {
+          _status = M.SampleProfileLoadingStatus.disabled;
+          _triggerOnProgress();
+        }
+      }
+      rethrow;
+    } finally {
+      _onProgress.close();
+    }
+  }
+
+  void _triggerOnProgress() {
+    _onProgress.add(new SampleProfileLoadingProgressEvent(this));
+  }
+
+  void reuse() {
+    _onProgress =
+      new StreamController<SampleProfileLoadingProgressEvent>.broadcast();
+    (() async {
+      _triggerOnProgress();
+      _onProgress.close();
+    }());
+  }
+}
+
+class IsolateSampleProfileRepository
+    implements M.IsolateSampleProfileRepository {
+  SampleProfileLoadingProgress _last;
+
+  Stream<SampleProfileLoadingProgressEvent> get(M.IsolateRef i,
+      M.SampleProfileTag t, {bool clear: false, bool forceFetch: false}) {
+    assert(clear != null);
+    assert(forceFetch != null);
+    S.Isolate isolate = i as S.Isolate;
+    assert(isolate != null);
+    if (_last != null && !clear && !forceFetch && _last.isolate == isolate) {
+      _last.reuse();
+    } else {
+      _last = new SampleProfileLoadingProgress(isolate, t, clear);
+    }
+    return _last.onProgress;
+  }
+}
+
+class ClassSampleProfileRepository
+    implements M.ClassSampleProfileRepository {
+  Stream<SampleProfileLoadingProgressEvent> get(M.ClassRef c,
+      M.SampleProfileTag t, {bool clear: false}) {
+    S.Class cls = c as S.Class;
+    assert(cls != null);
+    return new SampleProfileLoadingProgress(cls.isolate, t,
+        clear, cls: cls).onProgress;
+  }
+}
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index afd9240..525b1b7 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -1077,7 +1077,7 @@
   }
 }
 
-class HeapSpace extends Observable {
+class HeapSpace extends Observable implements M.HeapSpace {
   @observable int used = 0;
   @observable int capacity = 0;
   @observable int external = 0;
@@ -1139,7 +1139,7 @@
     return (new DateTime.now().difference(startTime));
   }
 
-  @observable ObservableMap counters = new ObservableMap();
+  @observable Map counters = {};
 
   void _updateRunState() {
     topFrame = (pauseEvent != null ? pauseEvent.topFrame : null);
@@ -1441,18 +1441,18 @@
       for (var i = 0; i < counts.length; i++) {
         sum += counts[i];
       }
-      // TODO: Why does this not work without this?
-      counters = toObservable({});
+      var _counters = {};
       if (sum == 0) {
         for (var i = 0; i < names.length; i++) {
-          counters[names[i]] = '0.0%';
+          _counters[names[i]] = '0.0%';
         }
       } else {
         for (var i = 0; i < names.length; i++) {
-          counters[names[i]] =
+          _counters[names[i]] =
               (counts[i] / sum * 100.0).toStringAsFixed(2) + '%';
         }
       }
+      counters = _counters;
     }
 
     updateHeapsFromMap(map['_heaps']);
@@ -1855,10 +1855,10 @@
 
 M.ErrorKind stringToErrorKind(String value) {
   switch(value) {
-    case 'UnhandledException': return M.ErrorKind.UnhandledException;
-    case 'LanguageError': return M.ErrorKind.UnhandledException;
-    case 'InternalError': return M.ErrorKind.InternalError;
-    case 'TerminationError': return M.ErrorKind.TerminationError;
+    case 'UnhandledException': return M.ErrorKind.unhandledException;
+    case 'LanguageError': return M.ErrorKind.unhandledException;
+    case 'InternalError': return M.ErrorKind.internalError;
+    case 'TerminationError': return M.ErrorKind.terminationError;
   }
   Logger.root.severe('Unrecognized error kind: $value');
   throw new FallThroughError();
diff --git a/runtime/observatory/lib/utils.dart b/runtime/observatory/lib/utils.dart
index cfc447c..a69af52 100644
--- a/runtime/observatory/lib/utils.dart
+++ b/runtime/observatory/lib/utils.dart
@@ -146,6 +146,10 @@
     return x.toStringAsFixed(2);
   }
 
+  static String formatDurationInSeconds(Duration x) {
+    return formatSeconds(x.inMilliseconds / Duration.MILLISECONDS_PER_SECOND);
+  }
+
   static bool runningInJavaScript() => identical(1.0, 1);
 }
 
diff --git a/runtime/observatory/observatory_sources.gypi b/runtime/observatory/observatory_sources.gypi
index fe89855..4e2ec39 100644
--- a/runtime/observatory/observatory_sources.gypi
+++ b/runtime/observatory/observatory_sources.gypi
@@ -49,8 +49,10 @@
     'lib/src/elements/context_view.html',
     'lib/src/elements/containers/virtual_collection.dart',
     'lib/src/elements/containers/virtual_tree.dart',
+    'lib/src/elements/cpu_profile_table.dart',
+    'lib/src/elements/cpu_profile_table.html',
     'lib/src/elements/cpu_profile.dart',
-    'lib/src/elements/cpu_profile.html',
+    'lib/src/elements/cpu_profile/virtual_tree.dart',
     'lib/src/elements/css/shared.css',
     'lib/src/elements/curly_block.dart',
     'lib/src/elements/curly_block_wrapper.dart',
@@ -100,9 +102,11 @@
     'lib/src/elements/io_view.dart',
     'lib/src/elements/io_view.html',
     'lib/src/elements/isolate_reconnect.dart',
-    'lib/src/elements/isolate_reconnect.html',
     'lib/src/elements/isolate_ref.dart',
     'lib/src/elements/isolate_ref_wrapper.dart',
+    'lib/src/elements/isolate/counter_chart.dart',
+    'lib/src/elements/isolate/shared_summary_wrapper.dart',
+    'lib/src/elements/isolate/shared_summary.dart',
     'lib/src/elements/isolate_summary.dart',
     'lib/src/elements/isolate_summary.html',
     'lib/src/elements/isolate_view.dart',
@@ -151,12 +155,12 @@
     'lib/src/elements/objectpool_view.dart',
     'lib/src/elements/objectpool_view.html',
     'lib/src/elements/observatory_application.dart',
-    'lib/src/elements/observatory_application.html',
     'lib/src/elements/observatory_element.dart',
     'lib/src/elements/persistent_handles.dart',
     'lib/src/elements/persistent_handles.html',
     'lib/src/elements/ports.dart',
     'lib/src/elements/ports.html',
+    'lib/src/elements/sample_buffer_control.dart',
     'lib/src/elements/script_inset.dart',
     'lib/src/elements/script_inset.html',
     'lib/src/elements/script_ref_wrapper.dart',
@@ -170,6 +174,7 @@
     'lib/src/elements/source_link_wrapper.dart',
     'lib/src/elements/source_link.dart',
     'lib/src/elements/shims/binding.dart',
+    'lib/src/elements/stack_trace_tree_config.dart',
     'lib/src/elements/timeline_page.dart',
     'lib/src/elements/timeline_page.html',
     'lib/src/elements/view_footer.dart',
@@ -187,11 +192,13 @@
     'lib/src/models/objects/flag.dart',
     'lib/src/models/objects/frame.dart',
     'lib/src/models/objects/function.dart',
+    'lib/src/models/objects/heap_space.dart',
     'lib/src/models/objects/instance.dart',
     'lib/src/models/objects/isolate.dart',
     'lib/src/models/objects/library.dart',
     'lib/src/models/objects/notification.dart',
     'lib/src/models/objects/object.dart',
+    'lib/src/models/objects/sample_profile.dart',
     'lib/src/models/objects/script.dart',
     'lib/src/models/objects/source_location.dart',
     'lib/src/models/objects/target.dart',
@@ -202,6 +209,7 @@
     'lib/src/models/repositories/flag.dart',
     'lib/src/models/repositories/instance.dart',
     'lib/src/models/repositories/notification.dart',
+    'lib/src/models/repositories/sample_profile.dart',
     'lib/src/models/repositories/script.dart',
     'lib/src/models/repositories/target.dart',
     'lib/src/repositories/class.dart',
@@ -209,6 +217,7 @@
     'lib/src/repositories/flag.dart',
     'lib/src/repositories/instance.dart',
     'lib/src/repositories/notification.dart',
+    'lib/src/repositories/sample_profile.dart',
     'lib/src/repositories/script.dart',
     'lib/src/repositories/settings.dart',
     'lib/src/repositories/target.dart',
diff --git a/runtime/observatory/tests/observatory_ui/class_ref/element_test.dart b/runtime/observatory/tests/observatory_ui/class_ref/element_test.dart
index 0f0eed2..41aeb10 100644
--- a/runtime/observatory/tests/observatory_ui/class_ref/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/class_ref/element_test.dart
@@ -1,24 +1,25 @@
 // Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+
 import 'dart:html';
 import 'package:unittest/unittest.dart';
 import 'package:observatory/src/elements/class_ref.dart';
 import '../mocks.dart';
 
-main(){
+main() {
   ClassRefElement.tag.ensureRegistration();
 
-  final IsolateRefMock isolate = new IsolateRefMock(id: 'i-id', name: 'i-name');
-  final ClassRefMock cls = new ClassRefMock(id: 'c-id', name: 'c-name');
+  const isolate = const IsolateRefMock();
+  const cls = const ClassRefMock();
   test('instantiation', () {
-    final ClassRefElement e = new ClassRefElement(isolate, cls);
+    final e = new ClassRefElement(isolate, cls);
     expect(e, isNotNull, reason: 'element correctly created');
     expect(e.isolate, equals(isolate));
     expect(e.cls, equals(cls));
   });
   test('elements created after attachment', () async {
-    final ClassRefElement e = new ClassRefElement(isolate, cls);
+    final e = new ClassRefElement(isolate, cls);
     document.body.append(e);
     await e.onRendered.first;
     expect(e.children.length, isNonZero, reason: 'has elements');
diff --git a/runtime/observatory/tests/observatory_ui/class_tree/element_test.dart b/runtime/observatory/tests/observatory_ui/class_tree/element_test.dart
index 518613f..5d20331 100644
--- a/runtime/observatory/tests/observatory_ui/class_tree/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/class_tree/element_test.dart
@@ -1,6 +1,7 @@
 // Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+
 import 'dart:html';
 import 'package:unittest/unittest.dart';
 import 'package:observatory/src/elements/class_tree.dart';
diff --git a/runtime/observatory/tests/observatory_ui/code_ref/element_test.dart b/runtime/observatory/tests/observatory_ui/code_ref/element_test.dart
index 694d81b..7a65c84 100644
--- a/runtime/observatory/tests/observatory_ui/code_ref/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/code_ref/element_test.dart
@@ -1,12 +1,13 @@
 // Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+
 import 'dart:html';
 import 'package:unittest/unittest.dart';
 import 'package:observatory/src/elements/code_ref.dart';
 import '../mocks.dart';
 
-main(){
+main() {
   CodeRefElement.tag.ensureRegistration();
 
   final isolate = new IsolateRefMock(id: 'i-id', name: 'i-name');
diff --git a/runtime/observatory/tests/observatory_ui/cpu_profile/element_test.dart b/runtime/observatory/tests/observatory_ui/cpu_profile/element_test.dart
new file mode 100644
index 0000000..249d465
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/cpu_profile/element_test.dart
@@ -0,0 +1,80 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:unittest/unittest.dart';
+import 'package:observatory/models.dart' as M;
+import 'package:observatory/src/elements/cpu_profile.dart';
+import 'package:observatory/src/elements/cpu_profile/virtual_tree.dart';
+import 'package:observatory/src/elements/stack_trace_tree_config.dart';
+import 'package:observatory/src/elements/sample_buffer_control.dart';
+import '../mocks.dart';
+
+main() {
+  CpuProfileElement.tag.ensureRegistration();
+
+  final sTag = SampleBufferControlElement.tag.name;
+  final cTag = StackTraceTreeConfigElement.tag.name;
+  final tTag = CpuProfileVirtualTreeElement.tag.name;
+
+  const vm = const VMMock();
+  const isolate = const IsolateRefMock();
+  final events = new EventRepositoryMock();
+  final notifs = new NotificationRepositoryMock();
+  test('instantiation', () {
+    final profiles = new IsolateSampleProfileRepositoryMock();
+    final e = new CpuProfileElement(vm, isolate, events, notifs, profiles);
+    expect(e, isNotNull, reason: 'element correctly created');
+  });
+  test('elements created', () async {
+    final controller
+        = new StreamController<M.SampleProfileLoadingProgressEvent>.broadcast();
+    final profiles = new IsolateSampleProfileRepositoryMock(
+      getter: (M.IsolateRef i, M.SampleProfileTag t, bool clear,
+          bool forceFetch) {
+        expect(i, equals(isolate));
+        expect(t, isNotNull);
+        expect(clear, isFalse);
+        expect(forceFetch, isFalse);
+        return controller.stream;
+      }
+    );
+    final e = new CpuProfileElement(vm, isolate, events, notifs, profiles);
+    document.body.append(e);
+    await e.onRendered.first;
+    expect(e.children.length, isNonZero, reason: 'has elements');
+    expect(e.querySelectorAll(sTag).length, isZero);
+    expect(e.querySelectorAll(cTag).length, isZero);
+    expect(e.querySelectorAll(tTag).length, isZero);
+    controller.add(new SampleProfileLoadingProgressEventMock(
+      progress: new SampleProfileLoadingProgressMock(
+        status: M.SampleProfileLoadingStatus.fetching
+      )
+    ));
+    await e.onRendered.first;
+    expect(e.querySelectorAll(sTag).length, equals(1));
+    expect(e.querySelectorAll(cTag).length, isZero);
+    expect(e.querySelectorAll(tTag).length, isZero);
+    controller.add(new SampleProfileLoadingProgressEventMock(
+      progress: new SampleProfileLoadingProgressMock(
+        status: M.SampleProfileLoadingStatus.loading
+      )
+    ));
+    controller.add(new SampleProfileLoadingProgressEventMock(
+      progress: new SampleProfileLoadingProgressMock(
+        status: M.SampleProfileLoadingStatus.loaded,
+        profile: new SampleProfileMock()
+      )
+    ));
+    controller.close();
+    await e.onRendered.first;
+    expect(e.querySelectorAll(sTag).length, equals(1));
+    expect(e.querySelectorAll(cTag).length, equals(1));
+    expect(e.querySelectorAll(tTag).length, equals(1));
+    e.remove();
+    await e.onRendered.first;
+    expect(e.children.length, isZero, reason: 'is empty');
+  });
+}
diff --git a/runtime/observatory/tests/observatory_ui/cpu_profile/element_test.html b/runtime/observatory/tests/observatory_ui/cpu_profile/element_test.html
new file mode 100644
index 0000000..f0e956d
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/cpu_profile/element_test.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <script type="text/javascript"
+      src="/root_dart/tools/testing/dart/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/runtime/observatory/tests/observatory_ui/cpu_profile/virtual-tree/element_test.dart b/runtime/observatory/tests/observatory_ui/cpu_profile/virtual-tree/element_test.dart
new file mode 100644
index 0000000..cb93e56
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/cpu_profile/virtual-tree/element_test.dart
@@ -0,0 +1,53 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'package:unittest/unittest.dart';
+import 'package:observatory/models.dart' as M;
+import 'package:observatory/src/elements/cpu_profile/virtual_tree.dart';
+import '../../mocks.dart';
+
+main() {
+  CpuProfileVirtualTreeElement.tag.ensureRegistration();
+  const isolate = const IsolateRefMock();
+  group('instantiation', () {
+    final profile = new SampleProfileMock();
+    test('default', () {
+      final e = new CpuProfileVirtualTreeElement(isolate, profile);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.isolate, equals(isolate));
+      expect(e.profile, equals(profile));
+      expect(e.mode, equals(ProfileTreeMode.function));
+      expect(e.direction, equals(M.ProfileTreeDirection.exclusive));
+    });
+    test('mode', () {
+      final e = new CpuProfileVirtualTreeElement(isolate, profile,
+          mode: ProfileTreeMode.code);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.isolate, equals(isolate));
+      expect(e.profile, equals(profile));
+      expect(e.mode, equals(ProfileTreeMode.code));
+      expect(e.direction, equals(M.ProfileTreeDirection.exclusive));
+    });
+    test('direction', () {
+      final e = new CpuProfileVirtualTreeElement(isolate, profile,
+          direction: M.ProfileTreeDirection.inclusive);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.isolate, equals(isolate));
+      expect(e.profile, equals(profile));
+      expect(e.mode, equals(ProfileTreeMode.function));
+      expect(e.direction, equals(M.ProfileTreeDirection.inclusive));
+    });
+  });
+  test('elements created after attachment', () async {
+    final profile = new SampleProfileMock();
+    final e = new CpuProfileVirtualTreeElement(isolate, profile);
+    document.body.append(e);
+    await e.onRendered.first;
+    expect(e.children.length, isNonZero, reason: 'has elements');
+    e.remove();
+    await e.onRendered.first;
+    expect(e.children.length, isZero, reason: 'is empty');
+  });
+}
diff --git a/runtime/observatory/tests/observatory_ui/cpu_profile/virtual-tree/element_test.html b/runtime/observatory/tests/observatory_ui/cpu_profile/virtual-tree/element_test.html
new file mode 100644
index 0000000..f0e956d
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/cpu_profile/virtual-tree/element_test.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <script type="text/javascript"
+      src="/root_dart/tools/testing/dart/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/runtime/observatory/tests/observatory_ui/curly_block/element_test.dart b/runtime/observatory/tests/observatory_ui/curly_block/element_test.dart
index 6010bc6..139e235 100644
--- a/runtime/observatory/tests/observatory_ui/curly_block/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/curly_block/element_test.dart
@@ -1,6 +1,7 @@
 // Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+
 import 'dart:html';
 import 'package:unittest/unittest.dart';
 import 'package:observatory/src/elements/curly_block.dart';
diff --git a/runtime/observatory/tests/observatory_ui/error_ref/element_test.dart b/runtime/observatory/tests/observatory_ui/error_ref/element_test.dart
index b131472..878f90a 100644
--- a/runtime/observatory/tests/observatory_ui/error_ref/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/error_ref/element_test.dart
@@ -1,6 +1,7 @@
 // Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+
 import 'dart:html';
 import 'package:unittest/unittest.dart';
 import 'package:observatory/src/elements/error_ref.dart';
diff --git a/runtime/observatory/tests/observatory_ui/flag_list/element_test.dart b/runtime/observatory/tests/observatory_ui/flag_list/element_test.dart
index d23fffa..327daa1 100644
--- a/runtime/observatory/tests/observatory_ui/flag_list/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/flag_list/element_test.dart
@@ -1,6 +1,7 @@
 // Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+
 import 'dart:html';
 import 'package:unittest/unittest.dart';
 import 'package:observatory/src/elements/flag_list.dart';
diff --git a/runtime/observatory/tests/observatory_ui/function_ref/element_test.dart b/runtime/observatory/tests/observatory_ui/function_ref/element_test.dart
index cd6b8af..4068493 100644
--- a/runtime/observatory/tests/observatory_ui/function_ref/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/function_ref/element_test.dart
@@ -1,12 +1,13 @@
 // Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+
 import 'dart:html';
 import 'package:unittest/unittest.dart';
 import 'package:observatory/src/elements/function_ref.dart';
 import '../mocks.dart';
 
-main(){
+main() {
   FunctionRefElement.tag.ensureRegistration();
 
   final isolate = new IsolateRefMock(id: 'i-id', name: 'i-name');
diff --git a/runtime/observatory/tests/observatory_ui/general_error/element_test.dart b/runtime/observatory/tests/observatory_ui/general_error/element_test.dart
index e056bac..71ba186 100644
--- a/runtime/observatory/tests/observatory_ui/general_error/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/general_error/element_test.dart
@@ -1,6 +1,7 @@
 // Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+
 import 'dart:html';
 import 'package:unittest/unittest.dart';
 import 'package:observatory/src/elements/general_error.dart';
diff --git a/runtime/observatory/tests/observatory_ui/isolate/counter_chart/element_test.dart b/runtime/observatory/tests/observatory_ui/isolate/counter_chart/element_test.dart
new file mode 100644
index 0000000..8aef7df
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/isolate/counter_chart/element_test.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'package:unittest/unittest.dart';
+import 'package:observatory/src/elements/isolate/counter_chart.dart';
+
+main() {
+  IsolateCounterChartElement.tag.ensureRegistration();
+
+  test('instantiation', () {
+    final e = new IsolateCounterChartElement({});
+    expect(e, isNotNull, reason: 'element correctly created');
+  });
+  test('elements created', () async {
+    final e = new IsolateCounterChartElement({});
+    document.body.append(e);
+    await e.onRendered.first;
+    expect(e.children.length, isNonZero, reason: 'has elements');
+    e.remove();
+    await e.onRendered.first;
+    expect(e.children.length, isZero, reason: 'is empty');
+  });
+}
diff --git a/runtime/observatory/tests/observatory_ui/isolate/counter_chart/element_test.html b/runtime/observatory/tests/observatory_ui/isolate/counter_chart/element_test.html
new file mode 100644
index 0000000..f0e956d
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/isolate/counter_chart/element_test.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <script type="text/javascript"
+      src="/root_dart/tools/testing/dart/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/runtime/observatory/tests/observatory_ui/isolate/isolate-shared-summary/element_test.dart b/runtime/observatory/tests/observatory_ui/isolate/isolate-shared-summary/element_test.dart
new file mode 100644
index 0000000..14aeeed
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/isolate/isolate-shared-summary/element_test.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'package:unittest/unittest.dart';
+import 'package:observatory/src/elements/isolate/counter_chart.dart';
+import 'package:observatory/src/elements/isolate/shared_summary.dart';
+import '../../mocks.dart';
+
+main() {
+  IsolateSharedSummaryElement.tag.ensureRegistration();
+
+  final cTag = IsolateCounterChartElement.tag.name;
+
+  const isolate = const IsolateMock();
+  test('instantiation', () {
+    final e = new IsolateSharedSummaryElement(isolate);
+    expect(e, isNotNull, reason: 'element correctly created');
+  });
+  test('elements created', () async {
+    final e = new IsolateSharedSummaryElement(isolate);
+    document.body.append(e);
+    await e.onRendered.first;
+    expect(e.children.length, isNonZero, reason: 'has elements');
+    expect(e.querySelectorAll(cTag).length, equals(1));
+    e.remove();
+    await e.onRendered.first;
+    expect(e.children.length, isZero, reason: 'is empty');
+  });
+}
diff --git a/runtime/observatory/tests/observatory_ui/isolate/isolate-shared-summary/element_test.html b/runtime/observatory/tests/observatory_ui/isolate/isolate-shared-summary/element_test.html
new file mode 100644
index 0000000..f0e956d
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/isolate/isolate-shared-summary/element_test.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <script type="text/javascript"
+      src="/root_dart/tools/testing/dart/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/runtime/observatory/tests/observatory_ui/isolate_reconnect/element_test.dart b/runtime/observatory/tests/observatory_ui/isolate_reconnect/element_test.dart
new file mode 100644
index 0000000..9b2a782
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/isolate_reconnect/element_test.dart
@@ -0,0 +1,80 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'package:unittest/unittest.dart';
+import 'package:observatory/src/elements/isolate_reconnect.dart';
+import 'package:observatory/src/elements/nav/notify.dart';
+import '../mocks.dart';
+
+main() {
+  IsolateReconnectElement.tag.ensureRegistration();
+
+  final nTag = NavNotifyElement.tag.name;
+
+  EventRepositoryMock events;
+  NotificationRepositoryMock notifications;
+  Uri uri;
+  const vm = const VMMock(isolates: const [
+    const IsolateMock(id: 'i-1-id'), const IsolateMock(id: 'i-2-id')
+  ]);
+  const missing = 'missing-id';
+  setUp(() {
+    events = new EventRepositoryMock();
+    notifications = new NotificationRepositoryMock();
+    uri = new  Uri(path: 'path');
+  });
+  test('instantiation', () {
+    final e = new IsolateReconnectElement(vm, events, notifications, missing,
+                                          uri);
+    expect(e, isNotNull, reason: 'element correctly created');
+    expect(e.vm, equals(vm));
+    expect(e.missing, equals(missing));
+    expect(e.uri, equals(uri));
+  });
+  test('elements created after attachment', () async {
+    final e = new IsolateReconnectElement(vm, events, notifications, missing,
+                                          uri);
+    document.body.append(e);
+    await e.onRendered.first;
+    expect(e.children.length, isNonZero, reason: 'has elements');
+    expect(e.querySelector(nTag), isNotNull, reason: 'has notifications');
+    expect(e.querySelectorAll('.isolate-link').length,
+        equals(vm.isolates.length), reason: 'has links');
+    e.remove();
+    await e.onRendered.first;
+    expect(e.children.length, isZero, reason: 'is empty');
+  });
+  group('updates', () {
+    test('are correctly listen', () async {
+      final e = new IsolateReconnectElement(vm, events, notifications, missing,
+                                            uri);
+      expect(events.onVMUpdateHasListener, isFalse);
+      document.body.append(e);
+      await e.onRendered.first;
+      expect(events.onVMUpdateHasListener, isTrue);
+      e.remove();
+      await e.onRendered.first;
+      expect(events.onVMUpdateHasListener, isFalse);
+    });
+    test('have effects', () async {
+      final e = new IsolateReconnectElement(vm, events, notifications, missing,
+                                            uri);
+      const vm2 = const VMMock(isolates: const [
+          const IsolateMock(id: 'i-1-id'), const IsolateMock(id: 'i-2-id'),
+          const IsolateMock(id: 'i-3-id')
+      ]);
+      document.body.append(e);
+      await e.onRendered.first;
+      expect(e.querySelectorAll('.isolate-link').length,
+          equals(vm.isolates.length));
+      events.add(new VMUpdateEventMock(vm: vm2));
+      await e.onRendered.first;
+      expect(e.querySelectorAll('.isolate-link').length,
+          equals(vm2.isolates.length));
+      e.remove();
+      await e.onRendered.first;
+    });
+  });
+}
diff --git a/runtime/observatory/tests/observatory_ui/isolate_reconnect/element_test.html b/runtime/observatory/tests/observatory_ui/isolate_reconnect/element_test.html
new file mode 100644
index 0000000..f0e956d
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/isolate_reconnect/element_test.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <script type="text/javascript"
+      src="/root_dart/tools/testing/dart/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/runtime/observatory/tests/observatory_ui/isolate_ref/element_test.dart b/runtime/observatory/tests/observatory_ui/isolate_ref/element_test.dart
index 2cfaafc..6d4e25b 100644
--- a/runtime/observatory/tests/observatory_ui/isolate_ref/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/isolate_ref/element_test.dart
@@ -1,12 +1,13 @@
 // Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+
 import 'dart:html';
 import 'package:unittest/unittest.dart';
 import 'package:observatory/src/elements/isolate_ref.dart';
 import '../mocks.dart';
 
-main(){
+main() {
   IsolateRefElement.tag.ensureRegistration();
 
   final ref = new IsolateRefMock(id: 'id', name: 'old-name');
diff --git a/runtime/observatory/tests/observatory_ui/library_ref/element_test.dart b/runtime/observatory/tests/observatory_ui/library_ref/element_test.dart
index 48291b5..f1e2dda 100644
--- a/runtime/observatory/tests/observatory_ui/library_ref/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/library_ref/element_test.dart
@@ -1,12 +1,13 @@
 // Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+
 import 'dart:html';
 import 'package:unittest/unittest.dart';
 import 'package:observatory/src/elements/library_ref.dart';
 import '../mocks.dart';
 
-main(){
+main() {
   LibraryRefElement.tag.ensureRegistration();
 
   const isolate = const IsolateRefMock(id: 'i-id', name: 'i-name');
diff --git a/runtime/observatory/tests/observatory_ui/mocks.dart b/runtime/observatory/tests/observatory_ui/mocks.dart
index b52b93b..dbe6645 100644
--- a/runtime/observatory/tests/observatory_ui/mocks.dart
+++ b/runtime/observatory/tests/observatory_ui/mocks.dart
@@ -16,9 +16,11 @@
 part 'mocks/objects/class.dart';
 part 'mocks/objects/flag.dart';
 part 'mocks/objects/function.dart';
+part 'mocks/objects/heap_space.dart';
 part 'mocks/objects/isolate.dart';
 part 'mocks/objects/library.dart';
 part 'mocks/objects/notification.dart';
+part 'mocks/objects/sample_profile.dart';
 part 'mocks/objects/script.dart';
 part 'mocks/objects/source_location.dart';
 part 'mocks/objects/target.dart';
@@ -29,5 +31,6 @@
 part 'mocks/repositories/flag.dart';
 part 'mocks/repositories/instance.dart';
 part 'mocks/repositories/notification.dart';
+part 'mocks/repositories/sample_profile.dart';
 part 'mocks/repositories/script.dart';
 part 'mocks/repositories/target.dart';
diff --git a/runtime/observatory/tests/observatory_ui/mocks/objects/heap_space.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/heap_space.dart
new file mode 100644
index 0000000..022414c
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/mocks/objects/heap_space.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of mocks;
+
+class HeapSpaceMock implements M.HeapSpace {
+  final int used;
+  final int capacity;
+  const HeapSpaceMock({this.used: 0, this.capacity: 1});
+}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/objects/isolate.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/isolate.dart
index d65b840..055b84e 100644
--- a/runtime/observatory/tests/observatory_ui/mocks/objects/isolate.dart
+++ b/runtime/observatory/tests/observatory_ui/mocks/objects/isolate.dart
@@ -18,8 +18,18 @@
   final String name;
   final DateTime startTime;
   final bool runnable;
+  final Iterable<M.LibraryRef> libraries;
+  final M.Error error;
+  final Iterable<String> extensionRPCs;
+  final Map counters;
+  final M.HeapSpace newSpace;
+  final M.HeapSpace oldSpace;
 
   const IsolateMock({this.id: 'i-id', this.number, this.name: 'i-name',
-                     this.startTime, this.runnable: true});
+                     this.startTime, this.runnable: true,
+                     this.libraries: const [], this.error,
+                     this.extensionRPCs: const [], this.counters: const {},
+                     this.newSpace: const HeapSpaceMock(),
+                     this.oldSpace: const HeapSpaceMock()});
   // TODO(cbernaschina) add other properties.
 }
diff --git a/runtime/observatory/tests/observatory_ui/mocks/objects/sample_profile.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/sample_profile.dart
new file mode 100644
index 0000000..4e8441c
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/mocks/objects/sample_profile.dart
@@ -0,0 +1,41 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of mocks;
+
+typedef M.FunctionCallTree SampleProfileMockLoadFunctionTreeCallback(
+    M.ProfileTreeDirection direction);
+typedef M.CodeCallTree SampleProfileMockLoadCodeTreeCallback(
+    M.ProfileTreeDirection direction);
+
+class SampleProfileMock implements M.SampleProfile {
+  final SampleProfileMockLoadFunctionTreeCallback _loadFunctionTree;
+  final SampleProfileMockLoadCodeTreeCallback _loadCodeTree;
+
+
+  final int sampleCount;
+  final int stackDepth;
+  final double sampleRate;
+  final double timeSpan;
+
+  M.FunctionCallTree loadFunctionTree(M.ProfileTreeDirection direction) {
+    if (_loadFunctionTree != null) {
+      return _loadFunctionTree(direction);
+    }
+    return null;
+  }
+  M.CodeCallTree loadCodeTree(M.ProfileTreeDirection direction) {
+    if (_loadCodeTree != null) {
+      return _loadCodeTree(direction);
+    }
+    return null;
+  }
+
+  SampleProfileMock({this.sampleCount: 0, this.stackDepth: 0,
+      this.sampleRate: 1.0, this.timeSpan: 1.0,
+      SampleProfileMockLoadFunctionTreeCallback loadFunctionTree,
+      SampleProfileMockLoadCodeTreeCallback loadCodeTree})
+    : _loadFunctionTree = loadFunctionTree,
+      _loadCodeTree = loadCodeTree;
+}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/repositories/sample_profile.dart b/runtime/observatory/tests/observatory_ui/mocks/repositories/sample_profile.dart
new file mode 100644
index 0000000..ffbf3bf
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/mocks/repositories/sample_profile.dart
@@ -0,0 +1,70 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of mocks;
+
+class SampleProfileLoadingProgressEventMock
+    implements M.SampleProfileLoadingProgressEvent {
+  final M.SampleProfileLoadingProgress progress;
+  SampleProfileLoadingProgressEventMock({this.progress});
+}
+
+class SampleProfileLoadingProgressMock
+    implements M.SampleProfileLoadingProgress {
+  final M.SampleProfileLoadingStatus status;
+  final double progress;
+  final Duration fetchingTime;
+  final Duration loadingTime;
+  final M.SampleProfile profile;
+
+  const SampleProfileLoadingProgressMock({
+      this.status: M.SampleProfileLoadingStatus.disabled,
+      this.progress: 0.0,
+      this.fetchingTime: const Duration(),
+      this.loadingTime: const Duration(),
+      this.profile
+    });
+}
+
+typedef Stream<M.SampleProfileLoadingProgressEvent>
+    ClassSampleProfileRepositoryMockCallback(M.ClassRef cls,
+        M.SampleProfileTag tag, bool clear);
+
+class ClassSampleProfileRepositoryMock
+    implements M.ClassSampleProfileRepository {
+  final ClassSampleProfileRepositoryMockCallback _get;
+
+  Stream<M.SampleProfileLoadingProgressEvent> get(M.ClassRef cls,
+      M.SampleProfileTag tag, {bool clear: false}) {
+    if (_get != null) {
+      return _get(cls, tag, clear);
+    }
+    return null;
+  }
+
+  ClassSampleProfileRepositoryMock(
+      {ClassSampleProfileRepositoryMockCallback getter})
+    : _get = getter;
+}
+
+typedef Stream<M.SampleProfileLoadingProgressEvent>
+    IsolateampleProfileRepositoryMockCallback(M.IsolateRef cls,
+        M.SampleProfileTag tag, bool clear, bool forceFetch);
+
+class IsolateSampleProfileRepositoryMock
+    implements M.IsolateSampleProfileRepository {
+  final IsolateampleProfileRepositoryMockCallback _get;
+
+  Stream<M.SampleProfileLoadingProgressEvent> get(M.IsolateRef isolate,
+      M.SampleProfileTag tag, {bool clear: false, bool forceFetch: false}) {
+    if (_get != null) {
+      return _get(isolate, tag, clear, forceFetch);
+    }
+    return null;
+  }
+
+  IsolateSampleProfileRepositoryMock(
+      {IsolateampleProfileRepositoryMockCallback getter})
+    : _get = getter;
+}
diff --git a/runtime/observatory/tests/observatory_ui/nav/bar/element_test.dart b/runtime/observatory/tests/observatory_ui/nav/bar/element_test.dart
index 98b9653..e450d3e 100644
--- a/runtime/observatory/tests/observatory_ui/nav/bar/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/nav/bar/element_test.dart
@@ -1,6 +1,7 @@
 // Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+
 import 'dart:html';
 import 'package:unittest/unittest.dart';
 import 'package:observatory/src/elements/nav/bar.dart';
diff --git a/runtime/observatory/tests/observatory_ui/nav/class-menu/element_test.dart b/runtime/observatory/tests/observatory_ui/nav/class-menu/element_test.dart
index 1b3766d..32fb9f0 100644
--- a/runtime/observatory/tests/observatory_ui/nav/class-menu/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/nav/class-menu/element_test.dart
@@ -1,12 +1,13 @@
 // Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+
 import 'dart:html';
 import 'package:unittest/unittest.dart';
 import 'package:observatory/src/elements/nav/class_menu.dart';
 import '../../mocks.dart';
 
-main(){
+main() {
   NavClassMenuElement.tag.ensureRegistration();
 
   final i_ref = const IsolateRefMock(id: 'i-id', name: 'i-name');
diff --git a/runtime/observatory/tests/observatory_ui/nav/isolate-menu/element_test.dart b/runtime/observatory/tests/observatory_ui/nav/isolate-menu/element_test.dart
index 235975f..3241c45 100644
--- a/runtime/observatory/tests/observatory_ui/nav/isolate-menu/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/nav/isolate-menu/element_test.dart
@@ -1,13 +1,14 @@
 // Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+
 import 'dart:html';
 import 'package:unittest/unittest.dart';
 import 'package:observatory/src/elements/nav/menu.dart';
 import 'package:observatory/src/elements/nav/isolate_menu.dart';
 import '../../mocks.dart';
 
-main(){
+main() {
   NavIsolateMenuElement.tag.ensureRegistration();
 
   final tag = NavMenuElement.tag.name;
diff --git a/runtime/observatory/tests/observatory_ui/nav/library-menu/element_test.dart b/runtime/observatory/tests/observatory_ui/nav/library-menu/element_test.dart
index 2144520..86fecea 100644
--- a/runtime/observatory/tests/observatory_ui/nav/library-menu/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/nav/library-menu/element_test.dart
@@ -1,12 +1,13 @@
 // Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+
 import 'dart:html';
 import 'package:unittest/unittest.dart';
 import 'package:observatory/src/elements/nav/library_menu.dart';
 import '../../mocks.dart';
 
-main(){
+main() {
   NavLibraryMenuElement.tag.ensureRegistration();
 
   final i_ref = const IsolateRefMock(id: 'i-id', name: 'i-name');
diff --git a/runtime/observatory/tests/observatory_ui/nav/menu-item/element_test.dart b/runtime/observatory/tests/observatory_ui/nav/menu-item/element_test.dart
index d439a60..5ab71f1 100644
--- a/runtime/observatory/tests/observatory_ui/nav/menu-item/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/nav/menu-item/element_test.dart
@@ -1,6 +1,7 @@
 // Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+
 import 'dart:html';
 import 'package:unittest/unittest.dart';
 import 'package:observatory/src/elements/nav/menu_item.dart';
diff --git a/runtime/observatory/tests/observatory_ui/nav/menu/element_test.dart b/runtime/observatory/tests/observatory_ui/nav/menu/element_test.dart
index 7e32086..5b35836 100644
--- a/runtime/observatory/tests/observatory_ui/nav/menu/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/nav/menu/element_test.dart
@@ -1,6 +1,7 @@
 // Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+
 import 'dart:html';
 import 'package:unittest/unittest.dart';
 import 'package:observatory/src/elements/nav/menu.dart';
diff --git a/runtime/observatory/tests/observatory_ui/nav/notify/element_test.dart b/runtime/observatory/tests/observatory_ui/nav/notify/element_test.dart
index 9cee6cf..cbdebba 100644
--- a/runtime/observatory/tests/observatory_ui/nav/notify/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/nav/notify/element_test.dart
@@ -1,6 +1,7 @@
 // Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+
 import 'dart:html' hide Notification, NotificationEvent;
 import 'package:unittest/unittest.dart';
 import 'package:observatory/models.dart' as M;
diff --git a/runtime/observatory/tests/observatory_ui/nav/notify_event/element_test.dart b/runtime/observatory/tests/observatory_ui/nav/notify_event/element_test.dart
index 9cea3f5..7c621bb 100644
--- a/runtime/observatory/tests/observatory_ui/nav/notify_event/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/nav/notify_event/element_test.dart
@@ -1,6 +1,7 @@
 // Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+
 import 'dart:html';
 import 'dart:async';
 import 'package:unittest/unittest.dart';
diff --git a/runtime/observatory/tests/observatory_ui/nav/notify_exception/connection_exception_test.dart b/runtime/observatory/tests/observatory_ui/nav/notify_exception/connection_exception_test.dart
index f09ed32..426828d 100644
--- a/runtime/observatory/tests/observatory_ui/nav/notify_exception/connection_exception_test.dart
+++ b/runtime/observatory/tests/observatory_ui/nav/notify_exception/connection_exception_test.dart
@@ -1,6 +1,7 @@
 // Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+
 import 'dart:html';
 import 'dart:async';
 import 'package:unittest/unittest.dart';
diff --git a/runtime/observatory/tests/observatory_ui/nav/notify_exception/exception_test.dart b/runtime/observatory/tests/observatory_ui/nav/notify_exception/exception_test.dart
index 4696ee8..e809b82 100644
--- a/runtime/observatory/tests/observatory_ui/nav/notify_exception/exception_test.dart
+++ b/runtime/observatory/tests/observatory_ui/nav/notify_exception/exception_test.dart
@@ -1,6 +1,7 @@
 // Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+
 import 'dart:html';
 import 'dart:async';
 import 'package:unittest/unittest.dart';
diff --git a/runtime/observatory/tests/observatory_ui/nav/refresh/element_test.dart b/runtime/observatory/tests/observatory_ui/nav/refresh/element_test.dart
index 05b3370..6752929 100644
--- a/runtime/observatory/tests/observatory_ui/nav/refresh/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/nav/refresh/element_test.dart
@@ -1,6 +1,7 @@
 // Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+
 import 'dart:html';
 import 'dart:async';
 import 'package:unittest/unittest.dart';
diff --git a/runtime/observatory/tests/observatory_ui/nav/top-menu/element_test.dart b/runtime/observatory/tests/observatory_ui/nav/top-menu/element_test.dart
index 5e62069..8a161b6 100644
--- a/runtime/observatory/tests/observatory_ui/nav/top-menu/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/nav/top-menu/element_test.dart
@@ -1,6 +1,7 @@
 // Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+
 import 'dart:html';
 import 'package:unittest/unittest.dart';
 import 'package:observatory/src/elements/nav/menu.dart';
diff --git a/runtime/observatory/tests/observatory_ui/nav/vm_menu/element_test.dart b/runtime/observatory/tests/observatory_ui/nav/vm_menu/element_test.dart
index 7aba8ed..a5596a7 100644
--- a/runtime/observatory/tests/observatory_ui/nav/vm_menu/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/nav/vm_menu/element_test.dart
@@ -1,6 +1,7 @@
 // Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+
 import 'dart:html';
 import 'package:unittest/unittest.dart';
 import 'package:observatory/src/elements/nav/menu.dart';
diff --git a/runtime/observatory/tests/observatory_ui/sample_buffer_control/element_test.dart b/runtime/observatory/tests/observatory_ui/sample_buffer_control/element_test.dart
new file mode 100644
index 0000000..aa82df1
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/sample_buffer_control/element_test.dart
@@ -0,0 +1,172 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:unittest/unittest.dart';
+import 'package:observatory/models.dart' as M;
+import 'package:observatory/src/elements/sample_buffer_control.dart';
+import '../mocks.dart';
+
+main() {
+  SampleBufferControlElement.tag.ensureRegistration();
+
+  group('instantiation', () {
+    SampleProfileLoadingProgressMock progress;
+    StreamController<SampleProfileLoadingProgressEventMock> events;
+    setUp(() {
+      progress = new SampleProfileLoadingProgressMock();
+      events = new StreamController<SampleProfileLoadingProgressEventMock>();
+    });
+    test('no additional parameters', () {
+      final e = new SampleBufferControlElement(progress, events.stream);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.progress, equals(progress));
+      expect(e.selectedTag, equals(M.SampleProfileTag.none));
+      expect(e.showTag, isTrue);
+    });
+    test('selected tag', () {
+      const tag = M.SampleProfileTag.userOnly;
+      final e = new SampleBufferControlElement(progress, events.stream,
+          selectedTag: tag);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.progress, equals(progress));
+      expect(e.selectedTag, equals(tag));
+      expect(e.showTag, isTrue);
+    });
+    test('show tag (true)', () {
+      final e = new SampleBufferControlElement(progress, events.stream,
+          showTag: true);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.progress, equals(progress));
+      expect(e.selectedTag, equals(M.SampleProfileTag.none));
+      expect(e.showTag, isTrue);
+    });
+    test('show tag (false)', () {
+      final e = new SampleBufferControlElement(progress, events.stream,
+          showTag: false);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.progress, equals(progress));
+      expect(e.selectedTag, equals(M.SampleProfileTag.none));
+      expect(e.showTag, isFalse);
+    });
+  });
+  group('elements', () {
+    SampleProfileLoadingProgressMock progress;
+    StreamController<SampleProfileLoadingProgressEventMock> events;
+    setUp(() {
+      progress = new SampleProfileLoadingProgressMock();
+      events = new StreamController<SampleProfileLoadingProgressEventMock>();
+    });
+    test('created after attachment', () async {
+      final e = new SampleBufferControlElement(progress, events.stream);
+      document.body.append(e);
+      await e.onRendered.first;
+      expect(e.children.length, isNonZero, reason: 'has elements');
+      e.remove();
+      await e.onRendered.first;
+      expect(e.children.length, isZero,
+        reason: 'is empty');
+    });
+    test('listen for status changes', () async {
+      final e = new SampleBufferControlElement(progress, events.stream);
+      expect(events.hasListener, isFalse);
+      document.body.append(e);
+      await e.onRendered.first;
+      expect(events.hasListener, isTrue);
+      events.add(new SampleProfileLoadingProgressEventMock(progress: progress));
+      events.close();
+      await e.onRendered.first;
+      e.remove();
+      await e.onRendered.first;
+    });
+    test('follow updates changes', () async {
+      final e = new SampleBufferControlElement(progress, events.stream);
+      document.body.append(e);
+      await e.onRendered.first;
+      expect(e.querySelector('select'), isNull);
+      events.add(new SampleProfileLoadingProgressEventMock(
+        progress: new SampleProfileLoadingProgressMock(
+          status: M.SampleProfileLoadingStatus.fetching
+      )));
+      await e.onRendered.first;
+      expect(e.querySelector('select'), isNull);
+      events.add(new SampleProfileLoadingProgressEventMock(
+        progress: new SampleProfileLoadingProgressMock(
+          status: M.SampleProfileLoadingStatus.loading
+      )));
+      await e.onRendered.first;
+      expect(e.querySelector('select'), isNull);
+      events.add(new SampleProfileLoadingProgressEventMock(
+        progress: new SampleProfileLoadingProgressMock(
+          status: M.SampleProfileLoadingStatus.loaded,
+          profile: new SampleProfileMock()
+      )));
+      events.close();
+      await e.onRendered.first;
+      expect(e.querySelector('select'), isNotNull);
+      e.remove();
+      await e.onRendered.first;
+    });
+    test('follow updates changes (no tag)', () async {
+      final e = new SampleBufferControlElement(progress, events.stream,
+        showTag: false);
+      document.body.append(e);
+      await e.onRendered.first;
+      expect(e.querySelector('select'), isNull);
+      events.add(new SampleProfileLoadingProgressEventMock(
+        progress: new SampleProfileLoadingProgressMock(
+          status: M.SampleProfileLoadingStatus.fetching
+      )));
+      await e.onRendered.first;
+      expect(e.querySelector('select'), isNull);
+      events.add(new SampleProfileLoadingProgressEventMock(
+        progress: new SampleProfileLoadingProgressMock(
+          status: M.SampleProfileLoadingStatus.loading
+      )));
+      await e.onRendered.first;
+      expect(e.querySelector('select'), isNull);
+      events.add(new SampleProfileLoadingProgressEventMock(
+        progress: new SampleProfileLoadingProgressMock(
+          status: M.SampleProfileLoadingStatus.loaded,
+          profile: new SampleProfileMock()
+      )));
+      await e.onRendered.first;
+      expect(e.querySelector('select'), isNull);
+      e.remove();
+      await e.onRendered.first;
+    });
+  });
+  group('events', () {
+    SampleProfileLoadingProgressMock progress;
+    StreamController<SampleProfileLoadingProgressEventMock> events;
+    setUp(() {
+      progress = new SampleProfileLoadingProgressMock();
+      events = new StreamController<SampleProfileLoadingProgressEventMock>();
+    });
+    test('onModeChange', () async {
+      final e = new SampleBufferControlElement(progress, events.stream);
+      document.body.append(e);
+      await e.onRendered.first;
+      events.add(new SampleProfileLoadingProgressEventMock(
+        progress: new SampleProfileLoadingProgressMock(
+          status: M.SampleProfileLoadingStatus.loaded,
+          profile: new SampleProfileMock()
+      )));
+      await e.onRendered.first;
+      expect(e.selectedTag, equals(M.SampleProfileTag.none));
+      e.onTagChange.listen(expectAsync((_) {
+        expect(e.selectedTag, equals(M.SampleProfileTag.userOnly));
+      }, count: 1));
+      final select = (e.querySelector('.tag-select') as SelectElement);
+      select.selectedIndex = select.options.indexOf(
+          (select.options.toSet()
+            ..removeAll(select.selectedOptions)).toList().first
+        );
+      select.dispatchEvent(new Event("change"));
+      e.remove();
+      await e.onRendered.first;
+    });
+  });
+}
diff --git a/runtime/observatory/tests/observatory_ui/sample_buffer_control/element_test.html b/runtime/observatory/tests/observatory_ui/sample_buffer_control/element_test.html
new file mode 100644
index 0000000..f0e956d
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/sample_buffer_control/element_test.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <script type="text/javascript"
+      src="/root_dart/tools/testing/dart/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/runtime/observatory/tests/observatory_ui/script_ref/element_test.dart b/runtime/observatory/tests/observatory_ui/script_ref/element_test.dart
index 6dc2b84..b6c6e93 100644
--- a/runtime/observatory/tests/observatory_ui/script_ref/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/script_ref/element_test.dart
@@ -1,6 +1,7 @@
 // Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+
 import 'dart:html';
 import 'package:unittest/unittest.dart';
 import 'package:observatory/src/elements/script_ref.dart';
diff --git a/runtime/observatory/tests/observatory_ui/source_link/element_test.dart b/runtime/observatory/tests/observatory_ui/source_link/element_test.dart
index 3dcb5dd..bd096b8 100644
--- a/runtime/observatory/tests/observatory_ui/source_link/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/source_link/element_test.dart
@@ -1,6 +1,7 @@
 // Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+
 import 'dart:html';
 import 'package:unittest/unittest.dart';
 import 'package:observatory/src/elements/source_link.dart';
diff --git a/runtime/observatory/tests/observatory_ui/stack_trace_tree_config/element_test.dart b/runtime/observatory/tests/observatory_ui/stack_trace_tree_config/element_test.dart
new file mode 100644
index 0000000..f8c0f00
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/stack_trace_tree_config/element_test.dart
@@ -0,0 +1,185 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'package:unittest/unittest.dart';
+import 'package:observatory/models.dart' as M;
+import 'package:observatory/src/elements/stack_trace_tree_config.dart';
+
+main() {
+  StackTraceTreeConfigElement.tag.ensureRegistration();
+
+  group('instantiation', () {
+    test('default', () {
+      final e = new StackTraceTreeConfigElement();
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.showMode, isTrue);
+      expect(e.showDirection, isTrue);
+      expect(e.showFilter, isTrue);
+      expect(e.filter, equals(''));
+      expect(e.mode, equals(ProfileTreeMode.function));
+      expect(e.direction, equals(M.ProfileTreeDirection.exclusive));
+    });
+    test('showMode', () {
+      final e = new StackTraceTreeConfigElement(showMode: false);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.showMode, isFalse);
+      expect(e.showDirection, isTrue);
+      expect(e.showFilter, isTrue);
+      expect(e.filter, equals(''));
+      expect(e.mode, equals(ProfileTreeMode.function));
+      expect(e.direction, equals(M.ProfileTreeDirection.exclusive));
+    });
+    test('showDirection', () {
+      final e = new StackTraceTreeConfigElement(showDirection: false);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.showMode, isTrue);
+      expect(e.showDirection, isFalse);
+      expect(e.showFilter, isTrue);
+      expect(e.filter, equals(''));
+      expect(e.mode, equals(ProfileTreeMode.function));
+      expect(e.direction, equals(M.ProfileTreeDirection.exclusive));
+    });
+    test('showFilter', () {
+      final e = new StackTraceTreeConfigElement(showFilter: false);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.showMode, isTrue);
+      expect(e.showDirection, isTrue);
+      expect(e.showFilter, isFalse);
+      expect(e.filter, equals(''));
+      expect(e.mode, equals(ProfileTreeMode.function));
+      expect(e.direction, equals(M.ProfileTreeDirection.exclusive));
+    });
+    test('filter', () {
+      final filter = 'filter-string';
+      final e = new StackTraceTreeConfigElement(filter: filter);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.showMode, isTrue);
+      expect(e.showDirection, isTrue);
+      expect(e.showFilter, isTrue);
+      expect(e.filter, equals(filter));
+      expect(e.mode, equals(ProfileTreeMode.function));
+      expect(e.direction, equals(M.ProfileTreeDirection.exclusive));
+    });
+    test('mode', () {
+      final e = new StackTraceTreeConfigElement(mode: ProfileTreeMode.code);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.showMode, isTrue);
+      expect(e.showDirection, isTrue);
+      expect(e.showFilter, isTrue);
+      expect(e.filter, equals(''));
+      expect(e.mode, equals(ProfileTreeMode.code));
+      expect(e.direction, equals(M.ProfileTreeDirection.exclusive));
+    });
+    test('default', () {
+      final e = new StackTraceTreeConfigElement(
+          direction: M.ProfileTreeDirection.inclusive);
+      expect(e, isNotNull, reason: 'element correctly created');
+      expect(e.showMode, isTrue);
+      expect(e.showDirection, isTrue);
+      expect(e.showFilter, isTrue);
+      expect(e.filter, equals(''));
+      expect(e.mode, equals(ProfileTreeMode.function));
+      expect(e.direction, equals(M.ProfileTreeDirection.inclusive));
+    });
+  });
+  group('elements', () {
+    test('created after attachment', () async {
+      final e = new StackTraceTreeConfigElement();
+      document.body.append(e);
+      await e.onRendered.first;
+      expect(e.children.length, isNonZero, reason: 'has elements');
+      e.remove();
+      await e.onRendered.first;
+      expect(e.children.length, isZero, reason: 'is empty');
+    });
+    test('react to mode change', () async {
+      final e = new StackTraceTreeConfigElement();
+      document.body.append(e);
+      await e.onRendered.first;
+      expect(e.mode, equals(ProfileTreeMode.function));
+      e.mode = ProfileTreeMode.code;
+      await e.onRendered.first;
+      expect(e.mode, equals(ProfileTreeMode.code));
+      e.remove();
+      await e.onRendered.first;
+      expect(e.children.length, isZero, reason: 'is empty');
+    });
+    test('react to direction change', () async {
+      final e = new StackTraceTreeConfigElement();
+      document.body.append(e);
+      await e.onRendered.first;
+      expect(e.direction, equals(M.ProfileTreeDirection.exclusive));
+      e.direction = M.ProfileTreeDirection.inclusive;
+      await e.onRendered.first;
+      expect(e.direction, equals(M.ProfileTreeDirection.inclusive));
+      e.remove();
+      await e.onRendered.first;
+      expect(e.children.length, isZero, reason: 'is empty');
+    });
+    test('react to filter change', () async {
+      final filter = 'filter-string';
+      final e = new StackTraceTreeConfigElement();
+      document.body.append(e);
+      await e.onRendered.first;
+      expect(e.filter, equals(''));
+      e.filter = filter;
+      await e.onRendered.first;
+      expect(e.filter, equals(filter));
+      e.remove();
+      await e.onRendered.first;
+      expect(e.children.length, isZero, reason: 'is empty');
+    });
+  });
+  group('events', () {
+    test('onModeChange', () async {
+      final e = new StackTraceTreeConfigElement();
+      document.body.append(e);
+      await e.onRendered.first;
+      expect(e.mode, equals(ProfileTreeMode.function));
+      e.onModeChange.listen(expectAsync((_) {
+        expect(e.mode, equals(ProfileTreeMode.code));
+      }, count: 1));
+      final select = (e.querySelector('.mode-select') as SelectElement);
+      select.selectedIndex = select.options.indexOf(
+          (select.options.toSet()
+            ..removeAll(select.selectedOptions)).toList().first
+        );
+      select.dispatchEvent(new Event("change"));
+      e.remove();
+      await e.onRendered.first;
+    });
+    test('onDirectionChange', () async {
+      final e = new StackTraceTreeConfigElement();
+      document.body.append(e);
+      await e.onRendered.first;
+      expect(e.direction, equals(M.ProfileTreeDirection.exclusive));
+      e.onDirectionChange.listen(expectAsync((_) {
+        expect(e.direction, equals(M.ProfileTreeDirection.inclusive));
+      }, count: 1));
+      final select = (e.querySelector('.direction-select') as SelectElement);
+      select.selectedIndex = select.options.indexOf(
+          (select.options.toSet()
+            ..removeAll(select.selectedOptions)).toList().first
+        );
+      select.dispatchEvent(new Event("change"));
+      e.remove();
+      await e.onRendered.first;
+    });
+    test('onFilterChange', () async {
+      final e = new StackTraceTreeConfigElement();
+      document.body.append(e);
+      await e.onRendered.first;
+      expect(e.direction, equals(M.ProfileTreeDirection.exclusive));
+      e.onFilterChange.listen(expectAsync((_) {
+        expect(e.filter, equals('value'));
+      }, count: 1));
+      var input = (e.querySelector('input') as TextInputElement);
+      input.value = 'value';
+      input.dispatchEvent(new Event("change"));
+      e.remove();
+      await e.onRendered.first;
+    });
+  });
+}
diff --git a/runtime/observatory/tests/observatory_ui/stack_trace_tree_config/element_test.html b/runtime/observatory/tests/observatory_ui/stack_trace_tree_config/element_test.html
new file mode 100644
index 0000000..f0e956d
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/stack_trace_tree_config/element_test.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="dart.unittest" content="full-stack-traces">
+  <style>
+     .unittest-table { font-family:monospace; border:1px; }
+     .unittest-pass { background: #6b3;}
+     .unittest-fail { background: #d55;}
+     .unittest-error { background: #a11;}
+  </style>
+  <script src="/packages/web_components/webcomponents.js"></script>
+  <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+  <script type="text/javascript"
+      src="/root_dart/tools/testing/dart/test_controller.js"></script>
+  %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/runtime/observatory/tests/observatory_ui/view_footer/element_test.dart b/runtime/observatory/tests/observatory_ui/view_footer/element_test.dart
index 143464e..77cb4cc 100644
--- a/runtime/observatory/tests/observatory_ui/view_footer/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/view_footer/element_test.dart
@@ -1,6 +1,7 @@
 // Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+
 import 'dart:html';
 import 'package:unittest/unittest.dart';
 import 'package:observatory/src/elements/view_footer.dart';
diff --git a/runtime/observatory/tests/observatory_ui/vm_connect/element_test.dart b/runtime/observatory/tests/observatory_ui/vm_connect/element_test.dart
index 270e0d5..84026e5 100644
--- a/runtime/observatory/tests/observatory_ui/vm_connect/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/vm_connect/element_test.dart
@@ -1,6 +1,7 @@
 // Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+
 import 'dart:html';
 import 'package:unittest/unittest.dart';
 import 'package:observatory/src/elements/nav/notify.dart';
diff --git a/runtime/observatory/tests/observatory_ui/vm_connect_target/element_test.dart b/runtime/observatory/tests/observatory_ui/vm_connect_target/element_test.dart
index 45efab6..b4011f9 100644
--- a/runtime/observatory/tests/observatory_ui/vm_connect_target/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/vm_connect_target/element_test.dart
@@ -1,6 +1,7 @@
 // Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+
 import 'dart:html';
 import 'package:unittest/unittest.dart';
 import 'package:observatory/src/elements/vm_connect_target.dart';
diff --git a/runtime/observatory/tests/service/dev_fs_http_put_test.dart b/runtime/observatory/tests/service/dev_fs_http_put_test.dart
new file mode 100644
index 0000000..c5639a8
--- /dev/null
+++ b/runtime/observatory/tests/service/dev_fs_http_put_test.dart
@@ -0,0 +1,101 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--error_on_bad_type --error_on_bad_override
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+import 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'test_helper.dart';
+
+Future<String> readResponse(HttpClientResponse response) {
+  var completer = new Completer();
+  var contents = new StringBuffer();
+  response.transform(UTF8.decoder).listen((String data) {
+    contents.write(data);
+  }, onDone: () => completer.complete(contents.toString()));
+  return completer.future;
+}
+
+
+var tests = [
+  // Write a file with the ? character in the filename.
+  (VM vm) async {
+    var fsId = 'test';
+    var filePath = '/foo/bar.dat';
+    var fileContents = [0, 1, 2, 3, 4, 5, 6, 255];
+    var fileContentsBase64 = BASE64.encode(fileContents);
+
+    var result;
+    // Create DevFS.
+    result = await vm.invokeRpcNoUpgrade('_createDevFS', { 'fsName': fsId });
+    expect(result['type'], equals('FileSystem'));
+    expect(result['name'], equals(fsId));
+    expect(result['uri'], new isInstanceOf<String>());
+
+    // Write the file by issuing an HTTP PUT.
+    HttpClient client = new HttpClient();
+    HttpClientRequest request =
+        await client.putUrl(Uri.parse(serviceHttpAddress));
+    request.headers.add('dev_fs_name', fsId);
+    request.headers.add('dev_fs_path', filePath);
+    request.add(GZIP.encode([9]));
+    HttpClientResponse response = await request.close();
+    String responseBody = await readResponse(response);
+    result = JSON.decode(responseBody);
+    expect(result['result']['type'], equals('Success'));
+
+    // Trigger an error by issuing an HTTP PUT.
+    request = await client.putUrl(Uri.parse(serviceHttpAddress));
+    request.headers.add('dev_fs_name', fsId);
+    // omit the 'dev_fs_path' parameter.
+    request.write(GZIP.encode(fileContents));
+    response = await request.close();
+    responseBody = await readResponse(response);
+    result = JSON.decode(responseBody);
+    Map error = result['error']['data'];
+    expect(error, isNotNull);
+    expect(error['details'].contains("expects the 'path' parameter"), isTrue);
+
+    // Write the file again but this time with the true file contents.
+    client = new HttpClient();
+    request =
+        await client.putUrl(Uri.parse(serviceHttpAddress));
+    request.headers.add('dev_fs_name', fsId);
+    request.headers.add('dev_fs_path', filePath);
+    request.add(GZIP.encode(fileContents));
+    response = await request.close();
+    responseBody = await readResponse(response);
+    result = JSON.decode(responseBody);
+    expect(result['result']['type'], equals('Success'));
+
+    // Close the HTTP client.
+    client.close();
+
+    // Read the file back.
+    result = await vm.invokeRpcNoUpgrade('_readDevFSFile', {
+        'fsName': fsId,
+        'path': filePath,
+    });
+    expect(result['type'], equals('FSFile'));
+    expect(result['fileContents'], equals(fileContentsBase64));
+
+    // List all the files in the file system.
+    result = await vm.invokeRpcNoUpgrade('_listDevFSFiles', {
+        'fsName': fsId,
+    });
+    expect(result['type'], equals('FSFileList'));
+    expect(result['files'].length, equals(1));
+    expect(result['files'][0]['name'], equals(filePath));
+
+    // Delete DevFS.
+    result = await vm.invokeRpcNoUpgrade('_deleteDevFS', {
+        'fsName': fsId,
+    });
+    expect(result['type'], equals('Success'));
+  },
+];
+
+main(args) async => runVMTests(args, tests);
diff --git a/runtime/observatory/tests/service/get_allocation_samples_test.dart b/runtime/observatory/tests/service/get_allocation_samples_test.dart
index 85626ee..d26c75f 100644
--- a/runtime/observatory/tests/service/get_allocation_samples_test.dart
+++ b/runtime/observatory/tests/service/get_allocation_samples_test.dart
@@ -4,6 +4,7 @@
 // VMOptions=--error_on_bad_type --error_on_bad_override
 
 import 'dart:developer';
+import 'package:observatory/models.dart' as M;
 import 'package:observatory/service_io.dart';
 import 'package:observatory/cpu_profile.dart';
 import 'package:unittest/unittest.dart';
@@ -61,10 +62,10 @@
     await fooClass.reload();
     expect(fooClass.traceAllocations, isFalse);
     CpuProfile cpuProfile = new CpuProfile();
-    cpuProfile.load(isolate, profileResponse);
+    await cpuProfile.load(isolate, profileResponse);
     cpuProfile.buildCodeCallerAndCallees();
     cpuProfile.buildFunctionCallerAndCallees();
-    var tree = cpuProfile.loadCodeTree('exclusive');
+    var tree = cpuProfile.loadCodeTree(M.ProfileTreeDirection.exclusive);
     var node = tree.root;
     var expected =
         ['Root', 'DRT_AllocateObject', 'test', 'test', '_Closure.call'];
diff --git a/runtime/observatory/web/index.html b/runtime/observatory/web/index.html
index 0659525..ccd9bfc 100644
--- a/runtime/observatory/web/index.html
+++ b/runtime/observatory/web/index.html
@@ -4,6 +4,7 @@
   <meta charset="utf-8">
   <title>Dart VM Observatory</title>
   <link rel="import" href="packages/polymer/polymer.html">
+  <link rel="stylesheet" href="packages/charted/charts/themes/quantum_theme.css">
   <link rel="stylesheet" href="packages/observatory/src/elements/css/shared.css">
   <link rel="import" href="packages/observatory/elements.html">
   <script src="packages/js_util/dist/js_util.js"></script>
@@ -11,6 +12,5 @@
   <script src="packages/browser/dart.js"></script>
 </head>
 <body style="height: 100%">
-  <observatory-application></observatory-application>
 </body>
 </html>
diff --git a/runtime/observatory/web/main.dart b/runtime/observatory/web/main.dart
index 41f3dc7..36c03ab 100644
--- a/runtime/observatory/web/main.dart
+++ b/runtime/observatory/web/main.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'dart:html';
 import 'package:logging/logging.dart';
 import 'package:polymer/polymer.dart';
 import 'package:observatory/elements.dart';
@@ -24,4 +25,6 @@
   Logger.root.info('Polymer initialized');
   await Polymer.onReady;
   Logger.root.info('Polymer elements have been upgraded');
+  document.body.children
+      .insert(0, document.createElement('observatory-application'));
 }
diff --git a/runtime/vm/assembler_arm64.cc b/runtime/vm/assembler_arm64.cc
index 54dcabb..705d8c8 100644
--- a/runtime/vm/assembler_arm64.cc
+++ b/runtime/vm/assembler_arm64.cc
@@ -13,12 +13,6 @@
 #include "vm/stack_frame.h"
 #include "vm/stub_code.h"
 
-// An extra check since we are assuming the existence of /proc/cpuinfo below.
-#if !defined(USING_SIMULATOR) && !defined(__linux__) && !defined(ANDROID) && \
-    !TARGET_OS_IOS
-#error ARM64 cross-compile only supported on Linux
-#endif
-
 namespace dart {
 
 DECLARE_FLAG(bool, check_code_pointer);
diff --git a/runtime/vm/assembler_arm64_test.cc b/runtime/vm/assembler_arm64_test.cc
index 329466a..3d95b7c 100644
--- a/runtime/vm/assembler_arm64_test.cc
+++ b/runtime/vm/assembler_arm64_test.cc
@@ -13,8 +13,6 @@
 
 namespace dart {
 
-static const intptr_t kTestStackSpace = 512 * kWordSize;
-
 #define __ assembler->
 
 ASSEMBLER_TEST_GENERATE(Simple, assembler) {
diff --git a/runtime/vm/cpu_arm64.cc b/runtime/vm/cpu_arm64.cc
index 881aebc..e612cce 100644
--- a/runtime/vm/cpu_arm64.cc
+++ b/runtime/vm/cpu_arm64.cc
@@ -3,10 +3,11 @@
 // BSD-style license that can be found in the LICENSE file.
 
 #include "vm/globals.h"
-
 #if defined(TARGET_ARCH_ARM64)
 
 #include "vm/cpu.h"
+#include "vm/cpu_arm64.h"
+
 #include "vm/cpuinfo.h"
 #include "vm/simulator.h"
 
@@ -31,13 +32,15 @@
 
   // ARM recommends using the gcc intrinsic __clear_cache on Linux and Android.
   // blogs.arm.com/software-enablement/141-caches-and-self-modifying-code/
-  #if defined(__linux__) || defined(ANDROID)
+  #if defined(TARGET_OS_ANDROID) || \
+      defined(TARGET_OS_FUCHSIA) || \
+      defined(TARGET_OS_LINUX)
     extern void __clear_cache(char*, char*);
     char* beg = reinterpret_cast<char*>(start);
     char* end = reinterpret_cast<char*>(start + size);
     ::__clear_cache(beg, end);
   #else
-    #error FlushICache only tested/supported on Linux and Android
+    #error FlushICache only tested/supported on Android, Fuchsia, and Linux
   #endif
 
 #endif
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index aff9955..61bd28f 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -1142,37 +1142,29 @@
   return Version::String();
 }
 
-DART_EXPORT char* Dart_Initialize(
-    const uint8_t* vm_isolate_snapshot,
-    const uint8_t* instructions_snapshot,
-    const uint8_t* data_snapshot,
-    Dart_IsolateCreateCallback create,
-    Dart_IsolateInterruptCallback interrupt,
-    Dart_IsolateUnhandledExceptionCallback unhandled,
-    Dart_IsolateShutdownCallback shutdown,
-    Dart_ThreadExitCallback thread_exit,
-    Dart_FileOpenCallback file_open,
-    Dart_FileReadCallback file_read,
-    Dart_FileWriteCallback file_write,
-    Dart_FileCloseCallback file_close,
-    Dart_EntropySource entropy_source,
-    Dart_GetVMServiceAssetsArchive get_service_assets) {
-  if (interrupt != NULL) {
+DART_EXPORT char* Dart_Initialize(Dart_InitializeParams* params) {
+  if (params == NULL) {
     return strdup("Dart_Initialize: "
-                  "Setting of interrupt callback is not supported.");
+                  "Dart_InitializeParams is null.");
   }
-  if (unhandled != NULL) {
+
+  if (params->version != DART_INITIALIZE_PARAMS_CURRENT_VERSION) {
     return strdup("Dart_Initialize: "
-                  "Setting of unhandled exception callback is not supported.");
+                  "Invalid Dart_InitializeParams version.");
   }
-  return Dart::InitOnce(vm_isolate_snapshot,
-                        instructions_snapshot,
-                        data_snapshot,
-                        create, shutdown,
-                        thread_exit,
-                        file_open, file_read, file_write, file_close,
-                        entropy_source,
-                        get_service_assets);
+
+  return Dart::InitOnce(params->vm_isolate_snapshot,
+                        params->instructions_snapshot,
+                        params->data_snapshot,
+                        params->create,
+                        params->shutdown,
+                        params->thread_exit,
+                        params->file_open,
+                        params->file_read,
+                        params->file_write,
+                        params->file_close,
+                        params->entropy_source,
+                        params->get_service_assets);
 }
 
 
@@ -1450,6 +1442,32 @@
 }
 
 
+DART_EXPORT void Dart_SetStickyError(Dart_Handle error) {
+  Thread* thread = Thread::Current();
+  DARTSCOPE(thread);
+  Isolate* isolate = thread->isolate();
+  CHECK_ISOLATE(isolate);
+  NoSafepointScope no_safepoint_scope;
+  if (isolate->sticky_error() != Error::null()) {
+    FATAL1("%s expects there to be no sticky error.", CURRENT_FUNC);
+  }
+  if (!::Dart_IsUnhandledExceptionError(error)) {
+    FATAL1("%s expects the error to be an unhandled exception error.",
+            CURRENT_FUNC);
+  }
+  isolate->SetStickyError(
+      Api::UnwrapErrorHandle(Z, error).raw());
+}
+
+
+DART_EXPORT bool Dart_HasStickyError() {
+  Isolate* isolate = Isolate::Current();
+  CHECK_ISOLATE(isolate);
+  NoSafepointScope no_safepoint_scope;
+  return isolate->sticky_error() != Error::null();
+}
+
+
 DART_EXPORT void Dart_ExitIsolate() {
   Thread* T = Thread::Current();
   CHECK_ISOLATE(T->isolate());
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 3dbf3f6..b7348e4 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -3618,6 +3618,19 @@
 }
 
 
+TEST_CASE(SetStickyError) {
+    const char* kScriptChars =
+      "main() => throw 'HI';";
+  Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
+  Dart_Handle retobj = Dart_Invoke(lib, NewString("main"), 0, NULL);
+  EXPECT(Dart_IsError(retobj));
+  EXPECT(Dart_IsUnhandledExceptionError(retobj));
+  EXPECT(!Dart_HasStickyError());
+  Dart_SetStickyError(retobj);
+  EXPECT(Dart_HasStickyError());
+}
+
+
 TEST_CASE(TypeGetNonParamtericTypes) {
   const char* kScriptChars =
       "class MyClass0 {\n"
diff --git a/runtime/vm/flow_graph_inliner.cc b/runtime/vm/flow_graph_inliner.cc
index a8e27c0..8ee6739 100644
--- a/runtime/vm/flow_graph_inliner.cc
+++ b/runtime/vm/flow_graph_inliner.cc
@@ -2102,86 +2102,6 @@
 }
 
 
-static intptr_t MethodKindToCid(MethodRecognizer::Kind kind) {
-  switch (kind) {
-    case MethodRecognizer::kImmutableArrayGetIndexed:
-      return kImmutableArrayCid;
-
-    case MethodRecognizer::kObjectArrayGetIndexed:
-    case MethodRecognizer::kObjectArraySetIndexed:
-      return kArrayCid;
-
-    case MethodRecognizer::kGrowableArrayGetIndexed:
-    case MethodRecognizer::kGrowableArraySetIndexed:
-      return kGrowableObjectArrayCid;
-
-    case MethodRecognizer::kFloat32ArrayGetIndexed:
-    case MethodRecognizer::kFloat32ArraySetIndexed:
-      return kTypedDataFloat32ArrayCid;
-
-    case MethodRecognizer::kFloat64ArrayGetIndexed:
-    case MethodRecognizer::kFloat64ArraySetIndexed:
-      return kTypedDataFloat64ArrayCid;
-
-    case MethodRecognizer::kInt8ArrayGetIndexed:
-    case MethodRecognizer::kInt8ArraySetIndexed:
-      return kTypedDataInt8ArrayCid;
-
-    case MethodRecognizer::kUint8ArrayGetIndexed:
-    case MethodRecognizer::kUint8ArraySetIndexed:
-      return kTypedDataUint8ArrayCid;
-
-    case MethodRecognizer::kUint8ClampedArrayGetIndexed:
-    case MethodRecognizer::kUint8ClampedArraySetIndexed:
-      return kTypedDataUint8ClampedArrayCid;
-
-    case MethodRecognizer::kExternalUint8ArrayGetIndexed:
-    case MethodRecognizer::kExternalUint8ArraySetIndexed:
-      return kExternalTypedDataUint8ArrayCid;
-
-    case MethodRecognizer::kExternalUint8ClampedArrayGetIndexed:
-    case MethodRecognizer::kExternalUint8ClampedArraySetIndexed:
-      return kExternalTypedDataUint8ClampedArrayCid;
-
-    case MethodRecognizer::kInt16ArrayGetIndexed:
-    case MethodRecognizer::kInt16ArraySetIndexed:
-      return kTypedDataInt16ArrayCid;
-
-    case MethodRecognizer::kUint16ArrayGetIndexed:
-    case MethodRecognizer::kUint16ArraySetIndexed:
-      return kTypedDataUint16ArrayCid;
-
-    case MethodRecognizer::kInt32ArrayGetIndexed:
-    case MethodRecognizer::kInt32ArraySetIndexed:
-      return kTypedDataInt32ArrayCid;
-
-    case MethodRecognizer::kUint32ArrayGetIndexed:
-    case MethodRecognizer::kUint32ArraySetIndexed:
-      return kTypedDataUint32ArrayCid;
-
-    case MethodRecognizer::kInt64ArrayGetIndexed:
-    case MethodRecognizer::kInt64ArraySetIndexed:
-      return kTypedDataInt64ArrayCid;
-
-    case MethodRecognizer::kFloat32x4ArrayGetIndexed:
-    case MethodRecognizer::kFloat32x4ArraySetIndexed:
-      return kTypedDataFloat32x4ArrayCid;
-
-    case MethodRecognizer::kInt32x4ArrayGetIndexed:
-    case MethodRecognizer::kInt32x4ArraySetIndexed:
-      return kTypedDataInt32x4ArrayCid;
-
-    case MethodRecognizer::kFloat64x2ArrayGetIndexed:
-    case MethodRecognizer::kFloat64x2ArraySetIndexed:
-      return kTypedDataFloat64x2ArrayCid;
-
-    default:
-      break;
-  }
-  return kIllegalCid;
-}
-
-
 static Instruction* GetCheckClass(FlowGraph* flow_graph,
                                   Definition* to_check,
                                   const ICData& unary_checks,
@@ -2204,8 +2124,7 @@
                              Definition* receiver,
                              TargetEntryInstr** entry,
                              Definition** last) {
-  intptr_t array_cid = MethodKindToCid(kind);
-  ASSERT(array_cid != kIllegalCid);
+  intptr_t array_cid = MethodRecognizer::MethodKindToReceiverCid(kind);
 
   Definition* array = receiver;
   Definition* index = call->ArgumentAt(1);
@@ -2262,8 +2181,7 @@
                              const ICData& value_check,
                              TargetEntryInstr** entry,
                              Definition** last) {
-  intptr_t array_cid = MethodKindToCid(kind);
-  ASSERT(array_cid != kIllegalCid);
+  intptr_t array_cid = MethodRecognizer::MethodKindToReceiverCid(kind);
 
   Definition* array = receiver;
   Definition* index = call->ArgumentAt(1);
diff --git a/runtime/vm/intrinsifier.cc b/runtime/vm/intrinsifier.cc
index 15a0fa9..93478fc 100644
--- a/runtime/vm/intrinsifier.cc
+++ b/runtime/vm/intrinsifier.cc
@@ -384,8 +384,8 @@
                                Thread::kNoDeoptId));
 }
 
-
-bool Intrinsifier::Build_ObjectArrayGetIndexed(FlowGraph* flow_graph) {
+static bool IntrinsifyArrayGetIndexed(FlowGraph* flow_graph,
+                                      intptr_t array_cid) {
   GraphEntryInstr* graph_entry = flow_graph->graph_entry();
   TargetEntryInstr* normal_entry = graph_entry->normal_entry();
   BlockBuilder builder(flow_graph, normal_entry);
@@ -393,199 +393,70 @@
   Definition* index = builder.AddParameter(1);
   Definition* array = builder.AddParameter(2);
 
-  PrepareIndexedOp(&builder, array, index, Array::length_offset());
-
-  Definition* result = builder.AddDefinition(
-      new LoadIndexedInstr(new Value(array),
-                           new Value(index),
-                           Instance::ElementSizeFor(kArrayCid),  // index scale
-                           kArrayCid,
-                           Thread::kNoDeoptId,
-                           builder.TokenPos()));
-  builder.AddIntrinsicReturn(new Value(result));
-  return true;
-}
-
-
-bool Intrinsifier::Build_ImmutableArrayGetIndexed(FlowGraph* flow_graph) {
-  return Build_ObjectArrayGetIndexed(flow_graph);
-}
-
-
-bool Intrinsifier::Build_Uint8ArrayGetIndexed(FlowGraph* flow_graph) {
-  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
-  TargetEntryInstr* normal_entry = graph_entry->normal_entry();
-  BlockBuilder builder(flow_graph, normal_entry);
-
-  Definition* index = builder.AddParameter(1);
-  Definition* array = builder.AddParameter(2);
-
-  PrepareIndexedOp(&builder, array, index, TypedData::length_offset());
-
-  Definition* result = builder.AddDefinition(
-      new LoadIndexedInstr(new Value(array),
-                           new Value(index),
-                           1,  // index scale
-                           kTypedDataUint8ArrayCid,
-                           Thread::kNoDeoptId,
-                           builder.TokenPos()));
-  builder.AddIntrinsicReturn(new Value(result));
-  return true;
-}
-
-
-bool Intrinsifier::Build_ExternalUint8ArrayGetIndexed(FlowGraph* flow_graph) {
-  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
-  TargetEntryInstr* normal_entry = graph_entry->normal_entry();
-  BlockBuilder builder(flow_graph, normal_entry);
-
-  Definition* index = builder.AddParameter(1);
-  Definition* array = builder.AddParameter(2);
-
-  PrepareIndexedOp(&builder, array, index, ExternalTypedData::length_offset());
-
-  Definition* elements = builder.AddDefinition(
-      new LoadUntaggedInstr(new Value(array),
-                            ExternalTypedData::data_offset()));
-  Definition* result = builder.AddDefinition(
-      new LoadIndexedInstr(new Value(elements),
-                           new Value(index),
-                           1,  // index scale
-                           kExternalTypedDataUint8ArrayCid,
-                           Thread::kNoDeoptId,
-                           builder.TokenPos()));
-  builder.AddIntrinsicReturn(new Value(result));
-  return true;
-}
-
-
-bool Intrinsifier::Build_Uint8ArraySetIndexed(FlowGraph* flow_graph) {
-  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
-  TargetEntryInstr* normal_entry = graph_entry->normal_entry();
-  BlockBuilder builder(flow_graph, normal_entry);
-
-  Definition* value = builder.AddParameter(1);
-  Definition* index = builder.AddParameter(2);
-  Definition* array = builder.AddParameter(3);
-
-  PrepareIndexedOp(&builder, array, index, TypedData::length_offset());
-
-  builder.AddInstruction(
-      new CheckSmiInstr(new Value(value),
-                        Thread::kNoDeoptId,
-                        builder.TokenPos()));
-
-  builder.AddInstruction(
-      new StoreIndexedInstr(new Value(array),
-                            new Value(index),
-                            new Value(value),
-                            kNoStoreBarrier,
-                            1,  // index scale
-                            kTypedDataUint8ArrayCid,
-                            Thread::kNoDeoptId,
-                            builder.TokenPos()));
-  // Return null.
-  Definition* null_def = builder.AddNullDefinition();
-  builder.AddIntrinsicReturn(new Value(null_def));
-  return true;
-}
-
-
-bool Intrinsifier::Build_ExternalUint8ArraySetIndexed(FlowGraph* flow_graph) {
-  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
-  TargetEntryInstr* normal_entry = graph_entry->normal_entry();
-  BlockBuilder builder(flow_graph, normal_entry);
-
-  Definition* value = builder.AddParameter(1);
-  Definition* index = builder.AddParameter(2);
-  Definition* array = builder.AddParameter(3);
-
-  PrepareIndexedOp(&builder, array, index, ExternalTypedData::length_offset());
-
-  builder.AddInstruction(
-      new CheckSmiInstr(new Value(value),
-                        Thread::kNoDeoptId,
-                        builder.TokenPos()));
-  Definition* elements = builder.AddDefinition(
-      new LoadUntaggedInstr(new Value(array),
-                            ExternalTypedData::data_offset()));
-  builder.AddInstruction(
-      new StoreIndexedInstr(new Value(elements),
-                            new Value(index),
-                            new Value(value),
-                            kNoStoreBarrier,
-                            1,  // index scale
-                            kExternalTypedDataUint8ArrayCid,
-                            Thread::kNoDeoptId,
-                            builder.TokenPos()));
-  // Return null.
-  Definition* null_def = builder.AddNullDefinition();
-  builder.AddIntrinsicReturn(new Value(null_def));
-  return true;
-}
-
-
-bool Intrinsifier::Build_Uint32ArraySetIndexed(FlowGraph* flow_graph) {
-  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
-  TargetEntryInstr* normal_entry = graph_entry->normal_entry();
-  BlockBuilder builder(flow_graph, normal_entry);
-
-  Definition* value = builder.AddParameter(1);
-  Definition* index = builder.AddParameter(2);
-  Definition* array = builder.AddParameter(3);
-
-  PrepareIndexedOp(&builder, array, index, TypedData::length_offset());
-
-  Definition* unboxed_value =
-      builder.AddUnboxInstr(kUnboxedUint32,
-                            new Value(value),
-                            /* is_checked = */ true);
-
-  builder.AddInstruction(
-      new StoreIndexedInstr(new Value(array),
-                            new Value(index),
-                            new Value(unboxed_value),
-                            kNoStoreBarrier,
-                            4,  // index scale
-                            kTypedDataUint32ArrayCid,
-                            Thread::kNoDeoptId,
-                            builder.TokenPos()));
-  // Return null.
-  Definition* null_def = builder.AddNullDefinition();
-  builder.AddIntrinsicReturn(new Value(null_def));
-  return true;
-}
-
-
-bool Intrinsifier::Build_Uint32ArrayGetIndexed(FlowGraph* flow_graph) {
-  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
-  TargetEntryInstr* normal_entry = graph_entry->normal_entry();
-  BlockBuilder builder(flow_graph, normal_entry);
-
-  Definition* index = builder.AddParameter(1);
-  Definition* array = builder.AddParameter(2);
-
-  PrepareIndexedOp(&builder, array, index, TypedData::length_offset());
-
-  Definition* unboxed_value = builder.AddDefinition(
-      new LoadIndexedInstr(new Value(array),
-                           new Value(index),
-                           4,  // index scale
-                           kTypedDataUint32ArrayCid,
-                           Thread::kNoDeoptId,
-                           builder.TokenPos()));
-  Definition* result = builder.AddDefinition(
-      BoxInstr::Create(kUnboxedUint32, new Value(unboxed_value)));
-  builder.AddIntrinsicReturn(new Value(result));
-  return true;
-}
-
-
-bool Intrinsifier::Build_Float64ArraySetIndexed(FlowGraph* flow_graph) {
-  if (!FlowGraphCompiler::SupportsUnboxedDoubles()) {
-    return false;
+  intptr_t length_offset = Array::length_offset();
+  if (RawObject::IsTypedDataClassId(array_cid)) {
+    length_offset = TypedData::length_offset();
+  } else if (RawObject::IsExternalTypedDataClassId(array_cid)) {
+    length_offset = ExternalTypedData::length_offset();
   }
 
+  PrepareIndexedOp(&builder, array, index, length_offset);
+
+  if (RawObject::IsExternalTypedDataClassId(array_cid)) {
+    array = builder.AddDefinition(
+      new LoadUntaggedInstr(new Value(array),
+                            ExternalTypedData::data_offset()));
+  }
+
+  Definition* result = builder.AddDefinition(
+      new LoadIndexedInstr(new Value(array),
+                           new Value(index),
+                           Instance::ElementSizeFor(array_cid),  // index scale
+                           array_cid,
+                           Thread::kNoDeoptId,
+                           builder.TokenPos()));
+  // Box and/or convert result if necessary.
+  switch (array_cid) {
+    case kTypedDataInt32ArrayCid:
+    case kExternalTypedDataInt32ArrayCid:
+      result = builder.AddDefinition(
+          BoxInstr::Create(kUnboxedInt32, new Value(result)));
+      break;
+    case kTypedDataUint32ArrayCid:
+    case kExternalTypedDataUint32ArrayCid:
+      result = builder.AddDefinition(
+          BoxInstr::Create(kUnboxedUint32, new Value(result)));
+      break;
+    case kTypedDataFloat32ArrayCid:
+      result = builder.AddDefinition(
+          new FloatToDoubleInstr(new Value(result), Thread::kNoDeoptId));
+      // Fall through.
+    case kTypedDataFloat64ArrayCid:
+      result = builder.AddDefinition(
+          BoxInstr::Create(kUnboxedDouble, new Value(result)));
+      break;
+    case kArrayCid:
+    case kImmutableArrayCid:
+    case kTypedDataInt8ArrayCid:
+    case kTypedDataUint8ArrayCid:
+    case kExternalTypedDataUint8ArrayCid:
+    case kTypedDataUint8ClampedArrayCid:
+    case kExternalTypedDataUint8ClampedArrayCid:
+    case kTypedDataInt16ArrayCid:
+    case kTypedDataUint16ArrayCid:
+      // Nothing to do.
+      break;
+    default:
+      UNREACHABLE();
+      break;
+  }
+  builder.AddIntrinsicReturn(new Value(result));
+  return true;
+}
+
+
+static bool IntrinsifyArraySetIndexed(FlowGraph* flow_graph,
+                                      intptr_t array_cid) {
   GraphEntryInstr* graph_entry = flow_graph->graph_entry();
   TargetEntryInstr* normal_entry = graph_entry->normal_entry();
   BlockBuilder builder(flow_graph, normal_entry);
@@ -594,33 +465,82 @@
   Definition* index = builder.AddParameter(2);
   Definition* array = builder.AddParameter(3);
 
-  PrepareIndexedOp(&builder, array, index, TypedData::length_offset());
+  intptr_t length_offset = Array::length_offset();
+  if (RawObject::IsTypedDataClassId(array_cid)) {
+    length_offset = TypedData::length_offset();
+  } else if (RawObject::IsExternalTypedDataClassId(array_cid)) {
+    length_offset = ExternalTypedData::length_offset();
+  }
 
-  const ICData& value_check = ICData::ZoneHandle(ICData::New(
-      flow_graph->function(),
-      String::Handle(flow_graph->function().name()),
-      Object::empty_array(),  // Dummy args. descr.
-      Thread::kNoDeoptId,
-      1,
-      false));
-  value_check.AddReceiverCheck(kDoubleCid, flow_graph->function());
-  builder.AddInstruction(
-      new CheckClassInstr(new Value(value),
-                          Thread::kNoDeoptId,
-                          value_check,
-                          builder.TokenPos()));
-  Definition* double_value =
-      builder.AddUnboxInstr(kUnboxedDouble,
-                            new Value(value),
-                            /* is_checked = */ true);
+  PrepareIndexedOp(&builder, array, index, length_offset);
 
+  // Value check/conversion.
+  switch (array_cid) {
+    case kTypedDataInt8ArrayCid:
+    case kTypedDataUint8ArrayCid:
+    case kExternalTypedDataUint8ArrayCid:
+    case kTypedDataUint8ClampedArrayCid:
+    case kExternalTypedDataUint8ClampedArrayCid:
+    case kTypedDataInt16ArrayCid:
+    case kTypedDataUint16ArrayCid:
+      builder.AddInstruction(new CheckSmiInstr(new Value(value),
+                                               Thread::kNoDeoptId,
+                                               builder.TokenPos()));
+      break;
+    case kTypedDataInt32ArrayCid:
+    case kExternalTypedDataInt32ArrayCid:
+      // Use same truncating unbox-instruction for int32 and uint32.
+      // Fall-through.
+    case kTypedDataUint32ArrayCid:
+    case kExternalTypedDataUint32ArrayCid:
+      // Supports smi and mint, slow-case for bigints.
+      value = builder.AddUnboxInstr(kUnboxedUint32,
+                                    new Value(value),
+                                    /* is_checked = */ false);
+      break;
+    case kTypedDataFloat32ArrayCid:
+    case kTypedDataFloat64ArrayCid: {
+      const ICData& value_check = ICData::ZoneHandle(ICData::New(
+          flow_graph->function(),
+          Symbols::Empty(),  // Dummy function name.
+          Object::empty_array(),  // Dummy args. descr.
+          Thread::kNoDeoptId,
+          1,
+          false));
+      value_check.AddReceiverCheck(kDoubleCid, flow_graph->function());
+      builder.AddInstruction(
+          new CheckClassInstr(new Value(value),
+                              Thread::kNoDeoptId,
+                              value_check,
+                              builder.TokenPos()));
+      value = builder.AddUnboxInstr(kUnboxedDouble,
+                                    new Value(value),
+                                    /* is_checked = */ true);
+      if (array_cid == kTypedDataFloat32ArrayCid) {
+        value = builder.AddDefinition(
+            new DoubleToFloatInstr(new Value(value), Thread::kNoDeoptId));
+      }
+      break;
+    }
+    default:
+      UNREACHABLE();
+  }
+
+  if (RawObject::IsExternalTypedDataClassId(array_cid)) {
+    array = builder.AddDefinition(
+      new LoadUntaggedInstr(new Value(array),
+                            ExternalTypedData::data_offset()));
+  }
+  // No store barrier.
+  ASSERT(RawObject::IsExternalTypedDataClassId(array_cid) ||
+         RawObject::IsTypedDataClassId(array_cid));
   builder.AddInstruction(
       new StoreIndexedInstr(new Value(array),
                             new Value(index),
-                            new Value(double_value),
+                            new Value(value),
                             kNoStoreBarrier,
-                            8,  // index scale
-                            kTypedDataFloat64ArrayCid,
+                            Instance::ElementSizeFor(array_cid),  // index scale
+                            array_cid,
                             Thread::kNoDeoptId,
                             builder.TokenPos()));
   // Return null.
@@ -630,34 +550,80 @@
 }
 
 
-bool Intrinsifier::Build_Float64ArrayGetIndexed(FlowGraph* flow_graph) {
-  if (!FlowGraphCompiler::SupportsUnboxedDoubles()) {
-    return false;
-  }
-
-  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
-  TargetEntryInstr* normal_entry = graph_entry->normal_entry();
-  BlockBuilder builder(flow_graph, normal_entry);
-
-  Definition* index = builder.AddParameter(1);
-  Definition* array = builder.AddParameter(2);
-
-  PrepareIndexedOp(&builder, array, index, TypedData::length_offset());
-
-  Definition* unboxed_value = builder.AddDefinition(
-      new LoadIndexedInstr(new Value(array),
-                           new Value(index),
-                           8,  // index scale
-                           kTypedDataFloat64ArrayCid,
-                           Thread::kNoDeoptId,
-                           builder.TokenPos()));
-  Definition* result = builder.AddDefinition(
-      BoxInstr::Create(kUnboxedDouble, new Value(unboxed_value)));
-  builder.AddIntrinsicReturn(new Value(result));
-  return true;
+#define DEFINE_ARRAY_GETTER_INTRINSIC(enum_name)                               \
+bool Intrinsifier::Build_##enum_name##GetIndexed(FlowGraph* flow_graph) {      \
+  return IntrinsifyArrayGetIndexed(                                            \
+      flow_graph,                                                              \
+      MethodRecognizer::MethodKindToReceiverCid(                               \
+          MethodRecognizer::k##enum_name##GetIndexed));                        \
 }
 
 
+#define DEFINE_ARRAY_SETTER_INTRINSIC(enum_name)                               \
+bool Intrinsifier::Build_##enum_name##SetIndexed(FlowGraph* flow_graph) {      \
+  return IntrinsifyArraySetIndexed(                                            \
+      flow_graph,                                                              \
+      MethodRecognizer::MethodKindToReceiverCid(                               \
+          MethodRecognizer::k##enum_name##SetIndexed));                        \
+}
+
+DEFINE_ARRAY_GETTER_INTRINSIC(ObjectArray)  // Setter in intrinsifier_<arch>.cc.
+DEFINE_ARRAY_GETTER_INTRINSIC(ImmutableArray)
+
+#define DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(enum_name)                       \
+DEFINE_ARRAY_GETTER_INTRINSIC(enum_name)                                       \
+DEFINE_ARRAY_SETTER_INTRINSIC(enum_name)
+
+DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Int8Array)
+DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint8Array)
+DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(ExternalUint8Array)
+DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint8ClampedArray)
+DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(ExternalUint8ClampedArray)
+DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Int16Array)
+DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint16Array)
+DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Int32Array)
+DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint32Array)
+
+#undef DEFINE_ARRAY_GETTER_SETTER_INTRINSICS
+#undef DEFINE_ARRAY_GETTER_INTRINSIC
+#undef DEFINE_ARRAY_SETTER_INTRINSIC
+
+
+#define DEFINE_FLOAT_ARRAY_GETTER_INTRINSIC(enum_name)                         \
+bool Intrinsifier::Build_##enum_name##GetIndexed(FlowGraph* flow_graph) {      \
+  if (!FlowGraphCompiler::SupportsUnboxedDoubles()) {                          \
+    return false;                                                              \
+  }                                                                            \
+  return IntrinsifyArrayGetIndexed(                                            \
+      flow_graph,                                                              \
+      MethodRecognizer::MethodKindToReceiverCid(                               \
+          MethodRecognizer::k##enum_name##GetIndexed));                        \
+}
+
+
+#define DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC(enum_name)                         \
+bool Intrinsifier::Build_##enum_name##SetIndexed(FlowGraph* flow_graph) {      \
+  if (!FlowGraphCompiler::SupportsUnboxedDoubles()) {                          \
+    return false;                                                              \
+  }                                                                            \
+  return IntrinsifyArraySetIndexed(                                            \
+      flow_graph,                                                              \
+      MethodRecognizer::MethodKindToReceiverCid(                               \
+          MethodRecognizer::k##enum_name##SetIndexed));                        \
+}
+
+#define DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS(enum_name)                 \
+DEFINE_FLOAT_ARRAY_GETTER_INTRINSIC(enum_name)                                 \
+DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC(enum_name)
+
+DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS(Float64Array)
+DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS(Float32Array)
+
+#undef DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS
+#undef DEFINE_FLOAT_ARRAY_GETTER_INTRINSIC
+#undef DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC
+
+
 static bool BuildCodeUnitAt(FlowGraph* flow_graph, intptr_t cid) {
   GraphEntryInstr* graph_entry = flow_graph->graph_entry();
   TargetEntryInstr* normal_entry = graph_entry->normal_entry();
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 52aaa44..028a130 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -1513,6 +1513,13 @@
 }
 
 
+void Isolate::SetStickyError(RawError* sticky_error) {
+  ASSERT(sticky_error_ == Error::null());
+  sticky_error_ = sticky_error;
+  message_handler()->PausedOnExit(true);
+}
+
+
 void Isolate::Run() {
   message_handler()->Run(Dart::thread_pool(),
                          RunIsolate,
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 2e603f1..9401e85 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -535,6 +535,9 @@
   void set_deoptimized_code_array(const GrowableObjectArray& value);
   void TrackDeoptimizedCode(const Code& code);
 
+  // Also sends a paused at exit event over the service protocol.
+  void SetStickyError(RawError* sticky_error);
+
   RawError* sticky_error() const { return sticky_error_; }
   void clear_sticky_error();
 
diff --git a/runtime/vm/method_recognizer.cc b/runtime/vm/method_recognizer.cc
index 03014ac..649a1fe 100644
--- a/runtime/vm/method_recognizer.cc
+++ b/runtime/vm/method_recognizer.cc
@@ -37,6 +37,87 @@
 }
 
 
+intptr_t MethodRecognizer::MethodKindToReceiverCid(Kind kind) {
+  switch (kind) {
+    case kImmutableArrayGetIndexed:
+      return kImmutableArrayCid;
+
+    case kObjectArrayGetIndexed:
+    case kObjectArraySetIndexed:
+      return kArrayCid;
+
+    case kGrowableArrayGetIndexed:
+    case kGrowableArraySetIndexed:
+      return kGrowableObjectArrayCid;
+
+    case kFloat32ArrayGetIndexed:
+    case kFloat32ArraySetIndexed:
+      return kTypedDataFloat32ArrayCid;
+
+    case kFloat64ArrayGetIndexed:
+    case kFloat64ArraySetIndexed:
+      return kTypedDataFloat64ArrayCid;
+
+    case kInt8ArrayGetIndexed:
+    case kInt8ArraySetIndexed:
+      return kTypedDataInt8ArrayCid;
+
+    case kUint8ArrayGetIndexed:
+    case kUint8ArraySetIndexed:
+      return kTypedDataUint8ArrayCid;
+
+    case kUint8ClampedArrayGetIndexed:
+    case kUint8ClampedArraySetIndexed:
+      return kTypedDataUint8ClampedArrayCid;
+
+    case kExternalUint8ArrayGetIndexed:
+    case kExternalUint8ArraySetIndexed:
+      return kExternalTypedDataUint8ArrayCid;
+
+    case kExternalUint8ClampedArrayGetIndexed:
+    case kExternalUint8ClampedArraySetIndexed:
+      return kExternalTypedDataUint8ClampedArrayCid;
+
+    case kInt16ArrayGetIndexed:
+    case kInt16ArraySetIndexed:
+      return kTypedDataInt16ArrayCid;
+
+    case kUint16ArrayGetIndexed:
+    case kUint16ArraySetIndexed:
+      return kTypedDataUint16ArrayCid;
+
+    case kInt32ArrayGetIndexed:
+    case kInt32ArraySetIndexed:
+      return kTypedDataInt32ArrayCid;
+
+    case kUint32ArrayGetIndexed:
+    case kUint32ArraySetIndexed:
+      return kTypedDataUint32ArrayCid;
+
+    case kInt64ArrayGetIndexed:
+    case kInt64ArraySetIndexed:
+      return kTypedDataInt64ArrayCid;
+
+    case kFloat32x4ArrayGetIndexed:
+    case kFloat32x4ArraySetIndexed:
+      return kTypedDataFloat32x4ArrayCid;
+
+    case kInt32x4ArrayGetIndexed:
+    case kInt32x4ArraySetIndexed:
+      return kTypedDataInt32x4ArrayCid;
+
+    case kFloat64x2ArrayGetIndexed:
+    case kFloat64x2ArraySetIndexed:
+      return kTypedDataFloat64x2ArrayCid;
+
+    default:
+      break;
+  }
+  UNREACHABLE();
+  return kIllegalCid;
+}
+
+
 #define KIND_TO_STRING(class_name, function_name, enum_name, type, fp) \
   #enum_name,
 static const char* recognized_list_method_name[] = {
diff --git a/runtime/vm/method_recognizer.h b/runtime/vm/method_recognizer.h
index 08226f8..cf185cf 100644
--- a/runtime/vm/method_recognizer.h
+++ b/runtime/vm/method_recognizer.h
@@ -13,7 +13,7 @@
 // When adding a new function add a 0 as fingerprint, build and run to get the
 // correct fingerprint from the mismatch error.
 #define OTHER_RECOGNIZED_LIST(V)                                               \
-  V(::, identical, ObjectIdentical, Bool, 0x12e69c8c)                          \
+  V(::, identical, ObjectIdentical, Bool, 0x49c6e96a)                          \
   V(ClassID, getID, ClassIDgetID, Smi, 0x528fd455)                             \
   V(Object, Object., ObjectConstructor, Dynamic, 0x681617fe)                   \
   V(_List, ., ObjectArrayAllocate, Array, 0x63078b15)                          \
@@ -111,22 +111,6 @@
   V(Int32x4, withFlagY, Int32x4WithFlagY, Int32x4, 0x6485a9c4)                 \
   V(Int32x4, withFlagZ, Int32x4WithFlagZ, Int32x4, 0x267acdfa)                 \
   V(Int32x4, withFlagW, Int32x4WithFlagW, Int32x4, 0x345ac675)                 \
-  V(Float32List, [], Float32ArrayGetIndexed, Double, 0x5686528f)               \
-  V(Float32List, []=, Float32ArraySetIndexed, Dynamic, 0x1b0d90df)             \
-  V(Int8List, [], Int8ArrayGetIndexed, Smi, 0x069af8b3)                        \
-  V(Int8List, []=, Int8ArraySetIndexed, Dynamic, 0x33994cd7)                   \
-  V(Uint8ClampedList, [], Uint8ClampedArrayGetIndexed, Smi, 0x027603ed)        \
-  V(Uint8ClampedList, []=, Uint8ClampedArraySetIndexed, Dynamic, 0x28f5f058)   \
-  V(_ExternalUint8ClampedArray, [], ExternalUint8ClampedArrayGetIndexed,       \
-    Smi, 0x027603ed)                                                           \
-  V(_ExternalUint8ClampedArray, []=, ExternalUint8ClampedArraySetIndexed,      \
-    Dynamic, 0x28f5f058)                                                       \
-  V(Int16List, [], Int16ArrayGetIndexed, Smi, 0x173cd6a1)                      \
-  V(Int16List, []=, Int16ArraySetIndexed, Dynamic, 0x32f84e3c)                 \
-  V(Uint16List, [], Uint16ArrayGetIndexed, Smi, 0x3ececa2f)                    \
-  V(Uint16List, []=, Uint16ArraySetIndexed, Dynamic, 0x5c3a0bb9)               \
-  V(Int32List, [], Int32ArrayGetIndexed, Dynamic, 0x262eef09)                  \
-  V(Int32List, []=, Int32ArraySetIndexed, Dynamic, 0x1b05b471)                 \
   V(Int64List, [], Int64ArrayGetIndexed, Dynamic, 0x0c0c939a)                  \
   V(Int64List, []=, Int64ArraySetIndexed, Dynamic, 0x3714d004)                 \
   V(Float32x4List, [], Float32x4ArrayGetIndexed, Float32x4, 0x01c7017b)        \
@@ -239,17 +223,17 @@
 
 
 #define MATH_LIB_INTRINSIC_LIST(V)                                             \
-  V(::, sqrt, MathSqrt, Double, 0x18e8d5f6)                                    \
+  V(::, sqrt, MathSqrt, Double, 0x1afb83d4)                                    \
   V(_Random, _nextState, Random_nextState, Dynamic, 0x1e4b0103)                \
 
 #define GRAPH_MATH_LIB_INTRINSIC_LIST(V)                                       \
-  V(::, sin, MathSin, Double, 0x0000fe08)                                      \
-  V(::, cos, MathCos, Double, 0x7794b33e)                                      \
-  V(::, tan, MathTan, Double, 0x4c1b72fd)                                      \
-  V(::, asin, MathAsin, Double, 0x640d48ad)                                    \
-  V(::, acos, MathAcos, Double, 0x42d46f81)                                    \
-  V(::, atan, MathAtan, Double, 0x4223f879)                                    \
-  V(::, atan2, MathAtan2, Double, 0x3553fb61)                                  \
+  V(::, sin, MathSin, Double, 0x0213abe6)                                      \
+  V(::, cos, MathCos, Double, 0x79a7611c)                                      \
+  V(::, tan, MathTan, Double, 0x4e2e20db)                                      \
+  V(::, asin, MathAsin, Double, 0x661ff68b)                                    \
+  V(::, acos, MathAcos, Double, 0x44e71d5f)                                    \
+  V(::, atan, MathAtan, Double, 0x4436a657)                                    \
+  V(::, atan2, MathAtan2, Double, 0x60a40743)                                  \
 
 #define TYPED_DATA_LIB_INTRINSIC_LIST(V)                                       \
   V(Int8List, ., TypedData_Int8Array_factory, TypedDataInt8Array, 0x2e7749e3)  \
@@ -281,15 +265,31 @@
     TypedDataFloat64x2Array, 0x18cbf4d9)                                       \
 
 #define GRAPH_TYPED_DATA_INTRINSICS_LIST(V)                                    \
+  V(Int8List, [], Int8ArrayGetIndexed, Smi, 0x069af8b3)                        \
+  V(Int8List, []=, Int8ArraySetIndexed, Dynamic, 0x33994cd7)                   \
   V(Uint8List, [], Uint8ArrayGetIndexed, Smi, 0x027603ed)                      \
   V(Uint8List, []=, Uint8ArraySetIndexed, Dynamic, 0x060d5256)                 \
   V(_ExternalUint8Array, [], ExternalUint8ArrayGetIndexed, Smi, 0x027603ed)    \
   V(_ExternalUint8Array, []=, ExternalUint8ArraySetIndexed, Dynamic,           \
     0x060d5256)                                                                \
+  V(Uint8ClampedList, [], Uint8ClampedArrayGetIndexed, Smi, 0x027603ed)        \
+  V(Uint8ClampedList, []=, Uint8ClampedArraySetIndexed, Dynamic, 0x28f5f058)   \
+  V(_ExternalUint8ClampedArray, [], ExternalUint8ClampedArrayGetIndexed,       \
+    Smi, 0x027603ed)                                                           \
+  V(_ExternalUint8ClampedArray, []=, ExternalUint8ClampedArraySetIndexed,      \
+    Dynamic, 0x28f5f058)                                                       \
+  V(Int16List, [], Int16ArrayGetIndexed, Smi, 0x173cd6a1)                      \
+  V(Int16List, []=, Int16ArraySetIndexed, Dynamic, 0x32f84e3c)                 \
+  V(Uint16List, [], Uint16ArrayGetIndexed, Smi, 0x3ececa2f)                    \
+  V(Uint16List, []=, Uint16ArraySetIndexed, Dynamic, 0x5c3a0bb9)               \
+  V(Int32List, [], Int32ArrayGetIndexed, Dynamic, 0x262eef09)                  \
+  V(Int32List, []=, Int32ArraySetIndexed, Dynamic, 0x1b05b471)                 \
   V(Uint32List, [], Uint32ArrayGetIndexed, Dynamic, 0x6040f7fb)                \
   V(Uint32List, []=, Uint32ArraySetIndexed, Dynamic, 0x3a4e1119)               \
   V(Float64List, [], Float64ArrayGetIndexed, Double, 0x7a27098d)               \
   V(Float64List, []=, Float64ArraySetIndexed, Dynamic, 0x139b2465)             \
+  V(Float32List, [], Float32ArrayGetIndexed, Double, 0x5686528f)               \
+  V(Float32List, []=, Float32ArraySetIndexed, Dynamic, 0x1b0d90df)             \
   V(_TypedList, get:length, TypedDataLength, Smi, 0x2090dc1a)                  \
   V(Float32x4, get:x, Float32x4ShuffleX, Double, 0x63d0c13f)                   \
   V(Float32x4, get:y, Float32x4ShuffleY, Double, 0x20343b1b)                   \
@@ -335,7 +335,7 @@
   V(::, _getDefaultTag, UserTag_defaultTag, Dynamic, 0x14ddc3b7)               \
   V(::, _getCurrentTag, Profiler_getCurrentTag, Dynamic, 0x486ee02d)           \
   V(::, _isDartStreamEnabled, Timeline_isDartStreamEnabled, Dynamic,           \
-    0x3fe92e14)                                                                \
+    0x1667ce76)                                                                \
 
 #define ALL_INTRINSICS_NO_INTEGER_LIB_LIST(V)                                  \
   CORE_LIB_INTRINSIC_LIST(V)                                                   \
@@ -421,19 +421,19 @@
   V(_ByteDataView, getUint64, ByteDataViewGetUint64, 0x2fab992e)               \
   V(_ByteDataView, getFloat32, ByteDataViewGetFloat32, 0x387e9fc6)             \
   V(_ByteDataView, getFloat64, ByteDataViewGetFloat64, 0x5396432d)             \
-  V(::, asin, MathAsin, 0x640d48ad)                                            \
-  V(::, acos, MathAcos, 0x42d46f81)                                            \
-  V(::, atan, MathAtan, 0x4223f879)                                            \
-  V(::, atan2, MathAtan2, 0x3553fb61)                                          \
-  V(::, cos, MathCos, 0x7794b33e)                                              \
-  V(::, exp, MathExp, 0x59769f9d)                                              \
-  V(::, log, MathLog, 0x2c12654e)                                              \
+  V(::, asin, MathAsin, 0x661ff68b)                                            \
+  V(::, acos, MathAcos, 0x44e71d5f)                                            \
+  V(::, atan, MathAtan, 0x4436a657)                                            \
+  V(::, atan2, MathAtan2, 0x60a40743)                                          \
+  V(::, cos, MathCos, 0x79a7611c)                                              \
+  V(::, exp, MathExp, 0x5b894d7b)                                              \
+  V(::, log, MathLog, 0x2e25132c)                                              \
   V(::, max, MathMax, 0x54121d6a)                                              \
   V(::, min, MathMin, 0x4276561c)                                              \
-  V(::, pow, MathPow, 0x7ab62ca7)                                              \
-  V(::, sin, MathSin, 0x0000fe08)                                              \
-  V(::, sqrt, MathSqrt, 0x18e8d5f6)                                            \
-  V(::, tan, MathTan, 0x4c1b72fd)                                              \
+  V(::, pow, MathPow, 0x438e3089)                                              \
+  V(::, sin, MathSin, 0x0213abe6)                                              \
+  V(::, sqrt, MathSqrt, 0x1afb83d4)                                            \
+  V(::, tan, MathTan, 0x4e2e20db)                                              \
   V(Lists, copy, ListsCopy, 0x21a194fa)                                        \
   V(_Bigint, get:_neg, Bigint_getNeg, 0x7bf17a57)                              \
   V(_Bigint, get:_used, Bigint_getUsed, 0x55041013)                            \
@@ -529,6 +529,7 @@
   static bool AlwaysInline(const Function& function);
   static bool PolymorphicTarget(const Function& function);
   static intptr_t ResultCid(const Function& function);
+  static intptr_t MethodKindToReceiverCid(Kind kind);
   static const char* KindToCString(Kind kind);
 #if defined(DART_NO_SNAPSHOT)
   static void InitializeState();
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 8626a5f..0543a07 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -52,6 +52,7 @@
     "Make initializing formal parameters visible in initializer list.");
 DEFINE_FLAG(bool, warn_super, false,
     "Warning if super initializer not last in initializer list.");
+DEFINE_FLAG(bool, warn_patch, false, "Warn on old-style patch syntax.");
 DEFINE_FLAG(bool, await_is_keyword, false,
     "await and yield are treated as proper keywords in synchronous code.");
 
@@ -4545,10 +4546,17 @@
   bool is_patch = false;
   bool is_abstract = false;
   TokenPosition declaration_pos =
-      metadata_pos.IsReal() ? metadata_pos : TokenPos();
-  if (is_patch_source() &&
+    metadata_pos.IsReal() ? metadata_pos : TokenPos();
+  if (is_patch_source() && IsPatchAnnotation(metadata_pos)) {
+    is_patch = true;
+    metadata_pos = TokenPosition::kNoSource;
+    declaration_pos = TokenPos();
+  } else if (is_patch_source() &&
       (CurrentToken() == Token::kIDENT) &&
       CurrentLiteral()->Equals("patch")) {
+    if (FLAG_warn_patch) {
+      ReportWarning("deprecated use of patch 'keyword'");
+    }
     ConsumeToken();
     is_patch = true;
   } else if (CurrentToken() == Token::kABSTRACT) {
@@ -5264,6 +5272,19 @@
 }
 
 
+bool Parser::IsPatchAnnotation(TokenPosition pos) {
+  if (pos == TokenPosition::kNoSource) {
+    return false;
+  }
+  TokenPosition saved_pos = TokenPos();
+  SetPosition(pos);
+  ExpectToken(Token::kAT);
+  bool is_patch = IsSymbol(Symbols::Patch());
+  SetPosition(saved_pos);
+  return is_patch;
+}
+
+
 TokenPosition Parser::SkipMetadata() {
   if (CurrentToken() != Token::kAT) {
     return TokenPosition::kNoSource;
@@ -5606,10 +5627,16 @@
   const bool is_static = true;
   bool is_external = false;
   bool is_patch = false;
-  if (is_patch_source() &&
+  if (is_patch_source() && IsPatchAnnotation(metadata_pos)) {
+    is_patch = true;
+    metadata_pos = TokenPosition::kNoSource;
+  } else if (is_patch_source() &&
       (CurrentToken() == Token::kIDENT) &&
       CurrentLiteral()->Equals("patch") &&
       (LookaheadToken(1) != Token::kLPAREN)) {
+    if (FLAG_warn_patch) {
+      ReportWarning("deprecated use of patch 'keyword'");
+    }
     ConsumeToken();
     is_patch = true;
   } else if (CurrentToken() == Token::kEXTERNAL) {
@@ -5729,9 +5756,15 @@
   bool is_external = false;
   bool is_patch = false;
   AbstractType& result_type = AbstractType::Handle(Z);
-  if (is_patch_source() &&
+  if (is_patch_source() && IsPatchAnnotation(metadata_pos)) {
+    is_patch = true;
+    metadata_pos = TokenPosition::kNoSource;
+  } else if (is_patch_source() &&
       (CurrentToken() == Token::kIDENT) &&
       CurrentLiteral()->Equals("patch")) {
+    if (FLAG_warn_patch) {
+      ReportWarning("deprecated use of patch 'keyword'");
+    }
     ConsumeToken();
     is_patch = true;
   } else if (CurrentToken() == Token::kEXTERNAL) {
diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h
index e29f86e..d2644b7 100644
--- a/runtime/vm/parser.h
+++ b/runtime/vm/parser.h
@@ -401,6 +401,7 @@
   void SkipToMatchingParenthesis();
   void SkipBlock();
   TokenPosition SkipMetadata();
+  bool IsPatchAnnotation(TokenPosition pos);
   void SkipTypeArguments();
   void SkipType(bool allow_void);
   void SkipInitializers();
diff --git a/runtime/vm/service_test.cc b/runtime/vm/service_test.cc
index c272b4c..4ec886d 100644
--- a/runtime/vm/service_test.cc
+++ b/runtime/vm/service_test.cc
@@ -115,6 +115,50 @@
 }
 
 
+TEST_CASE(Service_IsolateStickyError) {
+  const char* kScript =
+      "main() => throw 'HI THERE STICKY';\n";
+
+  Isolate* isolate = thread->isolate();
+  isolate->set_is_runnable(true);
+  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+  EXPECT_VALID(lib);
+  Library& vmlib = Library::Handle();
+  vmlib ^= Api::UnwrapHandle(lib);
+  EXPECT(!vmlib.IsNull());
+  Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
+  EXPECT(Dart_IsUnhandledExceptionError(result));
+  EXPECT(!Dart_HasStickyError());
+  EXPECT(Thread::Current()->sticky_error() == Error::null());
+
+  {
+    TransitionNativeToVM transition(thread);
+
+    JSONStream js;
+    isolate->PrintJSON(&js, false);
+    // No error property and no PauseExit state.
+    EXPECT_NOTSUBSTRING("\"error\":", js.ToCString());
+    EXPECT_NOTSUBSTRING("HI THERE STICKY", js.ToCString());
+    EXPECT_NOTSUBSTRING("PauseExit", js.ToCString());
+  }
+
+  // Set the sticky error.
+  Dart_SetStickyError(result);
+  EXPECT(Dart_HasStickyError());
+
+  {
+    TransitionNativeToVM transition(thread);
+
+    JSONStream js;
+    isolate->PrintJSON(&js, false);
+    // Error and PauseExit set.
+    EXPECT_SUBSTRING("\"error\":", js.ToCString());
+    EXPECT_SUBSTRING("HI THERE STICKY", js.ToCString());
+    EXPECT_SUBSTRING("PauseExit", js.ToCString());
+  }
+}
+
+
 TEST_CASE(Service_IdZones) {
   Zone* zone = thread->zone();
   Isolate* isolate = thread->isolate();
diff --git a/runtime/vm/simulator_arm.cc b/runtime/vm/simulator_arm.cc
index 24c934b..0ef9308 100644
--- a/runtime/vm/simulator_arm.cc
+++ b/runtime/vm/simulator_arm.cc
@@ -1531,7 +1531,7 @@
         Redirection* redirection = Redirection::FromSvcInstruction(instr);
         uword external = redirection->external_function();
         if (IsTracingExecution()) {
-          OS::Print("Call to host function at 0x%" Pd "\n", external);
+          THR_Print("Call to host function at 0x%" Pd "\n", external);
         }
 
         if ((redirection->call_kind() == kRuntimeCall) ||
@@ -3607,13 +3607,13 @@
 void Simulator::InstructionDecode(Instr* instr) {
   pc_modified_ = false;
   if (IsTracingExecution()) {
-    OS::Print("%" Pu64 " ", icount_);
+    THR_Print("%" Pu64 " ", icount_);
     const uword start = reinterpret_cast<uword>(instr);
     const uword end = start + Instr::kInstrSize;
     if (FLAG_support_disassembler) {
       Disassembler::Disassemble(start, end);
     } else {
-      OS::Print("Disassembler not supported in this mode.\n");
+      THR_Print("Disassembler not supported in this mode.\n");
     }
   }
   if (instr->ConditionField() == kSpecialCondition) {
diff --git a/runtime/vm/simulator_arm64.cc b/runtime/vm/simulator_arm64.cc
index b3cac8b..e517fa4 100644
--- a/runtime/vm/simulator_arm64.cc
+++ b/runtime/vm/simulator_arm64.cc
@@ -1603,7 +1603,7 @@
     Redirection* redirection = Redirection::FromHltInstruction(instr);
     uword external = redirection->external_function();
     if (IsTracingExecution()) {
-      OS::Print("Call to host function at 0x%" Pd "\n", external);
+      THR_Print("Call to host function at 0x%" Pd "\n", external);
     }
 
     if ((redirection->call_kind() == kRuntimeCall) ||
@@ -3406,13 +3406,13 @@
 void Simulator::InstructionDecode(Instr* instr) {
   pc_modified_ = false;
   if (IsTracingExecution()) {
-    OS::Print("%" Pu64 " ", icount_);
+    THR_Print("%" Pu64 " ", icount_);
     const uword start = reinterpret_cast<uword>(instr);
     const uword end = start + Instr::kInstrSize;
     if (FLAG_support_disassembler) {
       Disassembler::Disassemble(start, end);
     } else {
-      OS::Print("Disassembler not supported in this mode.\n");
+      THR_Print("Disassembler not supported in this mode.\n");
     }
   }
 
diff --git a/runtime/vm/simulator_mips.cc b/runtime/vm/simulator_mips.cc
index d980ca1..8eff9ed 100644
--- a/runtime/vm/simulator_mips.cc
+++ b/runtime/vm/simulator_mips.cc
@@ -1242,7 +1242,7 @@
       Redirection* redirection = Redirection::FromBreakInstruction(instr);
       uword external = redirection->external_function();
       if (IsTracingExecution()) {
-        OS::Print("Call to host function at 0x%" Pd "\n", external);
+        THR_Print("Call to host function at 0x%" Pd "\n", external);
       }
 
       if ((redirection->call_kind() == kRuntimeCall) ||
@@ -1994,13 +1994,13 @@
 
 void Simulator::InstructionDecode(Instr* instr) {
   if (IsTracingExecution()) {
-    OS::Print("%" Pu64 " ", icount_);
+    THR_Print("%" Pu64 " ", icount_);
     const uword start = reinterpret_cast<uword>(instr);
     const uword end = start + Instr::kInstrSize;
     if (FLAG_support_disassembler) {
       Disassembler::Disassemble(start, end);
     } else {
-      OS::Print("Disassembler not supported in this mode.\n");
+      THR_Print("Disassembler not supported in this mode.\n");
     }
   }
 
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc
index 406f0bc..5115963 100644
--- a/runtime/vm/thread.cc
+++ b/runtime/vm/thread.cc
@@ -642,6 +642,12 @@
 
 
 bool Thread::ObjectAtOffset(intptr_t offset, Object* object) {
+  if (Isolate::Current() == Dart::vm_isolate()) {
+    // --disassemble-stubs runs before all the references through
+    // thread have targets
+    return false;
+  }
+
 #define COMPUTE_OFFSET(type_name, member_name, expr, default_init_value)       \
   if (Thread::member_name##offset() == offset) {                               \
     *object = expr;                                                            \
diff --git a/sdk/lib/async/future.dart b/sdk/lib/async/future.dart
index e0e0617..b4d9c24 100644
--- a/sdk/lib/async/future.dart
+++ b/sdk/lib/async/future.dart
@@ -433,7 +433,7 @@
    * with a `test` parameter, instead of handling both value and error in a
    * single [then] call.
    */
-  Future/*<S>*/ then/*<S>*/(/*=S*/ onValue(T value), { Function onError });
+  Future/*<S>*/ then/*<S>*/(onValue(T value), { Function onError });
 
   /**
    * Handles errors emitted by this [Future].
diff --git a/sdk/lib/io/http_headers.dart b/sdk/lib/io/http_headers.dart
index 6b14ae2..3769b3f 100644
--- a/sdk/lib/io/http_headers.dart
+++ b/sdk/lib/io/http_headers.dart
@@ -760,12 +760,12 @@
         }
         maybeExpect("=");
         skipWS();
-        if(done()) {
+        if (done()) {
           parameters[name] = null;
           return;
         }
         String value = parseParameterValue();
-        if (name == 'charset' && this is _ContentType) {
+        if (name == 'charset' && this is _ContentType && value != null) {
           // Charset parameter of ContentTypes are always lower-case.
           value = value.toLowerCase();
         }
diff --git a/sdk/lib/vmservice/devfs.dart b/sdk/lib/vmservice/devfs.dart
index 4735512..7f940b9 100644
--- a/sdk/lib/vmservice/devfs.dart
+++ b/sdk/lib/vmservice/devfs.dart
@@ -121,6 +121,39 @@
     }
   }
 
+  Future<String> handlePutStream(Object fsName,
+                                 Object path,
+                                 Stream<List<int>> bytes) async {
+    // A dummy Message for error message construction.
+    Message message = new Message.forMethod('_writeDevFSFile');
+    var writeStreamFile = VMServiceEmbedderHooks.writeStreamFile;
+    if (writeStreamFile == null) {
+      return _encodeDevFSDisabledError(message);
+    }
+    if (fsName == null) {
+      return encodeMissingParamError(message, 'fsName');
+    }
+    if (fsName is! String) {
+      return encodeInvalidParamError(message, 'fsName');
+    }
+    var fs = _fsMap[fsName];
+    if (fs == null) {
+      return _encodeFileSystemDoesNotExistError(message, fsName);
+    }
+    if (path == null) {
+      return encodeMissingParamError(message, 'path');
+    }
+    if (path is! String) {
+      return encodeInvalidParamError(message, 'path');
+    }
+    Uri uri = fs.resolvePath(path);
+    if (uri == null) {
+      return encodeInvalidParamError(message, 'path');
+    }
+    await writeStreamFile(uri, bytes);
+    return encodeSuccess(message);
+  }
+
   Future<String> _listDevFS(Message message) async {
     var result = {};
     result['type'] = 'FileSystemList';
diff --git a/sdk/lib/vmservice/message.dart b/sdk/lib/vmservice/message.dart
index 295214c..0c02171 100644
--- a/sdk/lib/vmservice/message.dart
+++ b/sdk/lib/vmservice/message.dart
@@ -51,6 +51,9 @@
     return uri.pathSegments[0];
   }
 
+  Message.forMethod(String method)
+      : client = null, method = method, serial = '';
+
   Message.fromUri(this.client, Uri uri)
       : serial = '', method = _methodNameFromUri(uri) {
     params.addAll(uri.queryParameters);
diff --git a/sdk/lib/vmservice/vmservice.dart b/sdk/lib/vmservice/vmservice.dart
index df5642b..25ceb6a 100644
--- a/sdk/lib/vmservice/vmservice.dart
+++ b/sdk/lib/vmservice/vmservice.dart
@@ -116,6 +116,9 @@
 /// Called to write a file.
 typedef Future WriteFileCallback(Uri path, List<int> bytes);
 
+/// Called to write a stream into a file.
+typedef Future WriteStreamFileCallback(Uri path, Stream<List<int>> bytes);
+
 /// Called to read a file.
 typedef Future<List<int>> ReadFileCallback(Uri path);
 
@@ -130,6 +133,7 @@
   static CreateTempDirCallback createTempDir;
   static DeleteDirCallback deleteDir;
   static WriteFileCallback writeFile;
+  static WriteStreamFileCallback writeStreamFile;
   static ReadFileCallback readFile;
   static ListFilesCallback listFiles;
 }
@@ -146,7 +150,7 @@
   /// A port used to receive events from the VM.
   final RawReceivePort eventPort;
 
-  final _devfs = new DevFS();
+  final devfs = new DevFS();
 
   void _addClient(Client client) {
     assert(client.streams.isEmpty);
@@ -206,7 +210,7 @@
     for (var client in clientsList) {
       client.disconnect();
     }
-    _devfs.cleanup();
+    devfs.cleanup();
     if (VMServiceEmbedderHooks.cleanup != null) {
       await VMServiceEmbedderHooks.cleanup();
     }
@@ -401,8 +405,8 @@
     if (message.method == '_spawnUri') {
       return _spawnUri(message);
     }
-    if (_devfs.shouldHandleMessage(message)) {
-      return _devfs.handleMessage(message);
+    if (devfs.shouldHandleMessage(message)) {
+      return devfs.handleMessage(message);
     }
     if (message.params['isolateId'] != null) {
       return runningIsolates.route(message);
diff --git a/tests/compiler/dart2js/dart2js.status b/tests/compiler/dart2js/dart2js.status
index 7b4c8f9..0bb4d7d 100644
--- a/tests/compiler/dart2js/dart2js.status
+++ b/tests/compiler/dart2js/dart2js.status
@@ -37,7 +37,6 @@
 patch_test/bug: RuntimeError # Issue 21132
 
 quarantined/http_test: Pass, Slow
-inference_stats_test: Pass, Slow
 
 # These tests are for the now-deleted dart2dart variant of the CPS IR.
 # We want to adapt them to test the JS variant of the CPS IR instead,
diff --git a/tests/compiler/dart2js/inference_stats_test.dart b/tests/compiler/dart2js/inference_stats_test.dart
deleted file mode 100644
index a85ca39..0000000
--- a/tests/compiler/dart2js/inference_stats_test.dart
+++ /dev/null
@@ -1,340 +0,0 @@
-// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-// SharedOptions=-Dsend_stats=true
-
-/// Tests that we compute send metrics correctly in many simple scenarios.
-library dart2js.test.send_measurements_test;
-
-import 'dart:async';
-import 'package:test/test.dart';
-import 'package:dart2js_info/info.dart';
-import 'package:dart2js_info/src/util.dart' show
-    recursiveDiagnosticString;
-import 'memory_compiler.dart';
-
-main() {
-  test('nothing is reachable, nothing to count', () {
-    return _check('''
-      main() {}
-      test() { int x = 3; }
-      ''');
-  });
-
-  test('local variable read', () {
-    return _check('''
-      main() => test();
-      test() { int x = 3; int y = x; }
-      ''',
-      localSend: 1); // from `int y = x`;
-  });
-
-  test('generative constructor call', () {
-    return _check('''
-      class A {
-        get f => 1;
-      }
-      main() => test();
-      test() { new A(); }
-      ''',
-      constructorSend: 1);  // from new A()
-  });
-
-  group('instance call', () {
-    test('monomorphic only one implementor', () {
-      return _check('''
-        class A {
-          get f => 1;
-        }
-        main() => test();
-        test() { new A().f; }
-        ''',
-        constructorSend: 1, // new A()
-        instanceSend: 1);   // f resolved to A.f
-    });
-
-    test('monomorphic only one type possible from types', () {
-      return _check('''
-        class A {
-          get f => 1;
-        }
-        class B extends A {
-          get f => 1;
-        }
-        main() => test();
-        test() { new B().f; }
-        ''',
-        constructorSend: 1,
-        instanceSend: 1); // f resolved to B.f
-    });
-
-    test('monomorphic only one type possible from liveness', () {
-      return _check('''
-        class A {
-          get f => 1;
-        }
-        class B extends A {
-          get f => 1;
-        }
-        main() => test();
-        test() { A x = new B(); x.f; }
-        ''',
-        constructorSend: 1, // new B()
-        localSend: 1,       // x in x.f
-        instanceSend: 1);  // x.f known to resolve to B.f
-    });
-
-    test('monomorphic one possible, more than one live', () {
-      return _check('''
-        class A {
-          get f => 1;
-        }
-        class B extends A {
-          get f => 1;
-        }
-        main() { new A(); test(); }
-        test() { B x = new B(); x.f; }
-        ''',
-        constructorSend: 1, // new B()
-        localSend: 1,       // x in x.f
-        instanceSend: 1);   // x.f resolves to B.f
-    });
-
-    test('polymorphic-virtual couple possible types from liveness', () {
-        // Note: this would be an instanceSend if we used the inferrer.
-      return _check('''
-        class A {
-          get f => 1;
-        }
-        class B extends A {
-          get f => 1;
-        }
-        main() { new A(); test(); }
-        test() { A x = new B(); x.f; }
-        ''',
-        constructorSend: 1, // new B()
-        localSend: 1,       // x in x.f
-        virtualSend: 1);    // x.f may be A.f or B.f (types alone is not enough)
-    });
-
-    test("polymorphic-dynamic: type annotations don't help", () {
-      return _check('''
-        class A {
-          get f => 1;
-        }
-        class B extends A {
-          get f => 1;
-        }
-        main() { new A(); test(); }
-        test() { var x = new B(); x.f; }
-        ''',
-        constructorSend: 1, // new B()
-        localSend: 1,       // x in x.f
-        dynamicSend: 1);    // x.f could be any `f` or no `f`
-    });
-  });
-
-  group('instance this call', () {
-    test('monomorphic only one implementor', () {
-      return _check('''
-        class A {
-          get f => 1;
-          test() => this.f;
-        }
-        main() => new A().test();
-        ''',
-        instanceSend: 1);   // this.f resolved to A.f
-    });
-
-    test('monomorphic only one type possible from types & liveness', () {
-      return _check('''
-        class A {
-          get f => 1;
-          test() => this.f;
-        }
-        class B extends A {
-          get f => 1;
-        }
-        main() => new B().test();
-        ''',
-        instanceSend: 1); // this.f resolved to B.f
-    });
-
-    test('polymorphic-virtual couple possible types from liveness', () {
-        // Note: this would be an instanceSend if we used the inferrer.
-      return _check('''
-        class A {
-          get f => 1;
-          test() => this.f;
-        }
-        class B extends A {
-          get f => 1;
-        }
-        main() { new A(); new B().test(); }
-        ''',
-        virtualSend: 1);    // this.f may be A.f or B.f
-    });
-  });
-
-  group('noSuchMethod', () {
-    test('error will be thrown', () {
-      return _check('''
-        class A {
-        }
-        main() { test(); }
-        test() { new A().f; }
-        ''',
-        constructorSend: 1, // new B()
-        nsmErrorSend: 1);   // f not there, A has no nSM
-    });
-
-    test('nSM will be called - one option', () {
-      return _check('''
-        class A {
-          noSuchMethod(i) => null;
-        }
-        main() { test(); }
-        test() { new A().f; }
-        ''',
-        constructorSend: 1,    // new B()
-        singleNsmCallSend: 1); // f not there, A has nSM
-    });
-
-    // TODO(sigmund): is it worth splitting multiNSMvirtual?
-    test('nSM will be called - multiple options', () {
-      return _check('''
-        class A {
-          noSuchMethod(i) => null;
-        }
-        class B extends A {
-          noSuchMethod(i) => null;
-        }
-        main() { new A(); test(); }
-        test() { A x = new B(); x.f; }
-        ''',
-        constructorSend: 1,   // new B()
-        localSend: 1,         // x in x.f
-        multiNsmCallSend: 1); // f not there, A has nSM
-    });
-
-    // TODO(sigmund): is it worth splitting multiNSMvirtual?
-    test('nSM will be called - multiple options', () {
-      return _check('''
-        class A {
-          noSuchMethod(i) => null;
-        }
-        class B extends A {
-          // don't count A's nsm as distinct
-        }
-        main() { new A(); test(); }
-        test() { A x = new B(); x.f; }
-        ''',
-        constructorSend: 1,    // new B()
-        localSend: 1,          // x in x.f
-        singleNsmCallSend: 1); // f not there, A has nSM
-    });
-
-    test('nSM will be called - multiple options', () {
-      return _check('''
-        class A {
-          noSuchMethod(i) => null;
-        }
-        class B extends A {
-          get f => null;
-        }
-        main() { new A(); test(); }
-        test() { A x = new B(); x.f; }
-        ''',
-        constructorSend: 1,   // new B()
-        localSend: 1,         // x in x.f
-        dynamicSend: 1);      // f not known to be there there, A has nSM
-    });
-
-    test('nSM in super', () {
-      return _check('''
-        class A {
-          noSuchMethod(i) => null;
-        }
-        class B extends A {
-          get f => super.f;
-        }
-        main() { new A(); test(); }
-        test() { A x = new B(); x.f; }
-        ''',
-        singleNsmCallSend: 1, //   super.f
-        testMethod: 'f');
-    });
-  });
-}
-
-
-/// Checks that the `test` function in [code] produces the given distribution of
-/// sends.
-_check(String code, {int staticSend: 0, int superSend: 0, int localSend: 0,
-    int constructorSend: 0, int typeVariableSend: 0, int nsmErrorSend: 0,
-    int singleNsmCallSend: 0, int instanceSend: 0, int interceptorSend: 0,
-    int multiNsmCallSend: 0, int virtualSend: 0, int multiInterceptorSend: 0,
-    int dynamicSend: 0, String testMethod: 'test'}) async {
-
-  // Set up the expectation.
-  var expected = new Measurements();
-  int monomorphic = staticSend + superSend + localSend + constructorSend +
-    typeVariableSend + nsmErrorSend + singleNsmCallSend + instanceSend +
-    interceptorSend;
-  int polymorphic = multiNsmCallSend + virtualSend + multiInterceptorSend +
-    dynamicSend;
-
-  expected.counters[Metric.monomorphicSend] = monomorphic;
-  expected.counters[Metric.staticSend] = staticSend;
-  expected.counters[Metric.superSend] = superSend;
-  expected.counters[Metric.localSend] = localSend;
-  expected.counters[Metric.constructorSend] = constructorSend;
-  expected.counters[Metric.typeVariableSend] = typeVariableSend;
-  expected.counters[Metric.nsmErrorSend] = nsmErrorSend;
-  expected.counters[Metric.singleNsmCallSend] = singleNsmCallSend;
-  expected.counters[Metric.instanceSend] = instanceSend;
-  expected.counters[Metric.interceptorSend] = interceptorSend;
-
-  expected.counters[Metric.polymorphicSend] = polymorphic;
-  expected.counters[Metric.multiNsmCallSend] = multiNsmCallSend;
-  expected.counters[Metric.virtualSend] = virtualSend;
-  expected.counters[Metric.multiInterceptorSend] = multiInterceptorSend;
-  expected.counters[Metric.dynamicSend] = dynamicSend;
-
-  expected.counters[Metric.send] = monomorphic + polymorphic;
-
-  // Run the compiler to get the results.
-  var all = await _compileAndGetStats(code);
-  var function = all.functions.firstWhere((f) => f.name == testMethod,
-      orElse: () => null);
-  var result = function?.measurements;
-  if (function == null) {
-    expect(expected.counters[Metric.send], 0);
-    return;
-  }
-
-  expect(result, isNotNull);
-
-  _compareMetric(Metric key) {
-    var expectedValue = expected.counters[key];
-    var value = result.counters[key];
-    if (value == null) value = 0;
-    if (value == expectedValue) return;
-    expect(expectedValue, value,
-        reason: "count for `$key` didn't match:\n"
-        "expected measurements:\n${recursiveDiagnosticString(expected, key)}\n"
-        "actual measurements:\n${recursiveDiagnosticString(result, key)}");
-  }
-
-  _compareMetric(Metric.send);
-  expected.counters.keys.forEach(_compareMetric);
-}
-
-/// Helper that runs the compiler and returns the [GlobalResult] computed for
-/// it.
-Future<AllInfo> _compileAndGetStats(String program) async {
-  var result = await runCompiler(
-      memorySourceFiles: {'main.dart': program}, options: ['--dump-info']);
-  expect(result.compiler.compilationFailed, isFalse);
-  return result.compiler.dumpInfoTask.infoCollector.result;
-}
diff --git a/tests/compiler/dart2js/serialization/analysis3_test.dart b/tests/compiler/dart2js/serialization/analysis3_test.dart
new file mode 100644
index 0000000..84da9d9
--- /dev/null
+++ b/tests/compiler/dart2js/serialization/analysis3_test.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library dart2js.serialization.analysis3_test;
+
+import 'analysis_test_helper.dart' as test;
+import 'test_helper.dart';
+
+main() {
+  test.main(testSegment(3, test.SPLIT_COUNT, test.SKIP_COUNT));
+}
diff --git a/tests/compiler/dart2js/serialization/analysis4_test.dart b/tests/compiler/dart2js/serialization/analysis4_test.dart
new file mode 100644
index 0000000..ff5c1ac
--- /dev/null
+++ b/tests/compiler/dart2js/serialization/analysis4_test.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library dart2js.serialization.analysis4_test;
+
+import 'analysis_test_helper.dart' as test;
+import 'test_helper.dart';
+
+main() {
+  test.main(testSegment(4, test.SPLIT_COUNT, test.SKIP_COUNT));
+}
diff --git a/tests/compiler/dart2js/serialization/analysis_test_helper.dart b/tests/compiler/dart2js/serialization/analysis_test_helper.dart
index 52b0271..17926c6 100644
--- a/tests/compiler/dart2js/serialization/analysis_test_helper.dart
+++ b/tests/compiler/dart2js/serialization/analysis_test_helper.dart
@@ -18,7 +18,7 @@
 int SKIP_COUNT = 0;
 
 /// Number of groups that the [TESTS] are split into.
-int SPLIT_COUNT = 2;
+int SPLIT_COUNT = 4;
 
 main(List<String> args) {
   asyncTest(() async {
diff --git a/tests/compiler/dart2js/serialization/model_test_helper.dart b/tests/compiler/dart2js/serialization/model_test_helper.dart
index daf68663..18fd88c 100644
--- a/tests/compiler/dart2js/serialization/model_test_helper.dart
+++ b/tests/compiler/dart2js/serialization/model_test_helper.dart
@@ -11,6 +11,7 @@
 import 'package:compiler/src/closure.dart';
 import 'package:compiler/src/commandline_options.dart';
 import 'package:compiler/src/common.dart';
+import 'package:compiler/src/constants/values.dart';
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/deferred_load.dart';
 import 'package:compiler/src/elements/elements.dart';
@@ -161,6 +162,38 @@
         compilerNormal.deferredLoadTask.isProgramSplit,
         compilerDeserialized.deferredLoadTask.isProgramSplit,
         "isProgramSplit mismatch");
+
+    Map<ConstantValue, OutputUnit> constants1 =
+        compilerNormal.deferredLoadTask.outputUnitForConstantsForTesting;
+    Map<ConstantValue, OutputUnit> constants2 =
+        compilerDeserialized.deferredLoadTask.outputUnitForConstantsForTesting;
+    checkSets(
+        constants1.keys,
+        constants2.keys,
+        'deferredLoadTask._outputUnitForConstants.keys',
+        areConstantValuesEquivalent,
+        failOnUnfound: false,
+        failOnExtra: false,
+        onSameElement: (ConstantValue value1, ConstantValue value2) {
+          OutputUnit outputUnit1 = constants1[value1];
+          OutputUnit outputUnit2 = constants2[value2];
+          checkOutputUnits(outputUnit1, outputUnit2,
+              'for ${value1.toStructuredText()} '
+                  'vs ${value2.toStructuredText()}');
+        },
+        onUnfoundElement: (ConstantValue value1) {
+          OutputUnit outputUnit1 = constants1[value1];
+          Expect.isTrue(outputUnit1.isMainOutput,
+              "Missing deferred constant: ${value1.toStructuredText()}");
+        },
+        onExtraElement: (ConstantValue value2) {
+          OutputUnit outputUnit2 = constants2[value2];
+          Expect.isTrue(outputUnit2.isMainOutput,
+              "Extra deferred constant: ${value2.toStructuredText()}");
+        },
+        elementToString: (a) {
+          return '${a.toStructuredText()} -> ${constants1[a]}/${constants2[a]}';
+        });
   });
 }
 
@@ -244,7 +277,7 @@
       backend2.inlineCache.getCurrentCacheDecisionForTesting(element2),
       "Inline cache decision mismatch for $element1 vs $element2");
 
-  checkOutputUnits(compiler1, compiler2, element1, element2);
+  checkElementOutputUnits(compiler1, compiler2, element1, element2);
 }
 
 void checkMixinUses(
@@ -360,17 +393,24 @@
   return '(${node.runtimeType}) $text';
 }
 
-void checkOutputUnits(Compiler compiler1, Compiler compiler2, Element element1,
-    Element element2) {
+void checkElementOutputUnits(
+    Compiler compiler1, Compiler compiler2,
+    Element element1, Element element2) {
   OutputUnit outputUnit1 =
-      compiler1.deferredLoadTask.outputUnitForElement(element1);
+      compiler1.deferredLoadTask.getOutputUnitForElementForTesting(element1);
   OutputUnit outputUnit2 =
-      compiler2.deferredLoadTask.outputUnitForElement(element2);
+      compiler2.deferredLoadTask.getOutputUnitForElementForTesting(element2);
+  checkOutputUnits(outputUnit1, outputUnit2, 'for $element1 vs $element2');
+}
+
+void checkOutputUnits(
+    OutputUnit outputUnit1, OutputUnit outputUnit2, String message) {
+  if (outputUnit1 == null && outputUnit2 == null) return;
   check(outputUnit1, outputUnit2,
-      'OutputUnit.isMainOutput for $element1 vs $element2',
+      'OutputUnit.isMainOutput $message',
       outputUnit1.isMainOutput, outputUnit2.isMainOutput);
   checkSetEquivalence(outputUnit1, outputUnit2,
-      'OutputUnit.imports for $element1 vs $element2',
+      'OutputUnit.imports $message',
       outputUnit1.imports, outputUnit2.imports,
       (a, b) => areElementsEquivalent(a.declaration, b.declaration));
 }
\ No newline at end of file
diff --git a/tests/compiler/dart2js/serialization/test_data.dart b/tests/compiler/dart2js/serialization/test_data.dart
index 568b453..9fbd223 100644
--- a/tests/compiler/dart2js/serialization/test_data.dart
+++ b/tests/compiler/dart2js/serialization/test_data.dart
@@ -644,6 +644,35 @@
 }
 ''',
   }),
+
+  const Test('Use of dart:indexed_db', const {
+    'main.dart': '''
+import 'a.dart';
+
+main() {}
+''',
+  }, preserializedSourceFiles: const {
+    'a.dart': '''
+import 'dart:indexed_db';
+''',
+  }),
+
+  const Test('Deferred static access', const {},
+      preserializedSourceFiles: const {
+    'main.dart': '''
+import 'b.dart' deferred as prefix;
+
+main() => prefix.loadLibrary().then((_) => prefix.test2());
+''',
+    'b.dart': '''
+test2() => x;
+var x = const ConstClass(const ConstClass(1));
+class ConstClass {
+  final x;
+  const ConstClass(this.x);
+}
+''',
+  }),
 ];
 
 class Test {
diff --git a/tests/compiler/dart2js/serialization/test_helper.dart b/tests/compiler/dart2js/serialization/test_helper.dart
index 2c74a07..f5d986d 100644
--- a/tests/compiler/dart2js/serialization/test_helper.dart
+++ b/tests/compiler/dart2js/serialization/test_helper.dart
@@ -7,6 +7,7 @@
 import 'dart:collection';
 import 'package:compiler/src/common/resolution.dart';
 import 'package:compiler/src/constants/expressions.dart';
+import 'package:compiler/src/constants/values.dart';
 import 'package:compiler/src/dart_types.dart';
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/elements/elements.dart';
@@ -88,6 +89,15 @@
   }
 
   @override
+  bool testMaps(
+      var object1, var object2, String property, Map map1, Map map2,
+      [bool keyEquivalence(a, b) = equality,
+      bool valueEquivalence(a, b) = equality]) {
+    return checkMapEquivalence(object1, object2, property,
+        map1, map2, keyEquivalence, valueEquivalence);
+  }
+
+  @override
   bool testElements(
       Object object1, Object object2, String property,
       Element element1, Element element2) {
@@ -110,6 +120,12 @@
   }
 
   @override
+  bool testConstantValues(Object object1, Object object2, String property,
+      ConstantValue value1, ConstantValue value2) {
+    return areConstantValuesEquivalent(value1, value2);
+  }
+
+  @override
   bool testTypeLists(
       Object object1, Object object2, String property,
       List<DartType> list1, List<DartType> list2) {
@@ -125,6 +141,12 @@
   }
 
   @override
+  bool testConstantValueLists(Object object1, Object object2, String property,
+      List<ConstantValue> list1, List<ConstantValue> list2) {
+    return checkConstantValueLists(object1, object2, property, list1, list2);
+  }
+
+  @override
   bool testNodes(Object object1, Object object2, String property,
       Node node1, Node node2) {
     return new NodeEquivalenceVisitor(this).testNodes(
@@ -247,6 +269,38 @@
   return true;
 }
 
+/// Check equivalence of the two iterables, [set1] and [set1], as sets using
+/// [elementEquivalence] to compute the pair-wise equivalence.
+///
+/// Uses [object1], [object2] and [property] to provide context for failures.
+bool checkMapEquivalence(
+    var object1,
+    var object2,
+    String property,
+    Map map1,
+    Map map2,
+    bool sameKey(a, b),
+    bool sameValue(a, b)) {
+  List<List> common = <List>[];
+  List unfound = [];
+  Set remaining =
+      computeSetDifference(map1.keys, map2.keys, common, unfound,
+          sameElement: sameKey);
+  if (unfound.isNotEmpty || remaining.isNotEmpty) {
+    String message =
+        "Map key mismatch for `$property` on $object1 vs $object2: \n"
+        "Common:\n ${common.join('\n ')}\n"
+        "Unfound:\n ${unfound.join('\n ')}\n"
+        "Extra: \n ${remaining.join('\n ')}";
+    throw message;
+  }
+  for (List pair in common) {
+    check(object1, object2, 'Map value for `$property`',
+        map1[pair[0]], map2[pair[1]], sameValue);
+  }
+  return true;
+}
+
 /// Checks the equivalence of the identity (but not properties) of [element1]
 /// and [element2].
 ///
@@ -311,7 +365,23 @@
   }
 }
 
-/// Checks the pair-wise equivalence of the contants in [list1] and [list2].
+/// Checks the equivalence of [value1] and [value2].
+///
+/// Uses [object1], [object2] and [property] to provide context for failures.
+bool checkConstantValues(
+    Object object1, Object object2, String property,
+    ConstantValue value1, ConstantValue value2) {
+  if (identical(value1, value2)) return true;
+  if (value1 == null || value2 == null) {
+    return check(object1, object2, property, value1, value2);
+  } else {
+    return check(object1, object2, property, value1, value2,
+        (a, b) => const ConstantValueEquivalence(
+            const CheckStrategy()).visit(a, b));
+  }
+}
+
+/// Checks the pair-wise equivalence of the constants in [list1] and [list2].
 ///
 /// Uses [object1], [object2] and [property] to provide context for failures.
 bool checkConstantLists(
@@ -323,6 +393,18 @@
       list1, list2, checkConstants);
 }
 
+/// Checks the pair-wise equivalence of the constants values in [list1] and
+/// [list2].
+///
+/// Uses [object1], [object2] and [property] to provide context for failures.
+bool checkConstantValueLists(
+    Object object1, Object object2, String property,
+    List<ConstantValue> list1,
+    List<ConstantValue> list2) {
+  return checkListEquivalence(
+      object1, object2, property,
+      list1, list2, checkConstantValues);
+}
 
 /// Check member property equivalence between all members common to [compiler1]
 /// and [compiler2].
@@ -439,27 +521,41 @@
     {bool failOnUnfound: true,
     bool failOnExtra: true,
     bool verbose: false,
-    void onSameElement(a, b)}) {
+    void onSameElement(a, b),
+    void onUnfoundElement(a),
+    void onExtraElement(b),
+    String elementToString(key): defaultToString}) {
   List<List> common = <List>[];
   List unfound = [];
   Set remaining = computeSetDifference(
       set1, set2, common, unfound,
       sameElement: sameElement,
       checkElements: onSameElement);
+  if (onUnfoundElement != null) {
+    unfound.forEach(onUnfoundElement);
+  }
+  if (onExtraElement != null) {
+    remaining.forEach(onExtraElement);
+  }
   StringBuffer sb = new StringBuffer();
   sb.write("$messagePrefix:");
   if (verbose) {
-    sb.write("\n Common:\n  ${common.join('\n  ')}");
+    sb.write("\n Common: \n");
+    for (List pair in common) {
+      var element1 = pair[0];
+      var element2 = pair[1];
+      sb.write("  [${elementToString(element1)},"
+          "${elementToString(element2)}]\n");
+    }
   }
   if (unfound.isNotEmpty || verbose) {
-    sb.write("\n Unfound:\n  ${unfound.join('\n  ')}");
+    sb.write("\n Unfound:\n  ${unfound.map(elementToString).join('\n  ')}");
   }
   if (remaining.isNotEmpty || verbose) {
-    sb.write("\n Extra: \n  ${remaining.join('\n  ')}");
+    sb.write("\n Extra: \n  ${remaining.map(elementToString).join('\n  ')}");
   }
   String message = sb.toString();
   if (unfound.isNotEmpty || remaining.isNotEmpty) {
-
     if ((failOnUnfound && unfound.isNotEmpty) ||
         (failOnExtra && remaining.isNotEmpty)) {
       Expect.fail(message);
diff --git a/tests/language/string_interpolation1_negative_test.dart b/tests/language/string_interpolation1_test.dart
similarity index 79%
rename from tests/language/string_interpolation1_negative_test.dart
rename to tests/language/string_interpolation1_test.dart
index 15ccfe4..4555dd0 100644
--- a/tests/language/string_interpolation1_negative_test.dart
+++ b/tests/language/string_interpolation1_test.dart
@@ -11,8 +11,9 @@
 
 class StringInterpolation1NegativeTest {
   // Dollar not followed by "{" or identifier.
-  static const DOLLAR = const A("$");
-  testMain() {
+  static const DOLLAR = const A("$"); /// 01: compile-time error
+  static testMain() {
+    print(DOLLAR); /// 01: continued
   }
 }
 
diff --git a/tests/language/string_interpolation2_negative_test.dart b/tests/language/string_interpolation2_test.dart
similarity index 76%
rename from tests/language/string_interpolation2_negative_test.dart
rename to tests/language/string_interpolation2_test.dart
index ca5e269..55aa734 100644
--- a/tests/language/string_interpolation2_negative_test.dart
+++ b/tests/language/string_interpolation2_test.dart
@@ -5,8 +5,9 @@
 // A dollar must be followed by a "{" or an identifier.
 
 class StringInterpolation2NegativeTest {
-  testMain() {
-    print('C;Y1;X4;K"$/Month"');  // Dollar followed by "/".
+  static testMain() {
+    // Dollar followed by "/".
+    print('C;Y1;X4;K"$/Month"'); /// 01: compile-time error
   }
 }
 
diff --git a/tests/language/string_interpolation3_negative_test.dart b/tests/language/string_interpolation3_test.dart
similarity index 81%
rename from tests/language/string_interpolation3_negative_test.dart
rename to tests/language/string_interpolation3_test.dart
index 14e2525..4ccf8d5 100644
--- a/tests/language/string_interpolation3_negative_test.dart
+++ b/tests/language/string_interpolation3_test.dart
@@ -6,7 +6,8 @@
 
 class StringInterpolation3NegativeTest {
   static testMain() {
-    print('F;P4;F$2R');  // Dollar followed by a number.
+    // Dollar followed by a number.
+    print('F;P4;F$2R'); /// 01: compile-time error
   }
 }
 
diff --git a/tests/language/string_interpolation4_negative_test.dart b/tests/language/string_interpolation4_test.dart
similarity index 84%
rename from tests/language/string_interpolation4_negative_test.dart
rename to tests/language/string_interpolation4_test.dart
index bc7db6f..ab26160 100644
--- a/tests/language/string_interpolation4_negative_test.dart
+++ b/tests/language/string_interpolation4_test.dart
@@ -5,9 +5,9 @@
 // A dollar must be followed by a "{" or an identifier.
 
 class StringInterpolation4NegativeTest {
-  testMain() {
+  static testMain() {
     // Dollar not followed by "{" or identifier.
-    print("-" + "$" + "foo");
+    print("-" + "$" + "foo"); /// 01: compile-time error
   }
 }
 
diff --git a/tests/language/string_interpolation5_negative_test.dart b/tests/language/string_interpolation5_test.dart
similarity index 78%
rename from tests/language/string_interpolation5_negative_test.dart
rename to tests/language/string_interpolation5_test.dart
index 9d6197d..13cf3d3 100644
--- a/tests/language/string_interpolation5_negative_test.dart
+++ b/tests/language/string_interpolation5_test.dart
@@ -5,8 +5,9 @@
 // A dollar must be followed by a "{" or an identifier.
 
 class StringInterpolation5NegativeTest {
-  testMain() {
-    print("$1,000");  // Dollar followed by a number.
+  static testMain() {
+    // Dollar followed by a number.
+    print("$1,000"); /// 01: compile-time error
   }
 }
 
diff --git a/tests/language/string_interpolation6_negative_test.dart b/tests/language/string_interpolation6_test.dart
similarity index 80%
rename from tests/language/string_interpolation6_negative_test.dart
rename to tests/language/string_interpolation6_test.dart
index e90545f..155f9fb 100644
--- a/tests/language/string_interpolation6_negative_test.dart
+++ b/tests/language/string_interpolation6_test.dart
@@ -5,9 +5,10 @@
 // A dollar must be followed by a "{" or an identifier.
 
 class StringInterpolation6NegativeTest {
-  testMain() {
+  static testMain() {
     // Dollar not followed by "{" or identifier.
-    String regexp = "^(\\d\\d?)[-/](\\d\\d?)$";
+    String regexp;
+    regexp = "^(\\d\\d?)[-/](\\d\\d?)$"; /// 01: compile-time error
     print(regexp);
   }
 }
diff --git a/tests/standalone/io/http_headers_test.dart b/tests/standalone/io/http_headers_test.dart
index 1c84cd5..26edb5f 100644
--- a/tests/standalone/io/http_headers_test.dart
+++ b/tests/standalone/io/http_headers_test.dart
@@ -380,6 +380,11 @@
       "  text/html  ;  charset  =  utf-8  ;  xxx=yyy  ");
   check(contentType, "text", "html", {"charset": "utf-8", "xxx": "yyy"});
 
+  contentType = ContentType.parse("text/html; charset=;");
+  check(contentType, "text", "html", {"charset": null});
+  contentType = ContentType.parse("text/html; charset;");
+  check(contentType, "text", "html", {"charset": null});
+
   // Test builtin content types.
   check(ContentType.TEXT, "text", "plain", {"charset": "utf-8"});
   check(ContentType.HTML, "text", "html", {"charset": "utf-8"});
@@ -387,6 +392,20 @@
   check(ContentType.BINARY, "application", "octet-stream");
 }
 
+void testKnownContentTypes() {
+  // Well known content types used by the VM service.
+  ContentType.parse('text/html; charset=UTF-8');
+  ContentType.parse('application/dart; charset=UTF-8');
+  ContentType.parse('application/javascript; charset=UTF-8');
+  ContentType.parse('text/css; charset=UTF-8');
+  ContentType.parse('image/gif');
+  ContentType.parse('image/png');
+  ContentType.parse('image/jpeg');
+  ContentType.parse('image/jpeg');
+  ContentType.parse('image/svg+xml');
+  ContentType.parse('text/plain');
+}
+
 void testContentTypeCache() {
   _HttpHeaders headers = new _HttpHeaders("1.1");
   headers.set(HttpHeaders.CONTENT_TYPE, "text/html");
@@ -570,6 +589,7 @@
   testEnumeration();
   testHeaderValue();
   testContentType();
+  testKnownContentTypes();
   testContentTypeCache();
   testCookie();
   testInvalidCookie();
diff --git a/tests/standalone/io/raw_datagram_socket_test.dart b/tests/standalone/io/raw_datagram_socket_test.dart
index 20d841e..f3168fb 100644
--- a/tests/standalone/io/raw_datagram_socket_test.dart
+++ b/tests/standalone/io/raw_datagram_socket_test.dart
@@ -195,6 +195,25 @@
   }
 }
 
+testLoopbackMulticastError() {
+  var bindAddress = InternetAddress.ANY_IP_V4;
+  var multicastAddress = new InternetAddress("228.0.0.4");
+  asyncStart();
+  Future.wait([
+      RawDatagramSocket.bind(bindAddress, 0, reuseAddress: false),
+      RawDatagramSocket.bind(bindAddress, 0, reuseAddress: false)])
+    .then((values) {
+      var sender = values[0];
+      var receiver = values[1];
+      Expect.throws(
+          () { sender.joinMulticast(new InternetAddress("127.0.0.1")); },
+          (e) => e is! TypeError);
+      sender.close();
+      receiver.close();
+      asyncEnd();
+    });
+}
+
 testSendReceive(InternetAddress bindAddress, int dataSize) {
   asyncStart();
 
@@ -320,6 +339,7 @@
   }
   testBroadcast();
   testLoopbackMulticast();
+  testLoopbackMulticastError();
   testSendReceive(InternetAddress.LOOPBACK_IP_V4, 1000);
   testSendReceive(InternetAddress.LOOPBACK_IP_V6, 1000);
   if (!Platform.isMacOS) {
diff --git a/tools/FAKE_COMMITS b/tools/FAKE_COMMITS
index 63b6b4b..65dee12 100644
--- a/tools/FAKE_COMMITS
+++ b/tools/FAKE_COMMITS
@@ -17,3 +17,4 @@
 googlecode back up
 CIT outage - all slaves rebooted
 Authentication failure flake - rerun all bots
+Trigger bots after master restart - switch dart2js bots to use downloaded sdk.
\ No newline at end of file
diff --git a/tools/VERSION b/tools/VERSION
index 8bec38a..020fe18 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 1
 MINOR 19
 PATCH 0
-PRERELEASE 4
+PRERELEASE 5
 PRERELEASE_PATCH 0
diff --git a/tools/bots/bot.py b/tools/bots/bot.py
index cfd9076..b24fe74 100644
--- a/tools/bots/bot.py
+++ b/tools/bots/bot.py
@@ -271,14 +271,17 @@
     RunProcess(args)
 
 
-def RunProcess(command):
+def RunProcess(command, env=None):
   """
   Runs command.
 
   If a non-zero exit code is returned, raises an OSError with errno as the exit
   code.
   """
-  no_color_env = dict(os.environ)
+  if env is None:
+    no_color_env = dict(os.environ)
+  else:
+    no_color_env = env
   no_color_env['TERM'] = 'nocolor'
 
   exit_code = subprocess.call(command, env=no_color_env)
diff --git a/tools/bots/dart_sdk.py b/tools/bots/dart_sdk.py
index 92f89f8..ce8b5c9 100644
--- a/tools/bots/dart_sdk.py
+++ b/tools/bots/dart_sdk.py
@@ -4,6 +4,7 @@
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE file.
 
+import os
 import os.path
 import shutil
 import sys
@@ -21,8 +22,26 @@
 
 def BuildSDK():
   with bot.BuildStep('Build SDK'):
+    sysroot_env =  dict(os.environ)
+    if BUILD_OS == 'linux':
+      ia32root = os.path.join(bot_utils.DART_DIR, '..', 'sysroots',
+                              'build', 'linux', 'debian_wheezy_i386-sysroot')
+      sysroot_env['CXXFLAGS'] = ("--sysroot=%s -I=/usr/include/c++/4.6 "
+               "-I=/usr/include/c++/4.6/i486-linux-gnu") % ia32root
+      sysroot_env['LDFLAGS'] = '--sysroot=%s' % ia32root
+      sysroot_env['CFLAGS'] = '--sysroot=%s' % ia32root
     Run([sys.executable, './tools/build.py', '--mode=release',
-         '--arch=ia32,x64', 'create_sdk'])
+         '--arch=ia32', 'create_sdk'], env=sysroot_env)
+
+    x64root = os.path.join(bot_utils.DART_DIR, '..', 'sysroots', 'build',
+                           'linux', 'debian_wheezy_amd64-sysroot')
+    if BUILD_OS == 'linux':
+      sysroot_env['CXXFLAGS'] = ("--sysroot=%s -I=/usr/include/c++/4.6 "
+              "-I=/usr/include/c++/4.6/x86_64-linux-gnu") % x64root
+      sysroot_env['LDFLAGS'] = '--sysroot=%s' % x64root
+      sysroot_env['CFLAGS'] = '--sysroot=%s' % x64root
+    Run([sys.executable, './tools/build.py', '--mode=release',
+         '--arch=x64', 'create_sdk'], env=sysroot_env)
 
 def BuildDartdocAPIDocs(dirname):
   dart_sdk = os.path.join(bot_utils.DART_DIR,
@@ -214,9 +233,10 @@
                                                       mangled_filename)
     gsutil.upload(local_sha256, remote_path + '.sha256sum', public=True)
 
-def Run(command):
+def Run(command, env=None):
   print "Running %s" % ' '.join(command)
-  return bot.RunProcess(command)
+  print "Environment %s" % env
+  return bot.RunProcess(command, env=env)
 
 if __name__ == '__main__':
   # We always clobber the bot, to make sure releases are build from scratch
diff --git a/tools/deps/dartium.deps/DEPS b/tools/deps/dartium.deps/DEPS
index 9457e56..00ba641 100644
--- a/tools/deps/dartium.deps/DEPS
+++ b/tools/deps/dartium.deps/DEPS
@@ -9,7 +9,7 @@
 
 vars.update({
   "dartium_chromium_commit": "67a7ba9669f7bb0300ef35085d4e6bb98b1966cc",
-  "dartium_webkit_commit": "006cf3ee53f37973d2db812a62fc8f5f83b52948",
+  "dartium_webkit_commit": "522da5fa29843cb44afdc20328be356f693685d6",
   "chromium_base_revision": "338390",
 
   # We use mirrors of all github repos to guarantee reproducibility and
diff --git a/tools/download_chromium_sysroot.sh b/tools/download_chromium_sysroot.sh
new file mode 100755
index 0000000..75b3744
--- /dev/null
+++ b/tools/download_chromium_sysroot.sh
@@ -0,0 +1,23 @@
+#!/usr/bin/env bash
+#
+# Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+# Downloads the ia32 and x64 Debian wheezy sysroot that chromium uses,
+# Only tested and used on Ubuntu trusty linux. Used to keep glibc version low.
+# Creates directories called "build" and "tools" in the current directory.
+# After running this, source set_ia32_sysroot.sh or set_x64_sysroot.sh, in 
+# the same working directory, to set the compilation environment variables.
+# Sourcing a script means running the script with a '.', so that it runs
+# in the current shell, not a subshell, as in:
+#   . sdk/tools/set_ia32_sysroot.sh
+
+git clone https://chromium.googlesource.com/chromium/src/build
+mkdir tools
+cd tools
+git clone https://chromium.googlesource.com/external/gyp
+cd ..
+
+build/linux/sysroot_scripts/install-sysroot.py --arch i386
+build/linux/sysroot_scripts/install-sysroot.py --arch amd64
diff --git a/tools/set_ia32_sysroot.sh b/tools/set_ia32_sysroot.sh
new file mode 100755
index 0000000..c7156ce
--- /dev/null
+++ b/tools/set_ia32_sysroot.sh
@@ -0,0 +1,19 @@
+#!/usr/bin/env bash
+#
+# Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+# Sets the compiler environment variables to use a downloaded wheezy sysroot
+# when building Dart with architecture ia32.
+# Run this in the same working directory that you have run 
+# sdk/tools/download_chromium_sysroot.sh in.
+# Must be sourced, not run in a subshell, to modify the environment.
+# Run with the command ". sdk/tools/set_ia32_sysroot.sh"
+# Only tested and used on Ubuntu trusty linux. Used to build dart with
+# no requirement for glibc greater than version 2.14.
+
+export CXXFLAGS="--sysroot=$PWD/build/linux/debian_wheezy_i386-sysroot -I=/usr/include/c++/4.6 -I=/usr/include/c++/4.6/i486-linux-gnu"
+
+export LDFLAGS=--sysroot=$PWD/build/linux/debian_wheezy_i386-sysroot
+export CFLAGS=--sysroot=$PWD/build/linux/debian_wheezy_i386-sysroot
diff --git a/tools/set_x64_sysroot.sh b/tools/set_x64_sysroot.sh
new file mode 100755
index 0000000..bc28961
--- /dev/null
+++ b/tools/set_x64_sysroot.sh
@@ -0,0 +1,19 @@
+#!/usr/bin/env bash
+#
+# Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+# Sets the compiler environment variables to use a downloaded wheezy sysroot
+# when building Dart with architecture x64.
+# Run this in the same working directory that you have run 
+# sdk/tools/download_chromium_sysroot.sh in.
+# Must be sourced, not run in a subshell, to modify the environment.
+# Run with the command ". sdk/tools/set_x64_sysroot.sh"
+# Only tested and used on Ubuntu trusty linux. Used to build dart with
+# no requirement for glibc greater than version 2.14.
+
+export CXXFLAGS="--sysroot=$PWD/build/linux/debian_wheezy_amd64-sysroot -I=/usr/include/c++/4.6 -I=/usr/include/c++/4.6/x86_64-linux-gnu"
+
+export LDFLAGS=--sysroot=$PWD/build/linux/debian_wheezy_amd64-sysroot
+export CFLAGS=--sysroot=$PWD/build/linux/debian_wheezy_amd64-sysroot
diff --git a/tools/testing/dart/compiler_configuration.dart b/tools/testing/dart/compiler_configuration.dart
index bf6db43..f6ac871 100644
--- a/tools/testing/dart/compiler_configuration.dart
+++ b/tools/testing/dart/compiler_configuration.dart
@@ -34,6 +34,7 @@
 abstract class CompilerConfiguration {
   final bool isDebug;
   final bool isChecked;
+  final bool isStrong;
   final bool isHostChecked;
   final bool useSdk;
 
@@ -48,6 +49,7 @@
     // object.
     bool isDebug = configuration['mode'] == 'debug';
     bool isChecked = configuration['checked'];
+    bool isStrong = configuration['strong'];
     bool isHostChecked = configuration['host_checked'];
     bool useSdk = configuration['use_sdk'];
     bool isCsp = configuration['csp'];
@@ -61,6 +63,7 @@
         return new AnalyzerCompilerConfiguration(
             isDebug: isDebug,
             isChecked: isChecked,
+            isStrong: isStrong,
             isHostChecked: isHostChecked,
             useSdk: useSdk);
       case 'dart2js':
@@ -102,6 +105,7 @@
   CompilerConfiguration._subclass(
       {this.isDebug: false,
       this.isChecked: false,
+      this.isStrong: false,
       this.isHostChecked: false,
       this.useSdk: false});
 
@@ -604,10 +608,12 @@
 
 class AnalyzerCompilerConfiguration extends CompilerConfiguration {
   AnalyzerCompilerConfiguration(
-      {bool isDebug, bool isChecked, bool isHostChecked, bool useSdk})
+      {bool isDebug, bool isChecked, bool isStrong, bool isHostChecked, bool
+      useSdk})
       : super._subclass(
             isDebug: isDebug,
             isChecked: isChecked,
+            isStrong: isStrong,
             isHostChecked: isHostChecked,
             useSdk: useSdk);
 
@@ -640,9 +646,12 @@
       List arguments,
       Map<String, String> environmentOverrides) {
     arguments = new List.from(arguments);
-    if (isChecked) {
+    if (isChecked || isStrong) {
       arguments.add('--enable_type_checks');
     }
+    if (isStrong){
+      arguments.add('--strong');
+    }
     return new CommandArtifact(<Command>[
       commandBuilder.getAnalysisCommand('dart2analyzer',
           computeCompilerPath(buildDir), arguments, environmentOverrides,
diff --git a/tools/testing/dart/test_configurations.dart b/tools/testing/dart/test_configurations.dart
index ca3bfbe..84cbbb4 100644
--- a/tools/testing/dart/test_configurations.dart
+++ b/tools/testing/dart/test_configurations.dart
@@ -103,6 +103,7 @@
           .map((name) => conf[name])
           .toList();
       if (conf['checked']) settings.add('checked');
+      if (conf['strong']) settings.add('strong');
       if (conf['noopt']) settings.add('noopt');
       output_words.add(settings.join('_'));
     }
diff --git a/tools/testing/dart/test_options.dart b/tools/testing/dart/test_options.dart
index 6f76125..c685988 100644
--- a/tools/testing/dart/test_options.dart
+++ b/tools/testing/dart/test_options.dart
@@ -163,6 +163,9 @@
       new _TestOptionSpecification(
           'checked', 'Run tests in checked mode', ['--checked'], [], false,
           type: 'bool'),
+      new _TestOptionSpecification(
+          'strong', 'Run tests in strong mode', ['--strong'], [], false,
+          type: 'bool'),
       new _TestOptionSpecification('host_checked',
           'Run compiler in checked mode', ['--host-checked'], [], false,
           type: 'bool'),
diff --git a/tools/testing/dart/test_progress.dart b/tools/testing/dart/test_progress.dart
index b93294b..14910fa 100644
--- a/tools/testing/dart/test_progress.dart
+++ b/tools/testing/dart/test_progress.dart
@@ -255,6 +255,7 @@
     'compiler',
     'runtime',
     'checked',
+    'strong',
     'host_checked',
     'minified',
     'csp',
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index 2c4b541..abdde58 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -377,25 +377,27 @@
 
   String createOutputDirectory(Path testPath, String optionsName) {
     var checked = configuration['checked'] ? '-checked' : '';
+    var strong =  configuration['strong'] ? '-strong' : '';
     var minified = configuration['minified'] ? '-minified' : '';
     var sdk = configuration['use_sdk'] ? '-sdk' : '';
     var packages =
         configuration['use_public_packages'] ? '-public_packages' : '';
     var dirName = "${configuration['compiler']}-${configuration['runtime']}"
-        "$checked$minified$packages$sdk";
+        "$checked$strong$minified$packages$sdk";
     return createGeneratedTestDirectoryHelper(
         "tests", dirName, testPath, optionsName);
   }
 
   String createCompilationOutputDirectory(Path testPath) {
     var checked = configuration['checked'] ? '-checked' : '';
+    var strong =  configuration['strong'] ? '-strong' : '';
     var minified = configuration['minified'] ? '-minified' : '';
     var csp = configuration['csp'] ? '-csp' : '';
     var sdk = configuration['use_sdk'] ? '-sdk' : '';
     var packages =
         configuration['use_public_packages'] ? '-public_packages' : '';
     var dirName = "${configuration['compiler']}"
-        "$checked$minified$csp$packages$sdk";
+        "$checked$strong$minified$csp$packages$sdk";
     return createGeneratedTestDirectoryHelper(
         "compilations", dirName, testPath, "");
   }
@@ -2211,13 +2213,14 @@
         configuration['compiler'] == 'dart2appjit' ||
         configuration['compiler'] == 'precompiler') {
       var checked = configuration['checked'] ? '-checked' : '';
+      var strong =  configuration['strong'] ? '-strong' : '';
       var minified = configuration['minified'] ? '-minified' : '';
       var csp = configuration['csp'] ? '-csp' : '';
       var sdk = configuration['use_sdk'] ? '-sdk' : '';
       var packages =
           configuration['use_public_packages'] ? '-public_packages' : '';
       var dirName = "${configuration['compiler']}"
-          "$checked$minified$csp$packages$sdk";
+          "$checked$strong$minified$csp$packages$sdk";
       String generatedPath = "${TestUtils.buildDir(configuration)}"
           "/generated_compilations/$dirName";
       TestUtils.deleteDirectory(generatedPath);