Version 1.17.0-dev.2.0

Merge f7a3e215a50e232fe60b57a6cdea51cc82636b8b into dev
diff --git a/DEPS b/DEPS
index c4bf8bb..a040da2 100644
--- a/DEPS
+++ b/DEPS
@@ -49,7 +49,7 @@
   "dart_services_rev" : "@7aea2574e6f3924bf409a80afb8ad52aa2be4f97",
   "dart_style_tag": "@0.2.4",
   "dartdoc_tag" : "@v0.9.0",
-  "dev_compiler_rev": "@0ed6aeca35fa0e618ad0f7f19f3eba64afdd80c4",
+  "dev_compiler_rev": "@ec95b3c45819f4d0de847588fdaa752a8e4651fb",
   "fixnum_tag": "@0.10.4",
   "func_rev": "@8d4aea75c21be2179cb00dc2b94a71414653094e",
   "glob_rev": "@704cf75e4f26b417505c5c611bdaacd8808467dd",
diff --git a/pkg/analysis_server/lib/plugin/protocol/protocol.dart b/pkg/analysis_server/lib/plugin/protocol/protocol.dart
index 032e4f9..92ef921 100644
--- a/pkg/analysis_server/lib/plugin/protocol/protocol.dart
+++ b/pkg/analysis_server/lib/plugin/protocol/protocol.dart
@@ -160,7 +160,7 @@
    */
   Request(this.id, this.method,
       [Map<String, Object> params, this.clientRequestTime])
-      : _params = params != null ? params : new HashMap<String, Object>();
+      : _params = params ?? new HashMap<String, Object>();
 
   /**
    * Return a request parsed from the given json, or `null` if the [data] is
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index 5a06a6e..a00ab31 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -330,7 +330,7 @@
     sdkManager = new DartSdkManager(defaultSdkCreator);
     if (useSingleContextManager) {
       contextManager = new SingleContextManager(resourceProvider, sdkManager,
-          () => packageResolverProvider(null), analyzedFilesGlobs);
+          packageResolverProvider, analyzedFilesGlobs, defaultContextOptions);
     } else {
       contextManager = new ContextManagerImpl(
           resourceProvider,
@@ -1420,7 +1420,7 @@
     }
     // if library has not been resolved yet, the unit will be resolved later
     Source librarySource = librarySources[0];
-    if (context.getResult(librarySource, LIBRARY_ELEMENT5) == null) {
+    if (context.getResult(librarySource, LIBRARY_ELEMENT6) == null) {
       return null;
     }
     // if library has been already resolved, resolve unit
diff --git a/pkg/analysis_server/lib/src/computer/computer_hover.dart b/pkg/analysis_server/lib/src/computer/computer_hover.dart
index 33b5941..d4e10b4 100644
--- a/pkg/analysis_server/lib/src/computer/computer_hover.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_hover.dart
@@ -127,5 +127,5 @@
     return null;
   }
 
-  static _safeToString(obj) => obj != null ? obj.toString() : null;
+  static _safeToString(obj) => obj?.toString();
 }
diff --git a/pkg/analysis_server/lib/src/computer/computer_outline.dart b/pkg/analysis_server/lib/src/computer/computer_outline.dart
index 8603884..a89ff02 100644
--- a/pkg/analysis_server/lib/src/computer/computer_outline.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_outline.dart
@@ -41,8 +41,7 @@
             VariableDeclarationList fields = fieldDeclaration.fields;
             if (fields != null) {
               TypeName fieldType = fields.type;
-              String fieldTypeName =
-                  fieldType != null ? fieldType.toSource() : '';
+              String fieldTypeName = _safeToSource(fieldType);
               for (VariableDeclaration field in fields.variables) {
                 classContents.add(_newVariableOutline(fieldTypeName,
                     ElementKind.FIELD, field, fieldDeclaration.isStatic));
@@ -69,7 +68,7 @@
         VariableDeclarationList fields = fieldDeclaration.variables;
         if (fields != null) {
           TypeName fieldType = fields.type;
-          String fieldTypeName = fieldType != null ? fieldType.toSource() : '';
+          String fieldTypeName = _safeToSource(fieldType);
           for (VariableDeclaration field in fields.variables) {
             unitContents.add(_newVariableOutline(
                 fieldTypeName, ElementKind.TOP_LEVEL_VARIABLE, field, false));
@@ -207,7 +206,7 @@
     }
     _SourceRegion sourceRegion = _getSourceRegion(constructor);
     FormalParameterList parameters = constructor.parameters;
-    String parametersStr = parameters != null ? parameters.toSource() : '';
+    String parametersStr = _safeToSource(parameters);
     Element element = new Element(
         ElementKind.CONSTRUCTOR,
         name,
@@ -266,8 +265,8 @@
       kind = ElementKind.FUNCTION;
     }
     _SourceRegion sourceRegion = _getSourceRegion(function);
-    String parametersStr = parameters != null ? parameters.toSource() : '';
-    String returnTypeStr = returnType != null ? returnType.toSource() : '';
+    String parametersStr = _safeToSource(parameters);
+    String returnTypeStr = _safeToSource(returnType);
     Element element = new Element(
         kind,
         name,
@@ -291,8 +290,8 @@
     String name = nameNode.name;
     _SourceRegion sourceRegion = _getSourceRegion(node);
     FormalParameterList parameters = node.parameters;
-    String parametersStr = parameters != null ? parameters.toSource() : '';
-    String returnTypeStr = returnType != null ? returnType.toSource() : '';
+    String parametersStr = _safeToSource(parameters);
+    String returnTypeStr = _safeToSource(returnType);
     Element element = new Element(
         ElementKind.FUNCTION_TYPE_ALIAS,
         name,
@@ -320,8 +319,8 @@
       kind = ElementKind.METHOD;
     }
     _SourceRegion sourceRegion = _getSourceRegion(method);
-    String parametersStr = parameters != null ? parameters.toSource() : null;
-    String returnTypeStr = returnType != null ? returnType.toSource() : '';
+    String parametersStr = parameters?.toSource();
+    String returnTypeStr = _safeToSource(returnType);
     Element element = new Element(
         kind,
         name,
@@ -383,6 +382,9 @@
     engine.Element element = declaration.element;
     return element != null && element.isDeprecated;
   }
+
+  static String _safeToSource(AstNode node) =>
+      node == null ? '' : node.toSource();
 }
 
 /**
diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart
index a87fdc5..181eeac 100644
--- a/pkg/analysis_server/lib/src/context_manager.dart
+++ b/pkg/analysis_server/lib/src/context_manager.dart
@@ -16,6 +16,7 @@
 import 'package:analyzer/plugin/options.dart';
 import 'package:analyzer/plugin/resolver_provider.dart';
 import 'package:analyzer/source/analysis_options_provider.dart';
+import 'package:analyzer/source/config.dart';
 import 'package:analyzer/source/embedder.dart';
 import 'package:analyzer/source/package_map_provider.dart';
 import 'package:analyzer/source/package_map_resolver.dart';
@@ -597,7 +598,7 @@
       }
     } else {
       // Check for embedded options.
-      YamlMap embeddedOptions = _getEmbeddedOptions(info.context);
+      Map embeddedOptions = _getEmbeddedOptions(info.context);
       if (embeddedOptions != null) {
         options = _toStringMap(new Merger().merge(embeddedOptions, options));
       }
@@ -1072,6 +1073,27 @@
     folderMap[folder] = info.context;
     info.context.name = folder.path;
 
+    // Look for pubspec-specified analysis configuration.
+    File pubspec;
+    if (packagespecFile?.exists == true) {
+      if (packagespecFile.shortName == PUBSPEC_NAME) {
+        pubspec = packagespecFile;
+      }
+    }
+    if (pubspec == null) {
+      Resource child = folder.getChild(PUBSPEC_NAME);
+      if (child.exists && child is File) {
+        pubspec = child;
+      }
+    }
+    if (pubspec != null) {
+      File pubSource = resourceProvider.getFile(pubspec.path);
+      setConfiguration(
+          info.context,
+          new AnalysisConfiguration.fromPubspec(
+              pubSource, resourceProvider, disposition.packages));
+    }
+
     processOptionsForContext(info, optionMap);
 
     return info;
@@ -1235,18 +1257,36 @@
     return packageSpec;
   }
 
-  /// Get analysis options associated with an `_embedder.yaml`. If there is
-  /// more than one `_embedder.yaml` associated with the given context, `null`
-  /// is returned.
-  YamlMap _getEmbeddedOptions(AnalysisContext context) {
+  /// Get analysis options inherited from an `_embedder.yaml` (deprecated)
+  /// and/or a package specified configuration.  If more than one
+  /// `_embedder.yaml` is associated with the given context, the embedder is
+  /// skipped.
+  ///
+  /// Returns null if there are no embedded/configured options.
+  Map _getEmbeddedOptions(AnalysisContext context) {
+    Map embeddedOptions;
+
     if (context is InternalAnalysisContext) {
       EmbedderYamlLocator locator = context.embedderYamlLocator;
       Iterable<YamlMap> maps = locator.embedderYamls.values;
       if (maps.length == 1) {
-        return maps.first;
+        embeddedOptions = maps.first;
+      }
+
+      AnalysisConfiguration configuration = getConfiguration(context);
+      if (configuration != null) {
+        Map configMap = configuration.options;
+        if (configMap != null) {
+          if (embeddedOptions != null) {
+            embeddedOptions = new Merger().merge(embeddedOptions, configMap);
+          } else {
+            embeddedOptions = configMap;
+          }
+        }
       }
     }
-    return null;
+
+    return embeddedOptions;
   }
 
   /**
diff --git a/pkg/analysis_server/lib/src/operation/operation_analysis.dart b/pkg/analysis_server/lib/src/operation/operation_analysis.dart
index 6f71721..76b27ae 100644
--- a/pkg/analysis_server/lib/src/operation/operation_analysis.dart
+++ b/pkg/analysis_server/lib/src/operation/operation_analysis.dart
@@ -89,8 +89,7 @@
     return;
   }
   // Dart
-  CompilationUnit dartUnit =
-      resolvedDartUnit != null ? resolvedDartUnit : parsedDartUnit;
+  CompilationUnit dartUnit = resolvedDartUnit ?? parsedDartUnit;
   if (resolvedDartUnit != null) {
     if (server.hasAnalysisSubscription(
         protocol.AnalysisService.HIGHLIGHTS, file)) {
diff --git a/pkg/analysis_server/lib/src/server/driver.dart b/pkg/analysis_server/lib/src/server/driver.dart
index a5af1b22..6ccf8ae 100644
--- a/pkg/analysis_server/lib/src/server/driver.dart
+++ b/pkg/analysis_server/lib/src/server/driver.dart
@@ -334,7 +334,7 @@
    * Set the [plugins] that are defined outside the analysis_server package.
    */
   void set userDefinedPlugins(List<Plugin> plugins) {
-    _userDefinedPlugins = plugins == null ? <Plugin>[] : plugins;
+    _userDefinedPlugins = plugins ?? <Plugin>[];
   }
 
   /**
diff --git a/pkg/analysis_server/lib/src/services/completion/completion_performance.dart b/pkg/analysis_server/lib/src/services/completion/completion_performance.dart
index 0272fb8..7c64604 100644
--- a/pkg/analysis_server/lib/src/services/completion/completion_performance.dart
+++ b/pkg/analysis_server/lib/src/services/completion/completion_performance.dart
@@ -42,7 +42,7 @@
 
   void complete([String tag = null]) {
     _stopwatch.stop();
-    _logDuration(tag != null ? tag : 'total time', _stopwatch.elapsed);
+    _logDuration(tag ?? 'total time', _stopwatch.elapsed);
   }
 
   void logElapseTime(String tag) {
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/common_usage_sorter.dart b/pkg/analysis_server/lib/src/services/completion/dart/common_usage_sorter.dart
index 8f27b86..b448251 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/common_usage_sorter.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/common_usage_sorter.dart
@@ -55,7 +55,7 @@
     if (libElem is LibraryElement) {
       var unit = request.context.getResult(
           new LibrarySpecificUnit(libElem.source, request.source),
-          RESOLVED_UNIT4);
+          RESOLVED_UNIT5);
       if (unit is CompilationUnit) {
         return new CompletionTarget.forOffset(unit, request.offset);
       }
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 7be86e4..e582d37 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
@@ -311,7 +311,7 @@
       CompilationUnit unit = await _computeAsync(
           this,
           new LibrarySpecificUnit(libElem.source, unresolvedUnit.source),
-          RESOLVED_UNIT4,
+          RESOLVED_UNIT5,
           performance,
           'resolve library unit');
       checkAborted();
@@ -388,7 +388,7 @@
       unit = await _computeAsync(
           request,
           new LibrarySpecificUnit(libSource, source),
-          resultDescriptor ?? RESOLVED_UNIT4,
+          resultDescriptor ?? RESOLVED_UNIT5,
           performance,
           'resolve declarations');
     }
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart
index 750e623..d9778a5 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart
@@ -387,44 +387,6 @@
     }
   }
 
-  void _addLocalSuggestion_includeTypeNameSuggestions(
-      SimpleIdentifier id, TypeName typeName, protocol.ElementKind elemKind,
-      {bool isAbstract: false,
-      bool isDeprecated: false,
-      ClassDeclaration classDecl,
-      FormalParameterList param,
-      int relevance: DART_RELEVANCE_DEFAULT}) {
-    relevance = optype.typeNameSuggestionsFilter(
-        _staticTypeOfIdentifier(id), relevance);
-    if (relevance != null) {
-      _addLocalSuggestion(id, typeName, elemKind,
-          isAbstract: isAbstract,
-          isDeprecated: isDeprecated,
-          classDecl: classDecl,
-          param: param,
-          relevance: relevance);
-    }
-  }
-
-  void _addLocalSuggestion_includeReturnValueSuggestions(
-      SimpleIdentifier id, TypeName typeName, protocol.ElementKind elemKind,
-      {bool isAbstract: false,
-      bool isDeprecated: false,
-      ClassDeclaration classDecl,
-      FormalParameterList param,
-      int relevance: DART_RELEVANCE_DEFAULT}) {
-    relevance = optype.returnValueSuggestionsFilter(
-        _staticTypeOfIdentifier(id), relevance);
-    if (relevance != null) {
-      _addLocalSuggestion(id, typeName, elemKind,
-          isAbstract: isAbstract,
-          isDeprecated: isDeprecated,
-          classDecl: classDecl,
-          param: param,
-          relevance: relevance);
-    }
-  }
-
   void _addLocalSuggestion(
       SimpleIdentifier id, TypeName typeName, protocol.ElementKind elemKind,
       {bool isAbstract: false,
@@ -447,7 +409,7 @@
       suggestion.element = _createLocalElement(request.source, elemKind, id,
           isAbstract: isAbstract,
           isDeprecated: isDeprecated,
-          parameters: param != null ? param.toSource() : null,
+          parameters: param?.toSource(),
           returnType: typeName);
       if ((elemKind == protocol.ElementKind.METHOD ||
               elemKind == protocol.ElementKind.FUNCTION) &&
@@ -457,6 +419,44 @@
     }
   }
 
+  void _addLocalSuggestion_includeReturnValueSuggestions(
+      SimpleIdentifier id, TypeName typeName, protocol.ElementKind elemKind,
+      {bool isAbstract: false,
+      bool isDeprecated: false,
+      ClassDeclaration classDecl,
+      FormalParameterList param,
+      int relevance: DART_RELEVANCE_DEFAULT}) {
+    relevance = optype.returnValueSuggestionsFilter(
+        _staticTypeOfIdentifier(id), relevance);
+    if (relevance != null) {
+      _addLocalSuggestion(id, typeName, elemKind,
+          isAbstract: isAbstract,
+          isDeprecated: isDeprecated,
+          classDecl: classDecl,
+          param: param,
+          relevance: relevance);
+    }
+  }
+
+  void _addLocalSuggestion_includeTypeNameSuggestions(
+      SimpleIdentifier id, TypeName typeName, protocol.ElementKind elemKind,
+      {bool isAbstract: false,
+      bool isDeprecated: false,
+      ClassDeclaration classDecl,
+      FormalParameterList param,
+      int relevance: DART_RELEVANCE_DEFAULT}) {
+    relevance = optype.typeNameSuggestionsFilter(
+        _staticTypeOfIdentifier(id), relevance);
+    if (relevance != null) {
+      _addLocalSuggestion(id, typeName, elemKind,
+          isAbstract: isAbstract,
+          isDeprecated: isDeprecated,
+          classDecl: classDecl,
+          param: param,
+          relevance: relevance);
+    }
+  }
+
   void _addParameterInfo(
       CompletionSuggestion suggestion, FormalParameterList parameters) {
     var paramList = parameters.parameters;
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/variable_name_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/variable_name_contributor.dart
index 71ac473..2c4d913 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/variable_name_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/variable_name_contributor.dart
@@ -80,6 +80,7 @@
       }
 
       List<String> variableNameSuggestions = getCamelWordCombinations(strName);
+      variableNameSuggestions.remove(strName);
       List<CompletionSuggestion> suggestions = <CompletionSuggestion>[];
       for (String varName in variableNameSuggestions) {
         CompletionSuggestion suggestion = _createNameSuggestion(varName);
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 b1dd15b..f855a29 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -1044,8 +1044,7 @@
         } else {
           ClassDeclaration enclosingClass =
               node.getAncestor((node) => node is ClassDeclaration);
-          targetElement =
-              enclosingClass != null ? enclosingClass.element : null;
+          targetElement = enclosingClass?.element;
           argument = nameNode;
         }
       }
@@ -2145,10 +2144,7 @@
       if (n is MethodInvocation &&
           n.offset == errorOffset &&
           n.length == errorLength) {
-        Expression target = n.target;
-        while (target is ParenthesizedExpression) {
-          target = (target as ParenthesizedExpression).expression;
-        }
+        Expression target = n.target.unParenthesized;
         // replace "/" with "~/"
         BinaryExpression binary = target as BinaryExpression;
         _addReplaceEdit(rf.rangeToken(binary.operator), '~/');
@@ -2595,7 +2591,7 @@
     // return myFunction();
     if (parent is ReturnStatement) {
       ExecutableElement executable = getEnclosingExecutableElement(expression);
-      return executable != null ? executable.returnType : null;
+      return executable?.returnType;
     }
     // int v = myFunction();
     if (parent is VariableDeclaration) {
@@ -2653,7 +2649,7 @@
     // foo( myFunction() );
     if (parent is ArgumentList) {
       ParameterElement parameter = expression.bestParameterElement;
-      return parameter != null ? parameter.type : null;
+      return parameter?.type;
     }
     // bool
     {
diff --git a/pkg/analysis_server/lib/src/services/correction/namespace.dart b/pkg/analysis_server/lib/src/services/correction/namespace.dart
index b0058aa..0aa0b8d 100644
--- a/pkg/analysis_server/lib/src/services/correction/namespace.dart
+++ b/pkg/analysis_server/lib/src/services/correction/namespace.dart
@@ -46,7 +46,7 @@
     return importDirective.element;
   }
   ImportElementInfo info = internal_getImportElementInfo(prefixNode);
-  return info != null ? info.element : null;
+  return info?.element;
 }
 
 /**
diff --git a/pkg/analysis_server/lib/src/services/correction/sort_members.dart b/pkg/analysis_server/lib/src/services/correction/sort_members.dart
index 4592367..7cf8aa5 100644
--- a/pkg/analysis_server/lib/src/services/correction/sort_members.dart
+++ b/pkg/analysis_server/lib/src/services/correction/sort_members.dart
@@ -197,11 +197,16 @@
               directive.documentationComment.offset,
               directive.documentationComment.end);
         }
+        String annotationText;
+        if (directive.metadata.beginToken != null) {
+          annotationText = code.substring(directive.metadata.beginToken.offset,
+              directive.metadata.endToken.end);
+        }
         int offset = directive.firstTokenAfterCommentAndMetadata.offset;
         int length = directive.end - offset;
         String text = code.substring(offset, offset + length);
-        directives.add(new _DirectiveInfo(
-            directive, kind, uriContent, documentationText, text));
+        directives.add(new _DirectiveInfo(directive, kind, uriContent,
+            documentationText, annotationText, text));
       }
     }
     // nothing to do
@@ -245,6 +250,10 @@
             sb.write(endOfLine);
           }
         }
+        if (directive.annotationText != null) {
+          sb.write(directive.annotationText);
+          sb.write(endOfLine);
+        }
         sb.write(directive.text);
         sb.write(endOfLine);
       }
@@ -369,10 +378,11 @@
   final _DirectivePriority priority;
   final String uri;
   final String documentationText;
+  final String annotationText;
   final String text;
 
   _DirectiveInfo(this.directive, this.priority, this.uri,
-      this.documentationText, this.text);
+      this.documentationText, this.annotationText, this.text);
 
   @override
   int compareTo(_DirectiveInfo other) {
diff --git a/pkg/analysis_server/lib/src/services/correction/util.dart b/pkg/analysis_server/lib/src/services/correction/util.dart
index ca38579..551964a 100644
--- a/pkg/analysis_server/lib/src/services/correction/util.dart
+++ b/pkg/analysis_server/lib/src/services/correction/util.dart
@@ -1284,18 +1284,15 @@
    */
   _InvertedCondition _invertCondition0(Expression expression) {
     if (expression is BooleanLiteral) {
-      BooleanLiteral literal = expression;
-      if (literal.value) {
+      if (expression.value) {
         return _InvertedCondition._simple("false");
       } else {
         return _InvertedCondition._simple("true");
       }
-    }
-    if (expression is BinaryExpression) {
-      BinaryExpression binary = expression;
-      TokenType operator = binary.operator.type;
-      Expression le = binary.leftOperand;
-      Expression re = binary.rightOperand;
+    } else if (expression is BinaryExpression) {
+      TokenType operator = expression.operator.type;
+      Expression le = expression.leftOperand;
+      Expression re = expression.rightOperand;
       _InvertedCondition ls = _invertCondition0(le);
       _InvertedCondition rs = _invertCondition0(re);
       if (operator == TokenType.LT) {
@@ -1324,37 +1321,22 @@
         return _InvertedCondition._binary(
             TokenType.AMPERSAND_AMPERSAND.precedence, ls, " && ", rs);
       }
-    }
-    if (expression is IsExpression) {
-      IsExpression isExpression = expression;
-      String expressionSource = getNodeText(isExpression.expression);
-      String typeSource = getNodeText(isExpression.type);
-      if (isExpression.notOperator == null) {
+    } else if (expression is IsExpression) {
+      String expressionSource = getNodeText(expression.expression);
+      String typeSource = getNodeText(expression.type);
+      if (expression.notOperator == null) {
         return _InvertedCondition._simple("$expressionSource is! $typeSource");
       } else {
         return _InvertedCondition._simple("$expressionSource is $typeSource");
       }
-    }
-    if (expression is PrefixExpression) {
-      PrefixExpression prefixExpression = expression;
-      TokenType operator = prefixExpression.operator.type;
+    } else if (expression is PrefixExpression) {
+      TokenType operator = expression.operator.type;
       if (operator == TokenType.BANG) {
-        Expression operand = prefixExpression.operand;
-        while (operand is ParenthesizedExpression) {
-          ParenthesizedExpression pe = operand as ParenthesizedExpression;
-          operand = pe.expression;
-        }
+        Expression operand = expression.operand.unParenthesized;
         return _InvertedCondition._simple(getNodeText(operand));
       }
-    }
-    if (expression is ParenthesizedExpression) {
-      ParenthesizedExpression pe = expression;
-      Expression innerExpression = pe.expression;
-      while (innerExpression is ParenthesizedExpression) {
-        innerExpression =
-            (innerExpression as ParenthesizedExpression).expression;
-      }
-      return _invertCondition0(innerExpression);
+    } else if (expression is ParenthesizedExpression) {
+      return _invertCondition0(expression.unParenthesized);
     }
     DartType type = expression.bestType;
     if (type.displayName == "bool") {
diff --git a/pkg/analysis_server/lib/src/single_context_manager.dart b/pkg/analysis_server/lib/src/single_context_manager.dart
index bdc3a67..0a8c9f1 100644
--- a/pkg/analysis_server/lib/src/single_context_manager.dart
+++ b/pkg/analysis_server/lib/src/single_context_manager.dart
@@ -10,6 +10,7 @@
 
 import 'package:analysis_server/src/context_manager.dart';
 import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/plugin/resolver_provider.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
@@ -18,12 +19,6 @@
 import 'package:watcher/watcher.dart';
 
 /**
- * A function that will return a [UriResolver] that can be used to resolve
- * `package:` URIs in [SingleContextManager].
- */
-typedef UriResolver PackageResolverProvider();
-
-/**
  * Implementation of [ContextManager] that supports only one [AnalysisContext].
  * So, sources from all analysis roots are added to this single context. All
  * features that could otherwise cause creating additional contexts, such as
@@ -51,7 +46,7 @@
    * A function that will return a [UriResolver] that can be used to resolve
    * `package:` URIs.
    */
-  final PackageResolverProvider packageResolverProvider;
+  final ResolverProvider packageResolverProvider;
 
   /**
    * A list of the globs used to determine which files should be analyzed.
@@ -59,6 +54,11 @@
   final List<Glob> analyzedFilesGlobs;
 
   /**
+   * The default options used to create new analysis contexts.
+   */
+  final AnalysisOptionsImpl defaultContextOptions;
+
+  /**
    * The list of included paths (folders and files) most recently passed to
    * [setRoots].
    */
@@ -103,8 +103,12 @@
   /**
    * The [packageResolverProvider] must not be `null`.
    */
-  SingleContextManager(this.resourceProvider, this.sdkManager,
-      this.packageResolverProvider, this.analyzedFilesGlobs) {
+  SingleContextManager(
+      this.resourceProvider,
+      this.sdkManager,
+      this.packageResolverProvider,
+      this.analyzedFilesGlobs,
+      this.defaultContextOptions) {
     pathContext = resourceProvider.pathContext;
   }
 
@@ -196,8 +200,8 @@
     }
     // Create or update the analysis context.
     if (context == null) {
-      UriResolver packageResolver = packageResolverProvider();
-      context = callbacks.addContext(contextFolder, new AnalysisOptionsImpl(),
+      UriResolver packageResolver = packageResolverProvider(contextFolder);
+      context = callbacks.addContext(contextFolder, defaultContextOptions,
           new CustomPackageResolverDisposition(packageResolver));
       ChangeSet changeSet =
           _buildChangeSet(added: _includedFiles(includedPaths, excludedPaths));
diff --git a/pkg/analysis_server/lib/src/status/get_handler.dart b/pkg/analysis_server/lib/src/status/get_handler.dart
index a2cc48f..5b3f6de 100644
--- a/pkg/analysis_server/lib/src/status/get_handler.dart
+++ b/pkg/analysis_server/lib/src/status/get_handler.dart
@@ -461,6 +461,10 @@
     if (unit != null) {
       return unit;
     }
+    unit = entry.getValue(RESOLVED_UNIT13);
+    if (unit != null) {
+      return unit;
+    }
     return entry.getValue(RESOLVED_UNIT);
   }
 
@@ -492,6 +496,7 @@
         results.add(LIBRARY_ELEMENT3);
         results.add(LIBRARY_ELEMENT4);
         results.add(LIBRARY_ELEMENT5);
+        results.add(LIBRARY_ELEMENT6);
         results.add(LIBRARY_ELEMENT);
         results.add(LIBRARY_ERRORS_READY);
         results.add(PARSE_ERRORS);
@@ -518,6 +523,7 @@
       results.add(INFERABLE_STATIC_VARIABLES_IN_UNIT);
       results.add(LIBRARY_UNIT_ERRORS);
       results.add(RESOLVE_TYPE_NAMES_ERRORS);
+      results.add(RESOLVE_TYPE_BOUNDS_ERRORS);
       results.add(RESOLVE_UNIT_ERRORS);
       results.add(RESOLVED_UNIT1);
       results.add(RESOLVED_UNIT2);
@@ -531,6 +537,7 @@
       results.add(RESOLVED_UNIT10);
       results.add(RESOLVED_UNIT11);
       results.add(RESOLVED_UNIT12);
+      results.add(RESOLVED_UNIT13);
       results.add(RESOLVED_UNIT);
       results.add(STRONG_MODE_ERRORS);
       results.add(USED_IMPORTED_ELEMENTS);
diff --git a/pkg/analysis_server/test/context_manager_test.dart b/pkg/analysis_server/test/context_manager_test.dart
index d20e599..9f00603 100644
--- a/pkg/analysis_server/test/context_manager_test.dart
+++ b/pkg/analysis_server/test/context_manager_test.dart
@@ -78,6 +78,11 @@
 
   String projPath = '/my/proj';
 
+  AnalysisError missing_required_param = new AnalysisError(
+      new TestSource(), 0, 1, HintCode.MISSING_REQUIRED_PARAM, [
+    ['x']
+  ]);
+
   AnalysisError missing_return =
       new AnalysisError(new TestSource(), 0, 1, HintCode.MISSING_RETURN, [
     ['x']
@@ -284,6 +289,98 @@
     // No error means success.
   }
 
+  test_configed_options() async {
+    // Create files.
+    String libPath = newFolder([projPath, LIB_NAME]);
+    newFile([projPath, 'test', 'test.dart']);
+    newFile(
+        [projPath, 'pubspec.yaml'],
+        r'''
+dependencies:
+  test_pack: any
+analyzer:
+  configuration: test_pack/config
+''');
+
+    // Setup .packages file
+    newFile(
+        [projPath, '.packages'],
+        r'''
+test_pack:lib/''');
+
+    // Setup config.yaml.
+    newFile(
+        [libPath, 'config', 'config.yaml'],
+        r'''
+analyzer:
+  strong-mode: true
+  language:
+    enableSuperMixins: true
+  errors:
+    missing_return: false
+linter:
+  rules:
+    - avoid_as
+''');
+
+    // Setup .analysis_options
+    newFile(
+        [projPath, AnalysisEngine.ANALYSIS_OPTIONS_FILE],
+        r'''
+analyzer:
+  exclude:
+    - 'test/**'
+  language:
+    enableGenericMethods: true
+    enableAsync: false
+  errors:
+    unused_local_variable: false
+linter:
+  rules:
+    - camel_case_types
+''');
+
+    // Setup context.
+    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
+    await pumpEventQueue();
+
+    // Confirm that one context was created.
+    var contexts =
+        manager.contextsInAnalysisRoot(resourceProvider.newFolder(projPath));
+    expect(contexts, isNotNull);
+    expect(contexts, hasLength(1));
+
+    var context = contexts.first;
+
+    // Verify options.
+    // * from `config.yaml`:
+    expect(context.analysisOptions.strongMode, isTrue);
+    expect(context.analysisOptions.enableSuperMixins, isTrue);
+    expect(context.analysisOptions.enableAsync, isFalse);
+    // * from `.analysis_options`:
+    expect(context.analysisOptions.enableGenericMethods, isTrue);
+
+    // * verify tests are excluded
+    expect(callbacks.currentContextFilePaths[projPath].keys,
+        unorderedEquals(['/my/proj/.analysis_options']));
+
+    // Verify filter setup.
+    expect(errorProcessors, hasLength(2));
+
+    // * (config.)
+    expect(getProcessor(missing_return).severity, isNull);
+
+    // * (options.)
+    expect(getProcessor(unused_local_variable).severity, isNull);
+
+    // Verify lints.
+    var lintNames = lints.map((lint) => lint.name);
+    expect(
+        lintNames,
+        unorderedEquals(
+            ['avoid_as' /* config */, 'camel_case_types' /* options */]));
+  }
+
   void test_contextsInAnalysisRoot_nestedContext() {
     String subProjPath = posix.join(projPath, 'subproj');
     Folder subProjFolder = resourceProvider.newFolder(subProjPath);
@@ -362,6 +459,130 @@
     expect(contexts.first.sourceFactory.forUri('dart:typed_data'), isNotNull);
   }
 
+  test_embedder_and_configed_options() async {
+    // Create files.
+    String libPath = newFolder([projPath, LIB_NAME]);
+    String sdkExtPath = newFolder([projPath, 'sdk_ext']);
+    newFile([projPath, 'test', 'test.dart']);
+    newFile([sdkExtPath, 'entry.dart']);
+
+    // Setup pubspec with configuration.
+    newFile(
+        [projPath, 'pubspec.yaml'],
+        r'''
+dependencies:
+  test_pack: any
+analyzer:
+  configuration: test_pack/config
+''');
+
+    // Setup _embedder.yaml.
+    newFile(
+        [libPath, '_embedder.yaml'],
+        r'''
+embedded_libs:
+  "dart:foobar": "../sdk_ext/entry.dart"
+analyzer:
+  strong-mode: true
+  language:
+    enableSuperMixins: true
+  errors:
+    missing_return: false
+linter:
+  rules:
+    - avoid_as
+''');
+
+    // Setup .packages file
+    newFile(
+        [projPath, '.packages'],
+        r'''
+test_pack:lib/''');
+
+    // Setup .analysis_options
+    newFile(
+        [projPath, AnalysisEngine.ANALYSIS_OPTIONS_FILE],
+        r'''
+analyzer:
+  exclude:
+    - 'test/**'
+  language:
+    enableGenericMethods: true
+    enableAsync: false
+  errors:
+    unused_local_variable: false
+linter:
+  rules:
+    - camel_case_types
+''');
+
+    // Setup config.yaml.
+    newFile(
+        [libPath, 'config', 'config.yaml'],
+        r'''
+analyzer:
+  errors:
+    missing_required_param: error
+linter:
+  rules:
+    - always_specify_types
+''');
+
+    // Setup context.
+    manager.setRoots(<String>[projPath], <String>[], <String, String>{});
+    await pumpEventQueue();
+
+    // Confirm that one context was created.
+    var contexts =
+        manager.contextsInAnalysisRoot(resourceProvider.newFolder(projPath));
+    expect(contexts, isNotNull);
+    expect(contexts, hasLength(1));
+    var context = contexts[0];
+
+    // Verify options.
+    // * from `_embedder.yaml`:
+    expect(context.analysisOptions.strongMode, isTrue);
+    expect(context.analysisOptions.enableSuperMixins, isTrue);
+    expect(context.analysisOptions.enableAsync, isFalse);
+    // * from `.analysis_options`:
+    expect(context.analysisOptions.enableGenericMethods, isTrue);
+
+    // * verify tests are excluded
+    expect(
+        callbacks.currentContextFilePaths[projPath].keys,
+        unorderedEquals(
+            ['/my/proj/sdk_ext/entry.dart', '/my/proj/.analysis_options']));
+
+    // Verify filter setup.
+    expect(errorProcessors, hasLength(3));
+
+    // * (embedder.)
+    expect(getProcessor(missing_return).severity, isNull);
+
+    // * (config.)
+    expect(getProcessor(missing_required_param).severity, ErrorSeverity.ERROR);
+
+    // * (options.)
+    expect(getProcessor(unused_local_variable).severity, isNull);
+
+    // Verify lints.
+    var lintNames = lints.map((lint) => lint.name);
+
+    expect(
+        lintNames,
+        unorderedEquals([
+          'avoid_as' /* embedder */,
+          'always_specify_types' /* config*/,
+          'camel_case_types' /* options */
+        ]));
+
+    // Sanity check embedder libs.
+    var source = context.sourceFactory.forUri('dart:foobar');
+    expect(source, isNotNull);
+    expect(source.fullName,
+        '/my/proj/sdk_ext/entry.dart'.replaceAll('/', JavaFile.separator));
+  }
+
   test_embedder_options() async {
     // Create files.
     String libPath = newFolder([projPath, LIB_NAME]);
diff --git a/pkg/analysis_server/test/edit/sort_members_test.dart b/pkg/analysis_server/test/edit/sort_members_test.dart
index a955360..ee801df7 100644
--- a/pkg/analysis_server/test/edit/sort_members_test.dart
+++ b/pkg/analysis_server/test/edit/sort_members_test.dart
@@ -144,6 +144,40 @@
 ''');
   }
 
+  test_OK_directives_withAnnotation() async {
+    addTestFile('''
+library lib;
+
+export 'dart:bbb';
+@MyAnnotation(1)
+@MyAnnotation(2)
+import 'dart:bbb';
+@MyAnnotation(3)
+export 'dart:aaa';
+import 'dart:aaa';
+
+class MyAnnotation {
+  const MyAnnotation(_);
+}
+''');
+    return _assertSorted(r'''
+library lib;
+
+import 'dart:aaa';
+@MyAnnotation(1)
+@MyAnnotation(2)
+import 'dart:bbb';
+
+@MyAnnotation(3)
+export 'dart:aaa';
+export 'dart:bbb';
+
+class MyAnnotation {
+  const MyAnnotation(_);
+}
+''');
+  }
+
   test_OK_unitMembers_class() async {
     addTestFile('''
 class C {}
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
index dc011c1..08c83de 100644
--- a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
+++ b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
@@ -143,10 +143,10 @@
     if (elemOffset != null) {
       expect(cs.element.location.offset, elemOffset);
     }
-    if(paramName != null) {
+    if (paramName != null) {
       expect(cs.parameterName, paramName);
     }
-    if(paramType != null) {
+    if (paramType != null) {
       expect(cs.parameterType, paramType);
     }
     return cs;
@@ -262,8 +262,6 @@
       expect(cs.returnType, returnType);
     } else if (isNullExpectedReturnTypeConsideredDynamic) {
       expect(cs.returnType, 'dynamic');
-    } else {
-      expect(cs.returnType, isNull);
     }
     protocol.Element element = cs.element;
     expect(element, isNotNull);
@@ -278,8 +276,6 @@
       expect(element.returnType, returnType);
     } else if (isNullExpectedReturnTypeConsideredDynamic) {
       expect(element.returnType, 'dynamic');
-    } else {
-      expect(element.returnType, isNull);
     }
     assertHasParameterInfo(cs);
     return cs;
@@ -369,8 +365,7 @@
     return cs;
   }
 
-  CompletionSuggestion assertSuggestName(
-      String name,
+  CompletionSuggestion assertSuggestName(String name,
       {int relevance: DART_RELEVANCE_DEFAULT,
       String importUri,
       CompletionSuggestionKind kind: CompletionSuggestionKind.IDENTIFIER,
@@ -419,8 +414,6 @@
       expect(cs.returnType, returnType);
     } else if (isNullExpectedReturnTypeConsideredDynamic) {
       expect(cs.returnType, 'dynamic');
-    } else {
-      expect(cs.returnType, isNull);
     }
     protocol.Element element = cs.element;
     expect(element, isNotNull);
@@ -431,8 +424,6 @@
       expect(element.returnType, returnType);
     } else if (isNullExpectedReturnTypeConsideredDynamic) {
       expect(element.returnType, 'dynamic');
-    } else {
-      expect(element.returnType, isNull);
     }
     assertHasNoParameterInfo(cs);
     return cs;
diff --git a/pkg/analysis_server/test/services/completion/dart/imported_reference_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/imported_reference_contributor_test.dart
index 6b63ce0..51125e7 100644
--- a/pkg/analysis_server/test/services/completion/dart/imported_reference_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/imported_reference_contributor_test.dart
@@ -2729,7 +2729,7 @@
     // in which case suggestions will have null (unresolved) returnType
     assertSuggestTopLevelVar('T1', null);
     assertSuggestFunction('F1', null);
-    assertSuggestFunctionTypeAlias('D1', 'null');
+    assertSuggestFunctionTypeAlias('D1', 'dynamic');
     assertSuggestClass('C1');
     assertNotSuggested('T2');
     assertNotSuggested('F2');
diff --git a/pkg/analysis_server/test/services/completion/dart/variable_name_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/variable_name_contributor_test.dart
index 72a4cab..6896850 100644
--- a/pkg/analysis_server/test/services/completion/dart/variable_name_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/variable_name_contributor_test.dart
@@ -24,24 +24,24 @@
     return new VariableNameContributor();
   }
 
-  test_ExpressionStatement_short() async {
+  test_ExpressionStatement_dont_suggest_type() async {
     addTestSource('''
-    f() { A ^ }
+    f() { a ^ }
     ''');
     await computeSuggestions();
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertSuggestName('a');
+    assertNotSuggested('a');
   }
 
-  test_ExpressionStatement_short_semicolon() async {
+  test_ExpressionStatement_dont_suggest_type_semicolon() async {
     addTestSource('''
-    f() { A ^; }
+    f() { a ^; }
     ''');
     await computeSuggestions();
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertSuggestName('a');
+    assertNotSuggested('a');
   }
 
   test_ExpressionStatement_long() async {
@@ -100,9 +100,9 @@
     assertSuggestName('name');
   }
 
-  test_ExpressionStatement_top_level_short() async {
+  test_ExpressionStatement_short() async {
     addTestSource('''
-    A ^
+    f() { A ^ }
     ''');
     await computeSuggestions();
     expect(replacementOffset, completionOffset);
@@ -110,9 +110,9 @@
     assertSuggestName('a');
   }
 
-  test_ExpressionStatement_top_level_short_semicolon() async {
+  test_ExpressionStatement_short_semicolon() async {
     addTestSource('''
-    A ^;
+    f() { A ^; }
     ''');
     await computeSuggestions();
     expect(replacementOffset, completionOffset);
@@ -120,7 +120,27 @@
     assertSuggestName('a');
   }
 
-  test_ExpressionStatement_top_level_long() async {
+  test_TopLevelVariableDeclaration_dont_suggest_type() async {
+    addTestSource('''
+    a ^
+    ''');
+    await computeSuggestions();
+    expect(replacementOffset, completionOffset);
+    expect(replacementLength, 0);
+    assertNotSuggested('a');
+  }
+
+  test_TopLevelVariableDeclaration_dont_suggest_type_semicolon() async {
+    addTestSource('''
+    a ^;
+    ''');
+    await computeSuggestions();
+    expect(replacementOffset, completionOffset);
+    expect(replacementLength, 0);
+    assertNotSuggested('a');
+  }
+
+  test_TopLevelVariableDeclaration_long() async {
     addTestSource('''
     AbstractCrazyNonsenseClassName ^
     ''');
@@ -134,7 +154,7 @@
     assertSuggestName('name');
   }
 
-  test_ExpressionStatement_top_level_long_semicolon() async {
+  test_TopLevelVariableDeclaration_long_semicolon() async {
     addTestSource('''
     AbstractCrazyNonsenseClassName ^;
     ''');
@@ -148,7 +168,35 @@
     assertSuggestName('name');
   }
 
-  test_ExpressionStatement_top_level_prefixed() async {
+  test_TopLevelVariableDeclaration_partial() async {
+    addTestSource('''
+    AbstractCrazyNonsenseClassName abs^
+    ''');
+    await computeSuggestions();
+    expect(replacementOffset, completionOffset - 3);
+    expect(replacementLength, 3);
+    assertSuggestName('abstractCrazyNonsenseClassName');
+    assertSuggestName('crazyNonsenseClassName');
+    assertSuggestName('nonsenseClassName');
+    assertSuggestName('className');
+    assertSuggestName('name');
+  }
+
+  test_TopLevelVariableDeclaration_partial_semicolon() async {
+    addTestSource('''
+    AbstractCrazyNonsenseClassName abs^
+    ''');
+    await computeSuggestions();
+    expect(replacementOffset, completionOffset - 3);
+    expect(replacementLength, 3);
+    assertSuggestName('abstractCrazyNonsenseClassName');
+    assertSuggestName('crazyNonsenseClassName');
+    assertSuggestName('nonsenseClassName');
+    assertSuggestName('className');
+    assertSuggestName('name');
+  }
+
+  test_TopLevelVariableDeclaration_prefixed() async {
     addTestSource('''
     prefix.AbstractCrazyNonsenseClassName ^
     ''');
@@ -162,7 +210,7 @@
     assertSuggestName('name');
   }
 
-  test_ExpressionStatement_top_level_prefixed_semicolon() async {
+  test_TopLevelVariableDeclaration_prefixed_semicolon() async {
     addTestSource('''
     prefix.AbstractCrazyNonsenseClassName ^;
     ''');
@@ -176,24 +224,23 @@
     assertSuggestName('name');
   }
 
-  test_VariableDeclaration_short() async {
+  test_TopLevelVariableDeclaration_short() async {
     addTestSource('''
-    AAA a^
+    A ^
     ''');
     await computeSuggestions();
-    expect(replacementOffset, completionOffset-1);
-    expect(replacementLength, 1);
-    assertSuggestName('aaa');
+    expect(replacementOffset, completionOffset);
+    expect(replacementLength, 0);
+    assertSuggestName('a');
   }
 
-  test_VariableDeclaration_short_semicolon() async {
+  test_TopLevelVariableDeclaration_short_semicolon() async {
     addTestSource('''
-    AAA a^;
+    A ^;
     ''');
     await computeSuggestions();
-    expect(replacementOffset, completionOffset-1);
-    expect(replacementLength, 1);
-    assertSuggestName('aaa');
+    expect(replacementOffset, completionOffset);
+    expect(replacementLength, 0);
+    assertSuggestName('a');
   }
-
 }
diff --git a/pkg/analysis_server/test/single_context_manager_test.dart b/pkg/analysis_server/test/single_context_manager_test.dart
index f436006..25ab3bd 100644
--- a/pkg/analysis_server/test/single_context_manager_test.dart
+++ b/pkg/analysis_server/test/single_context_manager_test.dart
@@ -69,7 +69,7 @@
       return new MockSdk();
     });
     manager = new SingleContextManager(resourceProvider, sdkManager,
-        () => packageResolver, analysisFilesGlobs);
+        (_) => packageResolver, analysisFilesGlobs, new AnalysisOptionsImpl());
     callbacks = new TestContextManagerCallbacks(resourceProvider);
     manager.callbacks = callbacks;
   }
diff --git a/pkg/analyzer/doc/tasks.html b/pkg/analyzer/doc/tasks.html
index 5e242a5..4fdabc9 100644
--- a/pkg/analyzer/doc/tasks.html
+++ b/pkg/analyzer/doc/tasks.html
@@ -52,23 +52,24 @@
   CREATED_RESOLVED_UNIT [shape=box]
   CREATED_RESOLVED_UNIT1 [shape=box]
   CREATED_RESOLVED_UNIT10 -> InferInstanceMembersInUnitTask
-  CREATED_RESOLVED_UNIT10 -> InferStaticVariableTypeTask
-  CREATED_RESOLVED_UNIT10 -> PartiallyResolveUnitReferencesTask
-  CREATED_RESOLVED_UNIT10 -> ResolveInstanceFieldsInUnitTask
-  CREATED_RESOLVED_UNIT10 -> ResolveUnitTask
   CREATED_RESOLVED_UNIT10 [shape=box]
-  CREATED_RESOLVED_UNIT11 -> ResolveConstantExpressionTask
+  CREATED_RESOLVED_UNIT11 -> InferInstanceMembersInUnitTask
+  CREATED_RESOLVED_UNIT11 -> InferStaticVariableTypeTask
+  CREATED_RESOLVED_UNIT11 -> PartiallyResolveUnitReferencesTask
+  CREATED_RESOLVED_UNIT11 -> ResolveInstanceFieldsInUnitTask
+  CREATED_RESOLVED_UNIT11 -> ResolveUnitTask
   CREATED_RESOLVED_UNIT11 [shape=box]
+  CREATED_RESOLVED_UNIT12 -> ResolveConstantExpressionTask
   CREATED_RESOLVED_UNIT12 [shape=box]
+  CREATED_RESOLVED_UNIT13 [shape=box]
   CREATED_RESOLVED_UNIT2 [shape=box]
   CREATED_RESOLVED_UNIT3 [shape=box]
   CREATED_RESOLVED_UNIT4 [shape=box]
   CREATED_RESOLVED_UNIT5 [shape=box]
   CREATED_RESOLVED_UNIT6 [shape=box]
   CREATED_RESOLVED_UNIT7 [shape=box]
-  CREATED_RESOLVED_UNIT8 -> ResolveInstanceFieldsInUnitTask
   CREATED_RESOLVED_UNIT8 [shape=box]
-  CREATED_RESOLVED_UNIT9 -> InferInstanceMembersInUnitTask
+  CREATED_RESOLVED_UNIT9 -> ResolveInstanceFieldsInUnitTask
   CREATED_RESOLVED_UNIT9 [shape=box]
   ComputeConstantDependenciesTask -> CONSTANT_DEPENDENCIES
   ComputeConstantValueTask -> CONSTANT_VALUE
@@ -88,11 +89,12 @@
   EXPORTED_LIBRARIES -> ReadyLibraryElement2Task
   EXPORTED_LIBRARIES -> ReadyLibraryElement5Task
   EXPORTED_LIBRARIES -> ReadyLibraryElement6Task
+  EXPORTED_LIBRARIES -> ResolveTopLevelLibraryTypeBoundsTask
   EXPORTED_LIBRARIES [shape=box]
   EXPORT_SOURCE_CLOSURE -> BuildExportNamespaceTask
   EXPORT_SOURCE_CLOSURE [shape=box]
-  EvaluateUnitConstantsTask -> CREATED_RESOLVED_UNIT12
-  EvaluateUnitConstantsTask -> RESOLVED_UNIT12
+  EvaluateUnitConstantsTask -> CREATED_RESOLVED_UNIT13
+  EvaluateUnitConstantsTask -> RESOLVED_UNIT13
   GatherUsedImportedElementsTask -> USED_IMPORTED_ELEMENTS
   GatherUsedLocalElementsTask -> USED_LOCAL_ELEMENTS
   GenerateHintsTask -> HINTS
@@ -103,7 +105,8 @@
   IMPORTED_LIBRARIES -> ReadyLibraryElement2Task
   IMPORTED_LIBRARIES -> ReadyLibraryElement5Task
   IMPORTED_LIBRARIES -> ReadyLibraryElement6Task
-  IMPORTED_LIBRARIES -> ResolveUnitTypeNamesTask
+  IMPORTED_LIBRARIES -> ResolveTopLevelLibraryTypeBoundsTask
+  IMPORTED_LIBRARIES -> ResolveTopLevelUnitTypeBoundsTask
   IMPORTED_LIBRARIES [shape=box]
   INCLUDED_PARTS -> BuildLibraryElementTask
   INCLUDED_PARTS [shape=box]
@@ -115,11 +118,11 @@
   INFERRED_STATIC_VARIABLE -> InferStaticVariableTypesInUnitTask
   INFERRED_STATIC_VARIABLE [shape=box]
   IS_LAUNCHABLE [shape=box]
-  InferInstanceMembersInUnitTask -> CREATED_RESOLVED_UNIT10
-  InferInstanceMembersInUnitTask -> RESOLVED_UNIT10
+  InferInstanceMembersInUnitTask -> CREATED_RESOLVED_UNIT11
+  InferInstanceMembersInUnitTask -> RESOLVED_UNIT11
   InferStaticVariableTypeTask -> INFERRED_STATIC_VARIABLE
-  InferStaticVariableTypesInUnitTask -> CREATED_RESOLVED_UNIT8
-  InferStaticVariableTypesInUnitTask -> RESOLVED_UNIT8
+  InferStaticVariableTypesInUnitTask -> CREATED_RESOLVED_UNIT9
+  InferStaticVariableTypesInUnitTask -> RESOLVED_UNIT9
   LIBRARY_CYCLE [shape=box]
   LIBRARY_CYCLE_DEPENDENCIES -> InferInstanceMembersInUnitTask
   LIBRARY_CYCLE_DEPENDENCIES -> InferStaticVariableTypeTask
@@ -144,29 +147,34 @@
   LIBRARY_ELEMENT3 -> BuildExportNamespaceTask
   LIBRARY_ELEMENT3 -> BuildTypeProviderTask
   LIBRARY_ELEMENT3 [shape=box]
-  LIBRARY_ELEMENT4 -> ResolveLibraryTypeNamesTask
-  LIBRARY_ELEMENT4 -> ResolveUnitTypeNamesTask
+  LIBRARY_ELEMENT4 -> ResolveTopLevelLibraryTypeBoundsTask
+  LIBRARY_ELEMENT4 -> ResolveTopLevelUnitTypeBoundsTask
   LIBRARY_ELEMENT4 [shape=box]
-  LIBRARY_ELEMENT5 -> PartiallyResolveUnitReferencesTask
-  LIBRARY_ELEMENT5 -> PropagateVariableTypesInLibraryTask
-  LIBRARY_ELEMENT5 -> ReadyLibraryElement5Task
-  LIBRARY_ELEMENT5 -> ResolveInstanceFieldsInUnitTask
+  LIBRARY_ELEMENT5 -> ResolveLibraryTypeNamesTask
+  LIBRARY_ELEMENT5 -> ResolveTopLevelLibraryTypeBoundsTask
+  LIBRARY_ELEMENT5 -> ResolveUnitTypeNamesTask
   LIBRARY_ELEMENT5 [shape=box]
-  LIBRARY_ELEMENT6 -> PropagateVariableTypesInLibraryClosureTask
-  LIBRARY_ELEMENT6 -> ReadyLibraryElement6Task
+  LIBRARY_ELEMENT6 -> PartiallyResolveUnitReferencesTask
+  LIBRARY_ELEMENT6 -> PropagateVariableTypesInLibraryTask
+  LIBRARY_ELEMENT6 -> ReadyLibraryElement5Task
+  LIBRARY_ELEMENT6 -> ResolveInstanceFieldsInUnitTask
   LIBRARY_ELEMENT6 [shape=box]
-  LIBRARY_ELEMENT7 -> ResolveLibraryReferencesTask
-  LIBRARY_ELEMENT7 -> ResolveUnitTask
+  LIBRARY_ELEMENT7 -> PropagateVariableTypesInLibraryClosureTask
+  LIBRARY_ELEMENT7 -> ReadyLibraryElement6Task
   LIBRARY_ELEMENT7 [shape=box]
-  LIBRARY_ELEMENT8 -> EvaluateUnitConstantsTask
-  LIBRARY_ELEMENT8 -> ResolveLibraryTask
+  LIBRARY_ELEMENT8 -> ResolveLibraryReferencesTask
+  LIBRARY_ELEMENT8 -> ResolveUnitTask
   LIBRARY_ELEMENT8 [shape=box]
+  LIBRARY_ELEMENT9 -> EvaluateUnitConstantsTask
+  LIBRARY_ELEMENT9 -> ResolveLibraryTask
+  LIBRARY_ELEMENT9 [shape=box]
   LIBRARY_ERRORS_READY [shape=box]
   LIBRARY_SPECIFIC_UNITS -> GenerateHintsTask
   LIBRARY_SPECIFIC_UNITS -> PropagateVariableTypesInLibraryTask
   LIBRARY_SPECIFIC_UNITS -> ReadyResolvedUnitTask
   LIBRARY_SPECIFIC_UNITS -> ResolveLibraryReferencesTask
   LIBRARY_SPECIFIC_UNITS -> ResolveLibraryTypeNamesTask
+  LIBRARY_SPECIFIC_UNITS -> ResolveTopLevelLibraryTypeBoundsTask
   LIBRARY_SPECIFIC_UNITS [shape=box]
   LIBRARY_UNIT_ERRORS -> dartErrorsForUnit
   LIBRARY_UNIT_ERRORS [shape=box]
@@ -204,24 +212,24 @@
   ParseDartTask -> REFERENCED_SOURCES
   ParseDartTask -> SOURCE_KIND
   ParseDartTask -> UNITS
-  PartiallyResolveUnitReferencesTask -> CREATED_RESOLVED_UNIT6
+  PartiallyResolveUnitReferencesTask -> CREATED_RESOLVED_UNIT7
   PartiallyResolveUnitReferencesTask -> INFERABLE_STATIC_VARIABLES_IN_UNIT
   PartiallyResolveUnitReferencesTask -> PROPAGABLE_VARIABLES_IN_UNIT
-  PartiallyResolveUnitReferencesTask -> RESOLVED_UNIT6
+  PartiallyResolveUnitReferencesTask -> RESOLVED_UNIT7
   PropagateVariableTypeTask -> PROPAGATED_VARIABLE
-  PropagateVariableTypesInLibraryClosureTask -> LIBRARY_ELEMENT7
-  PropagateVariableTypesInLibraryTask -> LIBRARY_ELEMENT6
-  PropagateVariableTypesInUnitTask -> CREATED_RESOLVED_UNIT7
-  PropagateVariableTypesInUnitTask -> RESOLVED_UNIT7
+  PropagateVariableTypesInLibraryClosureTask -> LIBRARY_ELEMENT8
+  PropagateVariableTypesInLibraryTask -> LIBRARY_ELEMENT7
+  PropagateVariableTypesInUnitTask -> CREATED_RESOLVED_UNIT8
+  PropagateVariableTypesInUnitTask -> RESOLVED_UNIT8
   READY_LIBRARY_ELEMENT2 -> ComputeLibraryCycleTask
   READY_LIBRARY_ELEMENT2 -> ReadyLibraryElement2Task
   READY_LIBRARY_ELEMENT2 [shape=box]
-  READY_LIBRARY_ELEMENT5 -> PartiallyResolveUnitReferencesTask
-  READY_LIBRARY_ELEMENT5 -> ReadyLibraryElement5Task
-  READY_LIBRARY_ELEMENT5 [shape=box]
-  READY_LIBRARY_ELEMENT6 -> PropagateVariableTypesInLibraryClosureTask
-  READY_LIBRARY_ELEMENT6 -> ReadyLibraryElement6Task
+  READY_LIBRARY_ELEMENT6 -> PartiallyResolveUnitReferencesTask
+  READY_LIBRARY_ELEMENT6 -> ReadyLibraryElement5Task
   READY_LIBRARY_ELEMENT6 [shape=box]
+  READY_LIBRARY_ELEMENT7 -> PropagateVariableTypesInLibraryClosureTask
+  READY_LIBRARY_ELEMENT7 -> ReadyLibraryElement6Task
+  READY_LIBRARY_ELEMENT7 [shape=box]
   READY_RESOLVED_UNIT -> ResolveLibraryTask
   READY_RESOLVED_UNIT -> VerifyUnitTask
   READY_RESOLVED_UNIT [shape=box]
@@ -238,63 +246,72 @@
   RESOLVED_UNIT1 -> BuildLibraryElementTask
   RESOLVED_UNIT1 -> ResolveDirectiveElementsTask
   RESOLVED_UNIT1 [shape=box]
-  RESOLVED_UNIT10 -> ResolveUnitTask
+  RESOLVED_UNIT10 -> InferInstanceMembersInUnitTask
   RESOLVED_UNIT10 [shape=box]
-  RESOLVED_UNIT11 -> EvaluateUnitConstantsTask
-  RESOLVED_UNIT11 -> GatherUsedImportedElementsTask
-  RESOLVED_UNIT11 -> GatherUsedLocalElementsTask
-  RESOLVED_UNIT11 -> ResolveLibraryReferencesTask
+  RESOLVED_UNIT11 -> ResolveUnitTask
   RESOLVED_UNIT11 [shape=box]
-  RESOLVED_UNIT12 -> StrongModeVerifyUnitTask
+  RESOLVED_UNIT12 -> EvaluateUnitConstantsTask
+  RESOLVED_UNIT12 -> GatherUsedImportedElementsTask
+  RESOLVED_UNIT12 -> GatherUsedLocalElementsTask
+  RESOLVED_UNIT12 -> ResolveLibraryReferencesTask
   RESOLVED_UNIT12 [shape=box]
+  RESOLVED_UNIT13 -> StrongModeVerifyUnitTask
+  RESOLVED_UNIT13 [shape=box]
   RESOLVED_UNIT2 -> BuildEnumMemberElementsTask
   RESOLVED_UNIT2 [shape=box]
-  RESOLVED_UNIT3 -> ResolveUnitTypeNamesTask
+  RESOLVED_UNIT3 -> ResolveTopLevelUnitTypeBoundsTask
   RESOLVED_UNIT3 [shape=box]
-  RESOLVED_UNIT4 -> ResolveLibraryTypeNamesTask
-  RESOLVED_UNIT4 -> ResolveVariableReferencesTask
+  RESOLVED_UNIT4 -> ResolveTopLevelLibraryTypeBoundsTask
+  RESOLVED_UNIT4 -> ResolveUnitTypeNamesTask
   RESOLVED_UNIT4 [shape=box]
-  RESOLVED_UNIT5 -> PartiallyResolveUnitReferencesTask
+  RESOLVED_UNIT5 -> ResolveLibraryTypeNamesTask
+  RESOLVED_UNIT5 -> ResolveVariableReferencesTask
   RESOLVED_UNIT5 [shape=box]
-  RESOLVED_UNIT6 -> ComputeInferableStaticVariableDependenciesTask
-  RESOLVED_UNIT6 -> ComputePropagableVariableDependenciesTask
-  RESOLVED_UNIT6 -> PropagateVariableTypeTask
-  RESOLVED_UNIT6 -> PropagateVariableTypesInUnitTask
+  RESOLVED_UNIT6 -> PartiallyResolveUnitReferencesTask
   RESOLVED_UNIT6 [shape=box]
-  RESOLVED_UNIT7 -> InferStaticVariableTypeTask
-  RESOLVED_UNIT7 -> InferStaticVariableTypesInUnitTask
-  RESOLVED_UNIT7 -> PropagateVariableTypesInLibraryTask
+  RESOLVED_UNIT7 -> ComputeInferableStaticVariableDependenciesTask
+  RESOLVED_UNIT7 -> ComputePropagableVariableDependenciesTask
+  RESOLVED_UNIT7 -> PropagateVariableTypeTask
+  RESOLVED_UNIT7 -> PropagateVariableTypesInUnitTask
   RESOLVED_UNIT7 [shape=box]
-  RESOLVED_UNIT8 -> ResolveInstanceFieldsInUnitTask
+  RESOLVED_UNIT8 -> InferStaticVariableTypeTask
+  RESOLVED_UNIT8 -> InferStaticVariableTypesInUnitTask
+  RESOLVED_UNIT8 -> PropagateVariableTypesInLibraryTask
   RESOLVED_UNIT8 [shape=box]
-  RESOLVED_UNIT9 -> InferInstanceMembersInUnitTask
+  RESOLVED_UNIT9 -> ResolveInstanceFieldsInUnitTask
   RESOLVED_UNIT9 [shape=box]
+  RESOLVE_TYPE_BOUNDS_ERRORS -> LibraryUnitErrorsTask
+  RESOLVE_TYPE_BOUNDS_ERRORS [shape=box]
   RESOLVE_TYPE_NAMES_ERRORS -> LibraryUnitErrorsTask
   RESOLVE_TYPE_NAMES_ERRORS [shape=box]
   RESOLVE_UNIT_ERRORS -> LibraryUnitErrorsTask
   RESOLVE_UNIT_ERRORS [shape=box]
   ReadyLibraryElement2Task -> READY_LIBRARY_ELEMENT2
-  ReadyLibraryElement5Task -> READY_LIBRARY_ELEMENT5
-  ReadyLibraryElement6Task -> READY_LIBRARY_ELEMENT6
+  ReadyLibraryElement5Task -> READY_LIBRARY_ELEMENT6
+  ReadyLibraryElement6Task -> READY_LIBRARY_ELEMENT7
   ReadyResolvedUnitTask -> READY_RESOLVED_UNIT
   ResolveConstantExpressionTask -> CONSTANT_EXPRESSION_RESOLVED
   ResolveDirectiveElementsTask -> CREATED_RESOLVED_UNIT2
   ResolveDirectiveElementsTask -> RESOLVED_UNIT2
-  ResolveInstanceFieldsInUnitTask -> CREATED_RESOLVED_UNIT9
-  ResolveInstanceFieldsInUnitTask -> RESOLVED_UNIT9
-  ResolveLibraryReferencesTask -> LIBRARY_ELEMENT8
+  ResolveInstanceFieldsInUnitTask -> CREATED_RESOLVED_UNIT10
+  ResolveInstanceFieldsInUnitTask -> RESOLVED_UNIT10
+  ResolveLibraryReferencesTask -> LIBRARY_ELEMENT9
   ResolveLibraryReferencesTask -> REFERENCED_NAMES
   ResolveLibraryTask -> LIBRARY_ELEMENT
-  ResolveLibraryTypeNamesTask -> LIBRARY_ELEMENT5
+  ResolveLibraryTypeNamesTask -> LIBRARY_ELEMENT6
+  ResolveTopLevelLibraryTypeBoundsTask -> LIBRARY_ELEMENT5
+  ResolveTopLevelUnitTypeBoundsTask -> CREATED_RESOLVED_UNIT4
+  ResolveTopLevelUnitTypeBoundsTask -> RESOLVED_UNIT4
+  ResolveTopLevelUnitTypeBoundsTask -> RESOLVE_TYPE_BOUNDS_ERRORS
   ResolveUnitTask -> CONSTANT_EXPRESSIONS_DEPENDENCIES
-  ResolveUnitTask -> CREATED_RESOLVED_UNIT11
-  ResolveUnitTask -> RESOLVED_UNIT11
+  ResolveUnitTask -> CREATED_RESOLVED_UNIT12
+  ResolveUnitTask -> RESOLVED_UNIT12
   ResolveUnitTask -> RESOLVE_UNIT_ERRORS
-  ResolveUnitTypeNamesTask -> CREATED_RESOLVED_UNIT4
-  ResolveUnitTypeNamesTask -> RESOLVED_UNIT4
+  ResolveUnitTypeNamesTask -> CREATED_RESOLVED_UNIT5
+  ResolveUnitTypeNamesTask -> RESOLVED_UNIT5
   ResolveUnitTypeNamesTask -> RESOLVE_TYPE_NAMES_ERRORS
-  ResolveVariableReferencesTask -> CREATED_RESOLVED_UNIT5
-  ResolveVariableReferencesTask -> RESOLVED_UNIT5
+  ResolveVariableReferencesTask -> CREATED_RESOLVED_UNIT6
+  ResolveVariableReferencesTask -> RESOLVED_UNIT6
   ResolveVariableReferencesTask -> VARIABLE_REFERENCE_ERRORS
   SCAN_ERRORS -> dartErrorsForSource
   SCAN_ERRORS [shape=box]
@@ -320,6 +337,7 @@
   TYPE_PROVIDER -> PropagateVariableTypeTask
   TYPE_PROVIDER -> ResolveInstanceFieldsInUnitTask
   TYPE_PROVIDER -> ResolveLibraryTypeNamesTask
+  TYPE_PROVIDER -> ResolveTopLevelUnitTypeBoundsTask
   TYPE_PROVIDER -> ResolveUnitTask
   TYPE_PROVIDER -> ResolveUnitTypeNamesTask
   TYPE_PROVIDER -> ResolveVariableReferencesTask
diff --git a/pkg/analyzer/lib/dart/ast/ast.dart b/pkg/analyzer/lib/dart/ast/ast.dart
index 9e5bca2..89be5a5 100644
--- a/pkg/analyzer/lib/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/dart/ast/ast.dart
@@ -125,12 +125,9 @@
    * named constructor. The [arguments] can be `null` if the annotation is not
    * referencing a constructor.
    */
-  factory Annotation(
-      Token atSign,
-      Identifier name,
-      Token period,
-      SimpleIdentifier constructorName,
-      ArgumentList arguments) = AnnotationImpl;
+  factory Annotation(Token atSign, Identifier name, Token period,
+          SimpleIdentifier constructorName, ArgumentList arguments) =>
+      new AnnotationImpl(atSign, name, period, constructorName, arguments);
 
   /**
    * Return the arguments to the constructor being invoked, or `null` if this
@@ -288,8 +285,9 @@
   /**
    * Initialize a newly created as expression.
    */
-  factory AsExpression(Expression expression, Token asOperator, TypeName type) =
-      AsExpressionImpl;
+  factory AsExpression(
+          Expression expression, Token asOperator, TypeName type) =>
+      new AsExpressionImpl(expression, asOperator, type);
 
   /**
    * Return the 'as' operator.
@@ -337,13 +335,15 @@
    * be `null` if there is no message.
    */
   factory AssertStatement(
-      Token assertKeyword,
-      Token leftParenthesis,
-      Expression condition,
-      Token comma,
-      Expression message,
-      Token rightParenthesis,
-      Token semicolon) = AssertStatementImpl;
+          Token assertKeyword,
+          Token leftParenthesis,
+          Expression condition,
+          Token comma,
+          Expression message,
+          Token rightParenthesis,
+          Token semicolon) =>
+      new AssertStatementImpl(assertKeyword, leftParenthesis, condition, comma,
+          message, rightParenthesis, semicolon);
 
   /**
    * Return the token representing the 'assert' keyword.
@@ -433,8 +433,8 @@
    * Initialize a newly created assignment expression.
    */
   factory AssignmentExpression(
-          Expression leftHandSide, Token operator, Expression rightHandSide) =
-      AssignmentExpressionImpl;
+          Expression leftHandSide, Token operator, Expression rightHandSide) =>
+      new AssignmentExpressionImpl(leftHandSide, operator, rightHandSide);
 
   /**
    * Return the best element available for this operator. If resolution was able
@@ -862,8 +862,8 @@
   /**
    * Initialize a newly created await expression.
    */
-  factory AwaitExpression(Token awaitKeyword, Expression expression) =
-      AwaitExpressionImpl;
+  factory AwaitExpression(Token awaitKeyword, Expression expression) =>
+      new AwaitExpressionImpl(awaitKeyword, expression);
 
   /**
    * Return the 'await' keyword.
@@ -899,8 +899,8 @@
    * Initialize a newly created binary expression.
    */
   factory BinaryExpression(
-          Expression leftOperand, Token operator, Expression rightOperand) =
-      BinaryExpressionImpl;
+          Expression leftOperand, Token operator, Expression rightOperand) =>
+      new BinaryExpressionImpl(leftOperand, operator, rightOperand);
 
   /**
    * Return the best element available for this operator. If resolution was able
@@ -985,8 +985,8 @@
    * Initialize a newly created block of code.
    */
   factory Block(
-          Token leftBracket, List<Statement> statements, Token rightBracket) =
-      BlockImpl;
+          Token leftBracket, List<Statement> statements, Token rightBracket) =>
+      new BlockImpl(leftBracket, statements, rightBracket);
 
   /**
    * Return the left curly bracket.
@@ -1029,8 +1029,8 @@
    * for the block. The [star] can be `null` if there is no star following the
    * keyword (and must be `null` if there is no keyword).
    */
-  factory BlockFunctionBody(Token keyword, Token star, Block block) =
-      BlockFunctionBodyImpl;
+  factory BlockFunctionBody(Token keyword, Token star, Block block) =>
+      new BlockFunctionBodyImpl(keyword, star, block);
 
   /**
    * Return the block representing the body of the function.
@@ -1097,8 +1097,8 @@
    * there is no label associated with the statement.
    */
   factory BreakStatement(
-          Token breakKeyword, SimpleIdentifier label, Token semicolon) =
-      BreakStatementImpl;
+          Token breakKeyword, SimpleIdentifier label, Token semicolon) =>
+      new BreakStatementImpl(breakKeyword, label, semicolon);
 
   /**
    * Return the token representing the 'break' keyword.
@@ -1173,8 +1173,8 @@
    * [cascadeSections] must contain at least one element.
    */
   factory CascadeExpression(
-          Expression target, List<Expression> cascadeSections) =
-      CascadeExpressionImpl;
+          Expression target, List<Expression> cascadeSections) =>
+      new CascadeExpressionImpl(target, cascadeSections);
 
   /**
    * Return the cascade sections sharing the common target.
@@ -1212,15 +1212,25 @@
    * parameter is not defined.
    */
   factory CatchClause(
-      Token onKeyword,
-      TypeName exceptionType,
-      Token catchKeyword,
-      Token leftParenthesis,
-      SimpleIdentifier exceptionParameter,
-      Token comma,
-      SimpleIdentifier stackTraceParameter,
-      Token rightParenthesis,
-      Block body) = CatchClauseImpl;
+          Token onKeyword,
+          TypeName exceptionType,
+          Token catchKeyword,
+          Token leftParenthesis,
+          SimpleIdentifier exceptionParameter,
+          Token comma,
+          SimpleIdentifier stackTraceParameter,
+          Token rightParenthesis,
+          Block body) =>
+      new CatchClauseImpl(
+          onKeyword,
+          exceptionType,
+          catchKeyword,
+          leftParenthesis,
+          exceptionParameter,
+          comma,
+          stackTraceParameter,
+          rightParenthesis,
+          body);
 
   /**
    * Return the body of the catch block.
@@ -1346,18 +1356,31 @@
    * not have any members.
    */
   factory ClassDeclaration(
-      Comment comment,
-      List<Annotation> metadata,
-      Token abstractKeyword,
-      Token classKeyword,
-      SimpleIdentifier name,
-      TypeParameterList typeParameters,
-      ExtendsClause extendsClause,
-      WithClause withClause,
-      ImplementsClause implementsClause,
-      Token leftBracket,
-      List<ClassMember> members,
-      Token rightBracket) = ClassDeclarationImpl;
+          Comment comment,
+          List<Annotation> metadata,
+          Token abstractKeyword,
+          Token classKeyword,
+          SimpleIdentifier name,
+          TypeParameterList typeParameters,
+          ExtendsClause extendsClause,
+          WithClause withClause,
+          ImplementsClause implementsClause,
+          Token leftBracket,
+          List<ClassMember> members,
+          Token rightBracket) =>
+      new ClassDeclarationImpl(
+          comment,
+          metadata,
+          abstractKeyword,
+          classKeyword,
+          name,
+          typeParameters,
+          extendsClause,
+          withClause,
+          implementsClause,
+          leftBracket,
+          members,
+          rightBracket);
 
   /**
    * Return the 'abstract' keyword, or `null` if the keyword was absent.
@@ -1515,17 +1538,29 @@
    * if the class does not implement any interfaces.
    */
   factory ClassTypeAlias(
-      Comment comment,
-      List<Annotation> metadata,
-      Token keyword,
-      SimpleIdentifier name,
-      TypeParameterList typeParameters,
-      Token equals,
-      Token abstractKeyword,
-      TypeName superclass,
-      WithClause withClause,
-      ImplementsClause implementsClause,
-      Token semicolon) = ClassTypeAliasImpl;
+          Comment comment,
+          List<Annotation> metadata,
+          Token keyword,
+          SimpleIdentifier name,
+          TypeParameterList typeParameters,
+          Token equals,
+          Token abstractKeyword,
+          TypeName superclass,
+          WithClause withClause,
+          ImplementsClause implementsClause,
+          Token semicolon) =>
+      new ClassTypeAliasImpl(
+          comment,
+          metadata,
+          keyword,
+          name,
+          typeParameters,
+          equals,
+          abstractKeyword,
+          superclass,
+          withClause,
+          implementsClause,
+          semicolon);
 
   /**
    * Return the token for the 'abstract' keyword, or `null` if this is not
@@ -1716,8 +1751,8 @@
    * Initialize a newly created reference to a Dart element. The [newKeyword]
    * can be `null` if the reference is not to a constructor.
    */
-  factory CommentReference(Token newKeyword, Identifier identifier) =
-      CommentReferenceImpl;
+  factory CommentReference(Token newKeyword, Identifier identifier) =>
+      new CommentReferenceImpl(newKeyword, identifier);
 
   /**
    * Return the identifier being referenced.
@@ -1775,11 +1810,13 @@
    * be `null` if there are no declarations in the compilation unit.
    */
   factory CompilationUnit(
-      Token beginToken,
-      ScriptTag scriptTag,
-      List<Directive> directives,
-      List<CompilationUnitMember> declarations,
-      Token endToken) = CompilationUnitImpl;
+          Token beginToken,
+          ScriptTag scriptTag,
+          List<Directive> directives,
+          List<CompilationUnitMember> declarations,
+          Token endToken) =>
+      new CompilationUnitImpl(
+          beginToken, scriptTag, directives, declarations, endToken);
 
   /**
    * Set the first token included in this node's source range to the given
@@ -1872,12 +1909,10 @@
   /**
    * Initialize a newly created conditional expression.
    */
-  factory ConditionalExpression(
-      Expression condition,
-      Token question,
-      Expression thenExpression,
-      Token colon,
-      Expression elseExpression) = ConditionalExpressionImpl;
+  factory ConditionalExpression(Expression condition, Token question,
+          Expression thenExpression, Token colon, Expression elseExpression) =>
+      new ConditionalExpressionImpl(
+          condition, question, thenExpression, colon, elseExpression);
 
   /**
    * Return the token used to separate the then expression from the else
@@ -1958,13 +1993,15 @@
    * Initialize a newly created configuration.
    */
   factory Configuration(
-      Token ifKeyword,
-      Token leftParenthesis,
-      DottedName name,
-      Token equalToken,
-      StringLiteral value,
-      Token rightParenthesis,
-      StringLiteral libraryUri) = ConfigurationImpl;
+          Token ifKeyword,
+          Token leftParenthesis,
+          DottedName name,
+          Token equalToken,
+          StringLiteral value,
+          Token rightParenthesis,
+          StringLiteral libraryUri) =>
+      new ConfigurationImpl(ifKeyword, leftParenthesis, name, equalToken, value,
+          rightParenthesis, libraryUri);
 
   /**
    * Return the token for the equal operator, or `null` if the condition does
@@ -2084,19 +2121,33 @@
    * the constructor does not have a body.
    */
   factory ConstructorDeclaration(
-      Comment comment,
-      List<Annotation> metadata,
-      Token externalKeyword,
-      Token constKeyword,
-      Token factoryKeyword,
-      Identifier returnType,
-      Token period,
-      SimpleIdentifier name,
-      FormalParameterList parameters,
-      Token separator,
-      List<ConstructorInitializer> initializers,
-      ConstructorName redirectedConstructor,
-      FunctionBody body) = ConstructorDeclarationImpl;
+          Comment comment,
+          List<Annotation> metadata,
+          Token externalKeyword,
+          Token constKeyword,
+          Token factoryKeyword,
+          Identifier returnType,
+          Token period,
+          SimpleIdentifier name,
+          FormalParameterList parameters,
+          Token separator,
+          List<ConstructorInitializer> initializers,
+          ConstructorName redirectedConstructor,
+          FunctionBody body) =>
+      new ConstructorDeclarationImpl(
+          comment,
+          metadata,
+          externalKeyword,
+          constKeyword,
+          factoryKeyword,
+          returnType,
+          period,
+          name,
+          parameters,
+          separator,
+          initializers,
+          redirectedConstructor,
+          body);
 
   /**
    * Return the body of the constructor, or `null` if the constructor does not
@@ -2240,12 +2291,10 @@
    * the given name to the value of the given expression. The [thisKeyword] and
    * [period] can be `null` if the 'this' keyword was not specified.
    */
-  factory ConstructorFieldInitializer(
-      Token thisKeyword,
-      Token period,
-      SimpleIdentifier fieldName,
-      Token equals,
-      Expression expression) = ConstructorFieldInitializerImpl;
+  factory ConstructorFieldInitializer(Token thisKeyword, Token period,
+          SimpleIdentifier fieldName, Token equals, Expression expression) =>
+      new ConstructorFieldInitializerImpl(
+          thisKeyword, period, fieldName, equals, expression);
 
   /**
    * Return the token for the equal sign between the field name and the
@@ -2329,8 +2378,8 @@
    * Initialize a newly created constructor name. The [period] and [name] can be
    * `null` if the constructor being named is the unnamed constructor.
    */
-  factory ConstructorName(TypeName type, Token period, SimpleIdentifier name) =
-      ConstructorNameImpl;
+  factory ConstructorName(TypeName type, Token period, SimpleIdentifier name) =>
+      new ConstructorNameImpl(type, period, name);
 
   /**
    * Return the name of the constructor, or `null` if the specified constructor
@@ -2393,8 +2442,8 @@
    * there is no label associated with the statement.
    */
   factory ContinueStatement(
-          Token continueKeyword, SimpleIdentifier label, Token semicolon) =
-      ContinueStatementImpl;
+          Token continueKeyword, SimpleIdentifier label, Token semicolon) =>
+      new ContinueStatementImpl(continueKeyword, label, semicolon);
 
   /**
    * Return the token representing the 'continue' keyword.
@@ -2474,12 +2523,9 @@
    * corresponding attribute. The [keyword] can be `null` if a type name is
    * given. The [type] must be `null` if the keyword is 'var'.
    */
-  factory DeclaredIdentifier(
-      Comment comment,
-      List<Annotation> metadata,
-      Token keyword,
-      TypeName type,
-      SimpleIdentifier identifier) = DeclaredIdentifierImpl;
+  factory DeclaredIdentifier(Comment comment, List<Annotation> metadata,
+          Token keyword, TypeName type, SimpleIdentifier identifier) =>
+      new DeclaredIdentifierImpl(comment, metadata, keyword, type, identifier);
 
   @override
   LocalVariableElement get element;
@@ -2548,11 +2594,9 @@
    * Initialize a newly created default formal parameter. The [separator] and
    * [defaultValue] can be `null` if there is no default value.
    */
-  factory DefaultFormalParameter(
-      NormalFormalParameter parameter,
-      ParameterKind kind,
-      Token separator,
-      Expression defaultValue) = DefaultFormalParameterImpl;
+  factory DefaultFormalParameter(NormalFormalParameter parameter,
+          ParameterKind kind, Token separator, Expression defaultValue) =>
+      new DefaultFormalParameterImpl(parameter, kind, separator, defaultValue);
 
   /**
    * Return the expression computing the default value for the parameter, or
@@ -2639,13 +2683,15 @@
    * Initialize a newly created do loop.
    */
   factory DoStatement(
-      Token doKeyword,
-      Statement body,
-      Token whileKeyword,
-      Token leftParenthesis,
-      Expression condition,
-      Token rightParenthesis,
-      Token semicolon) = DoStatementImpl;
+          Token doKeyword,
+          Statement body,
+          Token whileKeyword,
+          Token leftParenthesis,
+          Expression condition,
+          Token rightParenthesis,
+          Token semicolon) =>
+      new DoStatementImpl(doKeyword, body, whileKeyword, leftParenthesis,
+          condition, rightParenthesis, semicolon);
 
   /**
    * Return the body of the loop.
@@ -2844,8 +2890,8 @@
    * but we allow it for consistency.)
    */
   factory EnumConstantDeclaration(
-          Comment comment, List<Annotation> metadata, SimpleIdentifier name) =
-      EnumConstantDeclarationImpl;
+          Comment comment, List<Annotation> metadata, SimpleIdentifier name) =>
+      new EnumConstantDeclarationImpl(comment, metadata, name);
 
   /**
    * Return the name of the constant.
@@ -2874,13 +2920,15 @@
    * value.
    */
   factory EnumDeclaration(
-      Comment comment,
-      List<Annotation> metadata,
-      Token enumKeyword,
-      SimpleIdentifier name,
-      Token leftBracket,
-      List<EnumConstantDeclaration> constants,
-      Token rightBracket) = EnumDeclarationImpl;
+          Comment comment,
+          List<Annotation> metadata,
+          Token enumKeyword,
+          SimpleIdentifier name,
+          Token leftBracket,
+          List<EnumConstantDeclaration> constants,
+          Token rightBracket) =>
+      new EnumDeclarationImpl(comment, metadata, enumKeyword, name, leftBracket,
+          constants, rightBracket);
 
   /**
    * Return the enumeration constants being declared.
@@ -2937,13 +2985,15 @@
    * are no combinators.
    */
   factory ExportDirective(
-      Comment comment,
-      List<Annotation> metadata,
-      Token keyword,
-      StringLiteral libraryUri,
-      List<Configuration> configurations,
-      List<Combinator> combinators,
-      Token semicolon) = ExportDirectiveImpl;
+          Comment comment,
+          List<Annotation> metadata,
+          Token keyword,
+          StringLiteral libraryUri,
+          List<Configuration> configurations,
+          List<Combinator> combinators,
+          Token semicolon) =>
+      new ExportDirectiveImpl(comment, metadata, keyword, libraryUri,
+          configurations, combinators, semicolon);
 }
 
 /**
@@ -3038,6 +3088,13 @@
    * Set the static type of this expression to the given [type].
    */
   void set staticType(DartType type);
+
+  /**
+   * If this expression is a parenthesized expression, return the result of
+   * unwrapping the expression inside the parentheses. Otherwise, return this
+   * expression.
+   */
+  Expression get unParenthesized;
 }
 
 /**
@@ -3055,7 +3112,9 @@
    * async function body.
    */
   factory ExpressionFunctionBody(Token keyword, Token functionDefinition,
-      Expression expression, Token semicolon) = ExpressionFunctionBodyImpl;
+          Expression expression, Token semicolon) =>
+      new ExpressionFunctionBodyImpl(
+          keyword, functionDefinition, expression, semicolon);
 
   /**
    * Return the expression representing the body of the function.
@@ -3108,8 +3167,8 @@
   /**
    * Initialize a newly created expression statement.
    */
-  factory ExpressionStatement(Expression expression, Token semicolon) =
-      ExpressionStatementImpl;
+  factory ExpressionStatement(Expression expression, Token semicolon) =>
+      new ExpressionStatementImpl(expression, semicolon);
 
   /**
    * Return the expression that comprises the statement.
@@ -3145,8 +3204,8 @@
   /**
    * Initialize a newly created extends clause.
    */
-  factory ExtendsClause(Token extendsKeyword, TypeName superclass) =
-      ExtendsClauseImpl;
+  factory ExtendsClause(Token extendsKeyword, TypeName superclass) =>
+      new ExtendsClauseImpl(extendsKeyword, superclass);
 
   /**
    * Return the token representing the 'extends' keyword.
@@ -3185,11 +3244,13 @@
    * not a static field.
    */
   factory FieldDeclaration(
-      Comment comment,
-      List<Annotation> metadata,
-      Token staticKeyword,
-      VariableDeclarationList fieldList,
-      Token semicolon) = FieldDeclarationImpl;
+          Comment comment,
+          List<Annotation> metadata,
+          Token staticKeyword,
+          VariableDeclarationList fieldList,
+          Token semicolon) =>
+      new FieldDeclarationImpl(
+          comment, metadata, staticKeyword, fieldList, semicolon);
 
   /**
    * Return the fields being declared.
@@ -3248,15 +3309,17 @@
    * parameter.
    */
   factory FieldFormalParameter(
-      Comment comment,
-      List<Annotation> metadata,
-      Token keyword,
-      TypeName type,
-      Token thisKeyword,
-      Token period,
-      SimpleIdentifier identifier,
-      TypeParameterList typeParameters,
-      FormalParameterList parameters) = FieldFormalParameterImpl;
+          Comment comment,
+          List<Annotation> metadata,
+          Token keyword,
+          TypeName type,
+          Token thisKeyword,
+          Token period,
+          SimpleIdentifier identifier,
+          TypeParameterList typeParameters,
+          FormalParameterList parameters) =>
+      new FieldFormalParameterImpl(comment, metadata, keyword, type,
+          thisKeyword, period, identifier, typeParameters, parameters);
 
   /**
    * Return the token representing either the 'final', 'const' or 'var' keyword,
@@ -3344,14 +3407,23 @@
    * `null` if this is not an asynchronous for loop.
    */
   factory ForEachStatement.withDeclaration(
-      Token awaitKeyword,
-      Token forKeyword,
-      Token leftParenthesis,
-      DeclaredIdentifier loopVariable,
-      Token inKeyword,
-      Expression iterator,
-      Token rightParenthesis,
-      Statement body) = ForEachStatementImpl.withDeclaration;
+          Token awaitKeyword,
+          Token forKeyword,
+          Token leftParenthesis,
+          DeclaredIdentifier loopVariable,
+          Token inKeyword,
+          Expression iterator,
+          Token rightParenthesis,
+          Statement body) =>
+      new ForEachStatementImpl.withDeclaration(
+          awaitKeyword,
+          forKeyword,
+          leftParenthesis,
+          loopVariable,
+          inKeyword,
+          iterator,
+          rightParenthesis,
+          body);
 
   /**
    * Initialize a newly created for-each statement whose loop control variable
@@ -3359,14 +3431,23 @@
    * is not an asynchronous for loop.
    */
   factory ForEachStatement.withReference(
-      Token awaitKeyword,
-      Token forKeyword,
-      Token leftParenthesis,
-      SimpleIdentifier identifier,
-      Token inKeyword,
-      Expression iterator,
-      Token rightParenthesis,
-      Statement body) = ForEachStatementImpl.withReference;
+          Token awaitKeyword,
+          Token forKeyword,
+          Token leftParenthesis,
+          SimpleIdentifier identifier,
+          Token inKeyword,
+          Expression iterator,
+          Token rightParenthesis,
+          Statement body) =>
+      new ForEachStatementImpl.withReference(
+          awaitKeyword,
+          forKeyword,
+          leftParenthesis,
+          identifier,
+          inKeyword,
+          iterator,
+          rightParenthesis,
+          body);
 
   /**
    * Return the token representing the 'await' keyword, or `null` if there is no
@@ -3630,16 +3711,27 @@
    * attribute.
    */
   factory ForStatement(
-      Token forKeyword,
-      Token leftParenthesis,
-      VariableDeclarationList variableList,
-      Expression initialization,
-      Token leftSeparator,
-      Expression condition,
-      Token rightSeparator,
-      List<Expression> updaters,
-      Token rightParenthesis,
-      Statement body) = ForStatementImpl;
+          Token forKeyword,
+          Token leftParenthesis,
+          VariableDeclarationList variableList,
+          Expression initialization,
+          Token leftSeparator,
+          Expression condition,
+          Token rightSeparator,
+          List<Expression> updaters,
+          Token rightParenthesis,
+          Statement body) =>
+      new ForStatementImpl(
+          forKeyword,
+          leftParenthesis,
+          variableList,
+          initialization,
+          leftSeparator,
+          condition,
+          rightSeparator,
+          updaters,
+          rightParenthesis,
+          body);
 
   /**
    * Return the body of the loop.
@@ -3830,13 +3922,15 @@
    * function is neither a getter or a setter.
    */
   factory FunctionDeclaration(
-      Comment comment,
-      List<Annotation> metadata,
-      Token externalKeyword,
-      TypeName returnType,
-      Token propertyKeyword,
-      SimpleIdentifier name,
-      FunctionExpression functionExpression) = FunctionDeclarationImpl;
+          Comment comment,
+          List<Annotation> metadata,
+          Token externalKeyword,
+          TypeName returnType,
+          Token propertyKeyword,
+          SimpleIdentifier name,
+          FunctionExpression functionExpression) =>
+      new FunctionDeclarationImpl(comment, metadata, externalKeyword,
+          returnType, propertyKeyword, name, functionExpression);
 
   @override
   ExecutableElement get element;
@@ -3933,10 +4027,9 @@
   /**
    * Initialize a newly created function declaration.
    */
-  factory FunctionExpression(
-      TypeParameterList typeParameters,
-      FormalParameterList parameters,
-      FunctionBody body) = FunctionExpressionImpl;
+  factory FunctionExpression(TypeParameterList typeParameters,
+          FormalParameterList parameters, FunctionBody body) =>
+      new FunctionExpressionImpl(typeParameters, parameters, body);
 
   /**
    * Return the body of the function, or `null` if this is an external function.
@@ -3998,10 +4091,10 @@
   /**
    * Initialize a newly created function expression invocation.
    */
-  factory FunctionExpressionInvocation(
-      Expression function,
-      TypeArgumentList typeArguments,
-      ArgumentList argumentList) = FunctionExpressionInvocationImpl;
+  factory FunctionExpressionInvocation(Expression function,
+          TypeArgumentList typeArguments, ArgumentList argumentList) =>
+      new FunctionExpressionInvocationImpl(
+          function, typeArguments, argumentList);
 
   /**
    * Set the list of arguments to the method to the given [argumentList].
@@ -4120,14 +4213,16 @@
    * type parameters.
    */
   factory FunctionTypeAlias(
-      Comment comment,
-      List<Annotation> metadata,
-      Token keyword,
-      TypeName returnType,
-      SimpleIdentifier name,
-      TypeParameterList typeParameters,
-      FormalParameterList parameters,
-      Token semicolon) = FunctionTypeAliasImpl;
+          Comment comment,
+          List<Annotation> metadata,
+          Token keyword,
+          TypeName returnType,
+          SimpleIdentifier name,
+          TypeParameterList typeParameters,
+          FormalParameterList parameters,
+          Token semicolon) =>
+      new FunctionTypeAliasImpl(comment, metadata, keyword, returnType, name,
+          typeParameters, parameters, semicolon);
 
   /**
    * Return the parameters associated with the function type.
@@ -4181,12 +4276,14 @@
    * was specified.
    */
   factory FunctionTypedFormalParameter(
-      Comment comment,
-      List<Annotation> metadata,
-      TypeName returnType,
-      SimpleIdentifier identifier,
-      TypeParameterList typeParameters,
-      FormalParameterList parameters) = FunctionTypedFormalParameterImpl;
+          Comment comment,
+          List<Annotation> metadata,
+          TypeName returnType,
+          SimpleIdentifier identifier,
+          TypeParameterList typeParameters,
+          FormalParameterList parameters) =>
+      new FunctionTypedFormalParameterImpl(comment, metadata, returnType,
+          identifier, typeParameters, parameters);
 
   /**
    * Return the parameters of the function-typed parameter.
@@ -4308,13 +4405,15 @@
    * [elseStatement] can be `null` if there is no else clause.
    */
   factory IfStatement(
-      Token ifKeyword,
-      Token leftParenthesis,
-      Expression condition,
-      Token rightParenthesis,
-      Statement thenStatement,
-      Token elseKeyword,
-      Statement elseStatement) = IfStatementImpl;
+          Token ifKeyword,
+          Token leftParenthesis,
+          Expression condition,
+          Token rightParenthesis,
+          Statement thenStatement,
+          Token elseKeyword,
+          Statement elseStatement) =>
+      new IfStatementImpl(ifKeyword, leftParenthesis, condition,
+          rightParenthesis, thenStatement, elseKeyword, elseStatement);
 
   /**
    * Return the condition used to determine which of the statements is executed
@@ -4460,8 +4559,8 @@
     //
     SimpleIdentifier prefix1 = import1.prefix;
     SimpleIdentifier prefix2 = import2.prefix;
-    String prefixStr1 = prefix1 != null ? prefix1.name : null;
-    String prefixStr2 = prefix2 != null ? prefix2.name : null;
+    String prefixStr1 = prefix1?.name;
+    String prefixStr2 = prefix2?.name;
     if (prefixStr1 != null || prefixStr2 != null) {
       if (prefixStr1 == null) {
         return -1;
@@ -4537,16 +4636,27 @@
    * are no combinators.
    */
   factory ImportDirective(
-      Comment comment,
-      List<Annotation> metadata,
-      Token keyword,
-      StringLiteral libraryUri,
-      List<Configuration> configurations,
-      Token deferredKeyword,
-      Token asKeyword,
-      SimpleIdentifier prefix,
-      List<Combinator> combinators,
-      Token semicolon) = ImportDirectiveImpl;
+          Comment comment,
+          List<Annotation> metadata,
+          Token keyword,
+          StringLiteral libraryUri,
+          List<Configuration> configurations,
+          Token deferredKeyword,
+          Token asKeyword,
+          SimpleIdentifier prefix,
+          List<Combinator> combinators,
+          Token semicolon) =>
+      new ImportDirectiveImpl(
+          comment,
+          metadata,
+          keyword,
+          libraryUri,
+          configurations,
+          deferredKeyword,
+          asKeyword,
+          prefix,
+          combinators,
+          semicolon);
 
   /**
    * Return the token representing the 'as' keyword, or `null` if the imported
@@ -4595,13 +4705,17 @@
    * Initialize a newly created index expression.
    */
   factory IndexExpression.forCascade(Token period, Token leftBracket,
-      Expression index, Token rightBracket) = IndexExpressionImpl.forCascade;
+          Expression index, Token rightBracket) =>
+      new IndexExpressionImpl.forCascade(
+          period, leftBracket, index, rightBracket);
 
   /**
    * Initialize a newly created index expression.
    */
   factory IndexExpression.forTarget(Expression target, Token leftBracket,
-      Expression index, Token rightBracket) = IndexExpressionImpl.forTarget;
+          Expression index, Token rightBracket) =>
+      new IndexExpressionImpl.forTarget(
+          target, leftBracket, index, rightBracket);
 
   /**
    * Return the auxiliary elements associated with this identifier, or `null` if
@@ -4758,10 +4872,10 @@
   /**
    * Initialize a newly created instance creation expression.
    */
-  factory InstanceCreationExpression(
-      Token keyword,
-      ConstructorName constructorName,
-      ArgumentList argumentList) = InstanceCreationExpressionImpl;
+  factory InstanceCreationExpression(Token keyword,
+          ConstructorName constructorName, ArgumentList argumentList) =>
+      new InstanceCreationExpressionImpl(
+          keyword, constructorName, argumentList);
 
   /**
    * Return the list of arguments to the constructor.
@@ -4883,8 +4997,8 @@
    * Initialize a newly created interpolation expression.
    */
   factory InterpolationExpression(
-          Token leftBracket, Expression expression, Token rightBracket) =
-      InterpolationExpressionImpl;
+          Token leftBracket, Expression expression, Token rightBracket) =>
+      new InterpolationExpressionImpl(leftBracket, expression, rightBracket);
 
   /**
    * Return the expression to be evaluated for the value to be converted into a
@@ -5052,7 +5166,8 @@
    * if the sense of the test is not negated.
    */
   factory IsExpression(Expression expression, Token isOperator,
-      Token notOperator, TypeName type) = IsExpressionImpl;
+          Token notOperator, TypeName type) =>
+      new IsExpressionImpl(expression, isOperator, notOperator, type);
 
   /**
    * Return the expression used to compute the value whose type is being tested.
@@ -5108,7 +5223,8 @@
   /**
    * Initialize a newly created label.
    */
-  factory Label(SimpleIdentifier label, Token colon) = LabelImpl;
+  factory Label(SimpleIdentifier label, Token colon) =>
+      new LabelImpl(label, colon);
 
   /**
    * Return the colon that separates the label from the statement.
@@ -5144,8 +5260,8 @@
   /**
    * Initialize a newly created labeled statement.
    */
-  factory LabeledStatement(List<Label> labels, Statement statement) =
-      LabeledStatementImpl;
+  factory LabeledStatement(List<Label> labels, Statement statement) =>
+      new LabeledStatementImpl(labels, statement);
 
   /**
    * Return the labels being associated with the statement.
@@ -5178,12 +5294,10 @@
    * [comment] and [metadata] can be `null` if the directive does not have the
    * corresponding attribute.
    */
-  factory LibraryDirective(
-      Comment comment,
-      List<Annotation> metadata,
-      Token libraryKeyword,
-      LibraryIdentifier name,
-      Token semicolon) = LibraryDirectiveImpl;
+  factory LibraryDirective(Comment comment, List<Annotation> metadata,
+          Token libraryKeyword, LibraryIdentifier name, Token semicolon) =>
+      new LibraryDirectiveImpl(
+          comment, metadata, libraryKeyword, name, semicolon);
 
   /**
    * Return the token representing the 'library' keyword.
@@ -5361,8 +5475,8 @@
   /**
    * Initialize a newly created map literal entry.
    */
-  factory MapLiteralEntry(Expression key, Token separator, Expression value) =
-      MapLiteralEntryImpl;
+  factory MapLiteralEntry(Expression key, Token separator, Expression value) =>
+      new MapLiteralEntryImpl(key, separator, value);
 
   /**
    * Return the expression computing the key with which the value will be
@@ -5428,17 +5542,29 @@
    * this method declares a getter.
    */
   factory MethodDeclaration(
-      Comment comment,
-      List<Annotation> metadata,
-      Token externalKeyword,
-      Token modifierKeyword,
-      TypeName returnType,
-      Token propertyKeyword,
-      Token operatorKeyword,
-      SimpleIdentifier name,
-      TypeParameterList typeParameters,
-      FormalParameterList parameters,
-      FunctionBody body) = MethodDeclarationImpl;
+          Comment comment,
+          List<Annotation> metadata,
+          Token externalKeyword,
+          Token modifierKeyword,
+          TypeName returnType,
+          Token propertyKeyword,
+          Token operatorKeyword,
+          SimpleIdentifier name,
+          TypeParameterList typeParameters,
+          FormalParameterList parameters,
+          FunctionBody body) =>
+      new MethodDeclarationImpl(
+          comment,
+          metadata,
+          externalKeyword,
+          modifierKeyword,
+          returnType,
+          propertyKeyword,
+          operatorKeyword,
+          name,
+          typeParameters,
+          parameters,
+          body);
 
   /**
    * Return the body of the method.
@@ -5586,11 +5712,13 @@
    * can be `null` if there is no target.
    */
   factory MethodInvocation(
-      Expression target,
-      Token operator,
-      SimpleIdentifier methodName,
-      TypeArgumentList typeArguments,
-      ArgumentList argumentList) = MethodInvocationImpl;
+          Expression target,
+          Token operator,
+          SimpleIdentifier methodName,
+          TypeArgumentList typeArguments,
+          ArgumentList argumentList) =>
+      new MethodInvocationImpl(
+          target, operator, methodName, typeArguments, argumentList);
 
   /**
    * Set the list of arguments to the method to the given [argumentList].
@@ -5727,8 +5855,8 @@
   /**
    * Initialize a newly created named expression..
    */
-  factory NamedExpression(Label name, Expression expression) =
-      NamedExpressionImpl;
+  factory NamedExpression(Label name, Expression expression) =>
+      new NamedExpressionImpl(name, expression);
 
   /**
    * Return the element representing the parameter being named by this
@@ -5809,8 +5937,8 @@
   /**
    * Initialize a newly created native clause.
    */
-  factory NativeClause(Token nativeKeyword, StringLiteral name) =
-      NativeClauseImpl;
+  factory NativeClause(Token nativeKeyword, StringLiteral name) =>
+      new NativeClauseImpl(nativeKeyword, name);
 
   /**
    * Return the name of the native object that implements the class.
@@ -5849,8 +5977,8 @@
    * a string literal, and a semicolon.
    */
   factory NativeFunctionBody(
-          Token nativeKeyword, StringLiteral stringLiteral, Token semicolon) =
-      NativeFunctionBodyImpl;
+          Token nativeKeyword, StringLiteral stringLiteral, Token semicolon) =>
+      new NativeFunctionBodyImpl(nativeKeyword, stringLiteral, semicolon);
 
   /**
    * Return the token representing 'native' that marks the start of the function
@@ -6024,7 +6152,9 @@
    * Initialize a newly created parenthesized expression.
    */
   factory ParenthesizedExpression(Token leftParenthesis, Expression expression,
-      Token rightParenthesis) = ParenthesizedExpressionImpl;
+          Token rightParenthesis) =>
+      new ParenthesizedExpressionImpl(
+          leftParenthesis, expression, rightParenthesis);
 
   /**
    * Return the expression within the parentheses.
@@ -6114,12 +6244,14 @@
    * corresponding attribute.
    */
   factory PartOfDirective(
-      Comment comment,
-      List<Annotation> metadata,
-      Token partKeyword,
-      Token ofKeyword,
-      LibraryIdentifier libraryName,
-      Token semicolon) = PartOfDirectiveImpl;
+          Comment comment,
+          List<Annotation> metadata,
+          Token partKeyword,
+          Token ofKeyword,
+          LibraryIdentifier libraryName,
+          Token semicolon) =>
+      new PartOfDirectiveImpl(
+          comment, metadata, partKeyword, ofKeyword, libraryName, semicolon);
 
   /**
    * Return the name of the library that the containing compilation unit is part
@@ -6176,8 +6308,8 @@
   /**
    * Initialize a newly created postfix expression.
    */
-  factory PostfixExpression(Expression operand, Token operator) =
-      PostfixExpressionImpl;
+  factory PostfixExpression(Expression operand, Token operator) =>
+      new PostfixExpressionImpl(operand, operator);
 
   /**
    * Return the best element available for this operator. If resolution was able
@@ -6251,8 +6383,8 @@
    * Initialize a newly created prefixed identifier.
    */
   factory PrefixedIdentifier(
-          SimpleIdentifier prefix, Token period, SimpleIdentifier identifier) =
-      PrefixedIdentifierImpl;
+          SimpleIdentifier prefix, Token period, SimpleIdentifier identifier) =>
+      new PrefixedIdentifierImpl(prefix, period, identifier);
 
   /**
    * Return the identifier being prefixed.
@@ -6309,8 +6441,8 @@
   /**
    * Initialize a newly created prefix expression.
    */
-  factory PrefixExpression(Token operator, Expression operand) =
-      PrefixExpressionImpl;
+  factory PrefixExpression(Token operator, Expression operand) =>
+      new PrefixExpressionImpl(operator, operand);
 
   /**
    * Return the best element available for this operator. If resolution was able
@@ -6387,8 +6519,8 @@
    * Initialize a newly created property access expression.
    */
   factory PropertyAccess(
-          Expression target, Token operator, SimpleIdentifier propertyName) =
-      PropertyAccessImpl;
+          Expression target, Token operator, SimpleIdentifier propertyName) =>
+      new PropertyAccessImpl(target, operator, propertyName);
 
   /**
    * Return `true` if this expression is cascaded. If it is, then the target of
@@ -6456,11 +6588,10 @@
    * with the given name with the given arguments. The [constructorName] can be
    * `null` if the constructor being invoked is the unnamed constructor.
    */
-  factory RedirectingConstructorInvocation(
-      Token thisKeyword,
-      Token period,
-      SimpleIdentifier constructorName,
-      ArgumentList argumentList) = RedirectingConstructorInvocationImpl;
+  factory RedirectingConstructorInvocation(Token thisKeyword, Token period,
+          SimpleIdentifier constructorName, ArgumentList argumentList) =>
+      new RedirectingConstructorInvocationImpl(
+          thisKeyword, period, constructorName, argumentList);
 
   /**
    * Return the list of arguments to the constructor.
@@ -6559,8 +6690,8 @@
    * if no explicit value was provided.
    */
   factory ReturnStatement(
-          Token returnKeyword, Expression expression, Token semicolon) =
-      ReturnStatementImpl;
+          Token returnKeyword, Expression expression, Token semicolon) =>
+      new ReturnStatementImpl(returnKeyword, expression, semicolon);
 
   /**
    * Return the expression computing the value to be returned, or `null` if no
@@ -6657,12 +6788,10 @@
    * corresponding attribute. The [keyword] can be `null` if a type was
    * specified. The [type] must be `null` if the keyword is 'var'.
    */
-  factory SimpleFormalParameter(
-      Comment comment,
-      List<Annotation> metadata,
-      Token keyword,
-      TypeName type,
-      SimpleIdentifier identifier) = SimpleFormalParameterImpl;
+  factory SimpleFormalParameter(Comment comment, List<Annotation> metadata,
+          Token keyword, TypeName type, SimpleIdentifier identifier) =>
+      new SimpleFormalParameterImpl(
+          comment, metadata, keyword, type, identifier);
 
   /**
    * Return the token representing either the 'final', 'const' or 'var' keyword,
@@ -6958,11 +7087,10 @@
    * [constructorName] can be `null` if the constructor being invoked is the
    * unnamed constructor.
    */
-  factory SuperConstructorInvocation(
-      Token superKeyword,
-      Token period,
-      SimpleIdentifier constructorName,
-      ArgumentList argumentList) = SuperConstructorInvocationImpl;
+  factory SuperConstructorInvocation(Token superKeyword, Token period,
+          SimpleIdentifier constructorName, ArgumentList argumentList) =>
+      new SuperConstructorInvocationImpl(
+          superKeyword, period, constructorName, argumentList);
 
   /**
    * Return the list of arguments to the constructor.
@@ -7061,7 +7189,8 @@
    * if there are no labels.
    */
   factory SwitchCase(List<Label> labels, Token keyword, Expression expression,
-      Token colon, List<Statement> statements) = SwitchCaseImpl;
+          Token colon, List<Statement> statements) =>
+      new SwitchCaseImpl(labels, keyword, expression, colon, statements);
 
   /**
    * Return the expression controlling whether the statements will be executed.
@@ -7151,13 +7280,15 @@
    * `null` if there are no switch members.
    */
   factory SwitchStatement(
-      Token switchKeyword,
-      Token leftParenthesis,
-      Expression expression,
-      Token rightParenthesis,
-      Token leftBracket,
-      List<SwitchMember> members,
-      Token rightBracket) = SwitchStatementImpl;
+          Token switchKeyword,
+          Token leftParenthesis,
+          Expression expression,
+          Token rightParenthesis,
+          Token leftBracket,
+          List<SwitchMember> members,
+          Token rightBracket) =>
+      new SwitchStatementImpl(switchKeyword, leftParenthesis, expression,
+          rightParenthesis, leftBracket, members, rightBracket);
 
   /**
    * Return the expression used to determine which of the switch members will be
@@ -7295,8 +7426,8 @@
   /**
    * Initialize a newly created throw expression.
    */
-  factory ThrowExpression(Token throwKeyword, Expression expression) =
-      ThrowExpressionImpl;
+  factory ThrowExpression(Token throwKeyword, Expression expression) =>
+      new ThrowExpressionImpl(throwKeyword, expression);
 
   /**
    * Return the expression computing the exception to be thrown.
@@ -7336,10 +7467,12 @@
    * the corresponding attribute.
    */
   factory TopLevelVariableDeclaration(
-      Comment comment,
-      List<Annotation> metadata,
-      VariableDeclarationList variableList,
-      Token semicolon) = TopLevelVariableDeclarationImpl;
+          Comment comment,
+          List<Annotation> metadata,
+          VariableDeclarationList variableList,
+          Token semicolon) =>
+      new TopLevelVariableDeclarationImpl(
+          comment, metadata, variableList, semicolon);
 
   /**
    * Return the semicolon terminating the declaration.
@@ -7381,11 +7514,13 @@
    * [finallyBlock] can be `null` if there is no finally clause.
    */
   factory TryStatement(
-      Token tryKeyword,
-      Block body,
-      List<CatchClause> catchClauses,
-      Token finallyKeyword,
-      Block finallyBlock) = TryStatementImpl;
+          Token tryKeyword,
+          Block body,
+          List<CatchClause> catchClauses,
+          Token finallyKeyword,
+          Block finallyBlock) =>
+      new TryStatementImpl(
+          tryKeyword, body, catchClauses, finallyKeyword, finallyBlock);
 
   /**
    * Return the body of the statement.
@@ -7558,8 +7693,8 @@
    * Initialize a newly created type name. The [typeArguments] can be `null` if
    * there are no type arguments.
    */
-  factory TypeName(Identifier name, TypeArgumentList typeArguments) =
-      TypeNameImpl;
+  factory TypeName(Identifier name, TypeArgumentList typeArguments) =>
+      new TypeNameImpl(name, typeArguments);
 
   /**
    * Return `true` if this type is a deferred type.
@@ -7618,12 +7753,9 @@
    * corresponding attribute. The [extendsKeyword] and [bound] can be `null` if
    * the parameter does not have an upper bound.
    */
-  factory TypeParameter(
-      Comment comment,
-      List<Annotation> metadata,
-      SimpleIdentifier name,
-      Token extendsKeyword,
-      TypeName bound) = TypeParameterImpl;
+  factory TypeParameter(Comment comment, List<Annotation> metadata,
+          SimpleIdentifier name, Token extendsKeyword, TypeName bound) =>
+      new TypeParameterImpl(comment, metadata, name, extendsKeyword, bound);
 
   /**
    * Return the name of the upper bound for legal arguments, or `null` if there
@@ -7784,8 +7916,8 @@
    * [initializer] can be `null` if there is no initializer.
    */
   factory VariableDeclaration(
-          SimpleIdentifier name, Token equals, Expression initializer) =
-      VariableDeclarationImpl;
+          SimpleIdentifier name, Token equals, Expression initializer) =>
+      new VariableDeclarationImpl(name, equals, initializer);
 
   @override
   VariableElement get element;
@@ -7858,12 +7990,10 @@
    * the corresponding attribute. The [keyword] can be `null` if a type was
    * specified. The [type] must be `null` if the keyword is 'var'.
    */
-  factory VariableDeclarationList(
-      Comment comment,
-      List<Annotation> metadata,
-      Token keyword,
-      TypeName type,
-      List<VariableDeclaration> variables) = VariableDeclarationListImpl;
+  factory VariableDeclarationList(Comment comment, List<Annotation> metadata,
+          Token keyword, TypeName type, List<VariableDeclaration> variables) =>
+      new VariableDeclarationListImpl(
+          comment, metadata, keyword, type, variables);
 
   /**
    * Return `true` if the variables in this list were declared with the 'const'
@@ -7922,8 +8052,8 @@
    * Initialize a newly created variable declaration statement.
    */
   factory VariableDeclarationStatement(
-          VariableDeclarationList variableList, Token semicolon) =
-      VariableDeclarationStatementImpl;
+          VariableDeclarationList variableList, Token semicolon) =>
+      new VariableDeclarationStatementImpl(variableList, semicolon);
 
   /**
    * Return the semicolon terminating the statement.
@@ -7958,12 +8088,10 @@
   /**
    * Initialize a newly created while statement.
    */
-  factory WhileStatement(
-      Token whileKeyword,
-      Token leftParenthesis,
-      Expression condition,
-      Token rightParenthesis,
-      Statement body) = WhileStatementImpl;
+  factory WhileStatement(Token whileKeyword, Token leftParenthesis,
+          Expression condition, Token rightParenthesis, Statement body) =>
+      new WhileStatementImpl(
+          whileKeyword, leftParenthesis, condition, rightParenthesis, body);
 
   /**
    * Return the body of the loop.
@@ -8063,7 +8191,8 @@
    * star was provided.
    */
   factory YieldStatement(Token yieldKeyword, Token star, Expression expression,
-      Token semicolon) = YieldStatementImpl;
+          Token semicolon) =>
+      new YieldStatementImpl(yieldKeyword, star, expression, semicolon);
 
   /**
    * Return the expression whose value will be yielded.
diff --git a/pkg/analyzer/lib/file_system/file_system.dart b/pkg/analyzer/lib/file_system/file_system.dart
index ba2bf4b..b841a36 100644
--- a/pkg/analyzer/lib/file_system/file_system.dart
+++ b/pkg/analyzer/lib/file_system/file_system.dart
@@ -218,7 +218,7 @@
     Resource resource =
         _provider.getResource(_provider.pathContext.fromUri(uri));
     if (resource is File) {
-      return resource.createSource(actualUri != null ? actualUri : uri);
+      return resource.createSource(actualUri ?? uri);
     }
     return null;
   }
diff --git a/pkg/analyzer/lib/file_system/memory_file_system.dart b/pkg/analyzer/lib/file_system/memory_file_system.dart
index 5035b93..3ec640e 100644
--- a/pkg/analyzer/lib/file_system/memory_file_system.dart
+++ b/pkg/analyzer/lib/file_system/memory_file_system.dart
@@ -188,7 +188,7 @@
     _MemoryFile file = new _MemoryFile(this, path);
     _pathToResource[path] = file;
     _pathToContent[path] = content;
-    _pathToTimestamp[path] = stamp != null ? stamp : nextStamp++;
+    _pathToTimestamp[path] = stamp ?? nextStamp++;
     _notifyWatchers(path, ChangeType.MODIFY);
     return file;
   }
diff --git a/pkg/analyzer/lib/plugin/resolver_provider.dart b/pkg/analyzer/lib/plugin/resolver_provider.dart
index ed0e366..33bb366 100644
--- a/pkg/analyzer/lib/plugin/resolver_provider.dart
+++ b/pkg/analyzer/lib/plugin/resolver_provider.dart
@@ -11,8 +11,5 @@
  * A function that will return a [UriResolver] that can be used to resolve a
  * specific kind of URI within the analysis context rooted at the given
  * [folder].
- *
- * The given [folder] may be `null` if analysis is performed in an environment
- * where URI resolution is always the same in any folder.
  */
 typedef UriResolver ResolverProvider(Folder folder);
diff --git a/pkg/analyzer/lib/source/analysis_options_provider.dart b/pkg/analyzer/lib/source/analysis_options_provider.dart
index 600dffc..3b6e330 100644
--- a/pkg/analyzer/lib/source/analysis_options_provider.dart
+++ b/pkg/analyzer/lib/source/analysis_options_provider.dart
@@ -73,7 +73,7 @@
           throw new OptionsFormatException(
               'Bad options file format (expected String scope key, '
               'got ${k.runtimeType})',
-              k != null ? k.span : doc.span);
+              (k ?? doc).span);
         }
         if (v != null && v is! YamlNode) {
           throw new OptionsFormatException(
diff --git a/pkg/analyzer/lib/source/config.dart b/pkg/analyzer/lib/source/config.dart
new file mode 100644
index 0000000..376c189
--- /dev/null
+++ b/pkg/analyzer/lib/source/config.dart
@@ -0,0 +1,107 @@
+// 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/file_system/file_system.dart';
+import 'package:analyzer/source/analysis_options_provider.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/task/model.dart';
+import 'package:analyzer/task/model.dart';
+import 'package:package_config/packages.dart';
+import 'package:yaml/src/yaml_node.dart';
+import 'package:yaml/yaml.dart';
+
+/// The descriptor used to associate analysis configuration with analysis
+/// contexts in configuration data.
+final ResultDescriptor<AnalysisConfiguration> ANALYSIS_CONFIGURATION =
+    new ResultDescriptorImpl('analysis.config', null);
+
+/// Return configuration associated with this [context], or `null` if there is
+/// none.
+AnalysisConfiguration getConfiguration(AnalysisContext context) =>
+    context.getConfigurationData(ANALYSIS_CONFIGURATION)
+    as AnalysisConfiguration;
+
+/// Associate this [config] with the given [context].
+void setConfiguration(AnalysisContext context, AnalysisConfiguration config) {
+  context.setConfigurationData(ANALYSIS_CONFIGURATION, config);
+}
+
+/// Analysis configuration.
+abstract class AnalysisConfiguration {
+  final AnalysisOptionsProvider optionsProvider = new AnalysisOptionsProvider();
+  final Packages packages;
+  final ResourceProvider resourceProvider;
+  AnalysisConfiguration(this.resourceProvider, this.packages);
+
+  factory AnalysisConfiguration.fromPubspec(
+          File pubspec, ResourceProvider resourceProvider, Packages packages) =>
+      new PubspecConfiguration(pubspec, resourceProvider, packages);
+
+  /// Get a map of options defined by this configuration (or `null` if none
+  /// are specified).
+  Map get options;
+}
+
+/// Describes an analysis configuration.
+class AnalysisConfigurationDescriptor {
+  /// The name of the package hosting the configuration.
+  String package;
+  /// The name of the configuration "pragma".
+  String pragma;
+
+  AnalysisConfigurationDescriptor.fromAnalyzerOptions(Map analyzerOptions) {
+    Object config = analyzerOptions['configuration'];
+    if (config is String) {
+      List<String> items = config.split('/');
+      if (items.length == 2) {
+        package = items[0].trim();
+        pragma = items[1].trim();
+      }
+    }
+  }
+
+  /// Return true if this descriptor is valid.
+  bool get isValid => package != null && pragma != null;
+}
+
+/// Pubspec-specified analysis configuration.
+class PubspecConfiguration extends AnalysisConfiguration {
+  final File pubspec;
+  PubspecConfiguration(
+      this.pubspec, ResourceProvider resourceProvider, Packages packages)
+      : super(resourceProvider, packages);
+
+  @override
+  Map get options {
+    //Safest not to cache (requested infrequently).
+    if (pubspec.exists) {
+      try {
+        String contents = pubspec.readAsStringSync();
+        YamlNode map = loadYamlNode(contents);
+        if (map is YamlMap) {
+          YamlNode config = map['analyzer'];
+          if (config is YamlMap) {
+            AnalysisConfigurationDescriptor descriptor =
+                new AnalysisConfigurationDescriptor.fromAnalyzerOptions(config);
+
+            if (descriptor.isValid) {
+              //Create a path, given descriptor and packagemap
+              Uri uri = packages.asMap()[descriptor.package];
+              Uri pragma = new Uri.file('config/${descriptor.pragma}.yaml',
+                  windows: false);
+              Uri optionsUri = uri.resolveUri(pragma);
+              File file = resourceProvider.getFile(optionsUri.toFilePath());
+              if (file.exists) {
+                return optionsProvider.getOptionsFromFile(file);
+              }
+            }
+          }
+        }
+      } catch (_) {
+        // Skip exceptional configurations.
+      }
+    }
+    return null;
+  }
+}
diff --git a/pkg/analyzer/lib/source/path_filter.dart b/pkg/analyzer/lib/source/path_filter.dart
index 816bc55..c207014 100644
--- a/pkg/analyzer/lib/source/path_filter.dart
+++ b/pkg/analyzer/lib/source/path_filter.dart
@@ -22,7 +22,7 @@
   /// Construct a new path filter rooted at [root] with [ignorePatterns].
   /// If [pathContext] is not specified, then the system path context is used.
   PathFilter(this.root, List<String> ignorePatterns, [path.Context pathContext])
-      : this.pathContext = pathContext != null ? pathContext : path.context {
+      : this.pathContext = pathContext ?? path.context {
     setIgnorePatterns(ignorePatterns);
   }
 
diff --git a/pkg/analyzer/lib/src/context/cache.dart b/pkg/analyzer/lib/src/context/cache.dart
index 7e6e0a0..c5641a9 100644
--- a/pkg/analyzer/lib/src/context/cache.dart
+++ b/pkg/analyzer/lib/src/context/cache.dart
@@ -514,7 +514,7 @@
     ResultData data = getResultData(descriptor);
     _setDependedOnResults(data, thisResult, dependedOn);
     data.state = CacheState.VALID;
-    data.value = value == null ? descriptor.defaultValue : value;
+    data.value = value ?? descriptor.defaultValue;
   }
 
   /**
@@ -922,7 +922,7 @@
    */
   List<Source> getSourcesWithFullName(String path) {
     List<Source> sources = pathToSource[path];
-    return sources != null ? sources : Source.EMPTY_LIST;
+    return sources ?? Source.EMPTY_LIST;
   }
 
   /**
diff --git a/pkg/analyzer/lib/src/context/context.dart b/pkg/analyzer/lib/src/context/context.dart
index 7815864..7540c0f 100644
--- a/pkg/analyzer/lib/src/context/context.dart
+++ b/pkg/analyzer/lib/src/context/context.dart
@@ -843,10 +843,8 @@
   }
 
   @override
-  InternalAnalysisContext getContextFor(Source source) {
-    InternalAnalysisContext context = _cache.getContextFor(source);
-    return context == null ? this : context;
-  }
+  InternalAnalysisContext getContextFor(Source source) =>
+      _cache.getContextFor(source) ?? this;
 
   @override
   Element getElement(ElementLocation location) {
@@ -1205,10 +1203,12 @@
       setValue(LIBRARY_ELEMENT6, library);
       setValue(LIBRARY_ELEMENT7, library);
       setValue(LIBRARY_ELEMENT8, library);
+      setValue(LIBRARY_ELEMENT9, library);
       setValue(LINE_INFO, new LineInfo(<int>[0]));
       setValue(PARSE_ERRORS, AnalysisError.NO_ERRORS);
       entry.setState(PARSED_UNIT, CacheState.FLUSHED);
       entry.setState(RESOLVE_TYPE_NAMES_ERRORS, CacheState.FLUSHED);
+      entry.setState(RESOLVE_TYPE_BOUNDS_ERRORS, CacheState.FLUSHED);
       setValue(SCAN_ERRORS, AnalysisError.NO_ERRORS);
       setValue(SOURCE_KIND, SourceKind.LIBRARY);
       entry.setState(TOKEN_STREAM, CacheState.FLUSHED);
@@ -1235,6 +1235,7 @@
       entry.setState(RESOLVED_UNIT10, CacheState.FLUSHED);
       entry.setState(RESOLVED_UNIT11, CacheState.FLUSHED);
       entry.setState(RESOLVED_UNIT12, CacheState.FLUSHED);
+      entry.setState(RESOLVED_UNIT13, CacheState.FLUSHED);
       // USED_IMPORTED_ELEMENTS
       // USED_LOCAL_ELEMENTS
       setValue(STRONG_MODE_ERRORS, AnalysisError.NO_ERRORS);
@@ -1314,6 +1315,7 @@
     entry.setState(RESOLVED_UNIT10, CacheState.FLUSHED);
     entry.setState(RESOLVED_UNIT11, CacheState.FLUSHED);
     entry.setState(RESOLVED_UNIT12, CacheState.FLUSHED);
+    entry.setState(RESOLVED_UNIT13, CacheState.FLUSHED);
     entry.setState(RESOLVED_UNIT, CacheState.FLUSHED);
   }
 
@@ -1549,12 +1551,12 @@
         new LibrarySpecificUnit(librarySource, unitSource);
     for (ResultDescriptor result in [
       RESOLVED_UNIT,
+      RESOLVED_UNIT13,
       RESOLVED_UNIT12,
       RESOLVED_UNIT11,
       RESOLVED_UNIT10,
       RESOLVED_UNIT9,
-      RESOLVED_UNIT8,
-      RESOLVED_UNIT7
+      RESOLVED_UNIT8
     ]) {
       CompilationUnit unit = getResult(target, result);
       if (unit != null) {
@@ -1790,6 +1792,7 @@
       entry.explicitlyAdded = true;
       entry.modificationTime = getModificationStamp(source);
       entry.setState(CONTENT, CacheState.INVALID);
+      entry.setState(MODIFICATION_TIME, CacheState.INVALID);
     }
   }
 
diff --git a/pkg/analyzer/lib/src/context/source.dart b/pkg/analyzer/lib/src/context/source.dart
index 3a22291..32792df 100644
--- a/pkg/analyzer/lib/src/context/source.dart
+++ b/pkg/analyzer/lib/src/context/source.dart
@@ -53,9 +53,8 @@
    */
   SourceFactoryImpl(this.resolvers,
       [this._packages, ResourceProvider resourceProvider])
-      : _resourceProvider = resourceProvider != null
-            ? resourceProvider
-            : PhysicalResourceProvider.INSTANCE;
+      : _resourceProvider =
+            resourceProvider ?? PhysicalResourceProvider.INSTANCE;
 
   /**
    * Return the [DartSdk] associated with this [SourceFactory], or `null` if
@@ -105,7 +104,7 @@
     // Default to the PackageMapUriResolver.
     PackageMapUriResolver resolver = resolvers
         .firstWhere((r) => r is PackageMapUriResolver, orElse: () => null);
-    return resolver != null ? resolver.packageMap : null;
+    return resolver?.packageMap;
   }
 
   /**
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index 2825ef5..ad6c9c8 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -43,7 +43,7 @@
    * valid, the list of [strings] must contain at least two elements.
    */
   AdjacentStringsImpl(List<StringLiteral> strings) {
-    _strings = new NodeList<StringLiteral>(this, strings);
+    _strings = new NodeListImpl<StringLiteral>(this, strings);
   }
 
   @override
@@ -96,9 +96,9 @@
    * and [metadata] can be `null` if the node does not have the corresponding
    * attribute.
    */
-  AnnotatedNodeImpl(Comment comment, List<Annotation> metadata) {
+  AnnotatedNodeImpl(CommentImpl comment, List<Annotation> metadata) {
     _comment = _becomeParentOf(comment);
-    _metadata = new NodeList<Annotation>(this, metadata);
+    _metadata = new NodeListImpl<Annotation>(this, metadata);
   }
 
   @override
@@ -124,7 +124,7 @@
 
   @override
   void set documentationComment(Comment comment) {
-    _comment = _becomeParentOf(comment);
+    _comment = _becomeParentOf(comment as AstNodeImpl);
   }
 
   @override
@@ -238,8 +238,8 @@
    * named constructor. The [arguments] can be `null` if the annotation is not
    * referencing a constructor.
    */
-  AnnotationImpl(this.atSign, Identifier name, this.period,
-      SimpleIdentifier constructorName, ArgumentList arguments) {
+  AnnotationImpl(this.atSign, IdentifierImpl name, this.period,
+      SimpleIdentifierImpl constructorName, ArgumentListImpl arguments) {
     _name = _becomeParentOf(name);
     _constructorName = _becomeParentOf(constructorName);
     _arguments = _becomeParentOf(arguments);
@@ -250,7 +250,7 @@
 
   @override
   void set arguments(ArgumentList arguments) {
-    _arguments = _becomeParentOf(arguments);
+    _arguments = _becomeParentOf(arguments as AstNodeImpl);
   }
 
   @override
@@ -269,7 +269,7 @@
 
   @override
   void set constructorName(SimpleIdentifier name) {
-    _constructorName = _becomeParentOf(name);
+    _constructorName = _becomeParentOf(name as AstNodeImpl);
   }
 
   @override
@@ -302,7 +302,7 @@
 
   @override
   void set name(Identifier name) {
-    _name = _becomeParentOf(name);
+    _name = _becomeParentOf(name as AstNodeImpl);
   }
 
   @override
@@ -372,7 +372,7 @@
    */
   ArgumentListImpl(
       this.leftParenthesis, List<Expression> arguments, this.rightParenthesis) {
-    _arguments = new NodeList<Expression>(this, arguments);
+    _arguments = new NodeListImpl<Expression>(this, arguments);
   }
 
   @override
@@ -499,7 +499,8 @@
   /**
    * Initialize a newly created as expression.
    */
-  AsExpressionImpl(Expression expression, this.asOperator, TypeName type) {
+  AsExpressionImpl(
+      ExpressionImpl expression, this.asOperator, TypeNameImpl type) {
     _expression = _becomeParentOf(expression);
     _type = _becomeParentOf(type);
   }
@@ -519,7 +520,7 @@
 
   @override
   void set expression(Expression expression) {
-    _expression = _becomeParentOf(expression);
+    _expression = _becomeParentOf(expression as AstNodeImpl);
   }
 
   @override
@@ -530,7 +531,7 @@
 
   @override
   void set type(TypeName name) {
-    _type = _becomeParentOf(name);
+    _type = _becomeParentOf(name as AstNodeImpl);
   }
 
   @override
@@ -598,9 +599,9 @@
   AssertStatementImpl(
       this.assertKeyword,
       this.leftParenthesis,
-      Expression condition,
+      ExpressionImpl condition,
       this.comma,
-      Expression message,
+      ExpressionImpl message,
       this.rightParenthesis,
       this.semicolon) {
     _condition = _becomeParentOf(condition);
@@ -625,7 +626,7 @@
 
   @override
   void set condition(Expression condition) {
-    _condition = _becomeParentOf(condition);
+    _condition = _becomeParentOf(condition as AstNodeImpl);
   }
 
   @override
@@ -636,7 +637,7 @@
 
   @override
   void set message(Expression expression) {
-    _message = _becomeParentOf(expression);
+    _message = _becomeParentOf(expression as AstNodeImpl);
   }
 
   @override
@@ -695,8 +696,8 @@
   /**
    * Initialize a newly created assignment expression.
    */
-  AssignmentExpressionImpl(
-      Expression leftHandSide, this.operator, Expression rightHandSide) {
+  AssignmentExpressionImpl(ExpressionImpl leftHandSide, this.operator,
+      ExpressionImpl rightHandSide) {
     if (leftHandSide == null || rightHandSide == null) {
       String message;
       if (leftHandSide == null) {
@@ -741,7 +742,7 @@
 
   @override
   void set leftHandSide(Expression expression) {
-    _leftHandSide = _becomeParentOf(expression);
+    _leftHandSide = _becomeParentOf(expression as AstNodeImpl);
   }
 
   @override
@@ -752,7 +753,7 @@
 
   @override
   void set rightHandSide(Expression expression) {
-    _rightHandSide = _becomeParentOf(expression);
+    _rightHandSide = _becomeParentOf(expression as AstNodeImpl);
   }
 
   /**
@@ -937,9 +938,9 @@
   /**
    * Make this node the parent of the given [child] node. Return the child node.
    */
-  AstNode _becomeParentOf(AstNode child) {
+  AstNode _becomeParentOf(AstNodeImpl child) {
     if (child != null) {
-      (child as AstNodeImpl)._parent = this;
+      child._parent = this;
     }
     return child;
   }
@@ -966,7 +967,7 @@
   /**
    * Initialize a newly created await expression.
    */
-  AwaitExpressionImpl(this.awaitKeyword, Expression expression) {
+  AwaitExpressionImpl(this.awaitKeyword, ExpressionImpl expression) {
     _expression = _becomeParentOf(expression);
   }
 
@@ -990,7 +991,7 @@
 
   @override
   void set expression(Expression expression) {
-    _expression = _becomeParentOf(expression);
+    _expression = _becomeParentOf(expression as AstNodeImpl);
   }
 
   @override
@@ -1050,7 +1051,7 @@
    * Initialize a newly created binary expression.
    */
   BinaryExpressionImpl(
-      Expression leftOperand, this.operator, Expression rightOperand) {
+      ExpressionImpl leftOperand, this.operator, ExpressionImpl rightOperand) {
     _leftOperand = _becomeParentOf(leftOperand);
     _rightOperand = _becomeParentOf(rightOperand);
   }
@@ -1079,7 +1080,7 @@
 
   @override
   void set leftOperand(Expression expression) {
-    _leftOperand = _becomeParentOf(expression);
+    _leftOperand = _becomeParentOf(expression as AstNodeImpl);
   }
 
   @override
@@ -1090,7 +1091,7 @@
 
   @override
   void set rightOperand(Expression expression) {
-    _rightOperand = _becomeParentOf(expression);
+    _rightOperand = _becomeParentOf(expression as AstNodeImpl);
   }
 
   /**
@@ -1171,7 +1172,7 @@
    * for the block. The [star] can be `null` if there is no star following the
    * keyword (and must be `null` if there is no keyword).
    */
-  BlockFunctionBodyImpl(this.keyword, this.star, Block block) {
+  BlockFunctionBodyImpl(this.keyword, this.star, BlockImpl block) {
     _block = _becomeParentOf(block);
   }
 
@@ -1188,7 +1189,7 @@
 
   @override
   void set block(Block block) {
-    _block = _becomeParentOf(block);
+    _block = _becomeParentOf(block as AstNodeImpl);
   }
 
   @override
@@ -1245,7 +1246,7 @@
    * Initialize a newly created block of code.
    */
   BlockImpl(this.leftBracket, List<Statement> statements, this.rightBracket) {
-    _statements = new NodeList<Statement>(this, statements);
+    _statements = new NodeListImpl<Statement>(this, statements);
   }
 
   @override
@@ -1360,7 +1361,7 @@
    * there is no label associated with the statement.
    */
   BreakStatementImpl(
-      this.breakKeyword, SimpleIdentifier label, this.semicolon) {
+      this.breakKeyword, SimpleIdentifierImpl label, this.semicolon) {
     _label = _becomeParentOf(label);
   }
 
@@ -1379,7 +1380,7 @@
 
   @override
   void set label(SimpleIdentifier identifier) {
-    _label = _becomeParentOf(identifier);
+    _label = _becomeParentOf(identifier as AstNodeImpl);
   }
 
   @override
@@ -1424,9 +1425,10 @@
    * Initialize a newly created cascade expression. The list of
    * [cascadeSections] must contain at least one element.
    */
-  CascadeExpressionImpl(Expression target, List<Expression> cascadeSections) {
+  CascadeExpressionImpl(
+      ExpressionImpl target, List<Expression> cascadeSections) {
     _target = _becomeParentOf(target);
-    _cascadeSections = new NodeList<Expression>(this, cascadeSections);
+    _cascadeSections = new NodeListImpl<Expression>(this, cascadeSections);
   }
 
   @override
@@ -1451,7 +1453,7 @@
 
   @override
   void set target(Expression target) {
-    _target = _becomeParentOf(target);
+    _target = _becomeParentOf(target as AstNodeImpl);
   }
 
   @override
@@ -1540,14 +1542,14 @@
    */
   CatchClauseImpl(
       this.onKeyword,
-      TypeName exceptionType,
+      TypeNameImpl exceptionType,
       this.catchKeyword,
       this.leftParenthesis,
-      SimpleIdentifier exceptionParameter,
+      SimpleIdentifierImpl exceptionParameter,
       this.comma,
-      SimpleIdentifier stackTraceParameter,
+      SimpleIdentifierImpl stackTraceParameter,
       this.rightParenthesis,
-      Block body) {
+      BlockImpl body) {
     _exceptionType = _becomeParentOf(exceptionType);
     _exceptionParameter = _becomeParentOf(exceptionParameter);
     _stackTraceParameter = _becomeParentOf(stackTraceParameter);
@@ -1567,7 +1569,7 @@
 
   @override
   void set body(Block block) {
-    _body = _becomeParentOf(block);
+    _body = _becomeParentOf(block as AstNodeImpl);
   }
 
   @override
@@ -1590,7 +1592,7 @@
 
   @override
   void set exceptionParameter(SimpleIdentifier parameter) {
-    _exceptionParameter = _becomeParentOf(parameter);
+    _exceptionParameter = _becomeParentOf(parameter as AstNodeImpl);
   }
 
   @override
@@ -1598,7 +1600,7 @@
 
   @override
   void set exceptionType(TypeName exceptionType) {
-    _exceptionType = _becomeParentOf(exceptionType);
+    _exceptionType = _becomeParentOf(exceptionType as AstNodeImpl);
   }
 
   @override
@@ -1606,7 +1608,7 @@
 
   @override
   void set stackTraceParameter(SimpleIdentifier parameter) {
-    _stackTraceParameter = _becomeParentOf(parameter);
+    _stackTraceParameter = _becomeParentOf(parameter as AstNodeImpl);
   }
 
   @override
@@ -1739,11 +1741,11 @@
       List<Annotation> metadata,
       this.abstractKeyword,
       this.classKeyword,
-      SimpleIdentifier name,
-      TypeParameterList typeParameters,
-      ExtendsClause extendsClause,
-      WithClause withClause,
-      ImplementsClause implementsClause,
+      SimpleIdentifierImpl name,
+      TypeParameterListImpl typeParameters,
+      ExtendsClauseImpl extendsClause,
+      WithClauseImpl withClause,
+      ImplementsClauseImpl implementsClause,
       this.leftBracket,
       List<ClassMember> members,
       this.rightBracket)
@@ -1752,7 +1754,7 @@
     _extendsClause = _becomeParentOf(extendsClause);
     _withClause = _becomeParentOf(withClause);
     _implementsClause = _becomeParentOf(implementsClause);
-    _members = new NodeList<ClassMember>(this, members);
+    _members = new NodeListImpl<ClassMember>(this, members);
   }
 
   @override
@@ -1770,8 +1772,7 @@
     ..add(rightBracket);
 
   @override
-  ClassElement get element =>
-      _name != null ? (_name.staticElement as ClassElement) : null;
+  ClassElement get element => _name?.staticElement as ClassElement;
 
   @override
   Token get endToken => rightBracket;
@@ -1781,7 +1782,7 @@
 
   @override
   void set extendsClause(ExtendsClause extendsClause) {
-    _extendsClause = _becomeParentOf(extendsClause);
+    _extendsClause = _becomeParentOf(extendsClause as AstNodeImpl);
   }
 
   @override
@@ -1797,7 +1798,7 @@
 
   @override
   void set implementsClause(ImplementsClause implementsClause) {
-    _implementsClause = _becomeParentOf(implementsClause);
+    _implementsClause = _becomeParentOf(implementsClause as AstNodeImpl);
   }
 
   @override
@@ -1811,7 +1812,7 @@
 
   @override
   void set nativeClause(NativeClause nativeClause) {
-    _nativeClause = _becomeParentOf(nativeClause);
+    _nativeClause = _becomeParentOf(nativeClause as AstNodeImpl);
   }
 
   @override
@@ -1819,7 +1820,7 @@
 
   @override
   void set typeParameters(TypeParameterList typeParameters) {
-    _typeParameters = _becomeParentOf(typeParameters);
+    _typeParameters = _becomeParentOf(typeParameters as AstNodeImpl);
   }
 
   @override
@@ -1827,7 +1828,7 @@
 
   @override
   void set withClause(WithClause withClause) {
-    _withClause = _becomeParentOf(withClause);
+    _withClause = _becomeParentOf(withClause as AstNodeImpl);
   }
 
   @override
@@ -1963,16 +1964,16 @@
    * if the class does not implement any interfaces.
    */
   ClassTypeAliasImpl(
-      Comment comment,
+      CommentImpl comment,
       List<Annotation> metadata,
       Token keyword,
-      SimpleIdentifier name,
-      TypeParameterList typeParameters,
+      SimpleIdentifierImpl name,
+      TypeParameterListImpl typeParameters,
       this.equals,
       this.abstractKeyword,
-      TypeName superclass,
-      WithClause withClause,
-      ImplementsClause implementsClause,
+      TypeNameImpl superclass,
+      WithClauseImpl withClause,
+      ImplementsClauseImpl implementsClause,
       Token semicolon)
       : super(comment, metadata, keyword, name, semicolon) {
     _typeParameters = _becomeParentOf(typeParameters);
@@ -1994,8 +1995,7 @@
     ..add(semicolon);
 
   @override
-  ClassElement get element =>
-      _name != null ? (_name.staticElement as ClassElement) : null;
+  ClassElement get element => _name?.staticElement as ClassElement;
 
   @override
   Token get firstTokenAfterCommentAndMetadata {
@@ -2010,7 +2010,7 @@
 
   @override
   void set implementsClause(ImplementsClause implementsClause) {
-    _implementsClause = _becomeParentOf(implementsClause);
+    _implementsClause = _becomeParentOf(implementsClause as AstNodeImpl);
   }
 
   @override
@@ -2021,7 +2021,7 @@
 
   @override
   void set superclass(TypeName superclass) {
-    _superclass = _becomeParentOf(superclass);
+    _superclass = _becomeParentOf(superclass as AstNodeImpl);
   }
 
   @override
@@ -2029,7 +2029,7 @@
 
   @override
   void set typeParameters(TypeParameterList typeParameters) {
-    _typeParameters = _becomeParentOf(typeParameters);
+    _typeParameters = _becomeParentOf(typeParameters as AstNodeImpl);
   }
 
   @override
@@ -2037,7 +2037,7 @@
 
   @override
   void set withClause(WithClause withClause) {
-    _withClause = _becomeParentOf(withClause);
+    _withClause = _becomeParentOf(withClause as AstNodeImpl);
   }
 
   @override
@@ -2123,7 +2123,7 @@
    * references.
    */
   CommentImpl(this.tokens, this._type, List<CommentReference> references) {
-    _references = new NodeList<CommentReference>(this, references);
+    _references = new NodeListImpl<CommentReference>(this, references);
   }
 
   @override
@@ -2207,7 +2207,7 @@
    * Initialize a newly created reference to a Dart element. The [newKeyword]
    * can be `null` if the reference is not to a constructor.
    */
-  CommentReferenceImpl(this.newKeyword, Identifier identifier) {
+  CommentReferenceImpl(this.newKeyword, IdentifierImpl identifier) {
     _identifier = _becomeParentOf(identifier);
   }
 
@@ -2226,7 +2226,7 @@
 
   @override
   void set identifier(Identifier identifier) {
-    _identifier = _becomeParentOf(identifier);
+    _identifier = _becomeParentOf(identifier as AstNodeImpl);
   }
 
   @override
@@ -2348,13 +2348,13 @@
    */
   CompilationUnitImpl(
       this.beginToken,
-      ScriptTag scriptTag,
+      ScriptTagImpl scriptTag,
       List<Directive> directives,
       List<CompilationUnitMember> declarations,
       this.endToken) {
     _scriptTag = _becomeParentOf(scriptTag);
-    _directives = new NodeList<Directive>(this, directives);
-    _declarations = new NodeList<CompilationUnitMember>(this, declarations);
+    _directives = new NodeListImpl<Directive>(this, directives);
+    _declarations = new NodeListImpl<CompilationUnitMember>(this, declarations);
   }
 
   @override
@@ -2391,7 +2391,7 @@
 
   @override
   void set scriptTag(ScriptTag scriptTag) {
-    _scriptTag = _becomeParentOf(scriptTag);
+    _scriptTag = _becomeParentOf(scriptTag as AstNodeImpl);
   }
 
   @override
@@ -2494,8 +2494,12 @@
   /**
    * Initialize a newly created conditional expression.
    */
-  ConditionalExpressionImpl(Expression condition, this.question,
-      Expression thenExpression, this.colon, Expression elseExpression) {
+  ConditionalExpressionImpl(
+      ExpressionImpl condition,
+      this.question,
+      ExpressionImpl thenExpression,
+      this.colon,
+      ExpressionImpl elseExpression) {
     _condition = _becomeParentOf(condition);
     _thenExpression = _becomeParentOf(thenExpression);
     _elseExpression = _becomeParentOf(elseExpression);
@@ -2517,7 +2521,7 @@
 
   @override
   void set condition(Expression expression) {
-    _condition = _becomeParentOf(expression);
+    _condition = _becomeParentOf(expression as AstNodeImpl);
   }
 
   @override
@@ -2525,7 +2529,7 @@
 
   @override
   void set elseExpression(Expression expression) {
-    _elseExpression = _becomeParentOf(expression);
+    _elseExpression = _becomeParentOf(expression as AstNodeImpl);
   }
 
   @override
@@ -2539,7 +2543,7 @@
 
   @override
   void set thenExpression(Expression expression) {
-    _thenExpression = _becomeParentOf(expression);
+    _thenExpression = _becomeParentOf(expression as AstNodeImpl);
   }
 
   @override
@@ -2582,11 +2586,11 @@
   ConfigurationImpl(
       this.ifKeyword,
       this.leftParenthesis,
-      DottedName name,
+      DottedNameImpl name,
       this.equalToken,
-      StringLiteral value,
+      StringLiteralImpl value,
       this.rightParenthesis,
-      StringLiteral libraryUri) {
+      StringLiteralImpl libraryUri) {
     _name = _becomeParentOf(name);
     _value = _becomeParentOf(value);
     _libraryUri = _becomeParentOf(libraryUri);
@@ -2613,7 +2617,7 @@
 
   @override
   void set libraryUri(StringLiteral libraryUri) {
-    _libraryUri = _becomeParentOf(libraryUri);
+    _libraryUri = _becomeParentOf(libraryUri as AstNodeImpl);
   }
 
   @override
@@ -2621,7 +2625,7 @@
 
   @override
   void set name(DottedName name) {
-    _name = _becomeParentOf(name);
+    _name = _becomeParentOf(name as AstNodeImpl);
   }
 
   @override
@@ -2629,7 +2633,7 @@
 
   @override
   void set value(StringLiteral value) {
-    _value = _becomeParentOf(value);
+    _value = _becomeParentOf(value as AstNodeImpl);
   }
 
   @override
@@ -2761,24 +2765,25 @@
    * the constructor does not have a body.
    */
   ConstructorDeclarationImpl(
-      Comment comment,
+      CommentImpl comment,
       List<Annotation> metadata,
       this.externalKeyword,
       this.constKeyword,
       this.factoryKeyword,
-      Identifier returnType,
+      IdentifierImpl returnType,
       this.period,
-      SimpleIdentifier name,
-      FormalParameterList parameters,
+      SimpleIdentifierImpl name,
+      FormalParameterListImpl parameters,
       this.separator,
       List<ConstructorInitializer> initializers,
-      ConstructorName redirectedConstructor,
-      FunctionBody body)
+      ConstructorNameImpl redirectedConstructor,
+      FunctionBodyImpl body)
       : super(comment, metadata) {
     _returnType = _becomeParentOf(returnType);
     _name = _becomeParentOf(name);
     _parameters = _becomeParentOf(parameters);
-    _initializers = new NodeList<ConstructorInitializer>(this, initializers);
+    _initializers =
+        new NodeListImpl<ConstructorInitializer>(this, initializers);
     _redirectedConstructor = _becomeParentOf(redirectedConstructor);
     _body = _becomeParentOf(body);
   }
@@ -2788,7 +2793,7 @@
 
   @override
   void set body(FunctionBody functionBody) {
-    _body = _becomeParentOf(functionBody);
+    _body = _becomeParentOf(functionBody as AstNodeImpl);
   }
 
   @override
@@ -2833,7 +2838,7 @@
 
   @override
   void set name(SimpleIdentifier identifier) {
-    _name = _becomeParentOf(identifier);
+    _name = _becomeParentOf(identifier as AstNodeImpl);
   }
 
   @override
@@ -2841,7 +2846,7 @@
 
   @override
   void set parameters(FormalParameterList parameters) {
-    _parameters = _becomeParentOf(parameters);
+    _parameters = _becomeParentOf(parameters as AstNodeImpl);
   }
 
   @override
@@ -2849,7 +2854,8 @@
 
   @override
   void set redirectedConstructor(ConstructorName redirectedConstructor) {
-    _redirectedConstructor = _becomeParentOf(redirectedConstructor);
+    _redirectedConstructor =
+        _becomeParentOf(redirectedConstructor as AstNodeImpl);
   }
 
   @override
@@ -2857,7 +2863,7 @@
 
   @override
   void set returnType(Identifier typeName) {
-    _returnType = _becomeParentOf(typeName);
+    _returnType = _becomeParentOf(typeName as AstNodeImpl);
   }
 
   @override
@@ -2919,7 +2925,7 @@
    * [period] can be `null` if the 'this' keyword was not specified.
    */
   ConstructorFieldInitializerImpl(this.thisKeyword, this.period,
-      SimpleIdentifier fieldName, this.equals, Expression expression) {
+      SimpleIdentifierImpl fieldName, this.equals, ExpressionImpl expression) {
     _fieldName = _becomeParentOf(fieldName);
     _expression = _becomeParentOf(expression);
   }
@@ -2948,7 +2954,7 @@
 
   @override
   void set expression(Expression expression) {
-    _expression = _becomeParentOf(expression);
+    _expression = _becomeParentOf(expression as AstNodeImpl);
   }
 
   @override
@@ -2956,7 +2962,7 @@
 
   @override
   void set fieldName(SimpleIdentifier identifier) {
-    _fieldName = _becomeParentOf(identifier);
+    _fieldName = _becomeParentOf(identifier as AstNodeImpl);
   }
 
   @override
@@ -3018,7 +3024,8 @@
    * Initialize a newly created constructor name. The [period] and [name] can be
    * `null` if the constructor being named is the unnamed constructor.
    */
-  ConstructorNameImpl(TypeName type, this.period, SimpleIdentifier name) {
+  ConstructorNameImpl(
+      TypeNameImpl type, this.period, SimpleIdentifierImpl name) {
     _type = _becomeParentOf(type);
     _name = _becomeParentOf(name);
   }
@@ -3043,7 +3050,7 @@
 
   @override
   void set name(SimpleIdentifier name) {
-    _name = _becomeParentOf(name);
+    _name = _becomeParentOf(name as AstNodeImpl);
   }
 
   @override
@@ -3051,7 +3058,7 @@
 
   @override
   void set type(TypeName type) {
-    _type = _becomeParentOf(type);
+    _type = _becomeParentOf(type as AstNodeImpl);
   }
 
   @override
@@ -3104,7 +3111,7 @@
    * there is no label associated with the statement.
    */
   ContinueStatementImpl(
-      this.continueKeyword, SimpleIdentifier label, this.semicolon) {
+      this.continueKeyword, SimpleIdentifierImpl label, this.semicolon) {
     _label = _becomeParentOf(label);
   }
 
@@ -3123,7 +3130,7 @@
 
   @override
   void set label(SimpleIdentifier identifier) {
-    _label = _becomeParentOf(identifier);
+    _label = _becomeParentOf(identifier as AstNodeImpl);
   }
 
   @override
@@ -3183,8 +3190,8 @@
    * corresponding attribute. The [keyword] can be `null` if a type name is
    * given. The [type] must be `null` if the keyword is 'var'.
    */
-  DeclaredIdentifierImpl(Comment comment, List<Annotation> metadata,
-      this.keyword, TypeName type, SimpleIdentifier identifier)
+  DeclaredIdentifierImpl(CommentImpl comment, List<Annotation> metadata,
+      this.keyword, TypeNameImpl type, SimpleIdentifierImpl identifier)
       : super(comment, metadata) {
     _type = _becomeParentOf(type);
     _identifier = _becomeParentOf(identifier);
@@ -3220,7 +3227,7 @@
 
   @override
   void set identifier(SimpleIdentifier identifier) {
-    _identifier = _becomeParentOf(identifier);
+    _identifier = _becomeParentOf(identifier as AstNodeImpl);
   }
 
   @override
@@ -3234,7 +3241,7 @@
 
   @override
   void set type(TypeName typeName) {
-    _type = _becomeParentOf(typeName);
+    _type = _becomeParentOf(typeName as AstNodeImpl);
   }
 
   @override
@@ -3308,8 +3315,8 @@
    * Initialize a newly created default formal parameter. The [separator] and
    * [defaultValue] can be `null` if there is no default value.
    */
-  DefaultFormalParameterImpl(NormalFormalParameter parameter, this.kind,
-      this.separator, Expression defaultValue) {
+  DefaultFormalParameterImpl(NormalFormalParameterImpl parameter, this.kind,
+      this.separator, ExpressionImpl defaultValue) {
     _parameter = _becomeParentOf(parameter);
     _defaultValue = _becomeParentOf(defaultValue);
   }
@@ -3326,7 +3333,7 @@
 
   @override
   void set defaultValue(Expression expression) {
-    _defaultValue = _becomeParentOf(expression);
+    _defaultValue = _becomeParentOf(expression as AstNodeImpl);
   }
 
   @override
@@ -3354,7 +3361,7 @@
 
   @override
   void set parameter(NormalFormalParameter formalParameter) {
-    _parameter = _becomeParentOf(formalParameter);
+    _parameter = _becomeParentOf(formalParameter as AstNodeImpl);
   }
 
   @override
@@ -3455,10 +3462,10 @@
    */
   DoStatementImpl(
       this.doKeyword,
-      Statement body,
+      StatementImpl body,
       this.whileKeyword,
       this.leftParenthesis,
-      Expression condition,
+      ExpressionImpl condition,
       this.rightParenthesis,
       this.semicolon) {
     _body = _becomeParentOf(body);
@@ -3473,7 +3480,7 @@
 
   @override
   void set body(Statement statement) {
-    _body = _becomeParentOf(statement);
+    _body = _becomeParentOf(statement as AstNodeImpl);
   }
 
   @override
@@ -3491,7 +3498,7 @@
 
   @override
   void set condition(Expression expression) {
-    _condition = _becomeParentOf(expression);
+    _condition = _becomeParentOf(expression as AstNodeImpl);
   }
 
   @override
@@ -3524,7 +3531,7 @@
    * Initialize a newly created dotted name.
    */
   DottedNameImpl(List<SimpleIdentifier> components) {
-    _components = new NodeList<SimpleIdentifier>(this, components);
+    _components = new NodeListImpl<SimpleIdentifier>(this, components);
   }
 
   @override
@@ -3690,7 +3697,7 @@
    * but we allow it for consistency.)
    */
   EnumConstantDeclarationImpl(
-      Comment comment, List<Annotation> metadata, SimpleIdentifier name)
+      CommentImpl comment, List<Annotation> metadata, SimpleIdentifierImpl name)
       : super(comment, metadata) {
     _name = _becomeParentOf(name);
   }
@@ -3699,8 +3706,7 @@
   Iterable get childEntities => super._childEntities..add(_name);
 
   @override
-  FieldElement get element =>
-      _name == null ? null : (_name.staticElement as FieldElement);
+  FieldElement get element => _name?.staticElement as FieldElement;
 
   @override
   Token get endToken => _name.endToken;
@@ -3713,7 +3719,7 @@
 
   @override
   void set name(SimpleIdentifier name) {
-    _name = _becomeParentOf(name);
+    _name = _becomeParentOf(name as AstNodeImpl);
   }
 
   @override
@@ -3773,7 +3779,7 @@
       List<EnumConstantDeclaration> constants,
       this.rightBracket)
       : super(comment, metadata, name) {
-    _constants = new NodeList<EnumConstantDeclaration>(this, constants);
+    _constants = new NodeListImpl<EnumConstantDeclaration>(this, constants);
   }
 
   @override
@@ -3789,8 +3795,7 @@
   NodeList<EnumConstantDeclaration> get constants => _constants;
 
   @override
-  ClassElement get element =>
-      _name != null ? (_name.staticElement as ClassElement) : null;
+  ClassElement get element => _name?.staticElement as ClassElement;
 
   @override
   Token get endToken => rightBracket;
@@ -3913,7 +3918,7 @@
    * async function body.
    */
   ExpressionFunctionBodyImpl(this.keyword, this.functionDefinition,
-      Expression expression, this.semicolon) {
+      ExpressionImpl expression, this.semicolon) {
     _expression = _becomeParentOf(expression);
   }
 
@@ -3945,7 +3950,7 @@
 
   @override
   void set expression(Expression expression) {
-    _expression = _becomeParentOf(expression);
+    _expression = _becomeParentOf(expression as AstNodeImpl);
   }
 
   @override
@@ -4063,6 +4068,9 @@
     }
     return null;
   }
+
+  @override
+  Expression get unParenthesized => this;
 }
 
 /**
@@ -4088,7 +4096,7 @@
   /**
    * Initialize a newly created expression statement.
    */
-  ExpressionStatementImpl(Expression expression, this.semicolon) {
+  ExpressionStatementImpl(ExpressionImpl expression, this.semicolon) {
     _expression = _becomeParentOf(expression);
   }
 
@@ -4112,7 +4120,7 @@
 
   @override
   void set expression(Expression expression) {
-    _expression = _becomeParentOf(expression);
+    _expression = _becomeParentOf(expression as AstNodeImpl);
   }
 
   @override
@@ -4149,7 +4157,7 @@
   /**
    * Initialize a newly created extends clause.
    */
-  ExtendsClauseImpl(this.extendsKeyword, TypeName superclass) {
+  ExtendsClauseImpl(this.extendsKeyword, TypeNameImpl superclass) {
     _superclass = _becomeParentOf(superclass);
   }
 
@@ -4168,7 +4176,7 @@
 
   @override
   void set superclass(TypeName name) {
-    _superclass = _becomeParentOf(name);
+    _superclass = _becomeParentOf(name as AstNodeImpl);
   }
 
   @override
@@ -4212,8 +4220,8 @@
    * corresponding attribute. The [staticKeyword] can be `null` if the field is
    * not a static field.
    */
-  FieldDeclarationImpl(Comment comment, List<Annotation> metadata,
-      this.staticKeyword, VariableDeclarationList fieldList, this.semicolon)
+  FieldDeclarationImpl(CommentImpl comment, List<Annotation> metadata,
+      this.staticKeyword, VariableDeclarationListImpl fieldList, this.semicolon)
       : super(comment, metadata) {
     _fieldList = _becomeParentOf(fieldList);
   }
@@ -4233,7 +4241,7 @@
 
   @override
   void set fields(VariableDeclarationList fields) {
-    _fieldList = _becomeParentOf(fields);
+    _fieldList = _becomeParentOf(fields as AstNodeImpl);
   }
 
   @override
@@ -4314,15 +4322,15 @@
    * parameter.
    */
   FieldFormalParameterImpl(
-      Comment comment,
+      CommentImpl comment,
       List<Annotation> metadata,
       this.keyword,
-      TypeName type,
+      TypeNameImpl type,
       this.thisKeyword,
       this.period,
-      SimpleIdentifier identifier,
-      TypeParameterList typeParameters,
-      FormalParameterList parameters)
+      SimpleIdentifierImpl identifier,
+      TypeParameterListImpl typeParameters,
+      FormalParameterListImpl parameters)
       : super(comment, metadata, identifier) {
     _type = _becomeParentOf(type);
     _typeParameters = _becomeParentOf(typeParameters);
@@ -4367,7 +4375,7 @@
 
   @override
   void set parameters(FormalParameterList parameters) {
-    _parameters = _becomeParentOf(parameters);
+    _parameters = _becomeParentOf(parameters as AstNodeImpl);
   }
 
   @override
@@ -4375,7 +4383,7 @@
 
   @override
   void set type(TypeName typeName) {
-    _type = _becomeParentOf(typeName);
+    _type = _becomeParentOf(typeName as AstNodeImpl);
   }
 
   @override
@@ -4383,7 +4391,7 @@
 
   @override
   void set typeParameters(TypeParameterList typeParameters) {
-    _typeParameters = _becomeParentOf(typeParameters);
+    _typeParameters = _becomeParentOf(typeParameters as AstNodeImpl);
   }
 
   @override
@@ -4469,11 +4477,11 @@
       this.awaitKeyword,
       this.forKeyword,
       this.leftParenthesis,
-      DeclaredIdentifier loopVariable,
+      DeclaredIdentifierImpl loopVariable,
       this.inKeyword,
-      Expression iterator,
+      ExpressionImpl iterator,
       this.rightParenthesis,
-      Statement body) {
+      StatementImpl body) {
     _loopVariable = _becomeParentOf(loopVariable);
     _iterable = _becomeParentOf(iterator);
     _body = _becomeParentOf(body);
@@ -4488,11 +4496,11 @@
       this.awaitKeyword,
       this.forKeyword,
       this.leftParenthesis,
-      SimpleIdentifier identifier,
+      SimpleIdentifierImpl identifier,
       this.inKeyword,
-      Expression iterator,
+      ExpressionImpl iterator,
       this.rightParenthesis,
-      Statement body) {
+      StatementImpl body) {
     _identifier = _becomeParentOf(identifier);
     _iterable = _becomeParentOf(iterator);
     _body = _becomeParentOf(body);
@@ -4506,7 +4514,7 @@
 
   @override
   void set body(Statement statement) {
-    _body = _becomeParentOf(statement);
+    _body = _becomeParentOf(statement as AstNodeImpl);
   }
 
   @override
@@ -4529,7 +4537,7 @@
 
   @override
   void set identifier(SimpleIdentifier identifier) {
-    _identifier = _becomeParentOf(identifier);
+    _identifier = _becomeParentOf(identifier as AstNodeImpl);
   }
 
   @override
@@ -4537,7 +4545,7 @@
 
   @override
   void set iterable(Expression expression) {
-    _iterable = _becomeParentOf(expression);
+    _iterable = _becomeParentOf(expression as AstNodeImpl);
   }
 
   @override
@@ -4545,7 +4553,7 @@
 
   @override
   void set loopVariable(DeclaredIdentifier variable) {
-    _loopVariable = _becomeParentOf(variable);
+    _loopVariable = _becomeParentOf(variable as AstNodeImpl);
   }
 
   @override
@@ -4652,7 +4660,7 @@
       this.leftDelimiter,
       this.rightDelimiter,
       this.rightParenthesis) {
-    _parameters = new NodeList<FormalParameter>(this, parameters);
+    _parameters = new NodeListImpl<FormalParameter>(this, parameters);
   }
 
   @override
@@ -4782,18 +4790,18 @@
   ForStatementImpl(
       this.forKeyword,
       this.leftParenthesis,
-      VariableDeclarationList variableList,
-      Expression initialization,
+      VariableDeclarationListImpl variableList,
+      ExpressionImpl initialization,
       this.leftSeparator,
-      Expression condition,
+      ExpressionImpl condition,
       this.rightSeparator,
       List<Expression> updaters,
       this.rightParenthesis,
-      Statement body) {
+      StatementImpl body) {
     _variableList = _becomeParentOf(variableList);
     _initialization = _becomeParentOf(initialization);
     _condition = _becomeParentOf(condition);
-    _updaters = new NodeList<Expression>(this, updaters);
+    _updaters = new NodeListImpl<Expression>(this, updaters);
     _body = _becomeParentOf(body);
   }
 
@@ -4805,7 +4813,7 @@
 
   @override
   void set body(Statement statement) {
-    _body = _becomeParentOf(statement);
+    _body = _becomeParentOf(statement as AstNodeImpl);
   }
 
   @override
@@ -4826,7 +4834,7 @@
 
   @override
   void set condition(Expression expression) {
-    _condition = _becomeParentOf(expression);
+    _condition = _becomeParentOf(expression as AstNodeImpl);
   }
 
   @override
@@ -4837,7 +4845,7 @@
 
   @override
   void set initialization(Expression initialization) {
-    _initialization = _becomeParentOf(initialization);
+    _initialization = _becomeParentOf(initialization as AstNodeImpl);
   }
 
   @override
@@ -4848,7 +4856,7 @@
 
   @override
   void set variables(VariableDeclarationList variableList) {
-    _variableList = _becomeParentOf(variableList);
+    _variableList = _becomeParentOf(variableList as AstNodeImpl);
   }
 
   @override
@@ -4975,13 +4983,13 @@
    * function is neither a getter or a setter.
    */
   FunctionDeclarationImpl(
-      Comment comment,
+      CommentImpl comment,
       List<Annotation> metadata,
       this.externalKeyword,
-      TypeName returnType,
+      TypeNameImpl returnType,
       this.propertyKeyword,
-      SimpleIdentifier name,
-      FunctionExpression functionExpression)
+      SimpleIdentifierImpl name,
+      FunctionExpressionImpl functionExpression)
       : super(comment, metadata, name) {
     _returnType = _becomeParentOf(returnType);
     _functionExpression = _becomeParentOf(functionExpression);
@@ -4996,8 +5004,7 @@
     ..add(_functionExpression);
 
   @override
-  ExecutableElement get element =>
-      _name != null ? (_name.staticElement as ExecutableElement) : null;
+  ExecutableElement get element => _name?.staticElement as ExecutableElement;
 
   @override
   Token get endToken => _functionExpression.endToken;
@@ -5021,7 +5028,7 @@
 
   @override
   void set functionExpression(FunctionExpression functionExpression) {
-    _functionExpression = _becomeParentOf(functionExpression);
+    _functionExpression = _becomeParentOf(functionExpression as AstNodeImpl);
   }
 
   @override
@@ -5035,7 +5042,7 @@
 
   @override
   void set returnType(TypeName returnType) {
-    _returnType = _becomeParentOf(returnType);
+    _returnType = _becomeParentOf(returnType as AstNodeImpl);
   }
 
   @override
@@ -5065,7 +5072,7 @@
    * Initialize a newly created function declaration statement.
    */
   FunctionDeclarationStatementImpl(FunctionDeclaration functionDeclaration) {
-    _functionDeclaration = _becomeParentOf(functionDeclaration);
+    _functionDeclaration = _becomeParentOf(functionDeclaration as AstNodeImpl);
   }
 
   @override
@@ -5082,7 +5089,7 @@
 
   @override
   void set functionDeclaration(FunctionDeclaration functionDeclaration) {
-    _functionDeclaration = _becomeParentOf(functionDeclaration);
+    _functionDeclaration = _becomeParentOf(functionDeclaration as AstNodeImpl);
   }
 
   @override
@@ -5129,8 +5136,8 @@
   /**
    * Initialize a newly created function declaration.
    */
-  FunctionExpressionImpl(TypeParameterList typeParameters,
-      FormalParameterList parameters, FunctionBody body) {
+  FunctionExpressionImpl(TypeParameterListImpl typeParameters,
+      FormalParameterListImpl parameters, FunctionBodyImpl body) {
     _typeParameters = _becomeParentOf(typeParameters);
     _parameters = _becomeParentOf(parameters);
     _body = _becomeParentOf(body);
@@ -5155,7 +5162,7 @@
 
   @override
   void set body(FunctionBody functionBody) {
-    _body = _becomeParentOf(functionBody);
+    _body = _becomeParentOf(functionBody as AstNodeImpl);
   }
 
   @override
@@ -5179,7 +5186,7 @@
 
   @override
   void set parameters(FormalParameterList parameters) {
-    _parameters = _becomeParentOf(parameters);
+    _parameters = _becomeParentOf(parameters as AstNodeImpl);
   }
 
   @override
@@ -5190,7 +5197,7 @@
 
   @override
   void set typeParameters(TypeParameterList typeParameters) {
-    _typeParameters = _becomeParentOf(typeParameters);
+    _typeParameters = _becomeParentOf(typeParameters as AstNodeImpl);
   }
 
   @override
@@ -5240,8 +5247,8 @@
   /**
    * Initialize a newly created function expression invocation.
    */
-  FunctionExpressionInvocationImpl(Expression function,
-      TypeArgumentList typeArguments, ArgumentList argumentList)
+  FunctionExpressionInvocationImpl(ExpressionImpl function,
+      TypeArgumentListImpl typeArguments, ArgumentListImpl argumentList)
       : super(typeArguments, argumentList) {
     _function = _becomeParentOf(function);
   }
@@ -5270,7 +5277,7 @@
 
   @override
   void set function(Expression expression) {
-    _function = _becomeParentOf(expression);
+    _function = _becomeParentOf(expression as AstNodeImpl);
   }
 
   @override
@@ -5323,13 +5330,13 @@
    * type parameters.
    */
   FunctionTypeAliasImpl(
-      Comment comment,
+      CommentImpl comment,
       List<Annotation> metadata,
       Token keyword,
-      TypeName returnType,
-      SimpleIdentifier name,
-      TypeParameterList typeParameters,
-      FormalParameterList parameters,
+      TypeNameImpl returnType,
+      SimpleIdentifierImpl name,
+      TypeParameterListImpl typeParameters,
+      FormalParameterListImpl parameters,
       Token semicolon)
       : super(comment, metadata, keyword, name, semicolon) {
     _returnType = _becomeParentOf(returnType);
@@ -5348,14 +5355,14 @@
 
   @override
   FunctionTypeAliasElement get element =>
-      _name != null ? (_name.staticElement as FunctionTypeAliasElement) : null;
+      _name?.staticElement as FunctionTypeAliasElement;
 
   @override
   FormalParameterList get parameters => _parameters;
 
   @override
   void set parameters(FormalParameterList parameters) {
-    _parameters = _becomeParentOf(parameters);
+    _parameters = _becomeParentOf(parameters as AstNodeImpl);
   }
 
   @override
@@ -5363,7 +5370,7 @@
 
   @override
   void set returnType(TypeName typeName) {
-    _returnType = _becomeParentOf(typeName);
+    _returnType = _becomeParentOf(typeName as AstNodeImpl);
   }
 
   @override
@@ -5371,7 +5378,7 @@
 
   @override
   void set typeParameters(TypeParameterList typeParameters) {
-    _typeParameters = _becomeParentOf(typeParameters);
+    _typeParameters = _becomeParentOf(typeParameters as AstNodeImpl);
   }
 
   @override
@@ -5420,12 +5427,12 @@
    * was specified.
    */
   FunctionTypedFormalParameterImpl(
-      Comment comment,
+      CommentImpl comment,
       List<Annotation> metadata,
-      TypeName returnType,
-      SimpleIdentifier identifier,
-      TypeParameterList typeParameters,
-      FormalParameterList parameters)
+      TypeNameImpl returnType,
+      SimpleIdentifierImpl identifier,
+      TypeParameterListImpl typeParameters,
+      FormalParameterListImpl parameters)
       : super(comment, metadata, identifier) {
     _returnType = _becomeParentOf(returnType);
     _typeParameters = _becomeParentOf(typeParameters);
@@ -5458,7 +5465,7 @@
 
   @override
   void set parameters(FormalParameterList parameters) {
-    _parameters = _becomeParentOf(parameters);
+    _parameters = _becomeParentOf(parameters as AstNodeImpl);
   }
 
   @override
@@ -5466,7 +5473,7 @@
 
   @override
   void set returnType(TypeName type) {
-    _returnType = _becomeParentOf(type);
+    _returnType = _becomeParentOf(type as AstNodeImpl);
   }
 
   @override
@@ -5474,7 +5481,7 @@
 
   @override
   void set typeParameters(TypeParameterList typeParameters) {
-    _typeParameters = _becomeParentOf(typeParameters);
+    _typeParameters = _becomeParentOf(typeParameters as AstNodeImpl);
   }
 
   @override
@@ -5509,7 +5516,7 @@
    */
   HideCombinatorImpl(Token keyword, List<SimpleIdentifier> hiddenNames)
       : super(keyword) {
-    _hiddenNames = new NodeList<SimpleIdentifier>(this, hiddenNames);
+    _hiddenNames = new NodeListImpl<SimpleIdentifier>(this, hiddenNames);
   }
 
   @override
@@ -5609,11 +5616,11 @@
   IfStatementImpl(
       this.ifKeyword,
       this.leftParenthesis,
-      Expression condition,
+      ExpressionImpl condition,
       this.rightParenthesis,
-      Statement thenStatement,
+      StatementImpl thenStatement,
       this.elseKeyword,
-      Statement elseStatement) {
+      StatementImpl elseStatement) {
     _condition = _becomeParentOf(condition);
     _thenStatement = _becomeParentOf(thenStatement);
     _elseStatement = _becomeParentOf(elseStatement);
@@ -5637,7 +5644,7 @@
 
   @override
   void set condition(Expression expression) {
-    _condition = _becomeParentOf(expression);
+    _condition = _becomeParentOf(expression as AstNodeImpl);
   }
 
   @override
@@ -5645,7 +5652,7 @@
 
   @override
   void set elseStatement(Statement statement) {
-    _elseStatement = _becomeParentOf(statement);
+    _elseStatement = _becomeParentOf(statement as AstNodeImpl);
   }
 
   @override
@@ -5661,7 +5668,7 @@
 
   @override
   void set thenStatement(Statement statement) {
-    _thenStatement = _becomeParentOf(statement);
+    _thenStatement = _becomeParentOf(statement as AstNodeImpl);
   }
 
   @override
@@ -5698,7 +5705,7 @@
    * Initialize a newly created implements clause.
    */
   ImplementsClauseImpl(this.implementsKeyword, List<TypeName> interfaces) {
-    _interfaces = new NodeList<TypeName>(this, interfaces);
+    _interfaces = new NodeListImpl<TypeName>(this, interfaces);
   }
 
   @override
@@ -5763,14 +5770,14 @@
    * are no combinators.
    */
   ImportDirectiveImpl(
-      Comment comment,
+      CommentImpl comment,
       List<Annotation> metadata,
       Token keyword,
-      StringLiteral libraryUri,
+      StringLiteralImpl libraryUri,
       List<Configuration> configurations,
       this.deferredKeyword,
       this.asKeyword,
-      SimpleIdentifier prefix,
+      SimpleIdentifierImpl prefix,
       List<Combinator> combinators,
       Token semicolon)
       : super(comment, metadata, keyword, libraryUri, configurations,
@@ -5795,7 +5802,7 @@
 
   @override
   void set prefix(SimpleIdentifier identifier) {
-    _prefix = _becomeParentOf(identifier);
+    _prefix = _becomeParentOf(identifier as AstNodeImpl);
   }
 
   @override
@@ -5885,15 +5892,15 @@
    * Initialize a newly created index expression.
    */
   IndexExpressionImpl.forCascade(
-      this.period, this.leftBracket, Expression index, this.rightBracket) {
+      this.period, this.leftBracket, ExpressionImpl index, this.rightBracket) {
     _index = _becomeParentOf(index);
   }
 
   /**
    * Initialize a newly created index expression.
    */
-  IndexExpressionImpl.forTarget(Expression target, this.leftBracket,
-      Expression index, this.rightBracket) {
+  IndexExpressionImpl.forTarget(ExpressionImpl target, this.leftBracket,
+      ExpressionImpl index, this.rightBracket) {
     _target = _becomeParentOf(target);
     _index = _becomeParentOf(index);
   }
@@ -5931,7 +5938,7 @@
 
   @override
   void set index(Expression expression) {
-    _index = _becomeParentOf(expression);
+    _index = _becomeParentOf(expression as AstNodeImpl);
   }
 
   @override
@@ -5963,7 +5970,7 @@
 
   @override
   void set target(Expression expression) {
-    _target = _becomeParentOf(expression);
+    _target = _becomeParentOf(expression as AstNodeImpl);
   }
 
   /**
@@ -6075,8 +6082,8 @@
   /**
    * Initialize a newly created instance creation expression.
    */
-  InstanceCreationExpressionImpl(this.keyword, ConstructorName constructorName,
-      ArgumentList argumentList) {
+  InstanceCreationExpressionImpl(this.keyword,
+      ConstructorNameImpl constructorName, ArgumentListImpl argumentList) {
     _constructorName = _becomeParentOf(constructorName);
     _argumentList = _becomeParentOf(argumentList);
   }
@@ -6086,7 +6093,7 @@
 
   @override
   void set argumentList(ArgumentList argumentList) {
-    _argumentList = _becomeParentOf(argumentList);
+    _argumentList = _becomeParentOf(argumentList as AstNodeImpl);
   }
 
   @override
@@ -6103,7 +6110,7 @@
 
   @override
   void set constructorName(ConstructorName name) {
-    _constructorName = _becomeParentOf(name);
+    _constructorName = _becomeParentOf(name as AstNodeImpl);
   }
 
   @override
@@ -6220,7 +6227,7 @@
    * Initialize a newly created interpolation expression.
    */
   InterpolationExpressionImpl(
-      this.leftBracket, Expression expression, this.rightBracket) {
+      this.leftBracket, ExpressionImpl expression, this.rightBracket) {
     _expression = _becomeParentOf(expression);
   }
 
@@ -6246,7 +6253,7 @@
 
   @override
   void set expression(Expression expression) {
-    _expression = _becomeParentOf(expression);
+    _expression = _becomeParentOf(expression as AstNodeImpl);
   }
 
   @override
@@ -6342,7 +6349,7 @@
    * Initialize a newly created invocation.
    */
   InvocationExpressionImpl(
-      TypeArgumentList typeArguments, ArgumentList argumentList) {
+      TypeArgumentListImpl typeArguments, ArgumentListImpl argumentList) {
     _typeArguments = _becomeParentOf(typeArguments);
     _argumentList = _becomeParentOf(argumentList);
   }
@@ -6351,14 +6358,14 @@
   ArgumentList get argumentList => _argumentList;
 
   void set argumentList(ArgumentList argumentList) {
-    _argumentList = _becomeParentOf(argumentList);
+    _argumentList = _becomeParentOf(argumentList as AstNodeImpl);
   }
 
   @override
   TypeArgumentList get typeArguments => _typeArguments;
 
   void set typeArguments(TypeArgumentList typeArguments) {
-    _typeArguments = _becomeParentOf(typeArguments);
+    _typeArguments = _becomeParentOf(typeArguments as AstNodeImpl);
   }
 }
 
@@ -6395,8 +6402,8 @@
    * Initialize a newly created is expression. The [notOperator] can be `null`
    * if the sense of the test is not negated.
    */
-  IsExpressionImpl(
-      Expression expression, this.isOperator, this.notOperator, TypeName type) {
+  IsExpressionImpl(ExpressionImpl expression, this.isOperator, this.notOperator,
+      TypeNameImpl type) {
     _expression = _becomeParentOf(expression);
     _type = _becomeParentOf(type);
   }
@@ -6419,7 +6426,7 @@
 
   @override
   void set expression(Expression expression) {
-    _expression = _becomeParentOf(expression);
+    _expression = _becomeParentOf(expression as AstNodeImpl);
   }
 
   @override
@@ -6430,7 +6437,7 @@
 
   @override
   void set type(TypeName name) {
-    _type = _becomeParentOf(name);
+    _type = _becomeParentOf(name as AstNodeImpl);
   }
 
   @override
@@ -6464,8 +6471,8 @@
   /**
    * Initialize a newly created labeled statement.
    */
-  LabeledStatementImpl(List<Label> labels, Statement statement) {
-    _labels = new NodeList<Label>(this, labels);
+  LabeledStatementImpl(List<Label> labels, StatementImpl statement) {
+    _labels = new NodeListImpl<Label>(this, labels);
     _statement = _becomeParentOf(statement);
   }
 
@@ -6493,7 +6500,7 @@
 
   @override
   void set statement(Statement statement) {
-    _statement = _becomeParentOf(statement);
+    _statement = _becomeParentOf(statement as AstNodeImpl);
   }
 
   @override
@@ -6531,7 +6538,7 @@
   /**
    * Initialize a newly created label.
    */
-  LabelImpl(SimpleIdentifier label, this.colon) {
+  LabelImpl(SimpleIdentifierImpl label, this.colon) {
     _label = _becomeParentOf(label);
   }
 
@@ -6549,7 +6556,7 @@
 
   @override
   void set label(SimpleIdentifier label) {
-    _label = _becomeParentOf(label);
+    _label = _becomeParentOf(label as AstNodeImpl);
   }
 
   @override
@@ -6591,8 +6598,8 @@
    * [comment] and [metadata] can be `null` if the directive does not have the
    * corresponding attribute.
    */
-  LibraryDirectiveImpl(Comment comment, List<Annotation> metadata,
-      this.libraryKeyword, LibraryIdentifier name, this.semicolon)
+  LibraryDirectiveImpl(CommentImpl comment, List<Annotation> metadata,
+      this.libraryKeyword, LibraryIdentifierImpl name, this.semicolon)
       : super(comment, metadata) {
     _name = _becomeParentOf(name);
   }
@@ -6615,7 +6622,7 @@
 
   @override
   void set name(LibraryIdentifier name) {
-    _name = _becomeParentOf(name);
+    _name = _becomeParentOf(name as AstNodeImpl);
   }
 
   @override
@@ -6646,7 +6653,7 @@
    * Initialize a newly created prefixed identifier.
    */
   LibraryIdentifierImpl(List<SimpleIdentifier> components) {
-    _components = new NodeList<SimpleIdentifier>(this, components);
+    _components = new NodeListImpl<SimpleIdentifier>(this, components);
   }
 
   @override
@@ -6732,7 +6739,7 @@
   ListLiteralImpl(Token constKeyword, TypeArgumentList typeArguments,
       this.leftBracket, List<Expression> elements, this.rightBracket)
       : super(constKeyword, typeArguments) {
-    _elements = new NodeList<Expression>(this, elements);
+    _elements = new NodeListImpl<Expression>(this, elements);
   }
 
   @override
@@ -6834,7 +6841,8 @@
   /**
    * Initialize a newly created map literal entry.
    */
-  MapLiteralEntryImpl(Expression key, this.separator, Expression value) {
+  MapLiteralEntryImpl(
+      ExpressionImpl key, this.separator, ExpressionImpl value) {
     _key = _becomeParentOf(key);
     _value = _becomeParentOf(value);
   }
@@ -6854,7 +6862,7 @@
 
   @override
   void set key(Expression string) {
-    _key = _becomeParentOf(string);
+    _key = _becomeParentOf(string as AstNodeImpl);
   }
 
   @override
@@ -6862,7 +6870,7 @@
 
   @override
   void set value(Expression expression) {
-    _value = _becomeParentOf(expression);
+    _value = _becomeParentOf(expression as AstNodeImpl);
   }
 
   @override
@@ -6909,7 +6917,7 @@
   MapLiteralImpl(Token constKeyword, TypeArgumentList typeArguments,
       this.leftBracket, List<MapLiteralEntry> entries, this.rightBracket)
       : super(constKeyword, typeArguments) {
-    _entries = new NodeList<MapLiteralEntry>(this, entries);
+    _entries = new NodeListImpl<MapLiteralEntry>(this, entries);
   }
 
   @override
@@ -7031,17 +7039,17 @@
    * this method declares a getter.
    */
   MethodDeclarationImpl(
-      Comment comment,
+      CommentImpl comment,
       List<Annotation> metadata,
       this.externalKeyword,
       this.modifierKeyword,
-      TypeName returnType,
+      TypeNameImpl returnType,
       this.propertyKeyword,
       this.operatorKeyword,
-      SimpleIdentifier name,
-      TypeParameterList typeParameters,
-      FormalParameterList parameters,
-      FunctionBody body)
+      SimpleIdentifierImpl name,
+      TypeParameterListImpl typeParameters,
+      FormalParameterListImpl parameters,
+      FunctionBodyImpl body)
       : super(comment, metadata) {
     _returnType = _becomeParentOf(returnType);
     _name = _becomeParentOf(name);
@@ -7055,7 +7063,7 @@
 
   @override
   void set body(FunctionBody functionBody) {
-    _body = _becomeParentOf(functionBody);
+    _body = _becomeParentOf(functionBody as AstNodeImpl);
   }
 
   @override
@@ -7077,8 +7085,7 @@
    * getter or a setter.
    */
   @override
-  ExecutableElement get element =>
-      _name != null ? (_name.staticElement as ExecutableElement) : null;
+  ExecutableElement get element => _name?.staticElement as ExecutableElement;
 
   @override
   Token get endToken => _body.endToken;
@@ -7123,7 +7130,7 @@
 
   @override
   void set name(SimpleIdentifier identifier) {
-    _name = _becomeParentOf(identifier);
+    _name = _becomeParentOf(identifier as AstNodeImpl);
   }
 
   @override
@@ -7131,7 +7138,7 @@
 
   @override
   void set parameters(FormalParameterList parameters) {
-    _parameters = _becomeParentOf(parameters);
+    _parameters = _becomeParentOf(parameters as AstNodeImpl);
   }
 
   @override
@@ -7139,7 +7146,7 @@
 
   @override
   void set returnType(TypeName typeName) {
-    _returnType = _becomeParentOf(typeName);
+    _returnType = _becomeParentOf(typeName as AstNodeImpl);
   }
 
   @override
@@ -7147,7 +7154,7 @@
 
   @override
   void set typeParameters(TypeParameterList typeParameters) {
-    _typeParameters = _becomeParentOf(typeParameters);
+    _typeParameters = _becomeParentOf(typeParameters as AstNodeImpl);
   }
 
   @override
@@ -7201,11 +7208,11 @@
    * can be `null` if there is no target.
    */
   MethodInvocationImpl(
-      Expression target,
+      ExpressionImpl target,
       this.operator,
-      SimpleIdentifier methodName,
-      TypeArgumentList typeArguments,
-      ArgumentList argumentList)
+      SimpleIdentifierImpl methodName,
+      TypeArgumentListImpl typeArguments,
+      ArgumentListImpl argumentList)
       : super(typeArguments, argumentList) {
     _target = _becomeParentOf(target);
     _methodName = _becomeParentOf(methodName);
@@ -7243,7 +7250,7 @@
 
   @override
   void set methodName(SimpleIdentifier identifier) {
-    _methodName = _becomeParentOf(identifier);
+    _methodName = _becomeParentOf(identifier as AstNodeImpl);
   }
 
   @override
@@ -7269,7 +7276,7 @@
 
   @override
   void set target(Expression expression) {
-    _target = _becomeParentOf(expression);
+    _target = _becomeParentOf(expression as AstNodeImpl);
   }
 
   @override
@@ -7301,7 +7308,7 @@
    * does not have the corresponding attribute.
    */
   NamedCompilationUnitMemberImpl(
-      Comment comment, List<Annotation> metadata, SimpleIdentifier name)
+      CommentImpl comment, List<Annotation> metadata, SimpleIdentifierImpl name)
       : super(comment, metadata) {
     _name = _becomeParentOf(name);
   }
@@ -7311,7 +7318,7 @@
 
   @override
   void set name(SimpleIdentifier identifier) {
-    _name = _becomeParentOf(identifier);
+    _name = _becomeParentOf(identifier as AstNodeImpl);
   }
 }
 
@@ -7336,7 +7343,7 @@
   /**
    * Initialize a newly created named expression..
    */
-  NamedExpressionImpl(Label name, Expression expression) {
+  NamedExpressionImpl(LabelImpl name, ExpressionImpl expression) {
     _name = _becomeParentOf(name);
     _expression = _becomeParentOf(expression);
   }
@@ -7365,7 +7372,7 @@
 
   @override
   void set expression(Expression expression) {
-    _expression = _becomeParentOf(expression);
+    _expression = _becomeParentOf(expression as AstNodeImpl);
   }
 
   @override
@@ -7373,7 +7380,7 @@
 
   @override
   void set name(Label identifier) {
-    _name = _becomeParentOf(identifier);
+    _name = _becomeParentOf(identifier as AstNodeImpl);
   }
 
   @override
@@ -7437,8 +7444,8 @@
       List<Combinator> combinators,
       this.semicolon)
       : super(comment, metadata, libraryUri) {
-    _configurations = new NodeList<Configuration>(this, configurations);
-    _combinators = new NodeList<Combinator>(this, combinators);
+    _configurations = new NodeListImpl<Configuration>(this, configurations);
+    _combinators = new NodeListImpl<Combinator>(this, combinators);
   }
 
   @override
@@ -7478,7 +7485,7 @@
   /**
    * Initialize a newly created native clause.
    */
-  NativeClauseImpl(this.nativeKeyword, StringLiteral name) {
+  NativeClauseImpl(this.nativeKeyword, StringLiteralImpl name) {
     _name = _becomeParentOf(name);
   }
 
@@ -7497,7 +7504,7 @@
 
   @override
   void set name(StringLiteral name) {
-    _name = _becomeParentOf(name);
+    _name = _becomeParentOf(name as AstNodeImpl);
   }
 
   @override
@@ -7542,7 +7549,7 @@
    * a string literal, and a semicolon.
    */
   NativeFunctionBodyImpl(
-      this.nativeKeyword, StringLiteral stringLiteral, this.semicolon) {
+      this.nativeKeyword, StringLiteralImpl stringLiteral, this.semicolon) {
     _stringLiteral = _becomeParentOf(stringLiteral);
   }
 
@@ -7563,7 +7570,7 @@
 
   @override
   void set stringLiteral(StringLiteral stringLiteral) {
-    _stringLiteral = _becomeParentOf(stringLiteral);
+    _stringLiteral = _becomeParentOf(stringLiteral as AstNodeImpl);
   }
 
   @override
@@ -7645,7 +7652,7 @@
     if (index < 0 || index >= _elements.length) {
       throw new RangeError("Index: $index, Size: ${_elements.length}");
     }
-    _owner._becomeParentOf(node);
+    _owner._becomeParentOf(node as AstNodeImpl);
     _elements[index] = node;
   }
 
@@ -7667,7 +7674,7 @@
     if (nodes != null && !nodes.isEmpty) {
       _elements.addAll(nodes);
       for (E node in nodes) {
-        _owner._becomeParentOf(node);
+        _owner._becomeParentOf(node as AstNodeImpl);
       }
       return true;
     }
@@ -7685,7 +7692,7 @@
     if (index < 0 || index > length) {
       throw new RangeError("Index: $index, Size: ${_elements.length}");
     }
-    _owner._becomeParentOf(node);
+    _owner._becomeParentOf(node as AstNodeImpl);
     if (length == 0) {
       _elements.add(node);
     } else {
@@ -7735,10 +7742,10 @@
    * [comment] and [metadata] can be `null` if the parameter does not have the
    * corresponding attribute.
    */
-  NormalFormalParameterImpl(
-      Comment comment, List<Annotation> metadata, SimpleIdentifier identifier) {
+  NormalFormalParameterImpl(CommentImpl comment, List<Annotation> metadata,
+      SimpleIdentifierImpl identifier) {
     _comment = _becomeParentOf(comment);
-    _metadata = new NodeList<Annotation>(this, metadata);
+    _metadata = new NodeListImpl<Annotation>(this, metadata);
     _identifier = _becomeParentOf(identifier);
   }
 
@@ -7747,7 +7754,7 @@
 
   @override
   void set documentationComment(Comment comment) {
-    _comment = _becomeParentOf(comment);
+    _comment = _becomeParentOf(comment as AstNodeImpl);
   }
 
   @override
@@ -7755,7 +7762,7 @@
 
   @override
   void set identifier(SimpleIdentifier identifier) {
-    _identifier = _becomeParentOf(identifier);
+    _identifier = _becomeParentOf(identifier as AstNodeImpl);
   }
 
   @override
@@ -7887,7 +7894,7 @@
    * Initialize a newly created parenthesized expression.
    */
   ParenthesizedExpressionImpl(
-      this.leftParenthesis, Expression expression, this.rightParenthesis) {
+      this.leftParenthesis, ExpressionImpl expression, this.rightParenthesis) {
     _expression = _becomeParentOf(expression);
   }
 
@@ -7908,13 +7915,24 @@
 
   @override
   void set expression(Expression expression) {
-    _expression = _becomeParentOf(expression);
+    _expression = _becomeParentOf(expression as AstNodeImpl);
   }
 
   @override
   int get precedence => 15;
 
   @override
+  Expression get unParenthesized {
+    // This is somewhat inefficient, but it avoids a stack overflow in the
+    // degenerate case.
+    Expression expression = _expression;
+    while (expression is ParenthesizedExpressionImpl) {
+      expression = (expression as ParenthesizedExpressionImpl)._expression;
+    }
+    return expression;
+  }
+
+  @override
   dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
       visitor.visitParenthesizedExpression(this);
 
@@ -8009,11 +8027,11 @@
    * corresponding attribute.
    */
   PartOfDirectiveImpl(
-      Comment comment,
+      CommentImpl comment,
       List<Annotation> metadata,
       this.partKeyword,
       this.ofKeyword,
-      LibraryIdentifier libraryName,
+      LibraryIdentifierImpl libraryName,
       this.semicolon)
       : super(comment, metadata) {
     _libraryName = _becomeParentOf(libraryName);
@@ -8040,7 +8058,7 @@
 
   @override
   void set libraryName(LibraryIdentifier libraryName) {
-    _libraryName = _becomeParentOf(libraryName);
+    _libraryName = _becomeParentOf(libraryName as AstNodeImpl);
   }
 
   @override
@@ -8093,7 +8111,7 @@
   /**
    * Initialize a newly created postfix expression.
    */
-  PostfixExpressionImpl(Expression operand, this.operator) {
+  PostfixExpressionImpl(ExpressionImpl operand, this.operator) {
     _operand = _becomeParentOf(operand);
   }
 
@@ -8121,7 +8139,7 @@
 
   @override
   void set operand(Expression expression) {
-    _operand = _becomeParentOf(expression);
+    _operand = _becomeParentOf(expression as AstNodeImpl);
   }
 
   @override
@@ -8198,8 +8216,8 @@
   /**
    * Initialize a newly created prefixed identifier.
    */
-  PrefixedIdentifierImpl(
-      SimpleIdentifier prefix, this.period, SimpleIdentifier identifier) {
+  PrefixedIdentifierImpl(SimpleIdentifierImpl prefix, this.period,
+      SimpleIdentifierImpl identifier) {
     _prefix = _becomeParentOf(prefix);
     _identifier = _becomeParentOf(identifier);
   }
@@ -8234,7 +8252,7 @@
 
   @override
   void set identifier(SimpleIdentifier identifier) {
-    _identifier = _becomeParentOf(identifier);
+    _identifier = _becomeParentOf(identifier as AstNodeImpl);
   }
 
   @override
@@ -8262,7 +8280,7 @@
 
   @override
   void set prefix(SimpleIdentifier identifier) {
-    _prefix = _becomeParentOf(identifier);
+    _prefix = _becomeParentOf(identifier as AstNodeImpl);
   }
 
   @override
@@ -8326,7 +8344,7 @@
   /**
    * Initialize a newly created prefix expression.
    */
-  PrefixExpressionImpl(this.operator, Expression operand) {
+  PrefixExpressionImpl(this.operator, ExpressionImpl operand) {
     _operand = _becomeParentOf(operand);
   }
 
@@ -8354,7 +8372,7 @@
 
   @override
   void set operand(Expression expression) {
-    _operand = _becomeParentOf(expression);
+    _operand = _becomeParentOf(expression as AstNodeImpl);
   }
 
   @override
@@ -8434,7 +8452,7 @@
    * Initialize a newly created property access expression.
    */
   PropertyAccessImpl(
-      Expression target, this.operator, SimpleIdentifier propertyName) {
+      ExpressionImpl target, this.operator, SimpleIdentifierImpl propertyName) {
     _target = _becomeParentOf(target);
     _propertyName = _becomeParentOf(propertyName);
   }
@@ -8469,7 +8487,7 @@
 
   @override
   void set propertyName(SimpleIdentifier identifier) {
-    _propertyName = _becomeParentOf(identifier);
+    _propertyName = _becomeParentOf(identifier as AstNodeImpl);
   }
 
   @override
@@ -8492,7 +8510,7 @@
 
   @override
   void set target(Expression expression) {
-    _target = _becomeParentOf(expression);
+    _target = _becomeParentOf(expression as AstNodeImpl);
   }
 
   @override
@@ -8550,7 +8568,7 @@
    * `null` if the constructor being invoked is the unnamed constructor.
    */
   RedirectingConstructorInvocationImpl(this.thisKeyword, this.period,
-      SimpleIdentifier constructorName, ArgumentList argumentList) {
+      SimpleIdentifierImpl constructorName, ArgumentListImpl argumentList) {
     _constructorName = _becomeParentOf(constructorName);
     _argumentList = _becomeParentOf(argumentList);
   }
@@ -8560,7 +8578,7 @@
 
   @override
   void set argumentList(ArgumentList argumentList) {
-    _argumentList = _becomeParentOf(argumentList);
+    _argumentList = _becomeParentOf(argumentList as AstNodeImpl);
   }
 
   @override
@@ -8578,7 +8596,7 @@
 
   @override
   void set constructorName(SimpleIdentifier identifier) {
-    _constructorName = _becomeParentOf(identifier);
+    _constructorName = _becomeParentOf(identifier as AstNodeImpl);
   }
 
   @override
@@ -8663,7 +8681,7 @@
    * if no explicit value was provided.
    */
   ReturnStatementImpl(
-      this.returnKeyword, Expression expression, this.semicolon) {
+      this.returnKeyword, ExpressionImpl expression, this.semicolon) {
     _expression = _becomeParentOf(expression);
   }
 
@@ -8682,7 +8700,7 @@
 
   @override
   void set expression(Expression expression) {
-    _expression = _becomeParentOf(expression);
+    _expression = _becomeParentOf(expression as AstNodeImpl);
   }
 
   @override
@@ -8748,7 +8766,7 @@
    */
   ShowCombinatorImpl(Token keyword, List<SimpleIdentifier> shownNames)
       : super(keyword) {
-    _shownNames = new NodeList<SimpleIdentifier>(this, shownNames);
+    _shownNames = new NodeListImpl<SimpleIdentifier>(this, shownNames);
   }
 
   @override
@@ -8799,8 +8817,8 @@
    * corresponding attribute. The [keyword] can be `null` if a type was
    * specified. The [type] must be `null` if the keyword is 'var'.
    */
-  SimpleFormalParameterImpl(Comment comment, List<Annotation> metadata,
-      this.keyword, TypeName type, SimpleIdentifier identifier)
+  SimpleFormalParameterImpl(CommentImpl comment, List<Annotation> metadata,
+      this.keyword, TypeNameImpl type, SimpleIdentifierImpl identifier)
       : super(comment, metadata, identifier) {
     _type = _becomeParentOf(type);
   }
@@ -8836,7 +8854,7 @@
 
   @override
   void set type(TypeName typeName) {
-    _type = _becomeParentOf(typeName);
+    _type = _becomeParentOf(typeName as AstNodeImpl);
   }
 
   @override
@@ -9184,7 +9202,7 @@
    * Initialize a newly created string interpolation expression.
    */
   StringInterpolationImpl(List<InterpolationElement> elements) {
-    _elements = new NodeList<InterpolationElement>(this, elements);
+    _elements = new NodeListImpl<InterpolationElement>(this, elements);
   }
 
   @override
@@ -9411,7 +9429,7 @@
    * unnamed constructor.
    */
   SuperConstructorInvocationImpl(this.superKeyword, this.period,
-      SimpleIdentifier constructorName, ArgumentList argumentList) {
+      SimpleIdentifierImpl constructorName, ArgumentListImpl argumentList) {
     _constructorName = _becomeParentOf(constructorName);
     _argumentList = _becomeParentOf(argumentList);
   }
@@ -9421,7 +9439,7 @@
 
   @override
   void set argumentList(ArgumentList argumentList) {
-    _argumentList = _becomeParentOf(argumentList);
+    _argumentList = _becomeParentOf(argumentList as AstNodeImpl);
   }
 
   @override
@@ -9439,7 +9457,7 @@
 
   @override
   void set constructorName(SimpleIdentifier identifier) {
-    _constructorName = _becomeParentOf(identifier);
+    _constructorName = _becomeParentOf(identifier as AstNodeImpl);
   }
 
   @override
@@ -9511,7 +9529,7 @@
    * Initialize a newly created switch case. The list of [labels] can be `null`
    * if there are no labels.
    */
-  SwitchCaseImpl(List<Label> labels, Token keyword, Expression expression,
+  SwitchCaseImpl(List<Label> labels, Token keyword, ExpressionImpl expression,
       Token colon, List<Statement> statements)
       : super(labels, keyword, colon, statements) {
     _expression = _becomeParentOf(expression);
@@ -9530,7 +9548,7 @@
 
   @override
   void set expression(Expression expression) {
-    _expression = _becomeParentOf(expression);
+    _expression = _becomeParentOf(expression as AstNodeImpl);
   }
 
   @override
@@ -9612,8 +9630,8 @@
    */
   SwitchMemberImpl(List<Label> labels, this.keyword, this.colon,
       List<Statement> statements) {
-    _labels = new NodeList<Label>(this, labels);
-    _statements = new NodeList<Statement>(this, statements);
+    _labels = new NodeListImpl<Label>(this, labels);
+    _statements = new NodeListImpl<Statement>(this, statements);
   }
 
   @override
@@ -9689,13 +9707,13 @@
   SwitchStatementImpl(
       this.switchKeyword,
       this.leftParenthesis,
-      Expression expression,
+      ExpressionImpl expression,
       this.rightParenthesis,
       this.leftBracket,
       List<SwitchMember> members,
       this.rightBracket) {
     _expression = _becomeParentOf(expression);
-    _members = new NodeList<SwitchMember>(this, members);
+    _members = new NodeListImpl<SwitchMember>(this, members);
   }
 
   @override
@@ -9719,7 +9737,7 @@
 
   @override
   void set expression(Expression expression) {
-    _expression = _becomeParentOf(expression);
+    _expression = _becomeParentOf(expression as AstNodeImpl);
   }
 
   @override
@@ -9839,7 +9857,7 @@
   /**
    * Initialize a newly created throw expression.
    */
-  ThrowExpressionImpl(this.throwKeyword, Expression expression) {
+  ThrowExpressionImpl(this.throwKeyword, ExpressionImpl expression) {
     _expression = _becomeParentOf(expression);
   }
 
@@ -9863,7 +9881,7 @@
 
   @override
   void set expression(Expression expression) {
-    _expression = _becomeParentOf(expression);
+    _expression = _becomeParentOf(expression as AstNodeImpl);
   }
 
   @override
@@ -9903,8 +9921,11 @@
    * of the [comment] and [metadata] can be `null` if the variable does not have
    * the corresponding attribute.
    */
-  TopLevelVariableDeclarationImpl(Comment comment, List<Annotation> metadata,
-      VariableDeclarationList variableList, this.semicolon)
+  TopLevelVariableDeclarationImpl(
+      CommentImpl comment,
+      List<Annotation> metadata,
+      VariableDeclarationListImpl variableList,
+      this.semicolon)
       : super(comment, metadata) {
     _variableList = _becomeParentOf(variableList);
   }
@@ -9927,7 +9948,7 @@
 
   @override
   void set variables(VariableDeclarationList variables) {
-    _variableList = _becomeParentOf(variables);
+    _variableList = _becomeParentOf(variables as AstNodeImpl);
   }
 
   @override
@@ -9983,10 +10004,14 @@
    * `null` if there are no catch clauses. The [finallyKeyword] and
    * [finallyBlock] can be `null` if there is no finally clause.
    */
-  TryStatementImpl(this.tryKeyword, Block body, List<CatchClause> catchClauses,
-      this.finallyKeyword, Block finallyBlock) {
+  TryStatementImpl(
+      this.tryKeyword,
+      BlockImpl body,
+      List<CatchClause> catchClauses,
+      this.finallyKeyword,
+      BlockImpl finallyBlock) {
     _body = _becomeParentOf(body);
-    _catchClauses = new NodeList<CatchClause>(this, catchClauses);
+    _catchClauses = new NodeListImpl<CatchClause>(this, catchClauses);
     _finallyBlock = _becomeParentOf(finallyBlock);
   }
 
@@ -9998,7 +10023,7 @@
 
   @override
   void set body(Block block) {
-    _body = _becomeParentOf(block);
+    _body = _becomeParentOf(block as AstNodeImpl);
   }
 
   @override
@@ -10029,7 +10054,7 @@
 
   @override
   void set finallyBlock(Block block) {
-    _finallyBlock = _becomeParentOf(block);
+    _finallyBlock = _becomeParentOf(block as AstNodeImpl);
   }
 
   @override
@@ -10109,7 +10134,7 @@
    */
   TypeArgumentListImpl(
       this.leftBracket, List<TypeName> arguments, this.rightBracket) {
-    _arguments = new NodeList<TypeName>(this, arguments);
+    _arguments = new NodeListImpl<TypeName>(this, arguments);
   }
 
   @override
@@ -10163,7 +10188,7 @@
    * if the literal is not a constant. The [typeArguments] can be `null` if no
    * type arguments were declared.
    */
-  TypedLiteralImpl(this.constKeyword, TypeArgumentList typeArguments) {
+  TypedLiteralImpl(this.constKeyword, TypeArgumentListImpl typeArguments) {
     _typeArguments = _becomeParentOf(typeArguments);
   }
 
@@ -10172,7 +10197,7 @@
 
   @override
   void set typeArguments(TypeArgumentList typeArguments) {
-    _typeArguments = _becomeParentOf(typeArguments);
+    _typeArguments = _becomeParentOf(typeArguments as AstNodeImpl);
   }
 
   ChildEntities get _childEntities =>
@@ -10211,7 +10236,7 @@
    * Initialize a newly created type name. The [typeArguments] can be `null` if
    * there are no type arguments.
    */
-  TypeNameImpl(Identifier name, TypeArgumentList typeArguments) {
+  TypeNameImpl(IdentifierImpl name, TypeArgumentListImpl typeArguments) {
     _name = _becomeParentOf(name);
     _typeArguments = _becomeParentOf(typeArguments);
   }
@@ -10248,7 +10273,7 @@
 
   @override
   void set name(Identifier identifier) {
-    _name = _becomeParentOf(identifier);
+    _name = _becomeParentOf(identifier as AstNodeImpl);
   }
 
   @override
@@ -10256,7 +10281,7 @@
 
   @override
   void set typeArguments(TypeArgumentList typeArguments) {
-    _typeArguments = _becomeParentOf(typeArguments);
+    _typeArguments = _becomeParentOf(typeArguments as AstNodeImpl);
   }
 
   @override
@@ -10300,8 +10325,8 @@
    * corresponding attribute. The [extendsKeyword] and [bound] can be `null` if
    * the parameter does not have an upper bound.
    */
-  TypeParameterImpl(Comment comment, List<Annotation> metadata,
-      SimpleIdentifier name, this.extendsKeyword, TypeName bound)
+  TypeParameterImpl(CommentImpl comment, List<Annotation> metadata,
+      SimpleIdentifierImpl name, this.extendsKeyword, TypeNameImpl bound)
       : super(comment, metadata) {
     _name = _becomeParentOf(name);
     _bound = _becomeParentOf(bound);
@@ -10312,7 +10337,7 @@
 
   @override
   void set bound(TypeName typeName) {
-    _bound = _becomeParentOf(typeName);
+    _bound = _becomeParentOf(typeName as AstNodeImpl);
   }
 
   @override
@@ -10321,7 +10346,7 @@
 
   @override
   TypeParameterElement get element =>
-      _name != null ? (_name.staticElement as TypeParameterElement) : null;
+      _name?.staticElement as TypeParameterElement;
 
   @override
   Token get endToken {
@@ -10339,7 +10364,7 @@
 
   @override
   void set name(SimpleIdentifier identifier) {
-    _name = _becomeParentOf(identifier);
+    _name = _becomeParentOf(identifier as AstNodeImpl);
   }
 
   @override
@@ -10381,7 +10406,7 @@
    */
   TypeParameterListImpl(
       this.leftBracket, List<TypeParameter> typeParameters, this.rightBracket) {
-    _typeParameters = new NodeList<TypeParameter>(this, typeParameters);
+    _typeParameters = new NodeListImpl<TypeParameter>(this, typeParameters);
   }
 
   @override
@@ -10446,7 +10471,7 @@
    * corresponding attribute.
    */
   UriBasedDirectiveImpl(
-      Comment comment, List<Annotation> metadata, StringLiteral uri)
+      CommentImpl comment, List<Annotation> metadata, StringLiteralImpl uri)
       : super(comment, metadata) {
     _uri = _becomeParentOf(uri);
   }
@@ -10456,7 +10481,7 @@
 
   @override
   void set uri(StringLiteral uri) {
-    _uri = _becomeParentOf(uri);
+    _uri = _becomeParentOf(uri as AstNodeImpl);
   }
 
   @override
@@ -10550,7 +10575,7 @@
    * [initializer] can be `null` if there is no initializer.
    */
   VariableDeclarationImpl(
-      SimpleIdentifier name, this.equals, Expression initializer)
+      SimpleIdentifierImpl name, this.equals, ExpressionImpl initializer)
       : super(null, null) {
     _name = _becomeParentOf(name);
     _initializer = _becomeParentOf(initializer);
@@ -10578,8 +10603,7 @@
   }
 
   @override
-  VariableElement get element =>
-      _name != null ? (_name.staticElement as VariableElement) : null;
+  VariableElement get element => _name?.staticElement as VariableElement;
 
   @override
   Token get endToken {
@@ -10597,7 +10621,7 @@
 
   @override
   void set initializer(Expression expression) {
-    _initializer = _becomeParentOf(expression);
+    _initializer = _becomeParentOf(expression as AstNodeImpl);
   }
 
   @override
@@ -10617,7 +10641,7 @@
 
   @override
   void set name(SimpleIdentifier identifier) {
-    _name = _becomeParentOf(identifier);
+    _name = _becomeParentOf(identifier as AstNodeImpl);
   }
 
   @override
@@ -10668,11 +10692,11 @@
    * the corresponding attribute. The [keyword] can be `null` if a type was
    * specified. The [type] must be `null` if the keyword is 'var'.
    */
-  VariableDeclarationListImpl(Comment comment, List<Annotation> metadata,
-      this.keyword, TypeName type, List<VariableDeclaration> variables)
+  VariableDeclarationListImpl(CommentImpl comment, List<Annotation> metadata,
+      this.keyword, TypeNameImpl type, List<VariableDeclaration> variables)
       : super(comment, metadata) {
     _type = _becomeParentOf(type);
-    _variables = new NodeList<VariableDeclaration>(this, variables);
+    _variables = new NodeListImpl<VariableDeclaration>(this, variables);
   }
 
   @override
@@ -10706,7 +10730,7 @@
 
   @override
   void set type(TypeName typeName) {
-    _type = _becomeParentOf(typeName);
+    _type = _becomeParentOf(typeName as AstNodeImpl);
   }
 
   @override
@@ -10747,7 +10771,7 @@
    * Initialize a newly created variable declaration statement.
    */
   VariableDeclarationStatementImpl(
-      VariableDeclarationList variableList, this.semicolon) {
+      VariableDeclarationListImpl variableList, this.semicolon) {
     _variableList = _becomeParentOf(variableList);
   }
 
@@ -10766,7 +10790,7 @@
 
   @override
   void set variables(VariableDeclarationList variables) {
-    _variableList = _becomeParentOf(variables);
+    _variableList = _becomeParentOf(variables as AstNodeImpl);
   }
 
   @override
@@ -10815,7 +10839,7 @@
    * Initialize a newly created while statement.
    */
   WhileStatementImpl(this.whileKeyword, this.leftParenthesis,
-      Expression condition, this.rightParenthesis, Statement body) {
+      ExpressionImpl condition, this.rightParenthesis, StatementImpl body) {
     _condition = _becomeParentOf(condition);
     _body = _becomeParentOf(body);
   }
@@ -10828,7 +10852,7 @@
 
   @override
   void set body(Statement statement) {
-    _body = _becomeParentOf(statement);
+    _body = _becomeParentOf(statement as AstNodeImpl);
   }
 
   @override
@@ -10844,7 +10868,7 @@
 
   @override
   void set condition(Expression expression) {
-    _condition = _becomeParentOf(expression);
+    _condition = _becomeParentOf(expression as AstNodeImpl);
   }
 
   @override
@@ -10882,7 +10906,7 @@
    * Initialize a newly created with clause.
    */
   WithClauseImpl(this.withKeyword, List<TypeName> mixinTypes) {
-    _mixinTypes = new NodeList<TypeName>(this, mixinTypes);
+    _mixinTypes = new NodeListImpl<TypeName>(this, mixinTypes);
   }
 
   @override
@@ -10942,7 +10966,7 @@
    * star was provided.
    */
   YieldStatementImpl(
-      this.yieldKeyword, this.star, Expression expression, this.semicolon) {
+      this.yieldKeyword, this.star, ExpressionImpl expression, this.semicolon) {
     _expression = _becomeParentOf(expression);
   }
 
@@ -10974,7 +10998,7 @@
 
   @override
   void set expression(Expression expression) {
-    _expression = _becomeParentOf(expression);
+    _expression = _becomeParentOf(expression as AstNodeImpl);
   }
 
   @override
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
index a87c085..cde4825 100644
--- a/pkg/analyzer/lib/src/dart/ast/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -3679,7 +3679,7 @@
    */
   NodeLocator(int startOffset, [int endOffset])
       : this._startOffset = startOffset,
-        this._endOffset = endOffset == null ? startOffset : endOffset;
+        this._endOffset = endOffset ?? startOffset;
 
   /**
    * Return the node that was found that corresponds to the given source range
@@ -3783,7 +3783,7 @@
    */
   NodeLocator2(int startOffset, [int endOffset])
       : this._startOffset = startOffset,
-        this._endOffset = endOffset == null ? startOffset : endOffset;
+        this._endOffset = endOffset ?? startOffset;
 
   /**
    * Search within the given AST [node] and return the node that was found,
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index 7f0a7b8..5c5a74d 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -85,10 +85,9 @@
    */
   ConstantEvaluationEngine(this.typeProvider, this._declaredVariables,
       {ConstantEvaluationValidator validator, TypeSystem typeSystem})
-      : validator = validator != null
-            ? validator
-            : new ConstantEvaluationValidator_ForProduction(),
-        typeSystem = typeSystem != null ? typeSystem : new TypeSystemImpl();
+      : validator =
+            validator ?? new ConstantEvaluationValidator_ForProduction(),
+        typeSystem = typeSystem ?? new TypeSystemImpl();
 
   /**
    * Check that the arguments to a call to fromEnvironment() are correct. The
@@ -1476,7 +1475,7 @@
    */
   void _error(AstNode node, ErrorCode code) {
     _errorReporter.reportErrorForNode(
-        code == null ? CompileTimeErrorCode.INVALID_CONSTANT : code, node);
+        code ?? CompileTimeErrorCode.INVALID_CONSTANT, node);
   }
 
   /**
@@ -1929,8 +1928,7 @@
    * compile time constant if the errors would have been reported by other parts
    * of the analysis engine.
    */
-  List<AnalysisError> get errors =>
-      _errors == null ? AnalysisError.NO_ERRORS : _errors;
+  List<AnalysisError> get errors => _errors ?? AnalysisError.NO_ERRORS;
 
   /**
    * Return `true` if the expression is a compile-time constant expression that
@@ -1973,7 +1971,7 @@
   final DartObjectImpl value;
 
   EvaluationResultImpl(this.value, [List<AnalysisError> errors]) {
-    this._errors = errors == null ? <AnalysisError>[] : errors;
+    this._errors = errors ?? <AnalysisError>[];
   }
 
   List<AnalysisError> get errors => _errors;
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 567c6fe..2175e9e 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -166,11 +166,8 @@
   List<ConstructorElement> get constructors {
     if (!isMixinApplication) {
       assert(_constructors != null);
-      return _constructors == null
-          ? ConstructorElement.EMPTY_LIST
-          : _constructors;
+      return _constructors ?? ConstructorElement.EMPTY_LIST;
     }
-
     return _computeMixinAppConstructors();
   }
 
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index 14e459e..7d08ca8 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -1564,8 +1564,7 @@
     }
     HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>();
     InterfaceType supertype = superclass;
-    ClassElement supertypeElement =
-        supertype == null ? null : supertype.element;
+    ClassElement supertypeElement = supertype?.element;
     while (supertype != null && !visitedClasses.contains(supertypeElement)) {
       visitedClasses.add(supertypeElement);
       PropertyAccessorElement element = supertype.getGetter(getterName);
@@ -1579,7 +1578,7 @@
         }
       }
       supertype = supertype.superclass;
-      supertypeElement = supertype == null ? null : supertype.element;
+      supertypeElement = supertype?.element;
     }
     return null;
   }
@@ -1669,8 +1668,7 @@
     }
     HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>();
     InterfaceType supertype = superclass;
-    ClassElement supertypeElement =
-        supertype == null ? null : supertype.element;
+    ClassElement supertypeElement = supertype?.element;
     while (supertype != null && !visitedClasses.contains(supertypeElement)) {
       visitedClasses.add(supertypeElement);
       MethodElement element = supertype.getMethod(methodName);
@@ -1684,7 +1682,7 @@
         }
       }
       supertype = supertype.superclass;
-      supertypeElement = supertype == null ? null : supertype.element;
+      supertypeElement = supertype?.element;
     }
     return null;
   }
@@ -1710,8 +1708,7 @@
     }
     HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>();
     InterfaceType supertype = superclass;
-    ClassElement supertypeElement =
-        supertype == null ? null : supertype.element;
+    ClassElement supertypeElement = supertype?.element;
     while (supertype != null && !visitedClasses.contains(supertypeElement)) {
       visitedClasses.add(supertypeElement);
       PropertyAccessorElement element = supertype.getSetter(setterName);
@@ -1725,7 +1722,7 @@
         }
       }
       supertype = supertype.superclass;
-      supertypeElement = supertype == null ? null : supertype.element;
+      supertypeElement = supertype?.element;
     }
     return null;
   }
diff --git a/pkg/analyzer/lib/src/dart/resolver/inheritance_manager.dart b/pkg/analyzer/lib/src/dart/resolver/inheritance_manager.dart
index 76cedf7..3f449de 100644
--- a/pkg/analyzer/lib/src/dart/resolver/inheritance_manager.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/inheritance_manager.dart
@@ -461,8 +461,7 @@
   List<Map<String, ExecutableElement>> _gatherInterfaceLookupMaps(
       ClassElement classElt, HashSet<ClassElement> visitedInterfaces) {
     InterfaceType supertype = classElt.supertype;
-    ClassElement superclassElement =
-        supertype != null ? supertype.element : null;
+    ClassElement superclassElement = supertype?.element;
     List<InterfaceType> mixins = classElt.mixins;
     List<InterfaceType> interfaces = classElt.interfaces;
     // Recursively collect the list of mappings from all of the interface types
diff --git a/pkg/analyzer/lib/src/dart/resolver/scope.dart b/pkg/analyzer/lib/src/dart/resolver/scope.dart
index f646167..0b17d71 100644
--- a/pkg/analyzer/lib/src/dart/resolver/scope.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/scope.dart
@@ -324,11 +324,8 @@
   LabelScope lookup(String targetLabel) {
     if (_label == targetLabel) {
       return this;
-    } else if (_outerScope != null) {
-      return _outerScope.lookup(targetLabel);
-    } else {
-      return null;
     }
+    return _outerScope?.lookup(targetLabel);
   }
 }
 
diff --git a/pkg/analyzer/lib/src/dart/scanner/reader.dart b/pkg/analyzer/lib/src/dart/scanner/reader.dart
index 1f5d87d..81f506e 100644
--- a/pkg/analyzer/lib/src/dart/scanner/reader.dart
+++ b/pkg/analyzer/lib/src/dart/scanner/reader.dart
@@ -109,12 +109,12 @@
   /**
    * The number of characters in the string.
    */
-  int _stringLength = 0;
+  int _stringLength;
 
   /**
-   * The index, relative to the string, of the last character that was read.
+   * The index, relative to the string, of the next character to be read.
    */
-  int _charOffset = 0;
+  int _charOffset;
 
   /**
    * Initialize a newly created reader to read the characters in the given
@@ -122,35 +122,35 @@
    */
   CharSequenceReader(this._sequence) {
     this._stringLength = _sequence.length;
-    this._charOffset = -1;
+    this._charOffset = 0;
   }
 
   @override
-  int get offset => _charOffset;
+  int get offset => _charOffset - 1;
 
   @override
   void set offset(int offset) {
-    _charOffset = offset;
+    _charOffset = offset + 1;
   }
 
   @override
   int advance() {
-    if (_charOffset + 1 >= _stringLength) {
+    if (_charOffset >= _stringLength) {
       return -1;
     }
-    return _sequence.codeUnitAt(++_charOffset);
+    return _sequence.codeUnitAt(_charOffset++);
   }
 
   @override
   String getString(int start, int endDelta) =>
-      _sequence.substring(start, _charOffset + 1 + endDelta).toString();
+      _sequence.substring(start, _charOffset + endDelta);
 
   @override
   int peek() {
-    if (_charOffset + 1 >= _stringLength) {
+    if (_charOffset >= _stringLength) {
       return -1;
     }
-    return _sequence.codeUnitAt(_charOffset + 1);
+    return _sequence.codeUnitAt(_charOffset);
   }
 }
 
diff --git a/pkg/analyzer/lib/src/generated/constant.dart b/pkg/analyzer/lib/src/generated/constant.dart
index b3a9e78..0bd0f84 100644
--- a/pkg/analyzer/lib/src/generated/constant.dart
+++ b/pkg/analyzer/lib/src/generated/constant.dart
@@ -120,7 +120,7 @@
    * types.
    */
   ConstantEvaluator(this._source, this._typeProvider, {TypeSystem typeSystem})
-      : _typeSystem = typeSystem != null ? typeSystem : new TypeSystemImpl();
+      : _typeSystem = typeSystem ?? new TypeSystemImpl();
 
   EvaluationResult evaluate(Expression expression) {
     RecordingErrorListener errorListener = new RecordingErrorListener();
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index 833e55e..c7b502f 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -613,7 +613,7 @@
     } else if (methodName.name == FunctionElement.LOAD_LIBRARY_NAME &&
         _isDeferredPrefix(target)) {
       if (node.operator.type == TokenType.QUESTION_PERIOD) {
-        _resolver.reportErrorForNode(
+        _resolver.errorReporter.reportErrorForNode(
             CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
             target,
             [(target as SimpleIdentifier).name]);
@@ -749,7 +749,8 @@
         identical(errorCode,
             CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT) ||
         identical(errorCode, StaticTypeWarningCode.UNDEFINED_FUNCTION)) {
-      _resolver.reportErrorForNode(errorCode, methodName, [methodName.name]);
+      _resolver.errorReporter
+          .reportErrorForNode(errorCode, methodName, [methodName.name]);
     } else if (identical(errorCode, StaticTypeWarningCode.UNDEFINED_METHOD)) {
       String targetTypeName;
       if (target == null) {
@@ -798,7 +799,7 @@
             }
           }
         }
-        targetTypeName = targetType == null ? null : targetType.displayName;
+        targetTypeName = targetType?.displayName;
         ErrorCode proxyErrorCode = (generatedWithTypePropagation
             ? HintCode.UNDEFINED_METHOD
             : StaticTypeWarningCode.UNDEFINED_METHOD);
@@ -817,8 +818,10 @@
       }
       DartType targetType = getSuperType(_getStaticType(target));
       String targetTypeName = targetType?.name;
-      _resolver.reportErrorForNode(StaticTypeWarningCode.UNDEFINED_SUPER_METHOD,
-          methodName, [methodName.name, targetTypeName]);
+      _resolver.errorReporter.reportErrorForNode(
+          StaticTypeWarningCode.UNDEFINED_SUPER_METHOD,
+          methodName,
+          [methodName.name, targetTypeName]);
     }
     return null;
   }
@@ -892,17 +895,21 @@
       }
       if (element == null) {
         if (identifier.inSetterContext()) {
-          _resolver.reportErrorForNode(StaticWarningCode.UNDEFINED_SETTER,
-              identifier, [identifier.name, prefixElement.name]);
+          _resolver.errorReporter.reportErrorForNode(
+              StaticWarningCode.UNDEFINED_SETTER,
+              identifier,
+              [identifier.name, prefixElement.name]);
           return null;
         }
         AstNode parent = node.parent;
         if (parent is Annotation) {
-          _resolver.reportErrorForNode(
+          _resolver.errorReporter.reportErrorForNode(
               CompileTimeErrorCode.INVALID_ANNOTATION, parent);
         } else {
-          _resolver.reportErrorForNode(StaticWarningCode.UNDEFINED_GETTER,
-              identifier, [identifier.name, prefixElement.name]);
+          _resolver.errorReporter.reportErrorForNode(
+              StaticWarningCode.UNDEFINED_GETTER,
+              identifier,
+              [identifier.name, prefixElement.name]);
         }
         return null;
       }
@@ -1077,25 +1084,25 @@
     ClassElement enclosingClass = _resolver.enclosingClass;
     if (_isFactoryConstructorReturnType(node) &&
         !identical(element, enclosingClass)) {
-      _resolver.reportErrorForNode(
+      _resolver.errorReporter.reportErrorForNode(
           CompileTimeErrorCode.INVALID_FACTORY_NAME_NOT_A_CLASS, node);
     } else if (_isConstructorReturnType(node) &&
         !identical(element, enclosingClass)) {
-      _resolver.reportErrorForNode(
+      _resolver.errorReporter.reportErrorForNode(
           CompileTimeErrorCode.INVALID_CONSTRUCTOR_NAME, node);
       element = null;
     } else if (element == null ||
         (element is PrefixElement && !_isValidAsPrefix(node))) {
       // TODO(brianwilkerson) Recover from this error.
       if (_isConstructorReturnType(node)) {
-        _resolver.reportErrorForNode(
+        _resolver.errorReporter.reportErrorForNode(
             CompileTimeErrorCode.INVALID_CONSTRUCTOR_NAME, node);
       } else {
         if (parent is Annotation) {
-          _resolver.reportErrorForNode(
+          _resolver.errorReporter.reportErrorForNode(
               CompileTimeErrorCode.INVALID_ANNOTATION, parent);
         } else if (element != null) {
-          _resolver.reportErrorForNode(
+          _resolver.errorReporter.reportErrorForNode(
               CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
               node,
               [element.name]);
@@ -1137,19 +1144,19 @@
       return null;
     }
     SimpleIdentifier name = node.constructorName;
-    String superName = name != null ? name.name : null;
+    String superName = name?.name;
     ConstructorElement element =
         superType.lookUpConstructor(superName, _definingLibrary);
     if (element == null ||
         (!enclosingClass.doesMixinLackConstructors &&
             !enclosingClass.isSuperConstructorAccessible(element))) {
       if (name != null) {
-        _resolver.reportErrorForNode(
+        _resolver.errorReporter.reportErrorForNode(
             CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER,
             node,
             [superType.displayName, name]);
       } else {
-        _resolver.reportErrorForNode(
+        _resolver.errorReporter.reportErrorForNode(
             CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT,
             node,
             [superType.displayName]);
@@ -1157,7 +1164,7 @@
       return null;
     } else {
       if (element.isFactory) {
-        _resolver.reportErrorForNode(
+        _resolver.errorReporter.reportErrorForNode(
             CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR, node, [element]);
       }
     }
@@ -1177,7 +1184,7 @@
   @override
   Object visitSuperExpression(SuperExpression node) {
     if (!_isSuperInValidContext(node)) {
-      _resolver.reportErrorForNode(
+      _resolver.errorReporter.reportErrorForNode(
           CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT, node);
     }
     return super.visitSuperExpression(node);
@@ -1526,7 +1533,7 @@
 
       NodeList<TypeName> arguments = typeArguments?.arguments;
       if (arguments != null && arguments.length != parameters.length) {
-        _resolver.reportErrorForNode(
+        _resolver.errorReporter.reportErrorForNode(
             StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS,
             node,
             [invokeType, parameters.length, arguments?.length ?? 0]);
@@ -1635,7 +1642,7 @@
       if (labelScope == null) {
         // There are no labels in scope, so by definition the label is
         // undefined.
-        _resolver.reportErrorForNode(
+        _resolver.errorReporter.reportErrorForNode(
             CompileTimeErrorCode.LABEL_UNDEFINED, labelNode, [labelNode.name]);
         return null;
       }
@@ -1643,7 +1650,7 @@
       if (definingScope == null) {
         // No definition of the given label name could be found in any
         // enclosing scope.
-        _resolver.reportErrorForNode(
+        _resolver.errorReporter.reportErrorForNode(
             CompileTimeErrorCode.LABEL_UNDEFINED, labelNode, [labelNode.name]);
         return null;
       }
@@ -1652,8 +1659,10 @@
       ExecutableElement labelContainer = definingScope.element
           .getAncestor((element) => element is ExecutableElement);
       if (!identical(labelContainer, _resolver.enclosingFunction)) {
-        _resolver.reportErrorForNode(CompileTimeErrorCode.LABEL_IN_OUTER_SCOPE,
-            labelNode, [labelNode.name]);
+        _resolver.errorReporter.reportErrorForNode(
+            CompileTimeErrorCode.LABEL_IN_OUTER_SCOPE,
+            labelNode,
+            [labelNode.name]);
       }
       return definingScope.node;
     }
@@ -1815,7 +1824,7 @@
   void _recordUndefinedNode(Element declaringElement, ErrorCode errorCode,
       AstNode node, List<Object> arguments) {
     if (_doesntHaveProxy(declaringElement)) {
-      _resolver.reportErrorForNode(errorCode, node, arguments);
+      _resolver.errorReporter.reportErrorForNode(errorCode, node, arguments);
     }
   }
 
@@ -1830,7 +1839,8 @@
   void _recordUndefinedOffset(Element declaringElement, ErrorCode errorCode,
       int offset, int length, List<Object> arguments) {
     if (_doesntHaveProxy(declaringElement)) {
-      _resolver.reportErrorForOffset(errorCode, offset, length, arguments);
+      _resolver.errorReporter
+          .reportErrorForOffset(errorCode, offset, length, arguments);
     }
   }
 
@@ -1845,7 +1855,7 @@
   void _recordUndefinedToken(Element declaringElement, ErrorCode errorCode,
       Token token, List<Object> arguments) {
     if (_doesntHaveProxy(declaringElement)) {
-      _resolver.reportErrorForToken(errorCode, token, arguments);
+      _resolver.errorReporter.reportErrorForToken(errorCode, token, arguments);
     }
   }
 
@@ -1951,7 +1961,7 @@
     }
     // we need constructor
     if (constructor == null) {
-      _resolver.reportErrorForNode(
+      _resolver.errorReporter.reportErrorForNode(
           CompileTimeErrorCode.INVALID_ANNOTATION, annotation);
       return;
     }
@@ -1965,19 +1975,19 @@
       Annotation annotation, PropertyAccessorElement accessorElement) {
     // accessor should be synthetic
     if (!accessorElement.isSynthetic) {
-      _resolver.reportErrorForNode(
+      _resolver.errorReporter.reportErrorForNode(
           CompileTimeErrorCode.INVALID_ANNOTATION, annotation);
       return;
     }
     // variable should be constant
     VariableElement variableElement = accessorElement.variable;
     if (!variableElement.isConst) {
-      _resolver.reportErrorForNode(
+      _resolver.errorReporter.reportErrorForNode(
           CompileTimeErrorCode.INVALID_ANNOTATION, annotation);
     }
     // no arguments
     if (annotation.arguments != null) {
-      _resolver.reportErrorForNode(
+      _resolver.errorReporter.reportErrorForNode(
           CompileTimeErrorCode.ANNOTATION_WITH_NON_CLASS,
           annotation.name,
           [annotation.name]);
@@ -2017,7 +2027,7 @@
   List<ParameterElement> _resolveArgumentsToParameters(bool reportAsError,
       ArgumentList argumentList, List<ParameterElement> parameters) {
     return ResolverVisitor.resolveArgumentsToParameters(
-        argumentList, parameters, _resolver.reportErrorForNode,
+        argumentList, parameters, _resolver.errorReporter.reportErrorForNode,
         reportAsError: reportAsError);
   }
 
@@ -2183,7 +2193,7 @@
       Element targetElement = target.staticElement;
       if (targetElement is PrefixElement) {
         if (isConditional) {
-          _resolver.reportErrorForNode(
+          _resolver.errorReporter.reportErrorForNode(
               CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
               target,
               [target.name]);
@@ -2288,9 +2298,8 @@
           shouldReportMissingMember_static ? staticType : propagatedType;
       Element staticOrPropagatedEnclosingElt = staticOrPropagatedType.element;
       bool isStaticProperty = _isStatic(staticOrPropagatedEnclosingElt);
-      DartType displayType = staticOrPropagatedType != null
-          ? staticOrPropagatedType
-          : propagatedType != null ? propagatedType : staticType;
+      DartType displayType =
+          staticOrPropagatedType ?? propagatedType ?? staticType;
       // Special getter cases.
       if (propertyName.inGetterContext()) {
         if (!isStaticProperty &&
@@ -2306,7 +2315,7 @@
             return;
           } else if (staticOrPropagatedEnclosingElt.isEnum &&
               propertyName.name == "_name") {
-            _resolver.reportErrorForNode(
+            _resolver.errorReporter.reportErrorForNode(
                 CompileTimeErrorCode.ACCESS_PRIVATE_ENUM_FIELD,
                 propertyName,
                 [propertyName.name]);
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index 96333ad..8db8ee0 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -816,7 +816,7 @@
    * analysis engine to the given [logger].
    */
   void set logger(Logger logger) {
-    this._logger = logger == null ? Logger.NULL : logger;
+    this._logger = logger ?? Logger.NULL;
   }
 
   /**
@@ -1200,14 +1200,6 @@
   bool enableAsync = true;
 
   /**
-   * A flag indicating whether interface libraries are to be supported (DEP 40).
-   */
-  bool get enableConditionalDirectives => true;
-
-  @deprecated
-  void set enableConditionalDirectives(_) {}
-
-  /**
    * A flag indicating whether generic methods are to be supported (DEP 22).
    */
   bool enableGenericMethods = false;
@@ -1349,6 +1341,14 @@
     _analyzeFunctionBodiesPredicate = value;
   }
 
+  /**
+   * A flag indicating whether interface libraries are to be supported (DEP 40).
+   */
+  bool get enableConditionalDirectives => true;
+
+  @deprecated
+  void set enableConditionalDirectives(_) {}
+
   @override
   int encodeCrossContextOptions() =>
       (enableAssertMessage ? ENABLE_ASSERT_FLAG : 0) |
diff --git a/pkg/analyzer/lib/src/generated/error.dart b/pkg/analyzer/lib/src/generated/error.dart
index 96cdd80..5d0cee2 100644
--- a/pkg/analyzer/lib/src/generated/error.dart
+++ b/pkg/analyzer/lib/src/generated/error.dart
@@ -3147,7 +3147,7 @@
    * Setting the source to `null` will cause the default source to be used.
    */
   void set source(Source source) {
-    this._source = source == null ? _defaultSource : source;
+    this._source = source ?? _defaultSource;
   }
 
   /**
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index c99057a..6d2f8b9 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -648,8 +648,7 @@
     try {
       _inAsync = node.isAsynchronous;
       _inGenerator = node.isGenerator;
-      FunctionType functionType =
-          _enclosingFunction == null ? null : _enclosingFunction.type;
+      FunctionType functionType = _enclosingFunction?.type;
       DartType expectedReturnType = functionType == null
           ? DynamicTypeImpl.instance
           : functionType.returnType;
@@ -770,6 +769,8 @@
       _errorReporter.reportErrorForNode(
           StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION_EXPRESSION,
           functionExpression);
+    } else if (expressionType is FunctionType) {
+      _checkTypeArguments(expressionType.element, node.typeArguments);
     }
     return super.visitFunctionExpressionInvocation(node);
   }
@@ -943,6 +944,8 @@
     }
     _checkForMissingRequiredParam(
         node.staticInvokeType, node.argumentList, methodName);
+    _checkTypeArguments(
+        node.methodName.staticElement, node.typeArguments, target?.staticType);
     return super.visitMethodInvocation(node);
   }
 
@@ -1404,7 +1407,7 @@
     // an error message once it's ready to "return false".
     if (!overridingFT.typeFormals.isEmpty) {
       if (overriddenFT.typeFormals.isEmpty) {
-        overriddenFT = _typeSystem.instantiateToBounds(overriddenFT);
+        overridingFT = _typeSystem.instantiateToBounds(overridingFT);
       } else {
         List<TypeParameterElement> params1 = overridingFT.typeFormals;
         List<TypeParameterElement> params2 = overriddenFT.typeFormals;
@@ -1792,8 +1795,7 @@
       return;
     }
     FormalParameterList formalParameterList = method.parameters;
-    NodeList<FormalParameter> parameterList =
-        formalParameterList != null ? formalParameterList.parameters : null;
+    NodeList<FormalParameter> parameterList = formalParameterList?.parameters;
     List<AstNode> parameters =
         parameterList != null ? new List.from(parameterList) : null;
     _checkForAllInvalidOverrideErrorCodesForExecutable(executableElement,
@@ -1916,8 +1918,7 @@
    * [StaticTypeWarningCode.RETURN_OF_INVALID_TYPE].
    */
   void _checkForAllReturnStatementErrorCodes(ReturnStatement statement) {
-    FunctionType functionType =
-        _enclosingFunction == null ? null : _enclosingFunction.type;
+    FunctionType functionType = _enclosingFunction?.type;
     DartType expectedReturnType = functionType == null
         ? DynamicTypeImpl.instance
         : functionType.returnType;
@@ -2034,8 +2035,7 @@
       return;
     }
     ParameterElement staticParameterElement = argument.staticParameterElement;
-    DartType staticParameterType =
-        staticParameterElement == null ? null : staticParameterElement.type;
+    DartType staticParameterType = staticParameterElement?.type;
     _checkForArgumentTypeNotAssignableWithExpectedTypes(argument,
         staticParameterType, StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE);
   }
@@ -3440,39 +3440,60 @@
     }
     if (_enclosingFunction.isAsynchronous) {
       if (_enclosingFunction.isGenerator) {
-        if (_options.strongMode) {
-          if (_enclosingFunction.returnType.element !=
-              _typeProvider.streamType.element) {
-            _errorReporter.reportErrorForNode(
-                StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE,
-                returnType);
-          }
-        } else if (!_typeSystem.isAssignableTo(
-            _enclosingFunction.returnType, _typeProvider.streamDynamicType)) {
-          _errorReporter.reportErrorForNode(
-              StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE,
-              returnType);
-        }
+        _checkForIllegalReturnTypeCode(
+            returnType,
+            _typeProvider.streamDynamicType,
+            StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE);
       } else {
-        if (_options.strongMode) {
-          if (_enclosingFunction.returnType.element !=
-              _typeProvider.futureType.element) {
-            _errorReporter.reportErrorForNode(
-                StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE, returnType);
-          }
-        } else if (!_typeSystem.isAssignableTo(
-            _enclosingFunction.returnType, _typeProvider.futureDynamicType)) {
-          _errorReporter.reportErrorForNode(
-              StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE, returnType);
-        }
+        _checkForIllegalReturnTypeCode(
+            returnType,
+            _typeProvider.futureDynamicType,
+            StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE);
       }
     } else if (_enclosingFunction.isGenerator) {
-      if (!_typeSystem.isAssignableTo(
-          _enclosingFunction.returnType, _typeProvider.iterableDynamicType)) {
-        _errorReporter.reportErrorForNode(
-            StaticTypeWarningCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE,
-            returnType);
+      _checkForIllegalReturnTypeCode(
+          returnType,
+          _typeProvider.iterableDynamicType,
+          StaticTypeWarningCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE);
+    }
+  }
+
+  /**
+   * If the current function is async, async*, or sync*, verify that its
+   * declared return type is assignable to Future, Stream, or Iterable,
+   * respectively. This is called by [_checkForIllegalReturnType] to check if
+   * the declared [returnTypeName] is assignable to the required [expectedType]
+   * and if not report [errorCode].
+   */
+  void _checkForIllegalReturnTypeCode(TypeName returnTypeName,
+      DartType expectedType, StaticTypeWarningCode errorCode) {
+    DartType returnType = _enclosingFunction.returnType;
+    if (_options.strongMode) {
+      //
+      // When checking an async/sync*/async* method, we know the exact type
+      // that will be returned (e.g. Future, Iterable, or Stream).
+      //
+      // For example an `async` function body will return a `Future<T>` for
+      // some `T` (possibly `dynamic`).
+      //
+      // We allow the declared return type to be a supertype of that
+      // (e.g. `dynamic`, `Object`), or Future<S> for some S.
+      // (We assume the T <: S relation is checked elsewhere.)
+      //
+      // We do not allow user-defined subtypes of Future, because an `async`
+      // method will never return those.
+      //
+      // To check for this, we ensure that `Future<bottom> <: returnType`.
+      //
+      // Similar logic applies for sync* and async*.
+      //
+      InterfaceType genericType = (expectedType.element as ClassElement).type;
+      DartType lowerBound = genericType.instantiate([BottomTypeImpl.instance]);
+      if (!_typeSystem.isSubtypeOf(lowerBound, returnType)) {
+        _errorReporter.reportErrorForNode(errorCode, returnTypeName);
       }
+    } else if (!_typeSystem.isAssignableTo(returnType, expectedType)) {
+      _errorReporter.reportErrorForNode(errorCode, returnTypeName);
     }
   }
 
@@ -3678,9 +3699,7 @@
     }
 
     // The type of the loop variable.
-    SimpleIdentifier variable = node.identifier != null
-        ? node.identifier
-        : node.loopVariable.identifier;
+    SimpleIdentifier variable = node.identifier ?? node.loopVariable.identifier;
     DartType variableType = getStaticType(variable);
 
     DartType loopType = node.awaitKeyword != null
@@ -3767,8 +3786,7 @@
         !executableElement.isOperator) {
       HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>();
       InterfaceType superclassType = _enclosingClass.supertype;
-      ClassElement superclassElement =
-          superclassType == null ? null : superclassType.element;
+      ClassElement superclassElement = superclassType?.element;
       bool executableElementPrivate =
           Identifier.isPrivateName(executableElementName);
       while (superclassElement != null &&
@@ -3820,8 +3838,7 @@
           }
         }
         superclassType = superclassElement.supertype;
-        superclassElement =
-            superclassType == null ? null : superclassType.element;
+        superclassElement = superclassType?.element;
       }
     }
     return false;
@@ -3839,8 +3856,7 @@
       return;
     }
     ParameterElement staticParameterElement = argument.staticParameterElement;
-    DartType staticParameterType =
-        staticParameterElement == null ? null : staticParameterElement.type;
+    DartType staticParameterType = staticParameterElement?.type;
     _checkForArgumentTypeNotAssignable(argument, staticParameterType, _intType,
         StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE);
   }
@@ -4571,6 +4587,10 @@
           FunctionType requiredMemberFT = _inheritanceManager
               .substituteTypeArgumentsInMemberFromInheritance(
                   requiredMemberType, memberName, enclosingType);
+          foundConcreteFT =
+              _typeSystem.typeToConcreteType(_typeProvider, foundConcreteFT);
+          requiredMemberFT =
+              _typeSystem.typeToConcreteType(_typeProvider, requiredMemberFT);
           if (_typeSystem.isSubtypeOf(foundConcreteFT, requiredMemberFT)) {
             continue;
           }
@@ -5217,13 +5237,14 @@
       int loopThroughIndex =
           math.min(typeNameArgList.length, boundingElts.length);
 
+      bool shouldSubstitute = typeArguments.length != 0 &&
+          typeArguments.length == typeParameters.length;
       for (int i = 0; i < loopThroughIndex; i++) {
         TypeName argTypeName = typeNameArgList[i];
         DartType argType = argTypeName.type;
         DartType boundType = boundingElts[i].bound;
         if (argType != null && boundType != null) {
-          if (typeArguments.length != 0 &&
-              typeArguments.length == typeParameters.length) {
+          if (shouldSubstitute) {
             boundType = boundType.substitute2(typeArguments, typeParameters);
           }
           if (!_typeSystem.isSubtypeOf(argType, boundType)) {
@@ -5646,6 +5667,82 @@
     }
   }
 
+  /**
+   * Verify that the given [typeArguments] are all within their bounds, as
+   * defined by the given [element].
+   *
+   * See [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS].
+   */
+  void _checkTypeArguments(Element element, TypeArgumentList typeArguments,
+      [DartType targetType]) {
+    if (element == null || typeArguments == null) {
+      return;
+    }
+    void reportError(
+        TypeName argument, DartType argumentType, DartType parameterType) {
+      _errorReporter.reportTypeErrorForNode(
+          StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS,
+          argument,
+          [argumentType, parameterType]);
+    }
+    if (element is FunctionTypedElement) {
+      _checkTypeArgumentsAgainstBounds(
+          element.typeParameters, typeArguments, targetType, reportError);
+    } else if (element is ClassElement) {
+      _checkTypeArgumentsAgainstBounds(
+          element.typeParameters, typeArguments, targetType, reportError);
+    } else if (element is ParameterElement || element is LocalVariableElement) {
+      // TODO(brianwilkerson) Implement this case
+    } else {
+      print('Unhandled element type: ${element.runtimeType}');
+    }
+  }
+
+  void _checkTypeArgumentsAgainstBounds(
+      List<TypeParameterElement> typeParameters,
+      TypeArgumentList typeArgumentList,
+      DartType targetType,
+      void reportError(
+          TypeName argument, DartType argumentType, DartType parameterType)) {
+    NodeList<TypeName> typeArguments = typeArgumentList.arguments;
+    int argumentsLength = typeArguments.length;
+    int maxIndex = math.min(typeParameters.length, argumentsLength);
+
+    bool shouldSubstitute =
+        argumentsLength != 0 && argumentsLength == typeParameters.length;
+    List<DartType> argumentTypes = shouldSubstitute
+        ? typeArguments.map((TypeName typeName) => typeName.type).toList()
+        : null;
+    List<DartType> parameterTypes = shouldSubstitute
+        ? typeParameters
+            .map((TypeParameterElement element) => element.type)
+            .toList()
+        : null;
+    List<DartType> targetTypeParameterTypes = null;
+    for (int i = 0; i < maxIndex; i++) {
+      TypeName argTypeName = typeArguments[i];
+      DartType argType = argTypeName.type;
+      DartType boundType = typeParameters[i].bound;
+      if (argType != null && boundType != null) {
+        if (targetType is ParameterizedType) {
+          if (targetTypeParameterTypes == null) {
+            targetTypeParameterTypes = targetType.typeParameters
+                .map((TypeParameterElement element) => element.type)
+                .toList();
+          }
+          boundType = boundType.substitute2(
+              targetType.typeArguments, targetTypeParameterTypes);
+        }
+        if (shouldSubstitute) {
+          boundType = boundType.substitute2(argumentTypes, parameterTypes);
+        }
+        if (!_typeSystem.isSubtypeOf(argType, boundType)) {
+          reportError(argTypeName, argType, boundType);
+        }
+      }
+    }
+  }
+
   DartType _computeReturnTypeForMethod(Expression returnExpression) {
     // This method should never be called for generators, since generators are
     // never allowed to contain return statements with expressions.
diff --git a/pkg/analyzer/lib/src/generated/incremental_resolver.dart b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
index 2b98d4a..04f9153 100644
--- a/pkg/analyzer/lib/src/generated/incremental_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
@@ -935,6 +935,8 @@
         isByTask(ResolveLibraryReferencesTask.DESCRIPTOR) ||
         isByTask(ResolveLibraryTask.DESCRIPTOR) ||
         isByTask(ResolveLibraryTypeNamesTask.DESCRIPTOR) ||
+        isByTask(ResolveTopLevelLibraryTypeBoundsTask.DESCRIPTOR) ||
+        isByTask(ResolveTopLevelUnitTypeBoundsTask.DESCRIPTOR) ||
         isByTask(ResolveUnitTask.DESCRIPTOR) ||
         isByTask(ResolveUnitTypeNamesTask.DESCRIPTOR) ||
         isByTask(ResolveVariableReferencesTask.DESCRIPTOR) ||
@@ -1254,6 +1256,7 @@
     _shiftErrors_NEW(LINTS);
     _shiftErrors_NEW(LIBRARY_UNIT_ERRORS);
     _shiftErrors_NEW(RESOLVE_TYPE_NAMES_ERRORS);
+    _shiftErrors_NEW(RESOLVE_TYPE_BOUNDS_ERRORS);
     _shiftErrors_NEW(RESOLVE_UNIT_ERRORS);
     _shiftErrors_NEW(STRONG_MODE_ERRORS);
     _shiftErrors_NEW(VARIABLE_REFERENCE_ERRORS);
@@ -1302,6 +1305,7 @@
 
   void _updateEntry() {
     _updateErrors_NEW(RESOLVE_TYPE_NAMES_ERRORS, []);
+    _updateErrors_NEW(RESOLVE_TYPE_BOUNDS_ERRORS, []);
     _updateErrors_NEW(RESOLVE_UNIT_ERRORS, _resolveErrors);
     _updateErrors_NEW(VARIABLE_REFERENCE_ERRORS, []);
     _updateErrors_NEW(VERIFY_ERRORS, _verifyErrors);
@@ -1722,7 +1726,7 @@
     } else if (token is TokenWithComment) {
       token.precedingComments = comment;
     } else {
-      Type parentType = token != null ? token.runtimeType : null;
+      Type parentType = token?.runtimeType;
       throw new AnalysisException('Uknown parent token type: $parentType');
     }
   }
diff --git a/pkg/analyzer/lib/src/generated/java_core.dart b/pkg/analyzer/lib/src/generated/java_core.dart
index d28dd98..752475d 100644
--- a/pkg/analyzer/lib/src/generated/java_core.dart
+++ b/pkg/analyzer/lib/src/generated/java_core.dart
@@ -37,7 +37,7 @@
     int index = int.parse(indexStr);
     Object arg = arguments[index];
     assert(arg != null);
-    return arg != null ? arg.toString() : null;
+    return arg?.toString();
   });
 }
 
diff --git a/pkg/analyzer/lib/src/generated/parser.dart b/pkg/analyzer/lib/src/generated/parser.dart
index 98a26e9..f63edfa 100644
--- a/pkg/analyzer/lib/src/generated/parser.dart
+++ b/pkg/analyzer/lib/src/generated/parser.dart
@@ -2120,7 +2120,7 @@
   final AnalysisErrorListener _errorListener;
 
   /**
-   * An [errorListener] lock, if more than `0`, then errors are not reported.
+   * An [_errorListener] lock, if more than `0`, then errors are not reported.
    */
   int _errorListenerLock = 0;
 
@@ -8199,12 +8199,8 @@
       _advance();
       variables.add(_parseVariableDeclaration());
     }
-    return new VariableDeclarationList(
-        commentAndMetadata != null ? commentAndMetadata.comment : null,
-        commentAndMetadata != null ? commentAndMetadata.metadata : null,
-        keyword,
-        type,
-        variables);
+    return new VariableDeclarationList(commentAndMetadata?.comment,
+        commentAndMetadata?.metadata, keyword, type, variables);
   }
 
   /**
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 3b06ea0..7f00554 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -77,17 +77,29 @@
   TypeSystem _typeSystem;
 
   /**
+   * The current library
+   */
+  LibraryElement _currentLibrary;
+
+  /**
    * Create a new instance of the [BestPracticesVerifier].
    *
    * @param errorReporter the error reporter
    */
-  BestPracticesVerifier(this._errorReporter, TypeProvider typeProvider,
+  BestPracticesVerifier(
+      this._errorReporter, TypeProvider typeProvider, this._currentLibrary,
       {TypeSystem typeSystem})
       : _futureNullType = typeProvider.futureNullType,
-        _typeSystem = (typeSystem != null) ? typeSystem : new TypeSystemImpl();
+        _typeSystem = typeSystem ?? new TypeSystemImpl();
 
   @override
   Object visitArgumentList(ArgumentList node) {
+    for (Expression argument in node.arguments) {
+      ParameterElement parameter = argument.bestParameterElement;
+      if (parameter?.parameterKind == ParameterKind.POSITIONAL) {
+        _checkForDeprecatedMemberUse(parameter, argument);
+      }
+    }
     _checkForArgumentTypesNotAssignableInList(node);
     return super.visitArgumentList(node);
   }
@@ -149,6 +161,20 @@
   }
 
   @override
+  Object visitConstructorDeclaration(ConstructorDeclaration node) {
+    if (node.element.isFactory) {
+      if (node.body is BlockFunctionBody) {
+        // Check the block for a return statement, if not, create the hint.
+        if (!ExitDetector.exits(node.body)) {
+          _errorReporter.reportErrorForNode(
+              HintCode.MISSING_RETURN, node, [node.returnType.name]);
+        }
+      }
+    }
+    return super.visitConstructorDeclaration(node);
+  }
+
+  @override
   Object visitDoStatement(DoStatement node) {
     _checkForPossibleNullCondition(node.condition);
     return super.visitDoStatement(node);
@@ -191,10 +217,8 @@
   Object visitImportDirective(ImportDirective node) {
     _checkForDeprecatedMemberUse(node.uriElement, node);
     ImportElement importElement = node.element;
-    if (importElement != null) {
-      if (importElement.isDeferred) {
-        _checkForLoadLibraryFunction(node, importElement);
-      }
+    if (importElement != null && importElement.isDeferred) {
+      _checkForLoadLibraryFunction(node, importElement);
     }
     return super.visitImportDirective(node);
   }
@@ -239,6 +263,12 @@
   Object visitMethodInvocation(MethodInvocation node) {
     _checkForCanBeNullAfterNullAware(node.realTarget, node.operator);
     _checkForInvalidProtectedMethodCalls(node);
+    DartType staticInvokeType = node.staticInvokeType;
+    if (staticInvokeType is InterfaceType) {
+      MethodElement methodElement = staticInvokeType.lookUpMethod(
+          FunctionElement.CALL_METHOD_NAME, _currentLibrary);
+      _checkForDeprecatedMemberUse(methodElement, node);
+    }
     return super.visitMethodInvocation(node);
   }
 
@@ -326,8 +356,7 @@
       return true;
     }
     Element rhsElement = rhsType.element;
-    LibraryElement libraryElement =
-        rhsElement != null ? rhsElement.library : null;
+    LibraryElement libraryElement = rhsElement?.library;
     if (libraryElement != null && libraryElement.isDartCore) {
       // if x is Object or null is Null
       if (rhsType.isObject ||
@@ -395,11 +424,8 @@
     // Hint case: test propagated type information
     //
     // Compute the best types to use.
-    DartType expectedBestType = expectedPropagatedType != null
-        ? expectedPropagatedType
-        : expectedStaticType;
-    DartType actualBestType =
-        actualPropagatedType != null ? actualPropagatedType : actualStaticType;
+    DartType expectedBestType = expectedPropagatedType ?? expectedStaticType;
+    DartType actualBestType = actualPropagatedType ?? actualStaticType;
     if (actualBestType != null && expectedBestType != null) {
       if (!_typeSystem.isAssignableTo(actualBestType, expectedBestType)) {
         _errorReporter.reportTypeErrorForNode(
@@ -424,13 +450,10 @@
       return false;
     }
     ParameterElement staticParameterElement = argument.staticParameterElement;
-    DartType staticParameterType =
-        staticParameterElement == null ? null : staticParameterElement.type;
+    DartType staticParameterType = staticParameterElement?.type;
     ParameterElement propagatedParameterElement =
         argument.propagatedParameterElement;
-    DartType propagatedParameterType = propagatedParameterElement == null
-        ? null
-        : propagatedParameterElement.type;
+    DartType propagatedParameterType = propagatedParameterElement?.type;
     return _checkForArgumentTypeNotAssignableWithExpectedTypes(
         argument,
         staticParameterType,
@@ -491,9 +514,7 @@
     if (operator?.type == TokenType.QUESTION_PERIOD) {
       return;
     }
-    while (target is ParenthesizedExpression) {
-      target = (target as ParenthesizedExpression).expression;
-    }
+    target = target?.unParenthesized;
     if (target is MethodInvocation) {
       if (target.operator?.type == TokenType.QUESTION_PERIOD) {
         _errorReporter.reportErrorForNode(
@@ -540,6 +561,11 @@
         if (!element.displayName.isEmpty) {
           displayName = "$displayName.${element.displayName}";
         }
+      } else if (displayName == FunctionElement.CALL_METHOD_NAME &&
+          node is MethodInvocation &&
+          node.staticInvokeType is InterfaceType) {
+        displayName =
+            "${node.staticInvokeType.displayName}.${element.displayName}";
       }
       _errorReporter.reportErrorForNode(
           HintCode.DEPRECATED_MEMBER_USE, node, [displayName]);
@@ -787,9 +813,7 @@
    * Produce a hint if the given [condition] could have a value of `null`.
    */
   void _checkForPossibleNullCondition(Expression condition) {
-    while (condition is ParenthesizedExpression) {
-      condition = (condition as ParenthesizedExpression).expression;
-    }
+    condition = condition?.unParenthesized;
     if (condition is BinaryExpression) {
       _checkForPossibleNullConditionInBinaryExpression(condition);
     } else if (condition is PrefixExpression) {
@@ -805,10 +829,8 @@
    */
   void _checkForPossibleNullConditionInBinaryExpression(
       BinaryExpression condition) {
-    Token operator = condition.operator;
-    if (operator != null &&
-        (operator.type == TokenType.AMPERSAND_AMPERSAND ||
-            operator.type == TokenType.BAR_BAR)) {
+    TokenType type = condition.operator?.type;
+    if (type == TokenType.AMPERSAND_AMPERSAND || type == TokenType.BAR_BAR) {
       _checkForPossibleNullCondition(condition.leftOperand);
       _checkForPossibleNullCondition(condition.rightOperand);
     }
@@ -830,14 +852,12 @@
    */
   void _checkForPossibleNullConditionInSimpleExpression(Expression condition) {
     if (condition is MethodInvocation) {
-      Token operator = condition.operator;
-      if (operator != null && operator.type == TokenType.QUESTION_PERIOD) {
+      if (condition.operator?.type == TokenType.QUESTION_PERIOD) {
         _errorReporter.reportErrorForNode(
             HintCode.NULL_AWARE_IN_CONDITION, condition);
       }
     } else if (condition is PropertyAccess) {
-      Token operator = condition.operator;
-      if (operator != null && operator.type == TokenType.QUESTION_PERIOD) {
+      if (condition.operator?.type == TokenType.QUESTION_PERIOD) {
         _errorReporter.reportErrorForNode(
             HintCode.NULL_AWARE_IN_CONDITION, condition);
       }
@@ -1717,8 +1737,8 @@
   bool _checkForIsDoubleHints(IsExpression node) {
     TypeName typeName = node.type;
     DartType type = typeName.type;
-    if (type != null && type.element != null) {
-      Element element = type.element;
+    Element element = type?.element;
+    if (element != null) {
       String typeNameStr = element.name;
       LibraryElement libraryElement = element.library;
       //      if (typeNameStr.equals(INT_TYPE_NAME) && libraryElement != null
@@ -1766,8 +1786,7 @@
    * @param errorReporter the error reporter
    */
   DeadCodeVerifier(this._errorReporter, {TypeSystem typeSystem})
-      : this._typeSystem =
-            (typeSystem != null) ? typeSystem : new TypeSystemImpl();
+      : this._typeSystem = typeSystem ?? new TypeSystemImpl();
 
   @override
   Object visitBinaryExpression(BinaryExpression node) {
@@ -1779,14 +1798,15 @@
       if (!_isDebugConstant(lhsCondition)) {
         EvaluationResultImpl lhsResult = _getConstantBooleanValue(lhsCondition);
         if (lhsResult != null) {
-          if (lhsResult.value.toBoolValue() == true && isBarBar) {
+          bool value = lhsResult.value.toBoolValue();
+          if (value == true && isBarBar) {
             // report error on else block: true || !e!
             _errorReporter.reportErrorForNode(
                 HintCode.DEAD_CODE, node.rightOperand);
             // only visit the LHS:
             lhsCondition?.accept(this);
             return null;
-          } else if (lhsResult.value.toBoolValue() == false && isAmpAmp) {
+          } else if (value == false && isAmpAmp) {
             // report error on if block: false && !e!
             _errorReporter.reportErrorForNode(
                 HintCode.DEAD_CODE, node.rightOperand);
@@ -1941,9 +1961,8 @@
       if (catchClause.onKeyword != null) {
         // on-catch clause found, verify that the exception type is not a
         // subtype of a previous on-catch exception type
-        TypeName typeName = catchClause.exceptionType;
-        if (typeName != null && typeName.type != null) {
-          DartType currentType = typeName.type;
+        DartType currentType = catchClause.exceptionType?.type;
+        if (currentType != null) {
           if (currentType.isObject) {
             // Found catch clause clause that has Object as an exception type,
             // this is equivalent to having a catch clause that doesn't have an
@@ -3758,7 +3777,7 @@
       }
       // All of the members exit, determine whether there are possible cases
       // that are not caught by the members.
-      DartType type = node.expression == null ? null : node.expression.bestType;
+      DartType type = node.expression?.bestType;
       if (type is InterfaceType) {
         ClassElement element = type.element;
         if (element != null && element.isEnum) {
@@ -4222,7 +4241,8 @@
       unit.accept(new Dart2JSVerifier(errorReporter));
     }
     // Dart best practices
-    unit.accept(new BestPracticesVerifier(errorReporter, _context.typeProvider,
+    unit.accept(new BestPracticesVerifier(
+        errorReporter, _context.typeProvider, _library,
         typeSystem: _context.typeSystem));
     unit.accept(new OverrideVerifier(errorReporter, _manager));
     // Find to-do comments
@@ -4486,7 +4506,7 @@
       String name = element.displayName;
       for (ImportDirective importDirective in importsLibrary) {
         Namespace namespace = _computeNamespace(importDirective);
-        if (namespace != null && namespace.get(name) != null) {
+        if (namespace?.get(name) != null) {
           _unusedImports.remove(importDirective);
           _removeFromUnusedShownNamesMap(element, importDirective);
         }
@@ -5598,16 +5618,12 @@
   }
 
   /**
-   * Return the static element associated with the given expression whose type can be promoted, or
-   * `null` if there is no element whose type can be promoted.
-   *
-   * @param expression the expression with which the element is associated
-   * @return the element associated with the given expression
+   * Return the static element associated with the given expression whose type
+   * can be promoted, or `null` if there is no element whose type can be
+   * promoted.
    */
   VariableElement getPromotionStaticElement(Expression expression) {
-    while (expression is ParenthesizedExpression) {
-      expression = (expression as ParenthesizedExpression).expression;
-    }
+    expression = expression?.unParenthesized;
     if (expression is SimpleIdentifier) {
       Element element = expression.staticElement;
       if (element is VariableElement) {
@@ -5764,7 +5780,7 @@
   void prepareToResolveMembersInClass(ClassDeclaration node) {
     _enclosingClassDeclaration = node;
     enclosingClass = node.element;
-    typeAnalyzer.thisType = enclosingClass == null ? null : enclosingClass.type;
+    typeAnalyzer.thisType = enclosingClass?.type;
   }
 
   /**
@@ -6017,9 +6033,7 @@
     //
     // Resolve the metadata in the library scope.
     //
-    if (node.metadata != null) {
-      node.metadata.accept(this);
-    }
+    node.metadata?.accept(this);
     _enclosingClassDeclaration = node;
     //
     // Continue the class resolution.
@@ -6027,13 +6041,12 @@
     ClassElement outerType = enclosingClass;
     try {
       enclosingClass = node.element;
-      typeAnalyzer.thisType =
-          enclosingClass == null ? null : enclosingClass.type;
+      typeAnalyzer.thisType = enclosingClass?.type;
       super.visitClassDeclaration(node);
       node.accept(elementResolver);
       node.accept(typeAnalyzer);
     } finally {
-      typeAnalyzer.thisType = outerType == null ? null : outerType.type;
+      typeAnalyzer.thisType = outerType?.type;
       enclosingClass = outerType;
       _enclosingClassDeclaration = null;
     }
@@ -6048,15 +6061,13 @@
     //
     // Resolve the metadata in the library scope.
     //
-    if (node.metadata != null) {
-      node.metadata.accept(this);
-    }
+    node.metadata?.accept(this);
     _enclosingClassDeclaration = node;
     //
     // Continue the class resolution.
     //
     enclosingClass = node.element;
-    typeAnalyzer.thisType = enclosingClass == null ? null : enclosingClass.type;
+    typeAnalyzer.thisType = enclosingClass?.type;
     node.accept(elementResolver);
     node.accept(typeAnalyzer);
   }
@@ -6274,13 +6285,12 @@
     ClassElement outerType = enclosingClass;
     try {
       enclosingClass = node.element;
-      typeAnalyzer.thisType =
-          enclosingClass == null ? null : enclosingClass.type;
+      typeAnalyzer.thisType = enclosingClass?.type;
       super.visitEnumDeclaration(node);
       node.accept(elementResolver);
       node.accept(typeAnalyzer);
     } finally {
-      typeAnalyzer.thisType = outerType == null ? null : outerType.type;
+      typeAnalyzer.thisType = outerType?.type;
       enclosingClass = outerType;
       _enclosingClassDeclaration = null;
     }
@@ -7093,8 +7103,7 @@
     FunctionType expectedClosureType = mayByFunctionType as FunctionType;
     // If the expectedClosureType is not more specific than the static type,
     // return.
-    DartType staticClosureType =
-        closure.element != null ? closure.element.type : null;
+    DartType staticClosureType = closure.element?.type;
     if (staticClosureType != null &&
         !expectedClosureType.isMoreSpecificThan(staticClosureType)) {
       return;
@@ -7145,9 +7154,7 @@
     // would eventually turn this into a method on Expression that returns a
     // termination indication (normal, abrupt with no exception, abrupt with an
     // exception).
-    while (expression is ParenthesizedExpression) {
-      expression = (expression as ParenthesizedExpression).expression;
-    }
+    expression = expression?.unParenthesized;
     return expression is ThrowExpression || expression is RethrowExpression;
   }
 
@@ -7464,6 +7471,10 @@
  * The abstract class `ScopedVisitor` maintains name and label scopes as an AST structure is
  * being visited.
  */
+/**
+ * The abstract class `ScopedVisitor` maintains name and label scopes as an AST structure is
+ * being visited.
+ */
 abstract class ScopedVisitor extends UnifyingAstVisitor<Object> {
   /**
    * The element for the library containing the compilation unit being visited.
@@ -7476,9 +7487,15 @@
   final Source source;
 
   /**
-   * The error listener that will be informed of any errors that are found during resolution.
+   * The object used to access the types from the core library.
    */
-  final AnalysisErrorListener errorListener;
+  final TypeProvider typeProvider;
+
+  /**
+   * The error reporter that will be informed of any errors that are found
+   * during resolution.
+   */
+  final ErrorReporter errorReporter;
 
   /**
    * The scope used to resolve identifiers.
@@ -7486,11 +7503,6 @@
   Scope nameScope;
 
   /**
-   * The object used to access the types from the core library.
-   */
-  final TypeProvider typeProvider;
-
-  /**
    * The scope used to resolve unlabeled `break` and `continue` statements.
    */
   ImplicitLabelScope _implicitLabelScope = ImplicitLabelScope.ROOT;
@@ -7522,9 +7534,11 @@
    * first be visited.  If `null` or unspecified, a new [LibraryScope] will be
    * created based on [definingLibrary] and [typeProvider].
    */
-  ScopedVisitor(
-      this.definingLibrary, this.source, this.typeProvider, this.errorListener,
-      {Scope nameScope}) {
+  ScopedVisitor(this.definingLibrary, Source source, this.typeProvider,
+      AnalysisErrorListener errorListener,
+      {Scope nameScope})
+      : source = source,
+        errorReporter = new ErrorReporter(errorListener, source) {
     if (nameScope == null) {
       this.nameScope = new LibraryScope(definingLibrary, errorListener);
     } else {
@@ -7559,46 +7573,6 @@
     return nameScope;
   }
 
-  /**
-   * Report an error with the given error code and arguments.
-   *
-   * @param errorCode the error code of the error to be reported
-   * @param node the node specifying the location of the error
-   * @param arguments the arguments to the error, used to compose the error message
-   */
-  void reportErrorForNode(ErrorCode errorCode, AstNode node,
-      [List<Object> arguments]) {
-    errorListener.onError(new AnalysisError(
-        source, node.offset, node.length, errorCode, arguments));
-  }
-
-  /**
-   * Report an error with the given error code and arguments.
-   *
-   * @param errorCode the error code of the error to be reported
-   * @param offset the offset of the location of the error
-   * @param length the length of the location of the error
-   * @param arguments the arguments to the error, used to compose the error message
-   */
-  void reportErrorForOffset(ErrorCode errorCode, int offset, int length,
-      [List<Object> arguments]) {
-    errorListener.onError(
-        new AnalysisError(source, offset, length, errorCode, arguments));
-  }
-
-  /**
-   * Report an error with the given error code and arguments.
-   *
-   * @param errorCode the error code of the error to be reported
-   * @param token the token specifying the location of the error
-   * @param arguments the arguments to the error, used to compose the error message
-   */
-  void reportErrorForToken(ErrorCode errorCode, Token token,
-      [List<Object> arguments]) {
-    errorListener.onError(new AnalysisError(
-        source, token.offset, token.length, errorCode, arguments));
-  }
-
   @override
   Object visitBlock(Block node) {
     Scope outerScope = nameScope;
@@ -8372,6 +8346,498 @@
 }
 
 /**
+ * Helper for resolving [TypeName]s.
+ *
+ * The client must set [nameScope] before calling [resolveTypeName].
+ */
+class TypeNameResolver {
+  final TypeSystem typeSystem;
+  final DartType dynamicType;
+  final DartType undefinedType;
+  final LibraryElement definingLibrary;
+  final Source source;
+  final AnalysisErrorListener errorListener;
+
+  Scope nameScope;
+
+  TypeNameResolver(this.typeSystem, TypeProvider typeProvider,
+      this.definingLibrary, this.source, this.errorListener)
+      : dynamicType = typeProvider.dynamicType,
+        undefinedType = typeProvider.undefinedType;
+
+  /**
+   * Report an error with the given error code and arguments.
+   *
+   * @param errorCode the error code of the error to be reported
+   * @param node the node specifying the location of the error
+   * @param arguments the arguments to the error, used to compose the error message
+   */
+  void reportErrorForNode(ErrorCode errorCode, AstNode node,
+      [List<Object> arguments]) {
+    errorListener.onError(new AnalysisError(
+        source, node.offset, node.length, errorCode, arguments));
+  }
+
+  /**
+   * Resolve the given [TypeName] - set its element and static type. Only the
+   * given [node] is resolved, all its children must be already resolved.
+   *
+   * The client must set [nameScope] before calling [resolveTypeName].
+   */
+  void resolveTypeName(TypeName node) {
+    Identifier typeName = node.name;
+    _setElement(typeName, null); // Clear old Elements from previous run.
+    TypeArgumentList argumentList = node.typeArguments;
+    Element element = nameScope.lookup(typeName, definingLibrary);
+    if (element == null) {
+      //
+      // Check to see whether the type name is either 'dynamic' or 'void',
+      // neither of which are in the name scope and hence will not be found by
+      // normal means.
+      //
+      if (typeName.name == dynamicType.name) {
+        _setElement(typeName, dynamicType.element);
+//        if (argumentList != null) {
+//          // TODO(brianwilkerson) Report this error
+//          reporter.reportError(StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS, node, dynamicType.getName(), 0, argumentList.getArguments().size());
+//        }
+        typeName.staticType = dynamicType;
+        node.type = dynamicType;
+        return;
+      }
+      VoidTypeImpl voidType = VoidTypeImpl.instance;
+      if (typeName.name == voidType.name) {
+        // There is no element for 'void'.
+//        if (argumentList != null) {
+//          // TODO(brianwilkerson) Report this error
+//          reporter.reportError(StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS, node, voidType.getName(), 0, argumentList.getArguments().size());
+//        }
+        typeName.staticType = voidType;
+        node.type = voidType;
+        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
+      // proceed.
+      //
+      AstNode parent = node.parent;
+      if (typeName is PrefixedIdentifier &&
+          parent is ConstructorName &&
+          argumentList == null) {
+        ConstructorName name = parent;
+        if (name.name == null) {
+          PrefixedIdentifier prefixedIdentifier =
+              typeName as PrefixedIdentifier;
+          SimpleIdentifier prefix = prefixedIdentifier.prefix;
+          element = nameScope.lookup(prefix, definingLibrary);
+          if (element is PrefixElement) {
+            AstNode grandParent = parent.parent;
+            if (grandParent is InstanceCreationExpression &&
+                grandParent.isConst) {
+              // If, if this is a const expression, then generate a
+              // CompileTimeErrorCode.CONST_WITH_NON_TYPE error.
+              reportErrorForNode(
+                  CompileTimeErrorCode.CONST_WITH_NON_TYPE,
+                  prefixedIdentifier.identifier,
+                  [prefixedIdentifier.identifier.name]);
+            } else {
+              // Else, if this expression is a new expression, report a
+              // NEW_WITH_NON_TYPE warning.
+              reportErrorForNode(
+                  StaticWarningCode.NEW_WITH_NON_TYPE,
+                  prefixedIdentifier.identifier,
+                  [prefixedIdentifier.identifier.name]);
+            }
+            _setElement(prefix, element);
+            return;
+          } else if (element != null) {
+            //
+            // Rewrite the constructor name. The parser, when it sees a
+            // constructor named "a.b", cannot tell whether "a" is a prefix and
+            // "b" is a class name, or whether "a" is a class name and "b" is a
+            // constructor name. It arbitrarily chooses the former, but in this
+            // case was wrong.
+            //
+            name.name = prefixedIdentifier.identifier;
+            name.period = prefixedIdentifier.period;
+            node.name = prefix;
+            typeName = prefix;
+          }
+        }
+      }
+    }
+    // check element
+    bool elementValid = element is! MultiplyDefinedElement;
+    if (elementValid &&
+        element is! ClassElement &&
+        _isTypeNameInInstanceCreationExpression(node)) {
+      SimpleIdentifier typeNameSimple = _getTypeSimpleIdentifier(typeName);
+      InstanceCreationExpression creation =
+          node.parent.parent as InstanceCreationExpression;
+      if (creation.isConst) {
+        if (element == null) {
+          reportErrorForNode(
+              CompileTimeErrorCode.UNDEFINED_CLASS, typeNameSimple, [typeName]);
+        } else {
+          reportErrorForNode(CompileTimeErrorCode.CONST_WITH_NON_TYPE,
+              typeNameSimple, [typeName]);
+        }
+        elementValid = false;
+      } else {
+        if (element != null) {
+          reportErrorForNode(
+              StaticWarningCode.NEW_WITH_NON_TYPE, typeNameSimple, [typeName]);
+          elementValid = false;
+        }
+      }
+    }
+    if (elementValid && element == null) {
+      // We couldn't resolve the type name.
+      // TODO(jwren) Consider moving the check for
+      // CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE from the
+      // ErrorVerifier, so that we don't have two errors on a built in
+      // identifier being used as a class name.
+      // See CompileTimeErrorCodeTest.test_builtInIdentifierAsType().
+      SimpleIdentifier typeNameSimple = _getTypeSimpleIdentifier(typeName);
+      RedirectingConstructorKind redirectingConstructorKind;
+      if (_isBuiltInIdentifier(node) && _isTypeAnnotation(node)) {
+        reportErrorForNode(CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE,
+            typeName, [typeName.name]);
+      } else if (typeNameSimple.name == "boolean") {
+        reportErrorForNode(
+            StaticWarningCode.UNDEFINED_CLASS_BOOLEAN, typeNameSimple, []);
+      } else if (_isTypeNameInCatchClause(node)) {
+        reportErrorForNode(StaticWarningCode.NON_TYPE_IN_CATCH_CLAUSE, typeName,
+            [typeName.name]);
+      } else if (_isTypeNameInAsExpression(node)) {
+        reportErrorForNode(
+            StaticWarningCode.CAST_TO_NON_TYPE, typeName, [typeName.name]);
+      } else if (_isTypeNameInIsExpression(node)) {
+        reportErrorForNode(StaticWarningCode.TYPE_TEST_WITH_UNDEFINED_NAME,
+            typeName, [typeName.name]);
+      } else if ((redirectingConstructorKind =
+              _getRedirectingConstructorKind(node)) !=
+          null) {
+        ErrorCode errorCode =
+            (redirectingConstructorKind == RedirectingConstructorKind.CONST
+                ? CompileTimeErrorCode.REDIRECT_TO_NON_CLASS
+                : StaticWarningCode.REDIRECT_TO_NON_CLASS);
+        reportErrorForNode(errorCode, typeName, [typeName.name]);
+      } else if (_isTypeNameInTypeArgumentList(node)) {
+        reportErrorForNode(StaticTypeWarningCode.NON_TYPE_AS_TYPE_ARGUMENT,
+            typeName, [typeName.name]);
+      } else {
+        reportErrorForNode(
+            StaticWarningCode.UNDEFINED_CLASS, typeName, [typeName.name]);
+      }
+      elementValid = false;
+    }
+    if (!elementValid) {
+      if (element is MultiplyDefinedElement) {
+        _setElement(typeName, element);
+      }
+      typeName.staticType = undefinedType;
+      node.type = undefinedType;
+      return;
+    }
+    DartType type = null;
+    if (element is ClassElement) {
+      _setElement(typeName, element);
+      type = element.type;
+    } else if (element is FunctionTypeAliasElement) {
+      _setElement(typeName, element);
+      type = element.type;
+    } else if (element is TypeParameterElement) {
+      _setElement(typeName, element);
+      type = element.type;
+//      if (argumentList != null) {
+//        // Type parameters cannot have type arguments.
+//        // TODO(brianwilkerson) Report this error.
+//        //      resolver.reportError(ResolverErrorCode.?, keyType);
+//      }
+    } else if (element is MultiplyDefinedElement) {
+      List<Element> elements = element.conflictingElements;
+      type = _getTypeWhenMultiplyDefined(elements);
+      if (type != null) {
+        node.type = type;
+      }
+    } else {
+      // The name does not represent a type.
+      RedirectingConstructorKind redirectingConstructorKind;
+      if (_isTypeNameInCatchClause(node)) {
+        reportErrorForNode(StaticWarningCode.NON_TYPE_IN_CATCH_CLAUSE, typeName,
+            [typeName.name]);
+      } else if (_isTypeNameInAsExpression(node)) {
+        reportErrorForNode(
+            StaticWarningCode.CAST_TO_NON_TYPE, typeName, [typeName.name]);
+      } else if (_isTypeNameInIsExpression(node)) {
+        reportErrorForNode(StaticWarningCode.TYPE_TEST_WITH_NON_TYPE, typeName,
+            [typeName.name]);
+      } else if ((redirectingConstructorKind =
+              _getRedirectingConstructorKind(node)) !=
+          null) {
+        ErrorCode errorCode =
+            (redirectingConstructorKind == RedirectingConstructorKind.CONST
+                ? CompileTimeErrorCode.REDIRECT_TO_NON_CLASS
+                : StaticWarningCode.REDIRECT_TO_NON_CLASS);
+        reportErrorForNode(errorCode, typeName, [typeName.name]);
+      } else if (_isTypeNameInTypeArgumentList(node)) {
+        reportErrorForNode(StaticTypeWarningCode.NON_TYPE_AS_TYPE_ARGUMENT,
+            typeName, [typeName.name]);
+      } else {
+        AstNode parent = typeName.parent;
+        while (parent is TypeName) {
+          parent = parent.parent;
+        }
+        if (parent is ExtendsClause ||
+            parent is ImplementsClause ||
+            parent is WithClause ||
+            parent is ClassTypeAlias) {
+          // Ignored. The error will be reported elsewhere.
+        } else {
+          reportErrorForNode(
+              StaticWarningCode.NOT_A_TYPE, typeName, [typeName.name]);
+        }
+      }
+      typeName.staticType = dynamicType;
+      node.type = dynamicType;
+      return;
+    }
+    if (argumentList != null) {
+      NodeList<TypeName> arguments = argumentList.arguments;
+      int argumentCount = arguments.length;
+      List<DartType> parameters = typeSystem.typeFormalsAsTypes(type);
+      int parameterCount = parameters.length;
+      List<DartType> typeArguments = new List<DartType>(parameterCount);
+      if (argumentCount == parameterCount) {
+        for (int i = 0; i < parameterCount; i++) {
+          TypeName argumentTypeName = arguments[i];
+          DartType argumentType = _getType(argumentTypeName);
+          if (argumentType == null) {
+            argumentType = dynamicType;
+          }
+          typeArguments[i] = argumentType;
+        }
+      } else {
+        reportErrorForNode(_getInvalidTypeParametersErrorCode(node), node,
+            [typeName.name, parameterCount, argumentCount]);
+        for (int i = 0; i < parameterCount; i++) {
+          typeArguments[i] = dynamicType;
+        }
+      }
+      type = typeSystem.instantiateType(type, typeArguments);
+    } else {
+      type = typeSystem.instantiateToBounds(type);
+    }
+    typeName.staticType = type;
+    node.type = type;
+  }
+
+  /**
+   * The number of type arguments in the given type name does not match the number of parameters in
+   * the corresponding class element. Return the error code that should be used to report this
+   * error.
+   *
+   * @param node the type name with the wrong number of type arguments
+   * @return the error code that should be used to report that the wrong number of type arguments
+   *         were provided
+   */
+  ErrorCode _getInvalidTypeParametersErrorCode(TypeName node) {
+    AstNode parent = node.parent;
+    if (parent is ConstructorName) {
+      parent = parent.parent;
+      if (parent is InstanceCreationExpression) {
+        if (parent.isConst) {
+          return CompileTimeErrorCode.CONST_WITH_INVALID_TYPE_PARAMETERS;
+        } else {
+          return StaticWarningCode.NEW_WITH_INVALID_TYPE_PARAMETERS;
+        }
+      }
+    }
+    return StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS;
+  }
+
+  /**
+   * Checks if the given type name is the target in a redirected constructor.
+   *
+   * @param typeName the type name to analyze
+   * @return some [RedirectingConstructorKind] if the given type name is used as the type in a
+   *         redirected constructor, or `null` otherwise
+   */
+  RedirectingConstructorKind _getRedirectingConstructorKind(TypeName typeName) {
+    AstNode parent = typeName.parent;
+    if (parent is ConstructorName) {
+      AstNode grandParent = parent.parent;
+      if (grandParent is ConstructorDeclaration) {
+        if (identical(grandParent.redirectedConstructor, parent)) {
+          if (grandParent.constKeyword != null) {
+            return RedirectingConstructorKind.CONST;
+          }
+          return RedirectingConstructorKind.NORMAL;
+        }
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Return the type represented by the given type name.
+   *
+   * @param typeName the type name representing the type to be returned
+   * @return the type represented by the type name
+   */
+  DartType _getType(TypeName typeName) {
+    DartType type = typeName.type;
+    if (type == null) {
+      return undefinedType;
+    }
+    return type;
+  }
+
+  /**
+   * Returns the simple identifier of the given (may be qualified) type name.
+   *
+   * @param typeName the (may be qualified) qualified type name
+   * @return the simple identifier of the given (may be qualified) type name.
+   */
+  SimpleIdentifier _getTypeSimpleIdentifier(Identifier typeName) {
+    if (typeName is SimpleIdentifier) {
+      return typeName;
+    } else {
+      return (typeName as PrefixedIdentifier).identifier;
+    }
+  }
+
+  /**
+   * Given the multiple elements to which a single name could potentially be resolved, return the
+   * single interface type that should be used, or `null` if there is no clear choice.
+   *
+   * @param elements the elements to which a single name could potentially be resolved
+   * @return the single interface type that should be used for the type name
+   */
+  InterfaceType _getTypeWhenMultiplyDefined(List<Element> elements) {
+    InterfaceType type = null;
+    for (Element element in elements) {
+      if (element is ClassElement) {
+        if (type != null) {
+          return null;
+        }
+        type = element.type;
+      }
+    }
+    return type;
+  }
+
+  /**
+   * Checks if the given type name is used as the type in an as expression.
+   *
+   * @param typeName the type name to analyzer
+   * @return `true` if the given type name is used as the type in an as expression
+   */
+  bool _isTypeNameInAsExpression(TypeName typeName) {
+    AstNode parent = typeName.parent;
+    if (parent is AsExpression) {
+      return identical(parent.type, typeName);
+    }
+    return false;
+  }
+
+  /**
+   * Checks if the given type name is used as the exception type in a catch clause.
+   *
+   * @param typeName the type name to analyzer
+   * @return `true` if the given type name is used as the exception type in a catch clause
+   */
+  bool _isTypeNameInCatchClause(TypeName typeName) {
+    AstNode parent = typeName.parent;
+    if (parent is CatchClause) {
+      return identical(parent.exceptionType, typeName);
+    }
+    return false;
+  }
+
+  /**
+   * Checks if the given type name is used as the type in an instance creation expression.
+   *
+   * @param typeName the type name to analyzer
+   * @return `true` if the given type name is used as the type in an instance creation
+   *         expression
+   */
+  bool _isTypeNameInInstanceCreationExpression(TypeName typeName) {
+    AstNode parent = typeName.parent;
+    if (parent is ConstructorName &&
+        parent.parent is InstanceCreationExpression) {
+      return parent != null && identical(parent.type, typeName);
+    }
+    return false;
+  }
+
+  /**
+   * Checks if the given type name is used as the type in an is expression.
+   *
+   * @param typeName the type name to analyzer
+   * @return `true` if the given type name is used as the type in an is expression
+   */
+  bool _isTypeNameInIsExpression(TypeName typeName) {
+    AstNode parent = typeName.parent;
+    if (parent is IsExpression) {
+      return identical(parent.type, typeName);
+    }
+    return false;
+  }
+
+  /**
+   * Checks if the given type name used in a type argument list.
+   *
+   * @param typeName the type name to analyzer
+   * @return `true` if the given type name is in a type argument list
+   */
+  bool _isTypeNameInTypeArgumentList(TypeName typeName) =>
+      typeName.parent is TypeArgumentList;
+
+  /**
+   * Records the new Element for a TypeName's Identifier.
+   *
+   * A null may be passed in to indicate that the element can't be resolved.
+   * (During a re-run of a task, it's important to clear any previous value
+   * of the element.)
+   */
+  void _setElement(Identifier typeName, Element element) {
+    if (typeName is SimpleIdentifier) {
+      typeName.staticElement = element;
+    } else if (typeName is PrefixedIdentifier) {
+      typeName.identifier.staticElement = element;
+      SimpleIdentifier prefix = typeName.prefix;
+      prefix.staticElement = nameScope.lookup(prefix, definingLibrary);
+    }
+  }
+
+  /**
+   * @return `true` if the name of the given [TypeName] is an built-in identifier.
+   */
+  static bool _isBuiltInIdentifier(TypeName node) {
+    Token token = node.name.beginToken;
+    return token.type == TokenType.KEYWORD;
+  }
+
+  /**
+   * @return `true` if given [TypeName] is used as a type annotation.
+   */
+  static bool _isTypeAnnotation(TypeName node) {
+    AstNode parent = node.parent;
+    if (parent is VariableDeclarationList) {
+      return identical(parent.type, node);
+    } else if (parent is FieldFormalParameter) {
+      return identical(parent.type, node);
+    } else if (parent is SimpleFormalParameter) {
+      return identical(parent.type, node);
+    }
+    return false;
+  }
+}
+
+/**
  * Instances of the class `TypeOverrideManager` manage the ability to override the type of an
  * element within a given context.
  */
@@ -8449,7 +8915,7 @@
    */
   DartType getBestType(VariableElement element) {
     DartType bestType = getType(element);
-    return bestType == null ? element.type : bestType;
+    return bestType ?? element.type;
   }
 
   /**
@@ -8577,12 +9043,7 @@
     if (_overridenTypes.containsKey(nonAccessor)) {
       return type;
     }
-    if (type != null) {
-      return type;
-    } else if (_outerScope != null) {
-      return _outerScope.getType(nonAccessor);
-    }
-    return null;
+    return type ?? _outerScope?.getType(element);
   }
 
   /**
@@ -8604,6 +9065,70 @@
 }
 
 /**
+ * This class resolves bounds of type parameters of classes, class and function
+ * type aliases.
+ */
+class TypeParameterBoundsResolver {
+  final TypeProvider typeProvider;
+  final LibraryElement library;
+  final Source source;
+  final AnalysisErrorListener errorListener;
+
+  Scope libraryScope = null;
+  TypeNameResolver typeNameResolver = null;
+
+  TypeParameterBoundsResolver(
+      this.typeProvider, this.library, this.source, this.errorListener);
+
+  /**
+   * Resolve bounds of type parameters of classes, class and function type
+   * aliases.
+   */
+  void resolveTypeBounds(CompilationUnit unit) {
+    for (CompilationUnitMember unitMember in unit.declarations) {
+      if (unitMember is ClassDeclaration) {
+        _resolveTypeParameters(unitMember.typeParameters,
+            () => new TypeParameterScope(libraryScope, unitMember.element));
+      } else if (unitMember is ClassTypeAlias) {
+        _resolveTypeParameters(unitMember.typeParameters,
+            () => new TypeParameterScope(libraryScope, unitMember.element));
+      } else if (unitMember is FunctionTypeAlias) {
+        _resolveTypeParameters(unitMember.typeParameters,
+            () => new FunctionTypeScope(libraryScope, unitMember.element));
+      }
+    }
+  }
+
+  void _resolveTypeName(TypeName typeName) {
+    typeName.typeArguments?.arguments?.forEach(_resolveTypeName);
+    typeNameResolver.resolveTypeName(typeName);
+    // TODO(scheglov) report error when don't apply type bounds for type bounds
+  }
+
+  void _resolveTypeParameters(
+      TypeParameterList typeParameters, Scope createTypeParametersScope()) {
+    if (typeParameters != null) {
+      Scope typeParametersScope = null;
+      for (TypeParameter typeParameter in typeParameters.typeParameters) {
+        TypeName bound = typeParameter.bound;
+        if (bound != null) {
+          libraryScope ??= new LibraryScope(library, errorListener);
+          typeParametersScope ??= createTypeParametersScope();
+          typeNameResolver ??= new TypeNameResolver(new TypeSystemImpl(),
+              typeProvider, library, source, errorListener);
+          typeNameResolver.nameScope = typeParametersScope;
+          _resolveTypeName(bound);
+          Element typeParameterElement = typeParameter.name.staticElement;
+          if (typeParameterElement is TypeParameterElementImpl) {
+            typeParameterElement.bound = bound.type;
+          }
+        }
+      }
+    }
+  }
+}
+
+/**
  * Instances of the class `TypePromotionManager` manage the ability to promote types of local
  * variables and formal parameters from their declared types based on control flow.
  */
@@ -8636,31 +9161,16 @@
   }
 
   /**
-   * Returns static type of the given variable - declared or promoted.
-   *
-   * @return the static type of the given variable - declared or promoted
+   * Return the static type of the given [variable] - declared or promoted.
    */
-  DartType getStaticType(VariableElement variable) {
-    DartType staticType = getType(variable);
-    if (staticType == null) {
-      staticType = variable.type;
-    }
-    return staticType;
-  }
+  DartType getStaticType(VariableElement variable) =>
+      getType(variable) ?? variable.type;
 
   /**
-   * Return the promoted type of the given element, or `null` if the type of the element has
-   * not been promoted.
-   *
-   * @param element the element whose type might have been promoted
-   * @return the promoted type of the given element
+   * Return the promoted type of the given [element], or `null` if the type of
+   * the element has not been promoted.
    */
-  DartType getType(Element element) {
-    if (currentScope == null) {
-      return null;
-    }
-    return currentScope.getType(element);
-  }
+  DartType getType(Element element) => currentScope?.getType(element);
 
   /**
    * Set the promoted type of the given element to the given type.
@@ -9195,6 +9705,11 @@
   TypeSystem _typeSystem;
 
   /**
+   * The helper to resolve [TypeName]s.
+   */
+  TypeNameResolver _typeNameResolver;
+
+  /**
    * Initialize a newly created visitor to resolve the nodes in an AST node.
    *
    * [definingLibrary] is the element for the library containing the node being
@@ -9218,6 +9733,8 @@
     _undefinedType = typeProvider.undefinedType;
     _strongMode = definingLibrary.context.analysisOptions.strongMode;
     _typeSystem = TypeSystem.create(definingLibrary.context);
+    _typeNameResolver = new TypeNameResolver(
+        _typeSystem, typeProvider, definingLibrary, source, errorListener);
   }
 
   @override
@@ -9262,7 +9779,7 @@
       if (exceptionTypeName == null) {
         exceptionType = typeProvider.dynamicType;
       } else {
-        exceptionType = _getType(exceptionTypeName);
+        exceptionType = _typeNameResolver._getType(exceptionTypeName);
       }
       _recordType(exception, exceptionType);
       Element element = exception.staticElement;
@@ -9402,7 +9919,7 @@
     if (typeName == null) {
       declaredType = _dynamicType;
     } else {
-      declaredType = _getType(typeName);
+      declaredType = _typeNameResolver._getType(typeName);
     }
     LocalVariableElementImpl element = node.element as LocalVariableElementImpl;
     element.type = declaredType;
@@ -9429,7 +9946,7 @@
             }
           }
         } else {
-          type = _getType(typeName);
+          type = _typeNameResolver._getType(typeName);
         }
         element.type = type;
       } else {
@@ -9531,7 +10048,7 @@
     if (typeName == null) {
       declaredType = _dynamicType;
     } else {
-      declaredType = _getType(typeName);
+      declaredType = _typeNameResolver._getType(typeName);
     }
     Element element = node.identifier.staticElement;
     if (element is ParameterElementImpl) {
@@ -9551,265 +10068,28 @@
   @override
   Object visitTypeName(TypeName node) {
     super.visitTypeName(node);
-    Identifier typeName = node.name;
-    _setElement(typeName, null); // Clear old Elements from previous run.
-    TypeArgumentList argumentList = node.typeArguments;
-    Element element = nameScope.lookup(typeName, definingLibrary);
-    if (element == null) {
-      //
-      // Check to see whether the type name is either 'dynamic' or 'void',
-      // neither of which are in the name scope and hence will not be found by
-      // normal means.
-      //
-      if (typeName.name == _dynamicType.name) {
-        _setElement(typeName, _dynamicType.element);
-        if (argumentList != null) {
-          // TODO(brianwilkerson) Report this error
-//          reporter.reportError(StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS, node, dynamicType.getName(), 0, argumentList.getArguments().size());
-        }
-        typeName.staticType = _dynamicType;
-        node.type = _dynamicType;
-        return null;
-      }
-      VoidTypeImpl voidType = VoidTypeImpl.instance;
-      if (typeName.name == voidType.name) {
-        // There is no element for 'void'.
-        if (argumentList != null) {
-          // TODO(brianwilkerson) Report this error
-//          reporter.reportError(StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS, node, voidType.getName(), 0, argumentList.getArguments().size());
-        }
-        typeName.staticType = voidType;
-        node.type = voidType;
-        return null;
-      }
-      //
-      // 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
-      // proceed.
-      //
-      AstNode parent = node.parent;
-      if (typeName is PrefixedIdentifier &&
-          parent is ConstructorName &&
-          argumentList == null) {
-        ConstructorName name = parent;
-        if (name.name == null) {
-          PrefixedIdentifier prefixedIdentifier =
-              typeName as PrefixedIdentifier;
-          SimpleIdentifier prefix = prefixedIdentifier.prefix;
-          element = nameScope.lookup(prefix, definingLibrary);
-          if (element is PrefixElement) {
-            AstNode grandParent = parent.parent;
-            if (grandParent is InstanceCreationExpression &&
-                grandParent.isConst) {
-              // If, if this is a const expression, then generate a
-              // CompileTimeErrorCode.CONST_WITH_NON_TYPE error.
-              reportErrorForNode(
-                  CompileTimeErrorCode.CONST_WITH_NON_TYPE,
-                  prefixedIdentifier.identifier,
-                  [prefixedIdentifier.identifier.name]);
-            } else {
-              // Else, if this expression is a new expression, report a
-              // NEW_WITH_NON_TYPE warning.
-              reportErrorForNode(
-                  StaticWarningCode.NEW_WITH_NON_TYPE,
-                  prefixedIdentifier.identifier,
-                  [prefixedIdentifier.identifier.name]);
-            }
-            _setElement(prefix, element);
-            return null;
-          } else if (element != null) {
-            //
-            // Rewrite the constructor name. The parser, when it sees a
-            // constructor named "a.b", cannot tell whether "a" is a prefix and
-            // "b" is a class name, or whether "a" is a class name and "b" is a
-            // constructor name. It arbitrarily chooses the former, but in this
-            // case was wrong.
-            //
-            name.name = prefixedIdentifier.identifier;
-            name.period = prefixedIdentifier.period;
-            node.name = prefix;
-            typeName = prefix;
-          }
-        }
-      }
-    }
-    // check element
-    bool elementValid = element is! MultiplyDefinedElement;
-    if (elementValid &&
-        element is! ClassElement &&
-        _isTypeNameInInstanceCreationExpression(node)) {
-      SimpleIdentifier typeNameSimple = _getTypeSimpleIdentifier(typeName);
-      InstanceCreationExpression creation =
-          node.parent.parent as InstanceCreationExpression;
-      if (creation.isConst) {
-        if (element == null) {
-          reportErrorForNode(
-              CompileTimeErrorCode.UNDEFINED_CLASS, typeNameSimple, [typeName]);
-        } else {
-          reportErrorForNode(CompileTimeErrorCode.CONST_WITH_NON_TYPE,
-              typeNameSimple, [typeName]);
-        }
-        elementValid = false;
-      } else {
-        if (element != null) {
-          reportErrorForNode(
-              StaticWarningCode.NEW_WITH_NON_TYPE, typeNameSimple, [typeName]);
-          elementValid = false;
-        }
-      }
-    }
-    if (elementValid && element == null) {
-      // We couldn't resolve the type name.
-      // TODO(jwren) Consider moving the check for
-      // CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE from the
-      // ErrorVerifier, so that we don't have two errors on a built in
-      // identifier being used as a class name.
-      // See CompileTimeErrorCodeTest.test_builtInIdentifierAsType().
-      SimpleIdentifier typeNameSimple = _getTypeSimpleIdentifier(typeName);
-      RedirectingConstructorKind redirectingConstructorKind;
-      if (_isBuiltInIdentifier(node) && _isTypeAnnotation(node)) {
-        reportErrorForNode(CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE,
-            typeName, [typeName.name]);
-      } else if (typeNameSimple.name == "boolean") {
-        reportErrorForNode(
-            StaticWarningCode.UNDEFINED_CLASS_BOOLEAN, typeNameSimple, []);
-      } else if (_isTypeNameInCatchClause(node)) {
-        reportErrorForNode(StaticWarningCode.NON_TYPE_IN_CATCH_CLAUSE, typeName,
-            [typeName.name]);
-      } else if (_isTypeNameInAsExpression(node)) {
-        reportErrorForNode(
-            StaticWarningCode.CAST_TO_NON_TYPE, typeName, [typeName.name]);
-      } else if (_isTypeNameInIsExpression(node)) {
-        reportErrorForNode(StaticWarningCode.TYPE_TEST_WITH_UNDEFINED_NAME,
-            typeName, [typeName.name]);
-      } else if ((redirectingConstructorKind =
-              _getRedirectingConstructorKind(node)) !=
-          null) {
-        ErrorCode errorCode =
-            (redirectingConstructorKind == RedirectingConstructorKind.CONST
-                ? CompileTimeErrorCode.REDIRECT_TO_NON_CLASS
-                : StaticWarningCode.REDIRECT_TO_NON_CLASS);
-        reportErrorForNode(errorCode, typeName, [typeName.name]);
-      } else if (_isTypeNameInTypeArgumentList(node)) {
-        reportErrorForNode(StaticTypeWarningCode.NON_TYPE_AS_TYPE_ARGUMENT,
-            typeName, [typeName.name]);
-      } else {
-        reportErrorForNode(
-            StaticWarningCode.UNDEFINED_CLASS, typeName, [typeName.name]);
-      }
-      elementValid = false;
-    }
-    if (!elementValid) {
-      if (element is MultiplyDefinedElement) {
-        _setElement(typeName, element);
-      }
-      typeName.staticType = _undefinedType;
-      node.type = _undefinedType;
-      return null;
-    }
-    DartType type = null;
-    if (element is ClassElement) {
-      _setElement(typeName, element);
-      type = element.type;
-    } else if (element is FunctionTypeAliasElement) {
-      _setElement(typeName, element);
-      type = element.type;
-    } else if (element is TypeParameterElement) {
-      _setElement(typeName, element);
-      type = element.type;
-      if (argumentList != null) {
-        // Type parameters cannot have type arguments.
-        // TODO(brianwilkerson) Report this error.
-        //      resolver.reportError(ResolverErrorCode.?, keyType);
-      }
-    } else if (element is MultiplyDefinedElement) {
-      List<Element> elements = element.conflictingElements;
-      type = _getTypeWhenMultiplyDefined(elements);
-      if (type != null) {
-        node.type = type;
-      }
-    } else {
-      // The name does not represent a type.
-      RedirectingConstructorKind redirectingConstructorKind;
-      if (_isTypeNameInCatchClause(node)) {
-        reportErrorForNode(StaticWarningCode.NON_TYPE_IN_CATCH_CLAUSE, typeName,
-            [typeName.name]);
-      } else if (_isTypeNameInAsExpression(node)) {
-        reportErrorForNode(
-            StaticWarningCode.CAST_TO_NON_TYPE, typeName, [typeName.name]);
-      } else if (_isTypeNameInIsExpression(node)) {
-        reportErrorForNode(StaticWarningCode.TYPE_TEST_WITH_NON_TYPE, typeName,
-            [typeName.name]);
-      } else if ((redirectingConstructorKind =
-              _getRedirectingConstructorKind(node)) !=
-          null) {
-        ErrorCode errorCode =
-            (redirectingConstructorKind == RedirectingConstructorKind.CONST
-                ? CompileTimeErrorCode.REDIRECT_TO_NON_CLASS
-                : StaticWarningCode.REDIRECT_TO_NON_CLASS);
-        reportErrorForNode(errorCode, typeName, [typeName.name]);
-      } else if (_isTypeNameInTypeArgumentList(node)) {
-        reportErrorForNode(StaticTypeWarningCode.NON_TYPE_AS_TYPE_ARGUMENT,
-            typeName, [typeName.name]);
-      } else {
-        AstNode parent = typeName.parent;
-        while (parent is TypeName) {
-          parent = parent.parent;
-        }
-        if (parent is ExtendsClause ||
-            parent is ImplementsClause ||
-            parent is WithClause ||
-            parent is ClassTypeAlias) {
-          // Ignored. The error will be reported elsewhere.
-        } else {
-          reportErrorForNode(
-              StaticWarningCode.NOT_A_TYPE, typeName, [typeName.name]);
-        }
-      }
-      typeName.staticType = _dynamicType;
-      node.type = _dynamicType;
-      return null;
-    }
-    if (argumentList != null) {
-      NodeList<TypeName> arguments = argumentList.arguments;
-      int argumentCount = arguments.length;
-      List<DartType> parameters = _typeSystem.typeFormalsAsTypes(type);
-      int parameterCount = parameters.length;
-      List<DartType> typeArguments = new List<DartType>(parameterCount);
-      if (argumentCount == parameterCount) {
-        for (int i = 0; i < parameterCount; i++) {
-          TypeName argumentTypeName = arguments[i];
-          DartType argumentType = _getType(argumentTypeName);
-          if (argumentType == null) {
-            argumentType = _dynamicType;
-          }
-          typeArguments[i] = argumentType;
-        }
-      } else {
-        reportErrorForNode(_getInvalidTypeParametersErrorCode(node), node,
-            [typeName.name, parameterCount, argumentCount]);
-        for (int i = 0; i < parameterCount; i++) {
-          typeArguments[i] = _dynamicType;
-        }
-      }
-      type = _typeSystem.instantiateType(type, typeArguments);
-    } else {
-      type = _typeSystem.instantiateToBounds(type);
-    }
-    typeName.staticType = type;
-    node.type = type;
+    _typeNameResolver.nameScope = this.nameScope;
+    _typeNameResolver.resolveTypeName(node);
     return null;
   }
 
   @override
   Object visitTypeParameter(TypeParameter node) {
     super.visitTypeParameter(node);
-    TypeName bound = node.bound;
-    if (bound != null) {
-      TypeParameterElementImpl typeParameter =
-          node.name.staticElement as TypeParameterElementImpl;
-      if (typeParameter != null) {
-        typeParameter.bound = bound.type;
+    AstNode parent2 = node.parent?.parent;
+    if (parent2 is ClassDeclaration ||
+        parent2 is ClassTypeAlias ||
+        parent2 is FunctionTypeAlias) {
+      // Bounds of parameters of classes and function type aliases are
+      // already resolved.
+    } else {
+      TypeName bound = node.bound;
+      if (bound != null) {
+        TypeParameterElementImpl typeParameter =
+            node.name.staticElement as TypeParameterElementImpl;
+        if (typeParameter != null) {
+          typeParameter.bound = bound.type;
+        }
       }
     }
     return null;
@@ -9823,7 +10103,7 @@
     if (typeName == null) {
       declaredType = _dynamicType;
     } else {
-      declaredType = _getType(typeName);
+      declaredType = _typeNameResolver._getType(typeName);
     }
     Element element = node.name.staticElement;
     if (element is VariableElement) {
@@ -9910,101 +10190,6 @@
   }
 
   /**
-   * The number of type arguments in the given type name does not match the number of parameters in
-   * the corresponding class element. Return the error code that should be used to report this
-   * error.
-   *
-   * @param node the type name with the wrong number of type arguments
-   * @return the error code that should be used to report that the wrong number of type arguments
-   *         were provided
-   */
-  ErrorCode _getInvalidTypeParametersErrorCode(TypeName node) {
-    AstNode parent = node.parent;
-    if (parent is ConstructorName) {
-      parent = parent.parent;
-      if (parent is InstanceCreationExpression) {
-        if (parent.isConst) {
-          return CompileTimeErrorCode.CONST_WITH_INVALID_TYPE_PARAMETERS;
-        } else {
-          return StaticWarningCode.NEW_WITH_INVALID_TYPE_PARAMETERS;
-        }
-      }
-    }
-    return StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS;
-  }
-
-  /**
-   * Checks if the given type name is the target in a redirected constructor.
-   *
-   * @param typeName the type name to analyze
-   * @return some [RedirectingConstructorKind] if the given type name is used as the type in a
-   *         redirected constructor, or `null` otherwise
-   */
-  RedirectingConstructorKind _getRedirectingConstructorKind(TypeName typeName) {
-    AstNode parent = typeName.parent;
-    if (parent is ConstructorName) {
-      AstNode grandParent = parent.parent;
-      if (grandParent is ConstructorDeclaration) {
-        if (identical(grandParent.redirectedConstructor, parent)) {
-          if (grandParent.constKeyword != null) {
-            return RedirectingConstructorKind.CONST;
-          }
-          return RedirectingConstructorKind.NORMAL;
-        }
-      }
-    }
-    return null;
-  }
-
-  /**
-   * Return the type represented by the given type name.
-   *
-   * @param typeName the type name representing the type to be returned
-   * @return the type represented by the type name
-   */
-  DartType _getType(TypeName typeName) {
-    DartType type = typeName.type;
-    if (type == null) {
-      return _undefinedType;
-    }
-    return type;
-  }
-
-  /**
-   * Returns the simple identifier of the given (may be qualified) type name.
-   *
-   * @param typeName the (may be qualified) qualified type name
-   * @return the simple identifier of the given (may be qualified) type name.
-   */
-  SimpleIdentifier _getTypeSimpleIdentifier(Identifier typeName) {
-    if (typeName is SimpleIdentifier) {
-      return typeName;
-    } else {
-      return (typeName as PrefixedIdentifier).identifier;
-    }
-  }
-
-  /**
-   * Given the multiple elements to which a single name could potentially be resolved, return the
-   * single interface type that should be used, or `null` if there is no clear choice.
-   *
-   * @param elements the elements to which a single name could potentially be resolved
-   * @return the single interface type that should be used for the type name
-   */
-  InterfaceType _getTypeWhenMultiplyDefined(List<Element> elements) {
-    InterfaceType type = null;
-    for (Element element in elements) {
-      if (element is ClassElement) {
-        if (type != null) {
-          return null;
-        }
-        type = element.type;
-      }
-    }
-    return type;
-  }
-
-  /**
    * In strong mode we infer "void" as the setter return type (as void is the
    * only legal return type for a setter). This allows us to give better
    * errors later if an invalid type is returned.
@@ -10019,73 +10204,6 @@
   }
 
   /**
-   * Checks if the given type name is used as the type in an as expression.
-   *
-   * @param typeName the type name to analyzer
-   * @return `true` if the given type name is used as the type in an as expression
-   */
-  bool _isTypeNameInAsExpression(TypeName typeName) {
-    AstNode parent = typeName.parent;
-    if (parent is AsExpression) {
-      return identical(parent.type, typeName);
-    }
-    return false;
-  }
-
-  /**
-   * Checks if the given type name is used as the exception type in a catch clause.
-   *
-   * @param typeName the type name to analyzer
-   * @return `true` if the given type name is used as the exception type in a catch clause
-   */
-  bool _isTypeNameInCatchClause(TypeName typeName) {
-    AstNode parent = typeName.parent;
-    if (parent is CatchClause) {
-      return identical(parent.exceptionType, typeName);
-    }
-    return false;
-  }
-
-  /**
-   * Checks if the given type name is used as the type in an instance creation expression.
-   *
-   * @param typeName the type name to analyzer
-   * @return `true` if the given type name is used as the type in an instance creation
-   *         expression
-   */
-  bool _isTypeNameInInstanceCreationExpression(TypeName typeName) {
-    AstNode parent = typeName.parent;
-    if (parent is ConstructorName &&
-        parent.parent is InstanceCreationExpression) {
-      return parent != null && identical(parent.type, typeName);
-    }
-    return false;
-  }
-
-  /**
-   * Checks if the given type name is used as the type in an is expression.
-   *
-   * @param typeName the type name to analyzer
-   * @return `true` if the given type name is used as the type in an is expression
-   */
-  bool _isTypeNameInIsExpression(TypeName typeName) {
-    AstNode parent = typeName.parent;
-    if (parent is IsExpression) {
-      return identical(parent.type, typeName);
-    }
-    return false;
-  }
-
-  /**
-   * Checks if the given type name used in a type argument list.
-   *
-   * @param typeName the type name to analyzer
-   * @return `true` if the given type name is in a type argument list
-   */
-  bool _isTypeNameInTypeArgumentList(TypeName typeName) =>
-      typeName.parent is TypeArgumentList;
-
-  /**
    * Record that the static type of the given node is the given type.
    *
    * @param expression the node whose type is to be recorded
@@ -10148,7 +10266,7 @@
             Element element2 = identifier2.staticElement;
             if (element != null && element == element2) {
               detectedRepeatOnIndex[j] = true;
-              reportErrorForNode(
+              errorReporter.reportErrorForNode(
                   CompileTimeErrorCode.IMPLEMENTS_REPEATED, typeName2, [name2]);
             }
           }
@@ -10173,7 +10291,7 @@
     if (type is InterfaceType) {
       ClassElement element = type.element;
       if (element != null && element.isEnum) {
-        reportErrorForNode(enumTypeError, typeName);
+        errorReporter.reportErrorForNode(enumTypeError, typeName);
         return null;
       }
       return type;
@@ -10182,9 +10300,9 @@
     // to be a DynamicTypeImpl
     Identifier name = typeName.name;
     if (name.name == Keyword.DYNAMIC.syntax) {
-      reportErrorForNode(dynamicTypeError, name, [name.name]);
+      errorReporter.reportErrorForNode(dynamicTypeError, name, [name.name]);
     } else {
-      reportErrorForNode(nonTypeError, name, [name.name]);
+      errorReporter.reportErrorForNode(nonTypeError, name, [name.name]);
     }
     return null;
   }
@@ -10216,23 +10334,6 @@
   }
 
   /**
-   * Records the new Element for a TypeName's Identifier.
-   *
-   * A null may be passed in to indicate that the element can't be resolved.
-   * (During a re-run of a task, it's important to clear any previous value
-   * of the element.)
-   */
-  void _setElement(Identifier typeName, Element element) {
-    if (typeName is SimpleIdentifier) {
-      typeName.staticElement = element;
-    } else if (typeName is PrefixedIdentifier) {
-      typeName.identifier.staticElement = element;
-      SimpleIdentifier prefix = typeName.prefix;
-      prefix.staticElement = nameScope.lookup(prefix, definingLibrary);
-    }
-  }
-
-  /**
    * Given a parameter element, create a function type based on the given return type and parameter
    * list and associate the created type with the element.
    *
@@ -10252,29 +10353,6 @@
     element.type = new FunctionTypeImpl(functionElement);
     functionElement.type = element.type;
   }
-
-  /**
-   * @return `true` if the name of the given [TypeName] is an built-in identifier.
-   */
-  static bool _isBuiltInIdentifier(TypeName node) {
-    Token token = node.name.beginToken;
-    return token.type == TokenType.KEYWORD;
-  }
-
-  /**
-   * @return `true` if given [TypeName] is used as a type annotation.
-   */
-  static bool _isTypeAnnotation(TypeName node) {
-    AstNode parent = node.parent;
-    if (parent is VariableDeclarationList) {
-      return identical(parent.type, node);
-    } else if (parent is FieldFormalParameter) {
-      return identical(parent.type, node);
-    } else if (parent is SimpleFormalParameter) {
-      return identical(parent.type, node);
-    }
-    return false;
-  }
 }
 
 /**
@@ -10714,7 +10792,7 @@
       this.parameterElements,
       DeclaredVariables declaredVariables,
       {TypeSystem typeSystem})
-      : _typeSystem = (typeSystem != null) ? typeSystem : new TypeSystemImpl(),
+      : _typeSystem = typeSystem ?? new TypeSystemImpl(),
         super(
             new ConstantEvaluationEngine(typeProvider, declaredVariables,
                 typeSystem: typeSystem),
diff --git a/pkg/analyzer/lib/src/generated/source.dart b/pkg/analyzer/lib/src/generated/source.dart
index 65e8f95..3032565 100644
--- a/pkg/analyzer/lib/src/generated/source.dart
+++ b/pkg/analyzer/lib/src/generated/source.dart
@@ -14,7 +14,8 @@
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/java_io.dart' show JavaFile;
 import 'package:analyzer/src/generated/sdk.dart' show DartSdk;
-import 'package:analyzer/src/generated/source_io.dart' show FileBasedSource;
+import 'package:analyzer/src/generated/source_io.dart'
+    show FileBasedSource, FileUriResolver, PackageUriResolver;
 import 'package:analyzer/task/model.dart';
 import 'package:package_config/packages.dart';
 import 'package:path/path.dart' as pathos;
@@ -111,7 +112,7 @@
     if (!fileUri.isAbsolute) return null;
 
     JavaFile javaFile = new JavaFile.fromUri(fileUri);
-    return new FileBasedSource(javaFile, actualUri != null ? actualUri : uri);
+    return new FileBasedSource(javaFile, actualUri ?? uri);
   }
 }
 
@@ -895,6 +896,20 @@
     }
     return null;
   }
+
+  /**
+   * Return the URI kind corresponding to the given scheme string.
+   */
+  static UriKind fromScheme(String scheme) {
+    if (scheme == PackageUriResolver.PACKAGE_SCHEME) {
+      return UriKind.PACKAGE_URI;
+    } else if (scheme == DartUriResolver.DART_SCHEME) {
+      return UriKind.DART_URI;
+    } else if (scheme == FileUriResolver.FILE_SCHEME) {
+      return UriKind.FILE_URI;
+    }
+    return UriKind.FILE_URI;
+  }
 }
 
 /**
diff --git a/pkg/analyzer/lib/src/generated/source_io.dart b/pkg/analyzer/lib/src/generated/source_io.dart
index 5c9c740..5b25c2c 100644
--- a/pkg/analyzer/lib/src/generated/source_io.dart
+++ b/pkg/analyzer/lib/src/generated/source_io.dart
@@ -98,7 +98,14 @@
 
   @override
   Source resolveAbsolute(Uri uri, [Uri actualUri]) {
-    return new FileBasedSource(uriToFileMap[uri], actualUri ?? uri);
+    JavaFile file = uriToFileMap[uri];
+    actualUri ??= uri;
+    if (file == null) {
+      return new NonExistingSource(
+          uri.toString(), actualUri, UriKind.fromScheme(actualUri.scheme));
+    } else {
+      return new FileBasedSource(file, actualUri);
+    }
   }
 
   @override
@@ -169,11 +176,10 @@
    * derived, otherwise a `file:` URI will be created based on the [file].
    */
   FileBasedSource(JavaFile file, [Uri uri])
-      : this.uri = (uri == null ? file.toURI() : uri),
+      : this.uri = uri ?? file.toURI(),
         this.file = file,
         id = _idTable.putIfAbsent(
-            '${uri == null ? file.toURI() : uri}@${file.getPath()}',
-            () => _idTable.length);
+            '${uri ?? file.toURI()}@${file.getPath()}', () => _idTable.length);
 
   @override
   TimestampedData<String> get contents {
@@ -229,14 +235,7 @@
   @override
   UriKind get uriKind {
     String scheme = uri.scheme;
-    if (scheme == PackageUriResolver.PACKAGE_SCHEME) {
-      return UriKind.PACKAGE_URI;
-    } else if (scheme == DartUriResolver.DART_SCHEME) {
-      return UriKind.DART_URI;
-    } else if (scheme == FileUriResolver.FILE_SCHEME) {
-      return UriKind.FILE_URI;
-    }
-    return UriKind.FILE_URI;
+    return UriKind.fromScheme(scheme);
   }
 
   @override
@@ -269,8 +268,7 @@
     if (!isFileUri(uri)) {
       return null;
     }
-    return new FileBasedSource(
-        new JavaFile.fromUri(uri), actualUri != null ? actualUri : uri);
+    return new FileBasedSource(new JavaFile.fromUri(uri), actualUri ?? uri);
   }
 
   @override
@@ -456,7 +454,7 @@
     }
     return new FileBasedSource(
         getCanonicalFile(_packagesDirectories[0], pkgName, relPath),
-        actualUri != null ? actualUri : uri);
+        actualUri ?? uri);
   }
 
   @override
@@ -545,7 +543,7 @@
       for (JavaFile dir in _relativeDirectories) {
         JavaFile file = new JavaFile.relative(dir, filePath);
         if (file.exists()) {
-          return new FileBasedSource(file, actualUri != null ? actualUri : uri);
+          return new FileBasedSource(file, actualUri ?? uri);
         }
       }
     }
diff --git a/pkg/analyzer/lib/src/plugin/engine_plugin.dart b/pkg/analyzer/lib/src/plugin/engine_plugin.dart
index 145c4aa..69b74c6 100644
--- a/pkg/analyzer/lib/src/plugin/engine_plugin.dart
+++ b/pkg/analyzer/lib/src/plugin/engine_plugin.dart
@@ -229,6 +229,8 @@
     registerExtension(taskId, ResolveLibraryReferencesTask.DESCRIPTOR);
     registerExtension(taskId, ResolveLibraryTask.DESCRIPTOR);
     registerExtension(taskId, ResolveLibraryTypeNamesTask.DESCRIPTOR);
+    registerExtension(taskId, ResolveTopLevelLibraryTypeBoundsTask.DESCRIPTOR);
+    registerExtension(taskId, ResolveTopLevelUnitTypeBoundsTask.DESCRIPTOR);
     registerExtension(taskId, ResolveUnitTask.DESCRIPTOR);
     registerExtension(taskId, ResolveUnitTypeNamesTask.DESCRIPTOR);
     registerExtension(taskId, ResolveVariableReferencesTask.DESCRIPTOR);
diff --git a/pkg/analyzer/lib/src/summary/format.dart b/pkg/analyzer/lib/src/summary/format.dart
index edaf034..b47ef55 100644
--- a/pkg/analyzer/lib/src/summary/format.dart
+++ b/pkg/analyzer/lib/src/summary/format.dart
@@ -4208,9 +4208,11 @@
   UnlinkedDocumentationCommentBuilder _documentationComment;
   int _inferredReturnTypeSlot;
   bool _isAbstract;
+  bool _isAsynchronous;
   bool _isConst;
   bool _isExternal;
   bool _isFactory;
+  bool _isGenerator;
   bool _isRedirectedConstructor;
   bool _isStatic;
   idl.UnlinkedExecutableKind _kind;
@@ -4320,6 +4322,17 @@
   }
 
   @override
+  bool get isAsynchronous => _isAsynchronous ??= false;
+
+  /**
+   * Indicates whether the executable has body marked as being asynchronous.
+   */
+  void set isAsynchronous(bool _value) {
+    assert(!_finished);
+    _isAsynchronous = _value;
+  }
+
+  @override
   bool get isConst => _isConst ??= false;
 
   /**
@@ -4353,6 +4366,17 @@
   }
 
   @override
+  bool get isGenerator => _isGenerator ??= false;
+
+  /**
+   * Indicates whether the executable has body marked as being a generator.
+   */
+  void set isGenerator(bool _value) {
+    assert(!_finished);
+    _isGenerator = _value;
+  }
+
+  @override
   bool get isRedirectedConstructor => _isRedirectedConstructor ??= false;
 
   /**
@@ -4566,7 +4590,7 @@
     _visibleOffset = _value;
   }
 
-  UnlinkedExecutableBuilder({List<UnlinkedConstBuilder> annotations, CodeRangeBuilder codeRange, List<UnlinkedConstructorInitializerBuilder> constantInitializers, int constCycleSlot, UnlinkedDocumentationCommentBuilder documentationComment, int inferredReturnTypeSlot, bool isAbstract, bool isConst, bool isExternal, bool isFactory, bool isRedirectedConstructor, bool isStatic, idl.UnlinkedExecutableKind kind, List<UnlinkedExecutableBuilder> localFunctions, List<UnlinkedLabelBuilder> localLabels, List<UnlinkedVariableBuilder> localVariables, String name, int nameEnd, int nameOffset, List<UnlinkedParamBuilder> parameters, int periodOffset, EntityRefBuilder redirectedConstructor, String redirectedConstructorName, EntityRefBuilder returnType, List<UnlinkedTypeParamBuilder> typeParameters, int visibleLength, int visibleOffset})
+  UnlinkedExecutableBuilder({List<UnlinkedConstBuilder> annotations, CodeRangeBuilder codeRange, List<UnlinkedConstructorInitializerBuilder> constantInitializers, int constCycleSlot, UnlinkedDocumentationCommentBuilder documentationComment, int inferredReturnTypeSlot, bool isAbstract, bool isAsynchronous, bool isConst, bool isExternal, bool isFactory, bool isGenerator, bool isRedirectedConstructor, bool isStatic, idl.UnlinkedExecutableKind kind, List<UnlinkedExecutableBuilder> localFunctions, List<UnlinkedLabelBuilder> localLabels, List<UnlinkedVariableBuilder> localVariables, String name, int nameEnd, int nameOffset, List<UnlinkedParamBuilder> parameters, int periodOffset, EntityRefBuilder redirectedConstructor, String redirectedConstructorName, EntityRefBuilder returnType, List<UnlinkedTypeParamBuilder> typeParameters, int visibleLength, int visibleOffset})
     : _annotations = annotations,
       _codeRange = codeRange,
       _constantInitializers = constantInitializers,
@@ -4574,9 +4598,11 @@
       _documentationComment = documentationComment,
       _inferredReturnTypeSlot = inferredReturnTypeSlot,
       _isAbstract = isAbstract,
+      _isAsynchronous = isAsynchronous,
       _isConst = isConst,
       _isExternal = isExternal,
       _isFactory = isFactory,
+      _isGenerator = isGenerator,
       _isRedirectedConstructor = isRedirectedConstructor,
       _isStatic = isStatic,
       _kind = kind,
@@ -4603,7 +4629,9 @@
     _codeRange = null;
     _constantInitializers?.forEach((b) => b.flushInformative());
     _documentationComment = null;
-    _localFunctions = null;
+    _isAsynchronous = null;
+    _isGenerator = null;
+    _localFunctions?.forEach((b) => b.flushInformative());
     _localLabels = null;
     _localVariables = null;
     _nameEnd = null;
@@ -4692,6 +4720,9 @@
     if (_isAbstract == true) {
       fbBuilder.addBool(10, true);
     }
+    if (_isAsynchronous == true) {
+      fbBuilder.addBool(27, true);
+    }
     if (_isConst == true) {
       fbBuilder.addBool(12, true);
     }
@@ -4701,6 +4732,9 @@
     if (_isFactory == true) {
       fbBuilder.addBool(8, true);
     }
+    if (_isGenerator == true) {
+      fbBuilder.addBool(28, true);
+    }
     if (_isRedirectedConstructor == true) {
       fbBuilder.addBool(13, true);
     }
@@ -4775,9 +4809,11 @@
   idl.UnlinkedDocumentationComment _documentationComment;
   int _inferredReturnTypeSlot;
   bool _isAbstract;
+  bool _isAsynchronous;
   bool _isConst;
   bool _isExternal;
   bool _isFactory;
+  bool _isGenerator;
   bool _isRedirectedConstructor;
   bool _isStatic;
   idl.UnlinkedExecutableKind _kind;
@@ -4839,6 +4875,12 @@
   }
 
   @override
+  bool get isAsynchronous {
+    _isAsynchronous ??= const fb.BoolReader().vTableGet(_bp, 27, false);
+    return _isAsynchronous;
+  }
+
+  @override
   bool get isConst {
     _isConst ??= const fb.BoolReader().vTableGet(_bp, 12, false);
     return _isConst;
@@ -4857,6 +4899,12 @@
   }
 
   @override
+  bool get isGenerator {
+    _isGenerator ??= const fb.BoolReader().vTableGet(_bp, 28, false);
+    return _isGenerator;
+  }
+
+  @override
   bool get isRedirectedConstructor {
     _isRedirectedConstructor ??= const fb.BoolReader().vTableGet(_bp, 13, false);
     return _isRedirectedConstructor;
@@ -4970,9 +5018,11 @@
     if (documentationComment != null) _result["documentationComment"] = documentationComment.toJson();
     if (inferredReturnTypeSlot != 0) _result["inferredReturnTypeSlot"] = inferredReturnTypeSlot;
     if (isAbstract != false) _result["isAbstract"] = isAbstract;
+    if (isAsynchronous != false) _result["isAsynchronous"] = isAsynchronous;
     if (isConst != false) _result["isConst"] = isConst;
     if (isExternal != false) _result["isExternal"] = isExternal;
     if (isFactory != false) _result["isFactory"] = isFactory;
+    if (isGenerator != false) _result["isGenerator"] = isGenerator;
     if (isRedirectedConstructor != false) _result["isRedirectedConstructor"] = isRedirectedConstructor;
     if (isStatic != false) _result["isStatic"] = isStatic;
     if (kind != idl.UnlinkedExecutableKind.functionOrMethod) _result["kind"] = kind.toString().split('.')[1];
@@ -5002,9 +5052,11 @@
     "documentationComment": documentationComment,
     "inferredReturnTypeSlot": inferredReturnTypeSlot,
     "isAbstract": isAbstract,
+    "isAsynchronous": isAsynchronous,
     "isConst": isConst,
     "isExternal": isExternal,
     "isFactory": isFactory,
+    "isGenerator": isGenerator,
     "isRedirectedConstructor": isRedirectedConstructor,
     "isStatic": isStatic,
     "kind": kind,
@@ -8114,7 +8166,7 @@
     _codeRange = null;
     _constExpr?.flushInformative();
     _documentationComment = null;
-    _initializer = null;
+    _initializer?.flushInformative();
     _nameOffset = null;
     _type?.flushInformative();
   }
diff --git a/pkg/analyzer/lib/src/summary/format.fbs b/pkg/analyzer/lib/src/summary/format.fbs
index 97528d7..44d5544 100644
--- a/pkg/analyzer/lib/src/summary/format.fbs
+++ b/pkg/analyzer/lib/src/summary/format.fbs
@@ -1624,6 +1624,11 @@
   isAbstract:bool (id: 10);
 
   /**
+   * Indicates whether the executable has body marked as being asynchronous.
+   */
+  isAsynchronous:bool (id: 27);
+
+  /**
    * Indicates whether the executable is declared using the `const` keyword.
    */
   isConst:bool (id: 12);
@@ -1639,6 +1644,11 @@
   isFactory:bool (id: 8);
 
   /**
+   * Indicates whether the executable has body marked as being a generator.
+   */
+  isGenerator:bool (id: 28);
+
+  /**
    * Indicates whether the executable is a redirected constructor.
    */
   isRedirectedConstructor:bool (id: 13);
diff --git a/pkg/analyzer/lib/src/summary/idl.dart b/pkg/analyzer/lib/src/summary/idl.dart
index d83c9ef..7992ccc 100644
--- a/pkg/analyzer/lib/src/summary/idl.dart
+++ b/pkg/analyzer/lib/src/summary/idl.dart
@@ -1670,6 +1670,13 @@
   bool get isAbstract;
 
   /**
+   * Indicates whether the executable has body marked as being asynchronous.
+   */
+  @informative
+  @Id(27)
+  bool get isAsynchronous;
+
+  /**
    * Indicates whether the executable is declared using the `const` keyword.
    */
   @Id(12)
@@ -1688,6 +1695,13 @@
   bool get isFactory;
 
   /**
+   * Indicates whether the executable has body marked as being a generator.
+   */
+  @informative
+  @Id(28)
+  bool get isGenerator;
+
+  /**
    * Indicates whether the executable is a redirected constructor.
    */
   @Id(13)
@@ -1713,7 +1727,6 @@
   /**
    * The list of local functions.
    */
-  @informative
   @Id(18)
   List<UnlinkedExecutable> get localFunctions;
 
@@ -2624,7 +2637,6 @@
    * The synthetic initializer function of the variable.  Absent if the variable
    * does not have an initializer.
    */
-  @informative
   @Id(13)
   UnlinkedExecutable get initializer;
 
diff --git a/pkg/analyzer/lib/src/summary/link.dart b/pkg/analyzer/lib/src/summary/link.dart
index 0aff6d2..e68b5df 100644
--- a/pkg/analyzer/lib/src/summary/link.dart
+++ b/pkg/analyzer/lib/src/summary/link.dart
@@ -271,6 +271,9 @@
         hasBeenInferred = !enclosingElement.isInBuildUnit;
 
   @override
+  List<PropertyAccessorElementForLink> get accessors;
+
+  @override
   ConstructorElementForLink get asConstructor => unnamedConstructor;
 
   @override
@@ -323,6 +326,12 @@
           _containedNames[field.name] = field;
         }
       }
+      for (PropertyAccessorElementForLink accessor in accessors) {
+        if (accessor.isStatic && !accessor.isSynthetic) {
+          // TODO(paulberry): add synthetic elements too?
+          _containedNames[accessor.name] = accessor;
+        }
+      }
       // TODO(paulberry): add methods.
     }
     return _containedNames.putIfAbsent(
@@ -1290,6 +1299,7 @@
     for (UnlinkedConstOperation operation in unlinkedConst.operations) {
       switch (operation) {
         case UnlinkedConstOperation.pushReference:
+        case UnlinkedConstOperation.invokeMethodRef:
           EntityRef ref = unlinkedConst.references[refPtr++];
           ConstVariableNode variable =
               compilationUnit._resolveRef(ref.reference).asConstVariable;
@@ -2782,6 +2792,9 @@
   @override
   bool get isDartAsync => _absoluteUri == 'dart:async';
 
+  @override
+  bool get isDartCore => _absoluteUri == 'dart:core';
+
   /**
    * If this library is part of the build unit being linked, return the library
    * cycle it is part of.  Otherwise return `null`.
@@ -3457,7 +3470,7 @@
  * linking.
  */
 abstract class PropertyAccessorElementForLink
-    implements PropertyAccessorElementImpl {
+    implements PropertyAccessorElementImpl, ReferenceableElementForLink {
   void link(CompilationUnitElementInBuildUnit compilationUnit);
 }
 
@@ -3478,6 +3491,18 @@
             unlinkedExecutable);
 
   @override
+  ConstructorElementForLink get asConstructor => null;
+
+  @override
+  ConstVariableNode get asConstVariable => null;
+
+  @override
+  DartType get asStaticType => returnType;
+
+  @override
+  TypeInferenceNode get asTypeInferenceNode => null;
+
+  @override
   PropertyAccessorElementForLink_Executable get correspondingGetter =>
       variable.getter;
 
@@ -3494,6 +3519,15 @@
       UnlinkedExecutableKind.getter ? ElementKind.GETTER : ElementKind.SETTER;
 
   @override
+  DartType buildType(DartType getTypeArgument(int i),
+          List<int> implicitFunctionTypeIndices) =>
+      DynamicTypeImpl.instance;
+
+  @override
+  ReferenceableElementForLink getContainedName(String name) =>
+      UndefinedElementForLink.instance;
+
+  @override
   noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
 
   @override
diff --git a/pkg/analyzer/lib/src/summary/package_bundle_reader.dart b/pkg/analyzer/lib/src/summary/package_bundle_reader.dart
index bde6e40..e765fae 100644
--- a/pkg/analyzer/lib/src/summary/package_bundle_reader.dart
+++ b/pkg/analyzer/lib/src/summary/package_bundle_reader.dart
@@ -63,6 +63,7 @@
           result == LIBRARY_ELEMENT6 ||
           result == LIBRARY_ELEMENT7 ||
           result == LIBRARY_ELEMENT8 ||
+          result == LIBRARY_ELEMENT9 ||
           result == LIBRARY_ELEMENT ||
           false) {
         LibraryElement libraryElement =
@@ -70,8 +71,8 @@
         entry.setValue(result, libraryElement, TargetedResult.EMPTY_LIST);
         return true;
       } else if (result == READY_LIBRARY_ELEMENT2 ||
-          result == READY_LIBRARY_ELEMENT5 ||
-          result == READY_LIBRARY_ELEMENT6) {
+          result == READY_LIBRARY_ELEMENT6 ||
+          result == READY_LIBRARY_ELEMENT7) {
         entry.setValue(result, true, TargetedResult.EMPTY_LIST);
         return true;
       } else if (result == SOURCE_KIND) {
diff --git a/pkg/analyzer/lib/src/summary/prelink.dart b/pkg/analyzer/lib/src/summary/prelink.dart
index e98b64b..ec947f0 100644
--- a/pkg/analyzer/lib/src/summary/prelink.dart
+++ b/pkg/analyzer/lib/src/summary/prelink.dart
@@ -274,6 +274,9 @@
                   UnlinkedExecutableKind.functionOrMethod &&
               executable.isStatic) {
             kind = ReferenceKind.method;
+          } else if (executable.kind == UnlinkedExecutableKind.getter &&
+              executable.isStatic) {
+            kind = ReferenceKind.propertyAccessor;
           }
           if (kind != null && executable.name.isNotEmpty) {
             namespace[executable.name] = new _Meaning(
diff --git a/pkg/analyzer/lib/src/summary/public_namespace_computer.dart b/pkg/analyzer/lib/src/summary/public_namespace_computer.dart
index 5cb6e8e5..684113e 100644
--- a/pkg/analyzer/lib/src/summary/public_namespace_computer.dart
+++ b/pkg/analyzer/lib/src/summary/public_namespace_computer.dart
@@ -83,14 +83,15 @@
         }
         if (member is MethodDeclaration &&
             member.isStatic &&
-            !member.isGetter &&
             !member.isSetter &&
             !member.isOperator) {
           String name = member.name.name;
           if (isPublic(name)) {
             cls.members.add(new UnlinkedPublicNameBuilder(
                 name: name,
-                kind: ReferenceKind.method,
+                kind: member.isGetter
+                    ? ReferenceKind.propertyAccessor
+                    : ReferenceKind.method,
                 numTypeParameters:
                     member.typeParameters?.typeParameters?.length ?? 0));
           }
diff --git a/pkg/analyzer/lib/src/summary/resynthesize.dart b/pkg/analyzer/lib/src/summary/resynthesize.dart
index 23fecd5..749812e 100644
--- a/pkg/analyzer/lib/src/summary/resynthesize.dart
+++ b/pkg/analyzer/lib/src/summary/resynthesize.dart
@@ -286,9 +286,6 @@
   Expression get expr => stack.single;
 
   Expression build() {
-    if (!uc.isValidConst) {
-      return AstFactory.identifier3(r'$$invalidConstExpr$$');
-    }
     for (UnlinkedConstOperation operation in uc.operations) {
       switch (operation) {
         case UnlinkedConstOperation.pushNull:
@@ -564,12 +561,12 @@
   void _pushExtractProperty() {
     Expression target = _pop();
     String name = uc.strings[stringPtr++];
-    // TODO(scheglov) Only String.length property access is supported.
-    assert(name == 'length');
-    _push(AstFactory.propertyAccess(
-        target,
-        AstFactory.identifier3('length')
-          ..staticElement = _getStringLengthElement()));
+    SimpleIdentifier propertyNode = AstFactory.identifier3(name);
+    // Only String.length property access can be potentially resolved.
+    if (name == 'length') {
+      propertyNode.staticElement = _getStringLengthElement();
+    }
+    _push(AstFactory.propertyAccess(target, propertyNode));
   }
 
   void _pushInstanceCreation() {
@@ -1928,7 +1925,9 @@
     }
     executableElement.type = new FunctionTypeImpl.elementWithNameAndArgs(
         executableElement, null, getCurrentTypeArguments(skipLevels: 1), false);
+    executableElement.asynchronous = serializedExecutable.isAsynchronous;
     executableElement.external = serializedExecutable.isExternal;
+    executableElement.generator = serializedExecutable.isGenerator;
     buildDocumentation(
         executableElement, serializedExecutable.documentationComment);
     buildAnnotations(executableElement, serializedExecutable.annotations);
diff --git a/pkg/analyzer/lib/src/summary/summarize_ast.dart b/pkg/analyzer/lib/src/summary/summarize_ast.dart
index 3c4ddb7..35c6d01 100644
--- a/pkg/analyzer/lib/src/summary/summarize_ast.dart
+++ b/pkg/analyzer/lib/src/summary/summarize_ast.dart
@@ -7,6 +7,7 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/dart/element/type.dart' show DartType;
 import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/idl.dart';
@@ -49,20 +50,20 @@
       Identifier name = annotation.name;
       EntityRefBuilder constructor;
       if (name is PrefixedIdentifier && annotation.constructorName == null) {
-        constructor = serializeConstructorName(
-            new TypeName(name.prefix, null), name.identifier);
+        constructor =
+            serializeConstructorRef(null, name.prefix, null, name.identifier);
       } else {
-        constructor = serializeConstructorName(
-            new TypeName(annotation.name, null), annotation.constructorName);
+        constructor = serializeConstructorRef(
+            null, annotation.name, null, annotation.constructorName);
       }
       serializeInstanceCreation(constructor, annotation.arguments);
     }
   }
 
   @override
-  EntityRefBuilder serializeConstructorName(
-      TypeName type, SimpleIdentifier name) {
-    EntityRefBuilder typeBuilder = serializeType(type);
+  EntityRefBuilder serializeConstructorRef(DartType type, Identifier typeName,
+      TypeArgumentList typeArguments, SimpleIdentifier name) {
+    EntityRefBuilder typeBuilder = serializeType(type, typeName, typeArguments);
     if (name == null) {
       return typeBuilder;
     } else {
@@ -117,8 +118,9 @@
   }
 
   @override
-  EntityRefBuilder serializeType(TypeName node) {
-    return visitor.serializeTypeName(node);
+  EntityRefBuilder serializeType(
+      DartType type, Identifier name, TypeArgumentList arguments) {
+    return visitor.serializeType(name, arguments);
   }
 }
 
@@ -575,6 +577,8 @@
     }
     b.isExternal = isExternal;
     b.isAbstract = !isExternal && body is EmptyFunctionBody;
+    b.isAsynchronous = body.isAsynchronous;
+    b.isGenerator = body.isGenerator;
     b.name = nameString;
     b.nameOffset = nameOffset;
     b.typeParameters =
@@ -750,12 +754,12 @@
    * a [EntityRef].  Note that this method does the right thing if the
    * name doesn't refer to an entity other than a type (e.g. a class member).
    */
-  EntityRefBuilder serializeTypeName(TypeName node) {
-    if (node == null) {
+  EntityRefBuilder serializeType(
+      Identifier identifier, TypeArgumentList typeArguments) {
+    if (identifier == null) {
       return null;
     } else {
       EntityRefBuilder b = new EntityRefBuilder();
-      Identifier identifier = node.name;
       if (identifier is SimpleIdentifier) {
         String name = identifier.name;
         int indexOffset = 0;
@@ -788,9 +792,9 @@
         throw new StateError(
             'Unexpected identifier type: ${identifier.runtimeType}');
       }
-      if (node.typeArguments != null) {
+      if (typeArguments != null) {
         // Trailing type arguments of type 'dynamic' should be omitted.
-        NodeList<TypeName> args = node.typeArguments.arguments;
+        NodeList<TypeName> args = typeArguments.arguments;
         int numArgsToSerialize = args.length;
         while (
             numArgsToSerialize > 0 && isDynamic(args[numArgsToSerialize - 1])) {
@@ -809,6 +813,16 @@
   }
 
   /**
+   * Serialize a type name (which might be defined in a nested scope, at top
+   * level within this library, or at top level within an imported library) to
+   * a [EntityRef].  Note that this method does the right thing if the
+   * name doesn't refer to an entity other than a type (e.g. a class member).
+   */
+  EntityRefBuilder serializeTypeName(TypeName node) {
+    return serializeType(node?.name, node?.typeArguments);
+  }
+
+  /**
    * Serialize the given [typeParameters] into a list of [UnlinkedTypeParam]s,
    * and also store them in [typeParameterScope].
    */
@@ -950,9 +964,10 @@
       b.isFactory = true;
       if (node.redirectedConstructor != null) {
         b.isRedirectedConstructor = true;
+        TypeName typeName = node.redirectedConstructor.type;
         b.redirectedConstructor = new _ConstExprSerializer(this, null)
-            .serializeConstructorName(node.redirectedConstructor.type,
-                node.redirectedConstructor.name);
+            .serializeConstructorRef(null, typeName.name,
+                typeName.typeArguments, node.redirectedConstructor.name);
       }
     } else {
       for (ConstructorInitializer initializer in node.initializers) {
diff --git a/pkg/analyzer/lib/src/summary/summarize_const_expr.dart b/pkg/analyzer/lib/src/summary/summarize_const_expr.dart
index 6362f01..17a0b51 100644
--- a/pkg/analyzer/lib/src/summary/summarize_const_expr.dart
+++ b/pkg/analyzer/lib/src/summary/summarize_const_expr.dart
@@ -6,6 +6,7 @@
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/dart/element/type.dart' show DartType;
 import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/idl.dart';
 
@@ -103,10 +104,12 @@
 
   /**
    * Return [EntityRefBuilder] that corresponds to the constructor having name
-   * [name] in the class identified by [type].
+   * [name] in the class identified by [typeName].  It is expected that [type]
+   * corresponds to the given [typeName] and [typeArguments].  The parameter
+   * [type] might be `null` if the type is not resolved.
    */
-  EntityRefBuilder serializeConstructorName(
-      TypeName type, SimpleIdentifier name);
+  EntityRefBuilder serializeConstructorRef(DartType type, Identifier typeName,
+      TypeArgumentList typeArguments, SimpleIdentifier name);
 
   /**
    * Return [EntityRefBuilder] that corresponds to the given [identifier].
@@ -127,9 +130,20 @@
   }
 
   /**
+   * Return [EntityRefBuilder] that corresponds to the [type] with the given
+   * [name] and [arguments].  It is expected that [type] corresponds to the
+   * given [name] and [arguments].  The parameter [type] might be `null` if the
+   * type is not resolved.
+   */
+  EntityRefBuilder serializeType(
+      DartType type, Identifier name, TypeArgumentList arguments);
+
+  /**
    * Return [EntityRefBuilder] that corresponds to the given [type].
    */
-  EntityRefBuilder serializeType(TypeName type);
+  EntityRefBuilder serializeTypeName(TypeName type) {
+    return serializeType(type?.type, type?.name, type?.typeArguments);
+  }
 
   /**
    * Return the [UnlinkedConstBuilder] that corresponds to the state of this
@@ -226,9 +240,10 @@
       if (!expr.isConst) {
         isValidConst = false;
       }
+      TypeName typeName = expr.constructorName.type;
       serializeInstanceCreation(
-          serializeConstructorName(
-              expr.constructorName.type, expr.constructorName.name),
+          serializeConstructorRef(typeName.type, typeName.name,
+              typeName.typeArguments, expr.constructorName.name),
           expr.argumentList);
     } else if (expr is ListLiteral) {
       _serializeListLiteral(expr);
@@ -271,12 +286,12 @@
     } else if (expr is AsExpression) {
       isValidConst = false;
       _serialize(expr.expression);
-      references.add(serializeType(expr.type));
+      references.add(serializeTypeName(expr.type));
       operations.add(UnlinkedConstOperation.typeCast);
     } else if (expr is IsExpression) {
       isValidConst = false;
       _serialize(expr.expression);
-      references.add(serializeType(expr.type));
+      references.add(serializeTypeName(expr.type));
       operations.add(UnlinkedConstOperation.typeCheck);
     } else if (expr is ThrowExpression) {
       isValidConst = false;
@@ -408,7 +423,7 @@
     ints.add(elements.length);
     if (expr.typeArguments != null &&
         expr.typeArguments.arguments.length == 1) {
-      references.add(serializeType(expr.typeArguments.arguments[0]));
+      references.add(serializeTypeName(expr.typeArguments.arguments[0]));
       operations.add(UnlinkedConstOperation.makeTypedList);
     } else {
       operations.add(UnlinkedConstOperation.makeUntypedList);
@@ -423,8 +438,8 @@
     ints.add(expr.entries.length);
     if (expr.typeArguments != null &&
         expr.typeArguments.arguments.length == 2) {
-      references.add(serializeType(expr.typeArguments.arguments[0]));
-      references.add(serializeType(expr.typeArguments.arguments[1]));
+      references.add(serializeTypeName(expr.typeArguments.arguments[0]));
+      references.add(serializeTypeName(expr.typeArguments.arguments[1]));
       operations.add(UnlinkedConstOperation.makeTypedMap);
     } else {
       operations.add(UnlinkedConstOperation.makeUntypedMap);
diff --git a/pkg/analyzer/lib/src/summary/summarize_elements.dart b/pkg/analyzer/lib/src/summary/summarize_elements.dart
index 353de09..b8828ec 100644
--- a/pkg/analyzer/lib/src/summary/summarize_elements.dart
+++ b/pkg/analyzer/lib/src/summary/summarize_elements.dart
@@ -609,6 +609,7 @@
       List<UnlinkedPublicNameBuilder> bs = <UnlinkedPublicNameBuilder>[];
       for (FieldElement field in cls.fields) {
         if (field.isStatic && field.isConst && field.isPublic) {
+          // TODO(paulberry): include non-consts
           // TODO(paulberry): should numTypeParameters include class params?
           bs.add(new UnlinkedPublicNameBuilder(
               name: field.name,
@@ -625,6 +626,17 @@
               numTypeParameters: method.typeParameters.length));
         }
       }
+      for (PropertyAccessorElement accessor in cls.accessors) {
+        if (accessor.isStatic &&
+            accessor.isGetter &&
+            accessor.isPublic &&
+            !accessor.isSynthetic) {
+          // TODO(paulberry): combine with field code above.
+          // TODO(paulberry): should numTypeParameters include class params?
+          bs.add(new UnlinkedPublicNameBuilder(
+              name: accessor.name, kind: ReferenceKind.propertyAccessor));
+        }
+      }
       for (ConstructorElement constructor in cls.constructors) {
         if (constructor.isPublic && constructor.name.isNotEmpty) {
           // TODO(paulberry): should numTypeParameters include class params?
@@ -794,6 +806,8 @@
       b.kind = UnlinkedExecutableKind.functionOrMethod;
     }
     b.isAbstract = executableElement.isAbstract;
+    b.isAsynchronous = executableElement.isAsynchronous;
+    b.isGenerator = executableElement.isGenerator;
     b.isStatic = executableElement.isStatic &&
         executableElement.enclosingElement is ClassElement;
     b.isExternal = executableElement.isExternal;
@@ -1331,21 +1345,19 @@
       EntityRefBuilder constructor;
       if (nameElement is ConstructorElement && name is PrefixedIdentifier) {
         assert(annotation.constructorName == null);
-        constructor = serializeConstructorName(
-            new TypeName(name.prefix, null)..type = nameElement.returnType,
-            name.identifier);
+        constructor = serializeConstructorRef(
+            nameElement.returnType, name.prefix, null, name.identifier);
       } else if (nameElement is TypeDefiningElement) {
-        constructor = serializeConstructorName(
-            new TypeName(annotation.name, null)..type = nameElement.type,
-            annotation.constructorName);
+        constructor = serializeConstructorRef(nameElement.type, annotation.name,
+            null, annotation.constructorName);
       } else if (nameElement == null) {
         // Unresolved annotation.
         if (name is PrefixedIdentifier && annotation.constructorName == null) {
-          constructor = serializeConstructorName(
-              new TypeName(name.prefix, null), name.identifier);
+          constructor =
+              serializeConstructorRef(null, name.prefix, null, name.identifier);
         } else {
-          constructor = serializeConstructorName(
-              new TypeName(annotation.name, null), annotation.constructorName);
+          constructor = serializeConstructorRef(
+              null, annotation.name, null, annotation.constructorName);
         }
       } else {
         throw new StateError('Unexpected annotation nameElement type:'
@@ -1356,9 +1368,9 @@
   }
 
   @override
-  EntityRefBuilder serializeConstructorName(
-      TypeName type, SimpleIdentifier name) {
-    EntityRefBuilder typeRef = serializeType(type);
+  EntityRefBuilder serializeConstructorRef(DartType type, Identifier typeName,
+      TypeArgumentList typeArguments, SimpleIdentifier name) {
+    EntityRefBuilder typeRef = serializeType(type, typeName, typeArguments);
     if (name == null) {
       return typeRef;
     } else {
@@ -1433,15 +1445,15 @@
   }
 
   @override
-  EntityRefBuilder serializeType(TypeName typeName) {
-    if (typeName != null) {
-      DartType type = typeName.type;
+  EntityRefBuilder serializeType(
+      DartType type, Identifier name, TypeArgumentList arguments) {
+    if (name != null) {
       if (type == null || type.isUndefined) {
-        return serializeIdentifier(typeName.name);
+        return serializeIdentifier(name);
       }
     }
-    DartType type = typeName != null ? typeName.type : DynamicTypeImpl.instance;
-    return serializer.serializeTypeRef(type, context);
+    DartType typeOrDynamic = type ?? DynamicTypeImpl.instance;
+    return serializer.serializeTypeRef(typeOrDynamic, context);
   }
 
   /**
diff --git a/pkg/analyzer/lib/src/summary/summary_sdk.dart b/pkg/analyzer/lib/src/summary/summary_sdk.dart
index f38ede3..77303c3 100644
--- a/pkg/analyzer/lib/src/summary/summary_sdk.dart
+++ b/pkg/analyzer/lib/src/summary/summary_sdk.dart
@@ -65,6 +65,7 @@
           result == LIBRARY_ELEMENT6 ||
           result == LIBRARY_ELEMENT7 ||
           result == LIBRARY_ELEMENT8 ||
+          result == LIBRARY_ELEMENT9 ||
           result == LIBRARY_ELEMENT) {
         // TODO(scheglov) try to find a way to avoid listing every result
         // e.g. "result.whenComplete == LIBRARY_ELEMENT"
@@ -73,8 +74,8 @@
         entry.setValue(result, libraryElement, TargetedResult.EMPTY_LIST);
         return true;
       } else if (result == READY_LIBRARY_ELEMENT2 ||
-          result == READY_LIBRARY_ELEMENT5 ||
-          result == READY_LIBRARY_ELEMENT6) {
+          result == READY_LIBRARY_ELEMENT6 ||
+          result == READY_LIBRARY_ELEMENT7) {
         entry.setValue(result, true, TargetedResult.EMPTY_LIST);
         return true;
       } else if (result == SOURCE_KIND) {
@@ -102,7 +103,8 @@
           result == CREATED_RESOLVED_UNIT7 ||
           result == CREATED_RESOLVED_UNIT8 ||
           result == CREATED_RESOLVED_UNIT9 ||
-          result == CREATED_RESOLVED_UNIT10) {
+          result == CREATED_RESOLVED_UNIT10 ||
+          result == CREATED_RESOLVED_UNIT11) {
         entry.setValue(result, true, TargetedResult.EMPTY_LIST);
         return true;
       }
diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart
index 283bca3..ca0f09d 100644
--- a/pkg/analyzer/lib/src/task/dart.dart
+++ b/pkg/analyzer/lib/src/task/dart.dart
@@ -233,6 +233,15 @@
     new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT12', false);
 
 /**
+ * The flag specifying that [RESOLVED_UNIT13] has been been computed for this
+ * compilation unit (without requiring that the AST for it still be in cache).
+ *
+ * The result is only available for [LibrarySpecificUnit]s.
+ */
+final ResultDescriptor<bool> CREATED_RESOLVED_UNIT13 =
+    new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT13', false);
+
+/**
  * The flag specifying that [RESOLVED_UNIT2] has been been computed for this
  * compilation unit (without requiring that the AST for it still be in cache).
  *
@@ -449,7 +458,7 @@
 /**
  * The partial [LibraryElement] associated with a library.
  *
- * [LIBRARY_ELEMENT4] plus resolved types for every element.
+ * [LIBRARY_ELEMENT5] plus resolved types type parameter bounds.
  *
  * The result is only available for [Source]s representing a library.
  */
@@ -460,7 +469,7 @@
 /**
  * The partial [LibraryElement] associated with a library.
  *
- * [LIBRARY_ELEMENT5] plus propagated types for propagable variables.
+ * [LIBRARY_ELEMENT5] plus resolved types for every element.
  *
  * The result is only available for [Source]s representing a library.
  */
@@ -471,7 +480,7 @@
 /**
  * The partial [LibraryElement] associated with a library.
  *
- * [LIBRARY_ELEMENT6] for the library and its import/export closure.
+ * [LIBRARY_ELEMENT6] plus propagated types for propagable variables.
  *
  * The result is only available for [Source]s representing a library.
  */
@@ -482,7 +491,7 @@
 /**
  * The partial [LibraryElement] associated with a library.
  *
- * The same as a [LIBRARY_ELEMENT7].
+ * [LIBRARY_ELEMENT7] for the library and its import/export closure.
  *
  * The result is only available for [Source]s representing a library.
  */
@@ -491,6 +500,17 @@
         cachingPolicy: ELEMENT_CACHING_POLICY);
 
 /**
+ * The partial [LibraryElement] associated with a library.
+ *
+ * The same as a [LIBRARY_ELEMENT8].
+ *
+ * The result is only available for [Source]s representing a library.
+ */
+final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT9 =
+    new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT9', null,
+        cachingPolicy: ELEMENT_CACHING_POLICY);
+
+/**
  * The flag specifying whether all analysis errors are computed in a specific
  * library.
  *
@@ -582,15 +602,6 @@
     new ResultDescriptor<bool>('READY_LIBRARY_ELEMENT2', false);
 
 /**
- * The flag specifying that [LIBRARY_ELEMENT5] is ready for a library and its
- * import/export closure.
- *
- * The result is only available for [Source]s representing a library.
- */
-final ResultDescriptor<bool> READY_LIBRARY_ELEMENT5 =
-    new ResultDescriptor<bool>('READY_LIBRARY_ELEMENT5', false);
-
-/**
  * The flag specifying that [LIBRARY_ELEMENT6] is ready for a library and its
  * import/export closure.
  *
@@ -600,6 +611,15 @@
     new ResultDescriptor<bool>('READY_LIBRARY_ELEMENT6', false);
 
 /**
+ * The flag specifying that [LIBRARY_ELEMENT7] is ready for a library and its
+ * import/export closure.
+ *
+ * The result is only available for [Source]s representing a library.
+ */
+final ResultDescriptor<bool> READY_LIBRARY_ELEMENT7 =
+    new ResultDescriptor<bool>('READY_LIBRARY_ELEMENT7', false);
+
+/**
  * The flag specifying that [RESOLVED_UNIT] is ready for all of the units of a
  * library.
  *
@@ -628,6 +648,18 @@
     new ListResultDescriptor<Source>('REFERENCED_SOURCES', Source.EMPTY_LIST);
 
 /**
+ * The errors produced while resolving bounds of type parameters of classes,
+ * class and function aliases.
+ *
+ * The list will be empty if there were no errors, but will not be `null`.
+ *
+ * The result is only available for [LibrarySpecificUnit]s.
+ */
+final ListResultDescriptor<AnalysisError> RESOLVE_TYPE_BOUNDS_ERRORS =
+    new ListResultDescriptor<AnalysisError>(
+        'RESOLVE_TYPE_BOUNDS_ERRORS', AnalysisError.NO_ERRORS);
+
+/**
  * The errors produced while resolving type names.
  *
  * The list will be empty if there were no errors, but will not be `null`.
@@ -663,9 +695,11 @@
         cachingPolicy: AST_CACHING_POLICY);
 
 /**
- * The resolved [CompilationUnit] associated with a compilation unit in which
- * the types of class members have been inferred in addition to everything that
- * is true of a [RESOLVED_UNIT9].
+ * The partially resolved [CompilationUnit] associated with a compilation unit.
+ *
+ * In addition to what is true of a [RESOLVED_UNIT9], tasks that use this value
+ * as an input can assume that the initializers of instance variables have been
+ * re-resolved.
  *
  * The result is only available for [LibrarySpecificUnit]s.
  */
@@ -674,8 +708,9 @@
         cachingPolicy: AST_CACHING_POLICY);
 
 /**
- * The resolved [CompilationUnit] associated with a compilation unit, with
- * constants not yet resolved.
+ * The resolved [CompilationUnit] associated with a compilation unit in which
+ * the types of class members have been inferred in addition to everything that
+ * is true of a [RESOLVED_UNIT10].
  *
  * The result is only available for [LibrarySpecificUnit]s.
  */
@@ -685,7 +720,7 @@
 
 /**
  * The resolved [CompilationUnit] associated with a compilation unit, with
- * constants resolved.
+ * constants not yet resolved.
  *
  * The result is only available for [LibrarySpecificUnit]s.
  */
@@ -694,6 +729,16 @@
         cachingPolicy: AST_CACHING_POLICY);
 
 /**
+ * The resolved [CompilationUnit] associated with a compilation unit, with
+ * constants resolved.
+ *
+ * The result is only available for [LibrarySpecificUnit]s.
+ */
+final ResultDescriptor<CompilationUnit> RESOLVED_UNIT13 =
+    new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT13', null,
+        cachingPolicy: AST_CACHING_POLICY);
+
+/**
  * The partially resolved [CompilationUnit] associated with a compilation unit.
  *
  * In addition to what is true of a [RESOLVED_UNIT1], tasks that use this value
@@ -722,9 +767,8 @@
  * The partially resolved [CompilationUnit] associated with a compilation unit.
  *
  * In addition to what is true of a [RESOLVED_UNIT3], tasks that use this value
- * as an input can assume that the types associated with declarations have been
- * resolved. This includes the types of superclasses, mixins, interfaces,
- * fields, return types, parameters, and local variables.
+ * as an input can assume that the types associated with type bounds have been
+ * resolved.
  *
  * The result is only available for [LibrarySpecificUnit]s.
  */
@@ -736,8 +780,9 @@
  * The partially resolved [CompilationUnit] associated with a compilation unit.
  *
  * In addition to what is true of a [RESOLVED_UNIT4], tasks that use this value
- * as an input can assume that references to local variables and formal
- * parameters have been resolved.
+ * as an input can assume that the types associated with declarations have been
+ * resolved. This includes the types of superclasses, mixins, interfaces,
+ * fields, return types, parameters, and local variables.
  *
  * The result is only available for [LibrarySpecificUnit]s.
  */
@@ -749,9 +794,8 @@
  * The partially resolved [CompilationUnit] associated with a compilation unit.
  *
  * In addition to what is true of a [RESOLVED_UNIT5], tasks that use this value
- * as an input can assume that elements and types associated with expressions
- * outside of method bodies (essentially initializers) have been initially
- * resolved.
+ * as an input can assume that references to local variables and formal
+ * parameters have been resolved.
  *
  * The result is only available for [LibrarySpecificUnit]s.
  */
@@ -763,8 +807,9 @@
  * The partially resolved [CompilationUnit] associated with a compilation unit.
  *
  * In addition to what is true of a [RESOLVED_UNIT6], tasks that use this value
- * as an input can assume that the types of final variables have been
- * propagated.
+ * as an input can assume that elements and types associated with expressions
+ * outside of method bodies (essentially initializers) have been initially
+ * resolved.
  *
  * The result is only available for [LibrarySpecificUnit]s.
  */
@@ -776,7 +821,8 @@
  * The partially resolved [CompilationUnit] associated with a compilation unit.
  *
  * In addition to what is true of a [RESOLVED_UNIT7], tasks that use this value
- * as an input can assume that the types of static variables have been inferred.
+ * as an input can assume that the types of final variables have been
+ * propagated.
  *
  * The result is only available for [LibrarySpecificUnit]s.
  */
@@ -788,8 +834,7 @@
  * The partially resolved [CompilationUnit] associated with a compilation unit.
  *
  * In addition to what is true of a [RESOLVED_UNIT8], tasks that use this value
- * as an input can assume that the initializers of instance variables have been
- * re-resolved.
+ * as an input can assume that the types of static variables have been inferred.
  *
  * The result is only available for [LibrarySpecificUnit]s.
  */
@@ -1921,7 +1966,7 @@
 class ComputeInferableStaticVariableDependenciesTask
     extends InferStaticVariableTask {
   /**
-   * The name of the [RESOLVED_UNIT6] input.
+   * The name of the [RESOLVED_UNIT7] input.
    */
   static const String UNIT_INPUT = 'UNIT_INPUT';
 
@@ -1975,7 +2020,7 @@
       CompilationUnitElementImpl unit = target
           .getAncestor((Element element) => element is CompilationUnitElement);
       return <String, TaskInput>{
-        UNIT_INPUT: RESOLVED_UNIT6
+        UNIT_INPUT: RESOLVED_UNIT7
             .of(new LibrarySpecificUnit(unit.librarySource, unit.source))
       };
     }
@@ -2105,7 +2150,7 @@
 class ComputePropagableVariableDependenciesTask
     extends InferStaticVariableTask {
   /**
-   * The name of the [RESOLVED_UNIT6] input.
+   * The name of the [RESOLVED_UNIT7] input.
    */
   static const String UNIT_INPUT = 'UNIT_INPUT';
 
@@ -2160,7 +2205,7 @@
       CompilationUnitElementImpl unit = target
           .getAncestor((Element element) => element is CompilationUnitElement);
       return <String, TaskInput>{
-        UNIT_INPUT: RESOLVED_UNIT6
+        UNIT_INPUT: RESOLVED_UNIT7
             .of(new LibrarySpecificUnit(unit.librarySource, unit.source))
       };
     }
@@ -2526,11 +2571,11 @@
 }
 
 /**
- * A task that builds [RESOLVED_UNIT12] for a unit.
+ * A task that builds [RESOLVED_UNIT13] for a unit.
  */
 class EvaluateUnitConstantsTask extends SourceBasedAnalysisTask {
   /**
-   * The name of the [RESOLVED_UNIT11] input.
+   * The name of the [RESOLVED_UNIT12] input.
    */
   static const String UNIT_INPUT = 'UNIT_INPUT';
 
@@ -2546,7 +2591,7 @@
       'EvaluateUnitConstantsTask',
       createTask,
       buildInputs,
-      <ResultDescriptor>[CREATED_RESOLVED_UNIT12, RESOLVED_UNIT12]);
+      <ResultDescriptor>[CREATED_RESOLVED_UNIT13, RESOLVED_UNIT13]);
 
   EvaluateUnitConstantsTask(AnalysisContext context, LibrarySpecificUnit target)
       : super(context, target);
@@ -2559,8 +2604,8 @@
     // No actual work needs to be performed; the task manager will ensure that
     // all constants are evaluated before this method is called.
     CompilationUnit unit = getRequiredInput(UNIT_INPUT);
-    outputs[RESOLVED_UNIT12] = unit;
-    outputs[CREATED_RESOLVED_UNIT12] = true;
+    outputs[RESOLVED_UNIT13] = unit;
+    outputs[CREATED_RESOLVED_UNIT13] = true;
   }
 
   /**
@@ -2571,8 +2616,8 @@
   static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
     LibrarySpecificUnit unit = target;
     return <String, TaskInput>{
-      'libraryElement': LIBRARY_ELEMENT8.of(unit.library),
-      UNIT_INPUT: RESOLVED_UNIT11.of(unit),
+      'libraryElement': LIBRARY_ELEMENT9.of(unit.library),
+      UNIT_INPUT: RESOLVED_UNIT12.of(unit),
       CONSTANT_VALUES:
           COMPILATION_UNIT_CONSTANTS.of(unit).toListOf(CONSTANT_VALUE),
       'constantExpressionsDependencies':
@@ -2595,7 +2640,7 @@
  */
 class GatherUsedImportedElementsTask extends SourceBasedAnalysisTask {
   /**
-   * The name of the [RESOLVED_UNIT11] input.
+   * The name of the [RESOLVED_UNIT12] input.
    */
   static const String UNIT_INPUT = 'UNIT_INPUT';
 
@@ -2639,7 +2684,7 @@
    */
   static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
     LibrarySpecificUnit unit = target;
-    return <String, TaskInput>{UNIT_INPUT: RESOLVED_UNIT11.of(unit)};
+    return <String, TaskInput>{UNIT_INPUT: RESOLVED_UNIT12.of(unit)};
   }
 
   /**
@@ -2657,7 +2702,7 @@
  */
 class GatherUsedLocalElementsTask extends SourceBasedAnalysisTask {
   /**
-   * The name of the [RESOLVED_UNIT11] input.
+   * The name of the [RESOLVED_UNIT12] input.
    */
   static const String UNIT_INPUT = 'UNIT_INPUT';
 
@@ -2701,7 +2746,7 @@
    */
   static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
     LibrarySpecificUnit unit = target;
-    return <String, TaskInput>{UNIT_INPUT: RESOLVED_UNIT11.of(unit)};
+    return <String, TaskInput>{UNIT_INPUT: RESOLVED_UNIT12.of(unit)};
   }
 
   /**
@@ -2719,7 +2764,7 @@
  */
 class GenerateHintsTask extends SourceBasedAnalysisTask {
   /**
-   * The name of the [RESOLVED_UNIT11] input.
+   * The name of the [RESOLVED_UNIT12] input.
    */
   static const String RESOLVED_UNIT_INPUT = 'RESOLVED_UNIT';
 
@@ -2805,7 +2850,8 @@
         new InheritanceManager(libraryElement);
     TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
 
-    unit.accept(new BestPracticesVerifier(errorReporter, typeProvider,
+    unit.accept(new BestPracticesVerifier(
+        errorReporter, typeProvider, libraryElement,
         typeSystem: typeSystem));
     unit.accept(new OverrideVerifier(errorReporter, inheritanceManager));
     // Find to-do comments.
@@ -2939,7 +2985,7 @@
   static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
 
   /**
-   * The name of the input whose value is the [RESOLVED_UNIT8] for the
+   * The name of the input whose value is the [RESOLVED_UNIT9] for the
    * compilation unit.
    */
   static const String UNIT_INPUT = 'UNIT_INPUT';
@@ -2951,7 +2997,7 @@
       'InferInstanceMembersInUnitTask',
       createTask,
       buildInputs,
-      <ResultDescriptor>[CREATED_RESOLVED_UNIT10, RESOLVED_UNIT10]);
+      <ResultDescriptor>[CREATED_RESOLVED_UNIT11, RESOLVED_UNIT11]);
 
   /**
    * Initialize a newly created task to build a library element for the given
@@ -2983,8 +3029,8 @@
     //
     // Record outputs.
     //
-    outputs[RESOLVED_UNIT10] = unit;
-    outputs[CREATED_RESOLVED_UNIT10] = true;
+    outputs[RESOLVED_UNIT11] = unit;
+    outputs[CREATED_RESOLVED_UNIT11] = true;
   }
 
   /**
@@ -2995,7 +3041,7 @@
   static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
     LibrarySpecificUnit unit = target;
     return <String, TaskInput>{
-      UNIT_INPUT: RESOLVED_UNIT9.of(unit),
+      UNIT_INPUT: RESOLVED_UNIT10.of(unit),
       TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request),
       // In strong mode, add additional dependencies to enforce inference
       // ordering.
@@ -3003,14 +3049,14 @@
       // Require that field re-resolution be complete for all units in the
       // current library cycle.
       'orderLibraryCycleTasks': LIBRARY_CYCLE_UNITS.of(unit).toList(
-          (CompilationUnitElement unit) => CREATED_RESOLVED_UNIT9.of(
+          (CompilationUnitElement unit) => CREATED_RESOLVED_UNIT10.of(
               new LibrarySpecificUnit(
                   (unit as CompilationUnitElementImpl).librarySource,
                   unit.source))),
       // Require that full inference be complete for all dependencies of the
       // current library cycle.
       'orderLibraryCycles': LIBRARY_CYCLE_DEPENDENCIES.of(unit).toList(
-          (CompilationUnitElement unit) => CREATED_RESOLVED_UNIT10.of(
+          (CompilationUnitElement unit) => CREATED_RESOLVED_UNIT11.of(
               new LibrarySpecificUnit(
                   (unit as CompilationUnitElementImpl).librarySource,
                   unit.source)))
@@ -3081,7 +3127,7 @@
  */
 class InferStaticVariableTypesInUnitTask extends SourceBasedAnalysisTask {
   /**
-   * The name of the input whose value is the [RESOLVED_UNIT7] for the
+   * The name of the input whose value is the [RESOLVED_UNIT8] for the
    * compilation unit.
    */
   static const String UNIT_INPUT = 'UNIT_INPUT';
@@ -3099,7 +3145,7 @@
       'InferStaticVariableTypesInUnitTask',
       createTask,
       buildInputs,
-      <ResultDescriptor>[CREATED_RESOLVED_UNIT8, RESOLVED_UNIT8]);
+      <ResultDescriptor>[CREATED_RESOLVED_UNIT9, RESOLVED_UNIT9]);
 
   /**
    * Initialize a newly created task to build a library element for the given
@@ -3123,8 +3169,8 @@
     // because the work has implicitly been done by virtue of the task model
     // preparing all of the inputs.
     //
-    outputs[RESOLVED_UNIT8] = unit;
-    outputs[CREATED_RESOLVED_UNIT8] = true;
+    outputs[RESOLVED_UNIT9] = unit;
+    outputs[CREATED_RESOLVED_UNIT9] = true;
   }
 
   /**
@@ -3138,7 +3184,7 @@
       INFERRED_VARIABLES_INPUT: INFERABLE_STATIC_VARIABLES_IN_UNIT
           .of(unit)
           .toListOf(INFERRED_STATIC_VARIABLE),
-      UNIT_INPUT: RESOLVED_UNIT7.of(unit)
+      UNIT_INPUT: RESOLVED_UNIT8.of(unit)
     };
   }
 
@@ -3169,7 +3215,7 @@
   static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
 
   /**
-   * The name of the [RESOLVED_UNIT7] input.
+   * The name of the [RESOLVED_UNIT8] input.
    */
   static const String UNIT_INPUT = 'UNIT_INPUT';
 
@@ -3260,14 +3306,14 @@
           .of(variable)
           .toListOf(INFERRED_STATIC_VARIABLE),
       TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request),
-      UNIT_INPUT: RESOLVED_UNIT7.of(unit),
+      UNIT_INPUT: RESOLVED_UNIT8.of(unit),
       // In strong mode, add additional dependencies to enforce inference
       // ordering.
 
       // Require that full inference be complete for all dependencies of the
       // current library cycle.
       'orderLibraryCycles': LIBRARY_CYCLE_DEPENDENCIES.of(unit).toList(
-          (CompilationUnitElement unit) => CREATED_RESOLVED_UNIT10.of(
+          (CompilationUnitElement unit) => CREATED_RESOLVED_UNIT11.of(
               new LibrarySpecificUnit(
                   (unit as CompilationUnitElementImpl).librarySource,
                   unit.source)))
@@ -3369,6 +3415,12 @@
       'RESOLVE_TYPE_NAMES_ERRORS';
 
   /**
+   * The name of the [RESOLVE_TYPE_BOUNDS_ERRORS] input.
+   */
+  static const String RESOLVE_TYPE_NAMES_ERRORS2_INPUT =
+      'RESOLVE_TYPE_NAMES_ERRORS2';
+
+  /**
    * The name of the [RESOLVE_UNIT_ERRORS] input.
    */
   static const String RESOLVE_UNIT_ERRORS_INPUT = 'RESOLVE_UNIT_ERRORS';
@@ -3410,6 +3462,7 @@
     errorLists.add(getRequiredInput(HINTS_INPUT));
     errorLists.add(getRequiredInput(LINTS_INPUT));
     errorLists.add(getRequiredInput(RESOLVE_TYPE_NAMES_ERRORS_INPUT));
+    errorLists.add(getRequiredInput(RESOLVE_TYPE_NAMES_ERRORS2_INPUT));
     errorLists.add(getRequiredInput(RESOLVE_UNIT_ERRORS_INPUT));
     errorLists.add(getRequiredInput(STRONG_MODE_ERRORS_INPUT));
     errorLists.add(getRequiredInput(VARIABLE_REFERENCE_ERRORS_INPUT));
@@ -3431,6 +3484,7 @@
       HINTS_INPUT: HINTS.of(unit),
       LINTS_INPUT: LINTS.of(unit),
       RESOLVE_TYPE_NAMES_ERRORS_INPUT: RESOLVE_TYPE_NAMES_ERRORS.of(unit),
+      RESOLVE_TYPE_NAMES_ERRORS2_INPUT: RESOLVE_TYPE_BOUNDS_ERRORS.of(unit),
       RESOLVE_UNIT_ERRORS_INPUT: RESOLVE_UNIT_ERRORS.of(unit),
       STRONG_MODE_ERRORS_INPUT: STRONG_MODE_ERRORS.of(unit),
       VARIABLE_REFERENCE_ERRORS_INPUT: VARIABLE_REFERENCE_ERRORS.of(unit),
@@ -3673,16 +3727,16 @@
 }
 
 /**
- * A task that builds [RESOLVED_UNIT6] for a unit.
+ * A task that builds [RESOLVED_UNIT7] for a unit.
  */
 class PartiallyResolveUnitReferencesTask extends SourceBasedAnalysisTask {
   /**
-   * The name of the [LIBRARY_ELEMENT5] input.
+   * The name of the [LIBRARY_ELEMENT6] input.
    */
   static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
 
   /**
-   * The name of the [RESOLVED_UNIT5] input.
+   * The name of the [RESOLVED_UNIT6] input.
    */
   static const String UNIT_INPUT = 'UNIT_INPUT';
 
@@ -3700,8 +3754,8 @@
       buildInputs, <ResultDescriptor>[
     INFERABLE_STATIC_VARIABLES_IN_UNIT,
     PROPAGABLE_VARIABLES_IN_UNIT,
-    CREATED_RESOLVED_UNIT6,
-    RESOLVED_UNIT6
+    CREATED_RESOLVED_UNIT7,
+    RESOLVED_UNIT7
   ]);
 
   PartiallyResolveUnitReferencesTask(
@@ -3735,8 +3789,8 @@
       outputs[INFERABLE_STATIC_VARIABLES_IN_UNIT] = VariableElement.EMPTY_LIST;
     }
     outputs[PROPAGABLE_VARIABLES_IN_UNIT] = visitor.propagableVariables;
-    outputs[RESOLVED_UNIT6] = unit;
-    outputs[CREATED_RESOLVED_UNIT6] = true;
+    outputs[RESOLVED_UNIT7] = unit;
+    outputs[CREATED_RESOLVED_UNIT7] = true;
   }
 
   /**
@@ -3747,9 +3801,9 @@
   static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
     LibrarySpecificUnit unit = target;
     return <String, TaskInput>{
-      'fullyBuiltLibraryElements': READY_LIBRARY_ELEMENT5.of(unit.library),
-      LIBRARY_INPUT: LIBRARY_ELEMENT5.of(unit.library),
-      UNIT_INPUT: RESOLVED_UNIT5.of(unit),
+      'fullyBuiltLibraryElements': READY_LIBRARY_ELEMENT6.of(unit.library),
+      LIBRARY_INPUT: LIBRARY_ELEMENT6.of(unit.library),
+      UNIT_INPUT: RESOLVED_UNIT6.of(unit),
       TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request),
       // In strong mode, add additional dependencies to enforce inference
       // ordering.
@@ -3757,7 +3811,7 @@
       // Require that full inference be complete for all dependencies of the
       // current library cycle.
       'orderLibraryCycles': LIBRARY_CYCLE_DEPENDENCIES.of(unit).toList(
-          (CompilationUnitElement unit) => CREATED_RESOLVED_UNIT10.of(
+          (CompilationUnitElement unit) => CREATED_RESOLVED_UNIT11.of(
               new LibrarySpecificUnit(
                   (unit as CompilationUnitElementImpl).librarySource,
                   unit.source)))
@@ -3781,7 +3835,7 @@
 class PropagateVariableTypesInLibraryClosureTask
     extends SourceBasedAnalysisTask {
   /**
-   * The name of the [LIBRARY_ELEMENT6] input.
+   * The name of the [LIBRARY_ELEMENT7] input.
    */
   static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
 
@@ -3792,7 +3846,7 @@
       'PropagateVariableTypesInLibraryClosureTask',
       createTask,
       buildInputs,
-      <ResultDescriptor>[LIBRARY_ELEMENT7]);
+      <ResultDescriptor>[LIBRARY_ELEMENT8]);
 
   PropagateVariableTypesInLibraryClosureTask(
       InternalAnalysisContext context, AnalysisTarget target)
@@ -3804,6 +3858,61 @@
   @override
   void internalPerform() {
     LibraryElement library = getRequiredInput(LIBRARY_INPUT);
+    outputs[LIBRARY_ELEMENT8] = library;
+  }
+
+  /**
+   * Return a map from the names of the inputs of this kind of task to the task
+   * input descriptors describing those inputs for a task with the
+   * given [target].
+   */
+  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
+    Source source = target;
+    return <String, TaskInput>{
+      'readyForClosure': READY_LIBRARY_ELEMENT7.of(source),
+      LIBRARY_INPUT: LIBRARY_ELEMENT7.of(source),
+    };
+  }
+
+  /**
+   * Create a [PropagateVariableTypesInLibraryClosureTask] based on the given
+   * [target] in the given [context].
+   */
+  static PropagateVariableTypesInLibraryClosureTask createTask(
+      AnalysisContext context, AnalysisTarget target) {
+    return new PropagateVariableTypesInLibraryClosureTask(context, target);
+  }
+}
+
+/**
+ * An artificial task that does nothing except to force propagated types for
+ * all propagable variables in the defining and part units of a library.
+ */
+class PropagateVariableTypesInLibraryTask extends SourceBasedAnalysisTask {
+  /**
+   * The name of the [LIBRARY_ELEMENT6] input.
+   */
+  static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
+
+  /**
+   * The task descriptor describing this kind of task.
+   */
+  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
+      'PropagateVariableTypesInLibraryTask',
+      createTask,
+      buildInputs,
+      <ResultDescriptor>[LIBRARY_ELEMENT7]);
+
+  PropagateVariableTypesInLibraryTask(
+      InternalAnalysisContext context, AnalysisTarget target)
+      : super(context, target);
+
+  @override
+  TaskDescriptor get descriptor => DESCRIPTOR;
+
+  @override
+  void internalPerform() {
+    LibraryElement library = getRequiredInput(LIBRARY_INPUT);
     outputs[LIBRARY_ELEMENT7] = library;
   }
 
@@ -3815,64 +3924,9 @@
   static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
     Source source = target;
     return <String, TaskInput>{
-      'readyForClosure': READY_LIBRARY_ELEMENT6.of(source),
-      LIBRARY_INPUT: LIBRARY_ELEMENT6.of(source),
-    };
-  }
-
-  /**
-   * Create a [PropagateVariableTypesInLibraryClosureTask] based on the given
-   * [target] in the given [context].
-   */
-  static PropagateVariableTypesInLibraryClosureTask createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new PropagateVariableTypesInLibraryClosureTask(context, target);
-  }
-}
-
-/**
- * An artificial task that does nothing except to force propagated types for
- * all propagable variables in the defining and part units of a library.
- */
-class PropagateVariableTypesInLibraryTask extends SourceBasedAnalysisTask {
-  /**
-   * The name of the [LIBRARY_ELEMENT5] input.
-   */
-  static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
-
-  /**
-   * The task descriptor describing this kind of task.
-   */
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'PropagateVariableTypesInLibraryTask',
-      createTask,
-      buildInputs,
-      <ResultDescriptor>[LIBRARY_ELEMENT6]);
-
-  PropagateVariableTypesInLibraryTask(
-      InternalAnalysisContext context, AnalysisTarget target)
-      : super(context, target);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  void internalPerform() {
-    LibraryElement library = getRequiredInput(LIBRARY_INPUT);
-    outputs[LIBRARY_ELEMENT6] = library;
-  }
-
-  /**
-   * Return a map from the names of the inputs of this kind of task to the task
-   * input descriptors describing those inputs for a task with the
-   * given [target].
-   */
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    Source source = target;
-    return <String, TaskInput>{
       'propagatedVariableTypesInUnits':
-          LIBRARY_SPECIFIC_UNITS.of(source).toListOf(RESOLVED_UNIT7),
-      LIBRARY_INPUT: LIBRARY_ELEMENT5.of(source),
+          LIBRARY_SPECIFIC_UNITS.of(source).toListOf(RESOLVED_UNIT8),
+      LIBRARY_INPUT: LIBRARY_ELEMENT6.of(source),
     };
   }
 
@@ -3892,7 +3946,7 @@
  */
 class PropagateVariableTypesInUnitTask extends SourceBasedAnalysisTask {
   /**
-   * The name of the input whose value is the [RESOLVED_UNIT6] for the
+   * The name of the input whose value is the [RESOLVED_UNIT7] for the
    * compilation unit.
    */
   static const String UNIT_INPUT = 'UNIT_INPUT';
@@ -3904,7 +3958,7 @@
       'PropagateVariableTypesInUnitTask',
       createTask,
       buildInputs,
-      <ResultDescriptor>[CREATED_RESOLVED_UNIT7, RESOLVED_UNIT7]);
+      <ResultDescriptor>[CREATED_RESOLVED_UNIT8, RESOLVED_UNIT8]);
 
   PropagateVariableTypesInUnitTask(
       InternalAnalysisContext context, LibrarySpecificUnit unit)
@@ -3924,8 +3978,8 @@
     // because the work has implicitly been done by virtue of the task model
     // preparing all of the inputs.
     //
-    outputs[RESOLVED_UNIT7] = unit;
-    outputs[CREATED_RESOLVED_UNIT7] = true;
+    outputs[RESOLVED_UNIT8] = unit;
+    outputs[CREATED_RESOLVED_UNIT8] = true;
   }
 
   /**
@@ -3938,7 +3992,7 @@
     return <String, TaskInput>{
       'variables':
           PROPAGABLE_VARIABLES_IN_UNIT.of(unit).toListOf(PROPAGATED_VARIABLE),
-      UNIT_INPUT: RESOLVED_UNIT6.of(unit)
+      UNIT_INPUT: RESOLVED_UNIT7.of(unit)
     };
   }
 
@@ -3963,7 +4017,7 @@
   static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
 
   /**
-   * The name of the [RESOLVED_UNIT6] input.
+   * The name of the [RESOLVED_UNIT7] input.
    */
   static const String UNIT_INPUT = 'UNIT_INPUT';
 
@@ -4049,7 +4103,7 @@
           .of(variable)
           .toListOf(PROPAGATED_VARIABLE),
       TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request),
-      UNIT_INPUT: RESOLVED_UNIT6.of(unit),
+      UNIT_INPUT: RESOLVED_UNIT7.of(unit),
     };
   }
 
@@ -4107,7 +4161,7 @@
 }
 
 /**
- * A task that ensures that [LIBRARY_ELEMENT5] is ready for the target library
+ * A task that ensures that [LIBRARY_ELEMENT6] is ready for the target library
  * source and its import/export closure.
  */
 class ReadyLibraryElement5Task extends SourceBasedAnalysisTask {
@@ -4115,52 +4169,9 @@
       'ReadyLibraryElement5Task',
       createTask,
       buildInputs,
-      <ResultDescriptor>[READY_LIBRARY_ELEMENT5]);
-
-  ReadyLibraryElement5Task(
-      InternalAnalysisContext context, AnalysisTarget target)
-      : super(context, target);
-
-  @override
-  TaskDescriptor get descriptor => DESCRIPTOR;
-
-  @override
-  bool get handlesDependencyCycles => true;
-
-  @override
-  void internalPerform() {
-    outputs[READY_LIBRARY_ELEMENT5] = true;
-  }
-
-  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
-    Source source = target;
-    return <String, TaskInput>{
-      'thisLibraryElementReady': LIBRARY_ELEMENT5.of(source),
-      'directlyImportedLibrariesReady':
-          IMPORTED_LIBRARIES.of(source).toListOf(READY_LIBRARY_ELEMENT5),
-      'directlyExportedLibrariesReady':
-          EXPORTED_LIBRARIES.of(source).toListOf(READY_LIBRARY_ELEMENT5),
-    };
-  }
-
-  static ReadyLibraryElement5Task createTask(
-      AnalysisContext context, AnalysisTarget target) {
-    return new ReadyLibraryElement5Task(context, target);
-  }
-}
-
-/**
- * A task that ensures that [LIBRARY_ELEMENT6] is ready for the target library
- * source and its import/export closure.
- */
-class ReadyLibraryElement6Task extends SourceBasedAnalysisTask {
-  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
-      'ReadyLibraryElement6Task',
-      createTask,
-      buildInputs,
       <ResultDescriptor>[READY_LIBRARY_ELEMENT6]);
 
-  ReadyLibraryElement6Task(
+  ReadyLibraryElement5Task(
       InternalAnalysisContext context, AnalysisTarget target)
       : super(context, target);
 
@@ -4186,6 +4197,49 @@
     };
   }
 
+  static ReadyLibraryElement5Task createTask(
+      AnalysisContext context, AnalysisTarget target) {
+    return new ReadyLibraryElement5Task(context, target);
+  }
+}
+
+/**
+ * A task that ensures that [LIBRARY_ELEMENT7] is ready for the target library
+ * source and its import/export closure.
+ */
+class ReadyLibraryElement6Task extends SourceBasedAnalysisTask {
+  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
+      'ReadyLibraryElement6Task',
+      createTask,
+      buildInputs,
+      <ResultDescriptor>[READY_LIBRARY_ELEMENT7]);
+
+  ReadyLibraryElement6Task(
+      InternalAnalysisContext context, AnalysisTarget target)
+      : super(context, target);
+
+  @override
+  TaskDescriptor get descriptor => DESCRIPTOR;
+
+  @override
+  bool get handlesDependencyCycles => true;
+
+  @override
+  void internalPerform() {
+    outputs[READY_LIBRARY_ELEMENT7] = true;
+  }
+
+  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
+    Source source = target;
+    return <String, TaskInput>{
+      'thisLibraryElementReady': LIBRARY_ELEMENT7.of(source),
+      'directlyImportedLibrariesReady':
+          IMPORTED_LIBRARIES.of(source).toListOf(READY_LIBRARY_ELEMENT7),
+      'directlyExportedLibrariesReady':
+          EXPORTED_LIBRARIES.of(source).toListOf(READY_LIBRARY_ELEMENT7),
+    };
+  }
+
   static ReadyLibraryElement6Task createTask(
       AnalysisContext context, AnalysisTarget target) {
     return new ReadyLibraryElement6Task(context, target);
@@ -4373,7 +4427,7 @@
           'Cannot build inputs for a ${target.runtimeType}');
     }
     return <String, TaskInput>{
-      'createdResolvedUnit': CREATED_RESOLVED_UNIT11
+      'createdResolvedUnit': CREATED_RESOLVED_UNIT12
           .of(new LibrarySpecificUnit(librarySource, target.source))
     };
   }
@@ -4468,7 +4522,7 @@
  */
 class ResolveInstanceFieldsInUnitTask extends SourceBasedAnalysisTask {
   /**
-   * The name of the [LIBRARY_ELEMENT5] input.
+   * The name of the [LIBRARY_ELEMENT6] input.
    */
   static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
 
@@ -4478,7 +4532,7 @@
   static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
 
   /**
-   * The name of the input whose value is the [RESOLVED_UNIT8] for the
+   * The name of the input whose value is the [RESOLVED_UNIT9] for the
    * compilation unit.
    */
   static const String UNIT_INPUT = 'UNIT_INPUT';
@@ -4490,7 +4544,7 @@
       'ResolveInstanceFieldsInUnitTask',
       createTask,
       buildInputs,
-      <ResultDescriptor>[CREATED_RESOLVED_UNIT9, RESOLVED_UNIT9]);
+      <ResultDescriptor>[CREATED_RESOLVED_UNIT10, RESOLVED_UNIT10]);
 
   /**
    * Initialize a newly created task to build a library element for the given
@@ -4527,8 +4581,8 @@
     //
     // Record outputs.
     //
-    outputs[RESOLVED_UNIT9] = unit;
-    outputs[CREATED_RESOLVED_UNIT9] = true;
+    outputs[RESOLVED_UNIT10] = unit;
+    outputs[CREATED_RESOLVED_UNIT10] = true;
   }
 
   /**
@@ -4539,8 +4593,8 @@
   static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
     LibrarySpecificUnit unit = target;
     return <String, TaskInput>{
-      UNIT_INPUT: RESOLVED_UNIT8.of(unit),
-      LIBRARY_INPUT: LIBRARY_ELEMENT5.of(unit.library),
+      UNIT_INPUT: RESOLVED_UNIT9.of(unit),
+      LIBRARY_INPUT: LIBRARY_ELEMENT6.of(unit.library),
       TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request),
       // In strong mode, add additional dependencies to enforce inference
       // ordering.
@@ -4548,14 +4602,14 @@
       // Require that static variable inference  be complete for all units in
       // the current library cycle.
       'orderLibraryCycleTasks': LIBRARY_CYCLE_UNITS.of(unit).toList(
-          (CompilationUnitElement unit) => CREATED_RESOLVED_UNIT8.of(
+          (CompilationUnitElement unit) => CREATED_RESOLVED_UNIT9.of(
               new LibrarySpecificUnit(
                   (unit as CompilationUnitElementImpl).librarySource,
                   unit.source))),
       // Require that full inference be complete for all dependencies of the
       // current library cycle.
       'orderLibraryCycles': LIBRARY_CYCLE_DEPENDENCIES.of(unit).toList(
-          (CompilationUnitElement unit) => CREATED_RESOLVED_UNIT10.of(
+          (CompilationUnitElement unit) => CREATED_RESOLVED_UNIT11.of(
               new LibrarySpecificUnit(
                   (unit as CompilationUnitElementImpl).librarySource,
                   unit.source)))
@@ -4573,17 +4627,17 @@
 }
 
 /**
- * A task that finishes resolution by requesting [RESOLVED_UNIT11] for every
- * unit in the libraries closure and produces [LIBRARY_ELEMENT8].
+ * A task that finishes resolution by requesting [RESOLVED_UNIT12] for every
+ * unit in the libraries closure and produces [LIBRARY_ELEMENT9].
  */
 class ResolveLibraryReferencesTask extends SourceBasedAnalysisTask {
   /**
-   * The name of the [LIBRARY_ELEMENT7] input.
+   * The name of the [LIBRARY_ELEMENT8] input.
    */
   static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
 
   /**
-   * The name of the list of [RESOLVED_UNIT11] input.
+   * The name of the list of [RESOLVED_UNIT12] input.
    */
   static const String UNITS_INPUT = 'UNITS_INPUT';
 
@@ -4594,7 +4648,7 @@
       'ResolveLibraryReferencesTask',
       createTask,
       buildInputs,
-      <ResultDescriptor>[LIBRARY_ELEMENT8, REFERENCED_NAMES]);
+      <ResultDescriptor>[LIBRARY_ELEMENT9, REFERENCED_NAMES]);
 
   ResolveLibraryReferencesTask(
       InternalAnalysisContext context, AnalysisTarget target)
@@ -4618,7 +4672,7 @@
     //
     // Record outputs.
     //
-    outputs[LIBRARY_ELEMENT8] = library;
+    outputs[LIBRARY_ELEMENT9] = library;
     outputs[REFERENCED_NAMES] = referencedNames;
   }
 
@@ -4630,8 +4684,8 @@
   static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
     Source source = target;
     return <String, TaskInput>{
-      LIBRARY_INPUT: LIBRARY_ELEMENT7.of(source),
-      UNITS_INPUT: LIBRARY_SPECIFIC_UNITS.of(source).toListOf(RESOLVED_UNIT11),
+      LIBRARY_INPUT: LIBRARY_ELEMENT8.of(source),
+      UNITS_INPUT: LIBRARY_SPECIFIC_UNITS.of(source).toListOf(RESOLVED_UNIT12),
     };
   }
 
@@ -4646,17 +4700,17 @@
 }
 
 /**
- * A task that finishes resolution by requesting [RESOLVED_UNIT12] for every
+ * A task that finishes resolution by requesting [RESOLVED_UNIT13] for every
  * unit in the libraries closure and produces [LIBRARY_ELEMENT].
  */
 class ResolveLibraryTask extends SourceBasedAnalysisTask {
   /**
-   * The name of the [LIBRARY_ELEMENT8] input.
+   * The name of the [LIBRARY_ELEMENT9] input.
    */
   static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
 
   /**
-   * The name of the list of [RESOLVED_UNIT12] input.
+   * The name of the list of [RESOLVED_UNIT13] input.
    */
   static const String UNITS_INPUT = 'UNITS_INPUT';
 
@@ -4695,7 +4749,7 @@
   static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
     Source source = target;
     return <String, TaskInput>{
-      LIBRARY_INPUT: LIBRARY_ELEMENT8.of(source),
+      LIBRARY_INPUT: LIBRARY_ELEMENT9.of(source),
       'thisLibraryClosureIsReady': READY_RESOLVED_UNIT.of(source),
     };
   }
@@ -4716,7 +4770,7 @@
  */
 class ResolveLibraryTypeNamesTask extends SourceBasedAnalysisTask {
   /**
-   * The name of the [LIBRARY_ELEMENT4] input.
+   * The name of the [LIBRARY_ELEMENT5] input.
    */
   static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
 
@@ -4732,7 +4786,7 @@
       'ResolveLibraryTypeNamesTask',
       createTask,
       buildInputs,
-      <ResultDescriptor>[LIBRARY_ELEMENT5]);
+      <ResultDescriptor>[LIBRARY_ELEMENT6]);
 
   ResolveLibraryTypeNamesTask(
       InternalAnalysisContext context, AnalysisTarget target)
@@ -4755,7 +4809,7 @@
     //
     // Record outputs.
     //
-    outputs[LIBRARY_ELEMENT5] = library;
+    outputs[LIBRARY_ELEMENT6] = library;
   }
 
   /**
@@ -4767,8 +4821,8 @@
     Source source = target;
     return <String, TaskInput>{
       'resolvedUnit':
-          LIBRARY_SPECIFIC_UNITS.of(source).toListOf(RESOLVED_UNIT4),
-      LIBRARY_INPUT: LIBRARY_ELEMENT4.of(source),
+          LIBRARY_SPECIFIC_UNITS.of(source).toListOf(RESOLVED_UNIT5),
+      LIBRARY_INPUT: LIBRARY_ELEMENT5.of(source),
       TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
     };
   }
@@ -4784,12 +4838,167 @@
 }
 
 /**
+ * An artificial task that does nothing except to force type parameter bounds
+ * type names resolution for the defining and part units of a library.
+ */
+class ResolveTopLevelLibraryTypeBoundsTask extends SourceBasedAnalysisTask {
+  /**
+   * The name of the [LIBRARY_ELEMENT4] input.
+   */
+  static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
+
+  /**
+   * The task descriptor describing this kind of task.
+   */
+  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
+      'ResolveTopLevelLibraryTypeBoundsTask',
+      createTask,
+      buildInputs,
+      <ResultDescriptor>[LIBRARY_ELEMENT5]);
+
+  ResolveTopLevelLibraryTypeBoundsTask(
+      InternalAnalysisContext context, AnalysisTarget target)
+      : super(context, target);
+
+  @override
+  TaskDescriptor get descriptor => DESCRIPTOR;
+
+  @override
+  bool get handlesDependencyCycles => true;
+
+  @override
+  void internalPerform() {
+    LibraryElement library = getRequiredInput(LIBRARY_INPUT);
+    outputs[LIBRARY_ELEMENT5] = library;
+  }
+
+  /**
+   * Return a map from the names of the inputs of this kind of task to the task
+   * input descriptors describing those inputs for a task with the
+   * given [target].
+   */
+  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
+    Source source = target;
+    return <String, TaskInput>{
+      LIBRARY_INPUT: LIBRARY_ELEMENT4.of(source),
+      'thisLibraryUnitsReady':
+          LIBRARY_SPECIFIC_UNITS.of(source).toListOf(RESOLVED_UNIT4),
+      'directlyImportedLibrariesReady':
+          IMPORTED_LIBRARIES.of(source).toListOf(LIBRARY_ELEMENT5),
+      'directlyExportedLibrariesReady':
+          EXPORTED_LIBRARIES.of(source).toListOf(LIBRARY_ELEMENT5),
+    };
+  }
+
+  /**
+   * Create a [ResolveTopLevelLibraryTypeBoundsTask] based on the given [target]
+   * in the given [context].
+   */
+  static ResolveTopLevelLibraryTypeBoundsTask createTask(
+      AnalysisContext context, AnalysisTarget target) {
+    return new ResolveTopLevelLibraryTypeBoundsTask(context, target);
+  }
+}
+
+/**
+ * A task that builds [RESOLVED_UNIT4] for a unit.
+ */
+class ResolveTopLevelUnitTypeBoundsTask extends SourceBasedAnalysisTask {
+  /**
+   * The name of the input whose value is the defining [LIBRARY_ELEMENT4].
+   */
+  static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
+
+  /**
+   * The name of the [RESOLVED_UNIT3] input.
+   */
+  static const String UNIT_INPUT = 'UNIT_INPUT';
+
+  /**
+   * The name of the [TYPE_PROVIDER] input.
+   */
+  static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
+
+  /**
+   * The task descriptor describing this kind of task.
+   */
+  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
+      'ResolveTopLevelUnitTypeBoundsTask',
+      createTask,
+      buildInputs, <ResultDescriptor>[
+    RESOLVE_TYPE_BOUNDS_ERRORS,
+    CREATED_RESOLVED_UNIT4,
+    RESOLVED_UNIT4
+  ]);
+
+  ResolveTopLevelUnitTypeBoundsTask(
+      InternalAnalysisContext context, AnalysisTarget target)
+      : super(context, target);
+
+  @override
+  TaskDescriptor get descriptor => DESCRIPTOR;
+
+  @override
+  void internalPerform() {
+    //
+    // Prepare inputs.
+    //
+    LibraryElement library = getRequiredInput(LIBRARY_INPUT);
+    CompilationUnit unit = getRequiredInput(UNIT_INPUT);
+    CompilationUnitElement unitElement = unit.element;
+    TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
+    //
+    // Resolve TypeName nodes.
+    //
+    RecordingErrorListener errorListener = new RecordingErrorListener();
+    new TypeParameterBoundsResolver(
+            typeProvider, library, unitElement.source, errorListener)
+        .resolveTypeBounds(unit);
+    //
+    // Record outputs.
+    //
+    outputs[RESOLVE_TYPE_BOUNDS_ERRORS] =
+        getTargetSourceErrors(errorListener, target);
+    outputs[RESOLVED_UNIT4] = unit;
+    outputs[CREATED_RESOLVED_UNIT4] = true;
+  }
+
+  /**
+   * Return a map from the names of the inputs of this kind of task to the task
+   * input descriptors describing those inputs for a task with the
+   * given [target].
+   */
+  static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
+    // TODO(brianwilkerson) This task updates the element model to have type
+    // information and updates the class hierarchy. It should produce a new
+    // version of the element model in order to record those changes.
+    LibrarySpecificUnit unit = target;
+    return <String, TaskInput>{
+      'importsExportNamespace':
+          IMPORTED_LIBRARIES.of(unit.library).toMapOf(LIBRARY_ELEMENT4),
+      LIBRARY_INPUT: LIBRARY_ELEMENT4.of(unit.library),
+      UNIT_INPUT: RESOLVED_UNIT3.of(unit),
+      TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
+    };
+  }
+
+  /**
+   * Create a [ResolveTopLevelUnitTypeBoundsTask] based on the given [target] in
+   * the given [context].
+   */
+  static ResolveTopLevelUnitTypeBoundsTask createTask(
+      AnalysisContext context, AnalysisTarget target) {
+    return new ResolveTopLevelUnitTypeBoundsTask(context, target);
+  }
+}
+
+/**
  * A task that resolves the bodies of top-level functions, constructors, and
  * methods within a single compilation unit.
  */
 class ResolveUnitTask extends SourceBasedAnalysisTask {
   /**
-   * The name of the input whose value is the defining [LIBRARY_ELEMENT7].
+   * The name of the input whose value is the defining [LIBRARY_ELEMENT8].
    */
   static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
 
@@ -4799,7 +5008,7 @@
   static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
 
   /**
-   * The name of the [RESOLVED_UNIT10] input.
+   * The name of the [RESOLVED_UNIT11] input.
    */
   static const String UNIT_INPUT = 'UNIT_INPUT';
 
@@ -4807,8 +5016,8 @@
       'ResolveUnitTask', createTask, buildInputs, <ResultDescriptor>[
     CONSTANT_EXPRESSIONS_DEPENDENCIES,
     RESOLVE_UNIT_ERRORS,
-    CREATED_RESOLVED_UNIT11,
-    RESOLVED_UNIT11
+    CREATED_RESOLVED_UNIT12,
+    RESOLVED_UNIT12
   ]);
 
   ResolveUnitTask(
@@ -4854,8 +5063,8 @@
     //
     outputs[CONSTANT_EXPRESSIONS_DEPENDENCIES] = constExprDependencies;
     outputs[RESOLVE_UNIT_ERRORS] = getTargetSourceErrors(errorListener, target);
-    outputs[RESOLVED_UNIT11] = unit;
-    outputs[CREATED_RESOLVED_UNIT11] = true;
+    outputs[RESOLVED_UNIT12] = unit;
+    outputs[CREATED_RESOLVED_UNIT12] = true;
   }
 
   /**
@@ -4866,16 +5075,16 @@
   static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
     LibrarySpecificUnit unit = target;
     return <String, TaskInput>{
-      LIBRARY_INPUT: LIBRARY_ELEMENT7.of(unit.library),
+      LIBRARY_INPUT: LIBRARY_ELEMENT8.of(unit.library),
       TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request),
-      UNIT_INPUT: RESOLVED_UNIT10.of(unit),
+      UNIT_INPUT: RESOLVED_UNIT11.of(unit),
       // In strong mode, add additional dependencies to enforce inference
       // ordering.
 
       // Require that inference be complete for all units in the
       // current library cycle.
       'orderLibraryCycleTasks': LIBRARY_CYCLE_UNITS.of(unit).toList(
-          (CompilationUnitElement unit) => CREATED_RESOLVED_UNIT10.of(
+          (CompilationUnitElement unit) => CREATED_RESOLVED_UNIT11.of(
               new LibrarySpecificUnit(
                   (unit as CompilationUnitElementImpl).librarySource,
                   unit.source)))
@@ -4893,16 +5102,16 @@
 }
 
 /**
- * A task that builds [RESOLVED_UNIT4] for a unit.
+ * A task that builds [RESOLVED_UNIT5] for a unit.
  */
 class ResolveUnitTypeNamesTask extends SourceBasedAnalysisTask {
   /**
-   * The name of the input whose value is the defining [LIBRARY_ELEMENT4].
+   * The name of the input whose value is the defining [LIBRARY_ELEMENT5].
    */
   static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
 
   /**
-   * The name of the [RESOLVED_UNIT3] input.
+   * The name of the [RESOLVED_UNIT4] input.
    */
   static const String UNIT_INPUT = 'UNIT_INPUT';
 
@@ -4917,8 +5126,8 @@
   static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
       'ResolveUnitTypeNamesTask', createTask, buildInputs, <ResultDescriptor>[
     RESOLVE_TYPE_NAMES_ERRORS,
-    CREATED_RESOLVED_UNIT4,
-    RESOLVED_UNIT4
+    CREATED_RESOLVED_UNIT5,
+    RESOLVED_UNIT5
   ]);
 
   ResolveUnitTypeNamesTask(
@@ -4949,8 +5158,8 @@
     //
     outputs[RESOLVE_TYPE_NAMES_ERRORS] =
         getTargetSourceErrors(errorListener, target);
-    outputs[RESOLVED_UNIT4] = unit;
-    outputs[CREATED_RESOLVED_UNIT4] = true;
+    outputs[RESOLVED_UNIT5] = unit;
+    outputs[CREATED_RESOLVED_UNIT5] = true;
   }
 
   /**
@@ -4964,10 +5173,8 @@
     // version of the element model in order to record those changes.
     LibrarySpecificUnit unit = target;
     return <String, TaskInput>{
-      'importsExportNamespace':
-          IMPORTED_LIBRARIES.of(unit.library).toMapOf(LIBRARY_ELEMENT4),
-      LIBRARY_INPUT: LIBRARY_ELEMENT4.of(unit.library),
-      UNIT_INPUT: RESOLVED_UNIT3.of(unit),
+      LIBRARY_INPUT: LIBRARY_ELEMENT5.of(unit.library),
+      UNIT_INPUT: RESOLVED_UNIT4.of(unit),
       TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
     };
   }
@@ -4983,7 +5190,7 @@
 }
 
 /**
- * A task that builds [RESOLVED_UNIT5] for a unit.
+ * A task that builds [RESOLVED_UNIT6] for a unit.
  */
 class ResolveVariableReferencesTask extends SourceBasedAnalysisTask {
   /**
@@ -4992,7 +5199,7 @@
   static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
 
   /**
-   * The name of the [RESOLVED_UNIT4] input.
+   * The name of the [RESOLVED_UNIT5] input.
    */
   static const String UNIT_INPUT = 'UNIT_INPUT';
 
@@ -5008,8 +5215,8 @@
       'ResolveVariableReferencesTask',
       createTask,
       buildInputs, <ResultDescriptor>[
-    CREATED_RESOLVED_UNIT5,
-    RESOLVED_UNIT5,
+    CREATED_RESOLVED_UNIT6,
+    RESOLVED_UNIT6,
     VARIABLE_REFERENCE_ERRORS
   ]);
 
@@ -5041,8 +5248,8 @@
     //
     // Record outputs.
     //
-    outputs[RESOLVED_UNIT5] = unit;
-    outputs[CREATED_RESOLVED_UNIT5] = true;
+    outputs[RESOLVED_UNIT6] = unit;
+    outputs[CREATED_RESOLVED_UNIT6] = true;
     outputs[VARIABLE_REFERENCE_ERRORS] =
         getTargetSourceErrors(errorListener, target);
   }
@@ -5056,7 +5263,7 @@
     LibrarySpecificUnit unit = target;
     return <String, TaskInput>{
       LIBRARY_INPUT: LIBRARY_ELEMENT1.of(unit.library),
-      UNIT_INPUT: RESOLVED_UNIT4.of(unit),
+      UNIT_INPUT: RESOLVED_UNIT5.of(unit),
       TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
     };
   }
@@ -5221,7 +5428,7 @@
  */
 class StrongModeVerifyUnitTask extends SourceBasedAnalysisTask {
   /**
-   * The name of the [RESOLVED_UNIT12] input.
+   * The name of the [RESOLVED_UNIT13] input.
    */
   static const String UNIT_INPUT = 'UNIT_INPUT';
 
@@ -5277,7 +5484,7 @@
   static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
     LibrarySpecificUnit unit = target;
     return <String, TaskInput>{
-      UNIT_INPUT: RESOLVED_UNIT12.of(unit),
+      UNIT_INPUT: RESOLVED_UNIT13.of(unit),
       TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request),
     };
   }
diff --git a/pkg/analyzer/lib/src/task/dart_work_manager.dart b/pkg/analyzer/lib/src/task/dart_work_manager.dart
index 0eb6613..8c8176a 100644
--- a/pkg/analyzer/lib/src/task/dart_work_manager.dart
+++ b/pkg/analyzer/lib/src/task/dart_work_manager.dart
@@ -41,6 +41,7 @@
     LINTS,
     LIBRARY_UNIT_ERRORS,
     RESOLVE_TYPE_NAMES_ERRORS,
+    RESOLVE_TYPE_BOUNDS_ERRORS,
     RESOLVE_UNIT_ERRORS,
     STRONG_MODE_ERRORS,
     VARIABLE_REFERENCE_ERRORS,
diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart
index 08d414b..3e6f6f5 100644
--- a/pkg/analyzer/lib/src/task/strong/checker.dart
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart
@@ -104,13 +104,14 @@
   final bool _hints;
 
   bool _failure = false;
-  CodeChecker(this.typeProvider, StrongTypeSystemImpl rules,
+  CodeChecker(TypeProvider typeProvider, StrongTypeSystemImpl rules,
       AnalysisErrorListener reporter,
       {bool hints: false})
-      : rules = rules,
+      : typeProvider = typeProvider,
+        rules = rules,
         reporter = reporter,
         _hints = hints,
-        _overrideChecker = new _OverrideChecker(rules, reporter);
+        _overrideChecker = new _OverrideChecker(typeProvider, rules, reporter);
 
   bool get failure => _failure || _overrideChecker._failure;
 
@@ -324,9 +325,7 @@
 
   @override
   void visitForEachStatement(ForEachStatement node) {
-    var loopVariable = node.identifier != null
-        ? node.identifier
-        : node.loopVariable?.identifier;
+    var loopVariable = node.identifier ?? node.loopVariable?.identifier;
 
     // Safely handle malformed statements.
     if (loopVariable != null) {
@@ -956,9 +955,10 @@
 class _OverrideChecker {
   bool _failure = false;
   final StrongTypeSystemImpl rules;
+  final TypeProvider _typeProvider;
   final AnalysisErrorListener _reporter;
 
-  _OverrideChecker(this.rules, this._reporter);
+  _OverrideChecker(this._typeProvider, this.rules, this._reporter);
 
   void check(ClassDeclaration node) {
     if (node.element.type.isObject) return;
@@ -1132,8 +1132,7 @@
 
     // Check overrides from its mixins
     for (int i = 0; i < type.mixins.length; i++) {
-      var loc =
-          errorLocation != null ? errorLocation : node.withClause.mixinTypes[i];
+      var loc = errorLocation ?? node.withClause.mixinTypes[i];
       for (var interfaceType in interfaces) {
         // We copy [seen] so we can report separately if more than one mixin or
         // the base class have an invalid override.
@@ -1145,8 +1144,10 @@
     // Check overrides from its superclasses
     if (includeParents) {
       var parent = type.superclass;
-      if (parent.isObject) return;
-      var loc = errorLocation != null ? errorLocation : node.extendsClause;
+      if (parent.isObject) {
+        return;
+      }
+      var loc = errorLocation ?? node.extendsClause;
       // No need to copy [seen] here because we made copies above when reporting
       // errors on mixins.
       _checkInterfacesOverrides(parent, interfaces, seen,
@@ -1225,7 +1226,20 @@
             errorLocation, element, type, subType, baseType));
       }
     }
-    if (!rules.isSubtypeOf(subType, baseType)) {
+    FunctionType concreteSubType = subType;
+    FunctionType concreteBaseType = baseType;
+    if (element is MethodElement) {
+      if (concreteSubType.typeFormals.isNotEmpty) {
+        if (concreteBaseType.typeFormals.isEmpty) {
+          concreteSubType = rules.instantiateToBounds(concreteSubType);
+        }
+      }
+      concreteSubType =
+          rules.typeToConcreteType(_typeProvider, concreteSubType);
+      concreteBaseType =
+          rules.typeToConcreteType(_typeProvider, concreteBaseType);
+    }
+    if (!rules.isSubtypeOf(concreteSubType, concreteBaseType)) {
       // See whether non-subtype cases fit one of our common patterns:
       //
       // Common pattern 1: Inferable return type (on getters and methods)
diff --git a/pkg/analyzer/lib/src/task/strong/info.dart b/pkg/analyzer/lib/src/task/strong/info.dart
index 41703e1..39885cd 100644
--- a/pkg/analyzer/lib/src/task/strong/info.dart
+++ b/pkg/analyzer/lib/src/task/strong/info.dart
@@ -212,10 +212,7 @@
   toErrorCode() => new HintCode(name, message);
 
   /// Whether this [node] is the target of a dynamic operation.
-  static bool get(AstNode node) {
-    var value = node.getProperty(_propertyName);
-    return value != null ? value : false;
-  }
+  static bool get(AstNode node) => node.getProperty(_propertyName) ?? false;
 
   /// Sets whether this node is the target of a dynamic operation.
   static bool set(AstNode node, bool value) {
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 6c8b8cc..126b5a6 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
 name: analyzer
-version: 0.27.3
+version: 0.27.4-alpha.1
 author: Dart Team <misc@dartlang.org>
 description: Static analyzer for Dart.
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer
diff --git a/pkg/analyzer/test/generated/compile_time_error_code_test.dart b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
index 34dd9b9..5bd95e5 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code_test.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
@@ -2209,7 +2209,7 @@
     Source source = addSource(r'''
 class A {
   int x;
-  factory A(this.x) {}
+  factory A(this.x) => null;
 }''');
     computeLibrarySourceErrors(source);
     assertErrors(
@@ -3201,7 +3201,7 @@
     Source source = addSource(r'''
 int B;
 class A {
-  factory B() {}
+  factory B() => null;
 }''');
     computeLibrarySourceErrors(source);
     assertErrors(
@@ -3212,7 +3212,7 @@
   void test_invalidFactoryNameNotAClass_notEnclosingClassName() {
     Source source = addSource(r'''
 class A {
-  factory B() {}
+  factory B() => null;
 }''');
     computeLibrarySourceErrors(source);
     assertErrors(
@@ -4736,7 +4736,7 @@
   void test_nonGenerativeConstructor_explicit() {
     Source source = addSource(r'''
 class A {
-  factory A.named() {}
+  factory A.named() => null;
 }
 class B extends A {
   B() : super.named();
@@ -4749,7 +4749,7 @@
   void test_nonGenerativeConstructor_implicit() {
     Source source = addSource(r'''
 class A {
-  factory A() {}
+  factory A() => null;
 }
 class B extends A {
   B();
@@ -4762,7 +4762,7 @@
   void test_nonGenerativeConstructor_implicit2() {
     Source source = addSource(r'''
 class A {
-  factory A() {}
+  factory A() => null;
 }
 class B extends A {
 }''');
@@ -5760,6 +5760,7 @@
 class B extends A {
   factory B() {
     super.m();
+    return null;
   }
 }''');
     computeLibrarySourceErrors(source);
diff --git a/pkg/analyzer/test/generated/hint_code_test.dart b/pkg/analyzer/test/generated/hint_code_test.dart
index 79cb436..7a05a39 100644
--- a/pkg/analyzer/test/generated/hint_code_test.dart
+++ b/pkg/analyzer/test/generated/hint_code_test.dart
@@ -658,6 +658,28 @@
     verify([source]);
   }
 
+  void test_deprecatedAnnotationUse_positional() {
+    Source source = addSource(r'''
+class A {
+  m([@deprecated int x]) {}
+  n() {m(1);}
+}''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]);
+    verify([source]);
+  }
+
+  void test_deprecatedAnnotationUse_named() {
+    Source source = addSource(r'''
+class A {
+  m({@deprecated int x}) {}
+  n() {m(x: 1);}
+}''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]);
+    verify([source]);
+  }
+
   void test_deprecatedAnnotationUse_export() {
     Source source = addSource("export 'deprecated_library.dart';");
     addNamedSource(
@@ -813,6 +835,21 @@
     verify([source]);
   }
 
+  void test_deprecatedAnnotationUse_call() {
+    Source source = addSource(r'''
+class A {
+  @deprecated
+  call() {}
+  m() {
+    A a = new A();
+    a();
+  }
+}''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]);
+    verify([source]);
+  }
+
   void test_divisionOptimization_double() {
     Source source = addSource(r'''
 f(double x, double y) {
@@ -1323,6 +1360,17 @@
     verify([source]);
   }
 
+  void test_missingReturn_factory() {
+    Source source = addSource(r'''
+class A {
+  factory A() {}
+}
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [HintCode.MISSING_RETURN]);
+    verify([source]);
+  }
+
   void test_missingReturn_method() {
     Source source = addSource(r'''
 class A {
diff --git a/pkg/analyzer/test/generated/incremental_resolver_test.dart b/pkg/analyzer/test/generated/incremental_resolver_test.dart
index 80c41e1..518f8c8a 100644
--- a/pkg/analyzer/test/generated/incremental_resolver_test.dart
+++ b/pkg/analyzer/test/generated/incremental_resolver_test.dart
@@ -4892,6 +4892,7 @@
     _assertCacheSourceResult(LIBRARY_ELEMENT6);
     _assertCacheSourceResult(LIBRARY_ELEMENT7);
     _assertCacheSourceResult(LIBRARY_ELEMENT8);
+    _assertCacheSourceResult(LIBRARY_ELEMENT9);
     if (expectCachePostConstantsValid) {
       _assertCacheSourceResult(LIBRARY_ELEMENT);
     }
@@ -4906,8 +4907,9 @@
     _assertCacheUnitResult(RESOLVED_UNIT9);
     _assertCacheUnitResult(RESOLVED_UNIT10);
     _assertCacheUnitResult(RESOLVED_UNIT11);
+    _assertCacheUnitResult(RESOLVED_UNIT12);
     if (expectCachePostConstantsValid) {
-      _assertCacheUnitResult(RESOLVED_UNIT12);
+      _assertCacheUnitResult(RESOLVED_UNIT13);
       _assertCacheUnitResult(RESOLVED_UNIT);
     }
   }
diff --git a/pkg/analyzer/test/generated/non_error_resolver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_test.dart
index 28f721e..e458070 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_test.dart
@@ -2827,7 +2827,7 @@
   void test_invalidFactoryNameNotAClass() {
     Source source = addSource(r'''
 class A {
-  factory A() {}
+  factory A() => null;
 }''');
     computeLibrarySourceErrors(source);
     assertNoErrors(source);
@@ -3491,7 +3491,7 @@
   void test_mixinDeclaresConstructor_factory() {
     Source source = addSource(r'''
 class A {
-  factory A() {}
+  factory A() => null;
 }
 class B extends Object with A {}''');
     computeLibrarySourceErrors(source);
@@ -4275,7 +4275,7 @@
     Source source = addSource(r'''
 class A {
   A.named() {}
-  factory A() {}
+  factory A() => null;
 }
 class B extends A {
   B() : super.named();
@@ -4693,7 +4693,7 @@
   factory B() = C;
 }
 class C implements B {
-  factory C() {}
+  factory C() => null;
 }''');
     computeLibrarySourceErrors(source);
     assertNoErrors(source);
diff --git a/pkg/analyzer/test/generated/static_type_warning_code_test.dart b/pkg/analyzer/test/generated/static_type_warning_code_test.dart
index 4568fe9..9b3f082 100644
--- a/pkg/analyzer/test/generated/static_type_warning_code_test.dart
+++ b/pkg/analyzer/test/generated/static_type_warning_code_test.dart
@@ -1288,6 +1288,64 @@
         [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
   }
 
+  void test_typeArgumentNotMatchingBounds_methodInvocation_localFunction() {
+    resetWithOptions(new AnalysisOptionsImpl()..strongMode = true);
+    assertErrorsInCode(
+        r'''
+class Point<T extends num> {
+  Point(T x, T y);
+}
+
+main() {
+  Point/*<T>*/ f/*<T extends num>*/(num/*=T*/ x, num/*=T*/ y) {
+    return new Point/*<T>*/(x, y);
+  }
+  print(f/*<String>*/('hello', 'world'));
+}
+''',
+        [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
+  }
+
+  void test_typeArgumentNotMatchingBounds_methodInvocation_method() {
+    resetWithOptions(new AnalysisOptionsImpl()..strongMode = true);
+    assertErrorsInCode(
+        r'''
+class Point<T extends num> {
+  Point(T x, T y);
+}
+
+class PointFactory {
+  Point/*<T>*/ point/*<T extends num>*/(num/*=T*/ x, num/*=T*/ y) {
+    return new Point/*<T>*/(x, y);
+  }
+}
+
+f(PointFactory factory) {
+  print(factory.point/*<String>*/('hello', 'world'));
+}
+''',
+        [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
+  }
+
+  void test_typeArgumentNotMatchingBounds_methodInvocation_topLevelFunction() {
+    resetWithOptions(new AnalysisOptionsImpl()..strongMode = true);
+    assertErrorsInCode(
+        r'''
+class Point<T extends num> {
+  Point(T x, T y);
+}
+
+Point/*<T>*/ f/*<T extends num>*/(num/*=T*/ x, num/*=T*/ y) {
+  return new Point/*<T>*/(x, y);
+}
+
+main() {
+  print(f/*<String>*/('hello', 'world'));
+}
+''',
+        [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]);
+  }
+
   void test_typeArgumentNotMatchingBounds_methodReturnType() {
     assertErrorsInCode(
         r'''
@@ -2361,4 +2419,51 @@
     }
     verify([source]);
   }
+
+  void test_legalAsyncGeneratorReturnType_function_supertypeOfStream() {
+    assertErrorsInCode(
+        '''
+import 'dart:async';
+f() async* { yield 42; }
+dynamic f2() async* { yield 42; }
+Object f3() async* { yield 42; }
+Stream f4() async* { yield 42; }
+Stream<dynamic> f5() async* { yield 42; }
+Stream<Object> f6() async* { yield 42; }
+Stream<num> f7() async* { yield 42; }
+Stream<int> f8() async* { yield 42; }
+''',
+        []);
+  }
+
+  void test_legalAsyncReturnType_function_supertypeOfFuture() {
+    assertErrorsInCode(
+        '''
+import 'dart:async';
+f() async { return 42; }
+dynamic f2() async { return 42; }
+Object f3() async { return 42; }
+Future f4() async { return 42; }
+Future<dynamic> f5() async { return 42; }
+Future<Object> f6() async { return 42; }
+Future<num> f7() async { return 42; }
+Future<int> f8() async { return 42; }
+''',
+        []);
+  }
+
+  void test_legalSyncGeneratorReturnType_function_supertypeOfIterable() {
+    assertErrorsInCode(
+        '''
+f() sync* { yield 42; }
+dynamic f2() sync* { yield 42; }
+Object f3() sync* { yield 42; }
+Iterable f4() sync* { yield 42; }
+Iterable<dynamic> f5() sync* { yield 42; }
+Iterable<Object> f6() sync* { yield 42; }
+Iterable<num> f7() sync* { yield 42; }
+Iterable<int> f8() sync* { yield 42; }
+''',
+        []);
+  }
 }
diff --git a/pkg/analyzer/test/generated/static_warning_code_test.dart b/pkg/analyzer/test/generated/static_warning_code_test.dart
index 1445233..f8fc40d 100644
--- a/pkg/analyzer/test/generated/static_warning_code_test.dart
+++ b/pkg/analyzer/test/generated/static_warning_code_test.dart
@@ -19,6 +19,21 @@
 
 @reflectiveTest
 class StaticWarningCodeTest extends ResolverTestCase {
+  void fail_argumentTypeNotAssignable_tearOff_required() {
+    Source source = addSource(r'''
+class C {
+  Object/*=T*/ f/*<T>*/(Object/*=T*/ x) => x;
+}
+g(C c) {
+  var h = c.f/*<int>*/;
+  print(h('s'));
+}
+''');
+    computeLibrarySourceErrors(source);
+    assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
+    verify([source]);
+  }
+
   void fail_undefinedGetter() {
     Source source = addSource(r'''
 ''');
diff --git a/pkg/analyzer/test/generated/strong_mode_test.dart b/pkg/analyzer/test/generated/strong_mode_test.dart
index 7bc5ed1..e169167 100644
--- a/pkg/analyzer/test/generated/strong_mode_test.dart
+++ b/pkg/analyzer/test/generated/strong_mode_test.dart
@@ -1958,10 +1958,10 @@
     resolveTestUnit(code);
     expectIdentifierType('ai', "A<dynamic>");
     expectIdentifierType('bi', "B<num>");
-    expectIdentifierType('ci', "C<int, B<int>, B<num>>");
+    expectIdentifierType('ci', "C<int, B<int>, B<dynamic>>");
     expectIdentifierType('aa', "A<dynamic>");
     expectIdentifierType('bb', "B<num>");
-    expectIdentifierType('cc', "C<int, B<int>, B<num>>");
+    expectIdentifierType('cc', "C<int, B<int>, B<dynamic>>");
   }
 
   void test_setterWithDynamicTypeIsError() {
diff --git a/pkg/analyzer/test/reflective_tests.dart b/pkg/analyzer/test/reflective_tests.dart
index 310e7d0..4788776 100644
--- a/pkg/analyzer/test/reflective_tests.dart
+++ b/pkg/analyzer/test/reflective_tests.dart
@@ -12,6 +12,13 @@
 
 /**
  * A marker annotation used to annotate overridden test methods (so we cannot
+ * rename them to `fail_`) which are expected to fail at `assert` in the
+ * checked mode.
+ */
+const _AssertFailingTest assertFailingTest = const _AssertFailingTest();
+
+/**
+ * A marker annotation used to annotate overridden test methods (so we cannot
  * rename them to `fail_`) which are expected to fail.
  */
 const _FailingTest failingTest = const _FailingTest();
@@ -23,6 +30,18 @@
 const ReflectiveTest reflectiveTest = const ReflectiveTest();
 
 /**
+ * Is `true` the application is running in the checked mode.
+ */
+final bool _isCheckedMode = () {
+  try {
+    assert(false);
+    return false;
+  } catch (_) {
+    return true;
+  }
+}();
+
+/**
  * Runs test methods existing in the given [type].
  *
  * Methods with names starting with `test` are run using [test] function.
@@ -58,7 +77,8 @@
       // test_
       if (memberName.startsWith('test_')) {
         test(memberName, () {
-          if (_hasFailingTestAnnotation(memberMirror)) {
+          if (_hasFailingTestAnnotation(memberMirror) ||
+              _isCheckedMode && _hasAssertFailingTestAnnotation(memberMirror)) {
             return _runFailingTest(classMirror, symbol);
           } else {
             return _runTest(classMirror, symbol);
@@ -88,10 +108,15 @@
   });
 }
 
-bool _hasFailingTestAnnotation(MethodMirror method) {
-  return method.metadata.any((InstanceMirror annotation) =>
-      annotation.type.reflectedType == _FailingTest);
-}
+bool _hasAnnotationInstance(DeclarationMirror declaration, instance) =>
+    declaration.metadata.any((InstanceMirror annotation) =>
+        identical(annotation.reflectee, instance));
+
+bool _hasAssertFailingTestAnnotation(MethodMirror method) =>
+    _hasAnnotationInstance(method, assertFailingTest);
+
+bool _hasFailingTestAnnotation(MethodMirror method) =>
+    _hasAnnotationInstance(method, failingTest);
 
 Future _invokeSymbolIfExists(InstanceMirror instanceMirror, Symbol symbol) {
   var invocationResult = null;
@@ -139,6 +164,15 @@
 
 /**
  * A marker annotation used to annotate overridden test methods (so we cannot
+ * rename them to `fail_`) which are expected to fail at `assert` in the
+ * checked mode.
+ */
+class _AssertFailingTest {
+  const _AssertFailingTest();
+}
+
+/**
+ * A marker annotation used to annotate overridden test methods (so we cannot
  * rename them to `fail_`) which are expected to fail.
  */
 class _FailingTest {
diff --git a/pkg/analyzer/test/source/config_test.dart b/pkg/analyzer/test/source/config_test.dart
new file mode 100644
index 0000000..ccbc056
--- /dev/null
+++ b/pkg/analyzer/test/source/config_test.dart
@@ -0,0 +1,24 @@
+// 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/source/config.dart';
+import 'package:unittest/unittest.dart';
+import 'package:yaml/yaml.dart';
+
+main() {
+  group('Analysis Config', () {
+    test('parseConfigSource', () {
+      String source = r'''
+analyzer:
+  configuration: google/strict
+''';
+      YamlMap options = loadYamlNode(source);
+      AnalysisConfigurationDescriptor descriptor =
+          new AnalysisConfigurationDescriptor.fromAnalyzerOptions(
+              options['analyzer']);
+      expect(descriptor.package, 'google');
+      expect(descriptor.pragma, 'strict');
+    });
+  });
+}
diff --git a/pkg/analyzer/test/source/test_all.dart b/pkg/analyzer/test/source/test_all.dart
index 725d23e..bca740b 100644
--- a/pkg/analyzer/test/source/test_all.dart
+++ b/pkg/analyzer/test/source/test_all.dart
@@ -8,6 +8,7 @@
 
 import '../utils.dart';
 import 'analysis_options_provider_test.dart' as analysis_options_provider_test;
+import 'config_test.dart' as config_test;
 import 'embedder_test.dart' as embedder_test;
 import 'error_processor_test.dart' as error_processor_test;
 import 'package_map_provider_test.dart' as package_map_provider_test;
@@ -20,6 +21,7 @@
   initializeTestEnvironment();
   group('source', () {
     analysis_options_provider_test.main();
+    config_test.main();
     embedder_test.main();
     error_processor_test.main();
     package_map_provider_test.main();
diff --git a/pkg/analyzer/test/src/context/context_test.dart b/pkg/analyzer/test/src/context/context_test.dart
index e19a173..ea41470 100644
--- a/pkg/analyzer/test/src/context/context_test.dart
+++ b/pkg/analyzer/test/src/context/context_test.dart
@@ -2131,6 +2131,7 @@
     entry.setState(RESOLVED_UNIT10, CacheState.FLUSHED);
     entry.setState(RESOLVED_UNIT11, CacheState.FLUSHED);
     entry.setState(RESOLVED_UNIT12, CacheState.FLUSHED);
+    entry.setState(RESOLVED_UNIT13, CacheState.FLUSHED);
     entry.setState(RESOLVED_UNIT, CacheState.FLUSHED);
 
     context.resolveCompilationUnit2(source, source);
diff --git a/pkg/analyzer/test/src/dart/element/element_test.dart b/pkg/analyzer/test/src/dart/element/element_test.dart
index ebee2d6..4b5ee12 100644
--- a/pkg/analyzer/test/src/dart/element/element_test.dart
+++ b/pkg/analyzer/test/src/dart/element/element_test.dart
@@ -2083,6 +2083,132 @@
     expect(f.type.toString(), '() \u2192 C<...>');
   }
 
+  void test_typeParameters_genericLocalFunction_genericMethod_genericClass() {
+    //
+    // class C<S> {
+    //   Object m<T>() {
+    //     U f<U>() => null;
+    //   }
+    // }
+    //
+    ClassElementImpl classElement =
+        ElementFactory.classElement('C', null, ['S']);
+    MethodElementImpl method = new MethodElementImpl('m', 0);
+    method.enclosingElement = classElement;
+    method.returnType = ElementFactory.objectType;
+    method.typeParameters = ElementFactory.typeParameters(['T']);
+    method.type = new FunctionTypeImpl(method);
+    FunctionElementImpl function = ElementFactory.functionElement('f');
+    function.enclosingElement = method;
+    function.typeParameters = ElementFactory.typeParameters(['U']);
+    function.returnType = function.typeParameters[0].type;
+    function.type = new FunctionTypeImpl(function);
+
+    List<TypeParameterElement> inheritedParameters = <TypeParameterElement>[];
+    inheritedParameters.addAll(method.typeParameters);
+    inheritedParameters.addAll(classElement.typeParameters);
+    expect(function.type.typeArguments,
+        unorderedEquals(_toTypes(inheritedParameters)));
+    expect(function.type.typeFormals, unorderedEquals(function.typeParameters));
+    expect(function.type.typeParameters, unorderedEquals(inheritedParameters));
+  }
+
+  void test_typeParameters_genericMethod_genericClass() {
+    //
+    // class C<S> {
+    //   Object m<T>() => null;
+    // }
+    //
+    ClassElementImpl classElement =
+        ElementFactory.classElement('C', null, ['S']);
+    MethodElementImpl method = new MethodElementImpl('m', 0);
+    method.enclosingElement = classElement;
+    method.returnType = ElementFactory.objectType;
+    method.typeParameters = ElementFactory.typeParameters(['T']);
+    method.type = new FunctionTypeImpl(method);
+
+    expect(method.type.typeArguments,
+        unorderedEquals(_toTypes(classElement.typeParameters)));
+    expect(method.type.typeFormals, unorderedEquals(method.typeParameters));
+    expect(method.type.typeParameters,
+        unorderedEquals(classElement.typeParameters));
+  }
+
+  void test_typeParameters_genericMethod_simpleClass() {
+    //
+    // class C<S> {
+    //   Object m<T>() => null;
+    // }
+    //
+    ClassElementImpl classElement = ElementFactory.classElement2('C');
+    MethodElementImpl method = new MethodElementImpl('m', 0);
+    method.enclosingElement = classElement;
+    method.returnType = ElementFactory.objectType;
+    method.typeParameters = ElementFactory.typeParameters(['T']);
+    method.type = new FunctionTypeImpl(method);
+
+    expect(method.type.typeArguments,
+        unorderedEquals(_toTypes(classElement.typeParameters)));
+    expect(method.type.typeFormals, unorderedEquals(method.typeParameters));
+    expect(method.type.typeParameters,
+        unorderedEquals(classElement.typeParameters));
+  }
+
+  void test_typeParameters_genericTopLevelFunction() {
+    //
+    // Object f<T>() => null;
+    //
+    FunctionElementImpl function = ElementFactory.functionElement('f');
+    function.returnType = ElementFactory.objectType;
+    function.typeParameters = ElementFactory.typeParameters(['T']);
+    function.type = new FunctionTypeImpl(function);
+
+    expect(function.type.typeArguments, isEmpty);
+    expect(function.type.typeFormals, unorderedEquals(function.typeParameters));
+    expect(function.type.typeParameters, isEmpty);
+  }
+
+  void test_typeParameters_simpleMethod_genericClass() {
+    //
+    // class C<S> {
+    //   Object m<T>() => null;
+    // }
+    //
+    ClassElementImpl classElement =
+        ElementFactory.classElement('C', null, ['S']);
+    MethodElementImpl method = new MethodElementImpl('m', 0);
+    method.enclosingElement = classElement;
+    method.typeParameters = ElementFactory.typeParameters(['T']);
+    method.returnType = ElementFactory.objectType;
+    method.type = new FunctionTypeImpl(method);
+
+    expect(method.type.typeArguments,
+        unorderedEquals(_toTypes(classElement.typeParameters)));
+    expect(method.type.typeFormals, unorderedEquals(method.typeParameters));
+    expect(method.type.typeParameters,
+        unorderedEquals(classElement.typeParameters));
+  }
+
+  void test_typeParameters_simpleMethod_simpleClass() {
+    //
+    // class C<S> {
+    //   Object m<T>() => null;
+    // }
+    //
+    ClassElementImpl classElement = ElementFactory.classElement2('C');
+    MethodElementImpl method = new MethodElementImpl('m', 0);
+    method.enclosingElement = classElement;
+    method.typeParameters = ElementFactory.typeParameters(['T']);
+    method.returnType = ElementFactory.objectType;
+    method.type = new FunctionTypeImpl(method);
+
+    expect(method.type.typeArguments,
+        unorderedEquals(_toTypes(classElement.typeParameters)));
+    expect(method.type.typeFormals, unorderedEquals(method.typeParameters));
+    expect(method.type.typeParameters,
+        unorderedEquals(classElement.typeParameters));
+  }
+
   void test_withTypeArguments() {
     ClassElementImpl enclosingClass = ElementFactory.classElement2("C", ["E"]);
     MethodElementImpl methodElement =
@@ -2094,6 +2220,10 @@
     expect(arguments, hasLength(1));
     expect(arguments[0], expectedType);
   }
+
+  Iterable<DartType> _toTypes(List<TypeParameterElement> typeParameters) {
+    return typeParameters.map((TypeParameterElement element) => element.type);
+  }
 }
 
 @reflectiveTest
diff --git a/pkg/analyzer/test/src/summary/linker_test.dart b/pkg/analyzer/test/src/summary/linker_test.dart
index e5f0dfa..ef33f95 100644
--- a/pkg/analyzer/test/src/summary/linker_test.dart
+++ b/pkg/analyzer/test/src/summary/linker_test.dart
@@ -454,6 +454,20 @@
         'int');
   }
 
+  void test_leastUpperBound_functionAndClass() {
+    createLinker('''
+class C {}
+void f() {}
+var x = {
+  'C': C,
+  'f': f
+};
+''');
+    LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri);
+    library.libraryCycleForLink.ensureLinked();
+    // No assertions--just make sure it doesn't crash.
+  }
+
   void test_libraryCycle_ignoresDependenciesOutsideBuildUnit() {
     createLinker('import "dart:async";');
     LibraryCycleForLink libraryCycle = testLibrary.libraryCycleForLink;
diff --git a/pkg/analyzer/test/src/summary/resynthesize_ast_test.dart b/pkg/analyzer/test/src/summary/resynthesize_ast_test.dart
index 9d7a10d..420b70f 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_ast_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_ast_test.dart
@@ -44,6 +44,9 @@
   }
 
   @override
+  bool get mayCheckTypesOfLocals => false;
+
+  @override
   bool get skipBrokenAstInference => true;
 
   @override
@@ -79,26 +82,26 @@
 
   @override
   @failingTest
-  void test_blockBodiedLambdas_async_allReturnsAreValues() {
-    super.test_blockBodiedLambdas_async_allReturnsAreValues();
+  void test_blockBodiedLambdas_async_allReturnsAreFutures_topLevel() {
+    super.test_blockBodiedLambdas_async_allReturnsAreFutures_topLevel();
   }
 
   @override
   @failingTest
-  void test_blockBodiedLambdas_async_alReturnsAreFutures() {
-    super.test_blockBodiedLambdas_async_alReturnsAreFutures();
+  void test_blockBodiedLambdas_async_allReturnsAreValues_topLevel() {
+    super.test_blockBodiedLambdas_async_allReturnsAreValues_topLevel();
   }
 
   @override
   @failingTest
-  void test_blockBodiedLambdas_async_mixOfValuesAndFutures() {
-    super.test_blockBodiedLambdas_async_mixOfValuesAndFutures();
+  void test_blockBodiedLambdas_async_mixOfValuesAndFutures_topLevel() {
+    super.test_blockBodiedLambdas_async_mixOfValuesAndFutures_topLevel();
   }
 
   @override
   @failingTest
-  void test_blockBodiedLambdas_asyncStar() {
-    super.test_blockBodiedLambdas_asyncStar();
+  void test_blockBodiedLambdas_asyncStar_topLevel() {
+    super.test_blockBodiedLambdas_asyncStar_topLevel();
   }
 
   @override
@@ -109,32 +112,26 @@
 
   @override
   @failingTest
-  void test_blockBodiedLambdas_doesNotInferBottom_async() {
-    super.test_blockBodiedLambdas_doesNotInferBottom_async();
+  void test_blockBodiedLambdas_doesNotInferBottom_async_topLevel() {
+    super.test_blockBodiedLambdas_doesNotInferBottom_async_topLevel();
   }
 
   @override
   @failingTest
-  void test_blockBodiedLambdas_doesNotInferBottom_asyncStar() {
-    super.test_blockBodiedLambdas_doesNotInferBottom_asyncStar();
+  void test_blockBodiedLambdas_doesNotInferBottom_asyncStar_topLevel() {
+    super.test_blockBodiedLambdas_doesNotInferBottom_asyncStar_topLevel();
   }
 
   @override
   @failingTest
-  void test_blockBodiedLambdas_doesNotInferBottom_sync() {
-    super.test_blockBodiedLambdas_doesNotInferBottom_sync();
+  void test_blockBodiedLambdas_doesNotInferBottom_sync_topLevel() {
+    super.test_blockBodiedLambdas_doesNotInferBottom_sync_topLevel();
   }
 
   @override
   @failingTest
-  void test_blockBodiedLambdas_doesNotInferBottom_syncStar() {
-    super.test_blockBodiedLambdas_doesNotInferBottom_syncStar();
-  }
-
-  @override
-  @failingTest
-  void test_blockBodiedLambdas_downwardsIncompatibleWithUpwardsInference() {
-    super.test_blockBodiedLambdas_downwardsIncompatibleWithUpwardsInference();
+  void test_blockBodiedLambdas_doesNotInferBottom_syncStar_topLevel() {
+    super.test_blockBodiedLambdas_doesNotInferBottom_syncStar_topLevel();
   }
 
   @override
@@ -145,44 +142,14 @@
 
   @override
   @failingTest
-  void test_blockBodiedLambdas_nestedLambdas() {
-    super.test_blockBodiedLambdas_nestedLambdas();
+  void test_blockBodiedLambdas_nestedLambdas_topLevel() {
+    super.test_blockBodiedLambdas_nestedLambdas_topLevel();
   }
 
   @override
   @failingTest
-  void test_blockBodiedLambdas_noReturn() {
-    super.test_blockBodiedLambdas_noReturn();
-  }
-
-  @override
-  @failingTest
-  void test_blockBodiedLambdas_syncStar() {
-    super.test_blockBodiedLambdas_syncStar();
-  }
-
-  @override
-  @failingTest
-  void test_canInferAlsoFromStaticAndInstanceFieldsFlagOn() {
-    super.test_canInferAlsoFromStaticAndInstanceFieldsFlagOn();
-  }
-
-  @override
-  @failingTest
-  void test_downwardsInferenceAnnotations() {
-    super.test_downwardsInferenceAnnotations();
-  }
-
-  @override
-  @failingTest
-  void test_downwardsInferenceAsyncAwait() {
-    super.test_downwardsInferenceAsyncAwait();
-  }
-
-  @override
-  @failingTest
-  void test_downwardsInferenceForEach() {
-    super.test_downwardsInferenceForEach();
+  void test_blockBodiedLambdas_syncStar_topLevel() {
+    super.test_blockBodiedLambdas_syncStar_topLevel();
   }
 
   @override
@@ -199,12 +166,6 @@
 
   @override
   @failingTest
-  void test_downwardsInferenceYieldYieldStar() {
-    super.test_downwardsInferenceYieldYieldStar();
-  }
-
-  @override
-  @failingTest
   void test_genericMethods_inferJSBuiltin() {
     super.test_genericMethods_inferJSBuiltin();
   }
@@ -562,6 +523,42 @@
     super.test_inferenceInCyclesIsDeterministic();
   }
 
+  @override
+  @failingTest
+  void test_instantiateToBounds_generic2_hasBound_definedAfter() {
+    super.test_instantiateToBounds_generic2_hasBound_definedAfter();
+  }
+
+  @override
+  @failingTest
+  void test_instantiateToBounds_generic2_hasBound_definedBefore() {
+    super.test_instantiateToBounds_generic2_hasBound_definedBefore();
+  }
+
+  @override
+  @failingTest
+  void test_instantiateToBounds_generic2_noBound() {
+    super.test_instantiateToBounds_generic2_noBound();
+  }
+
+  @override
+  @failingTest
+  void test_instantiateToBounds_generic_hasBound_definedAfter() {
+    super.test_instantiateToBounds_generic_hasBound_definedAfter();
+  }
+
+  @override
+  @failingTest
+  void test_instantiateToBounds_generic_hasBound_definedBefore() {
+    super.test_instantiateToBounds_generic_hasBound_definedBefore();
+  }
+
+  @override
+  @failingTest
+  void test_instantiateToBounds_notGeneric() {
+    super.test_instantiateToBounds_notGeneric();
+  }
+
   void test_invokeMethod_notGeneric_genericClass() {
     var unit = checkFile(r'''
 class C<T> {
@@ -584,18 +581,6 @@
 
   @override
   @failingTest
-  void test_listLiteralsShouldNotInferBottom() {
-    super.test_listLiteralsShouldNotInferBottom();
-  }
-
-  @override
-  @failingTest
-  void test_mapLiteralsShouldNotInferBottom() {
-    super.test_mapLiteralsShouldNotInferBottom();
-  }
-
-  @override
-  @failingTest
   void test_nullLiteralShouldNotInferAsBottom() {
     super.test_nullLiteralShouldNotInferAsBottom();
   }
@@ -636,42 +621,12 @@
 
   @override
   @failingTest
-  void test_constructor_initializers_field_notConst() {
-    super.test_constructor_initializers_field_notConst();
-  }
-
-  @override
-  @failingTest
   void test_inferred_function_type_in_generic_class_constructor() {
     super.test_inferred_function_type_in_generic_class_constructor();
   }
 
   @override
   @failingTest
-  void test_metadata_constructor_call_named() {
-    super.test_metadata_constructor_call_named();
-  }
-
-  @override
-  @failingTest
-  void test_metadata_constructor_call_named_prefixed() {
-    super.test_metadata_constructor_call_named_prefixed();
-  }
-
-  @override
-  @failingTest
-  void test_metadata_constructor_call_unnamed() {
-    super.test_metadata_constructor_call_unnamed();
-  }
-
-  @override
-  @failingTest
-  void test_metadata_constructor_call_with_args() {
-    super.test_metadata_constructor_call_with_args();
-  }
-
-  @override
-  @failingTest
   void test_type_reference_to_import_part_in_subdir() {
     super.test_type_reference_to_import_part_in_subdir();
   }
diff --git a/pkg/analyzer/test/src/summary/resynthesize_test.dart b/pkg/analyzer/test/src/summary/resynthesize_test.dart
index b4e87cd..c3ae04d 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_test.dart
@@ -42,7 +42,6 @@
  */
 abstract class AbstractResynthesizeTest extends AbstractSingleUnitTest {
   Set<Source> otherLibrarySources = new Set<Source>();
-  bool constantInitializersAreInvalid = false;
 
   bool get checkPropagatedTypes => true;
 
@@ -335,11 +334,7 @@
       } else if (oItem is ConstructorFieldInitializer &&
           rItem is ConstructorFieldInitializer) {
         compareConstAsts(rItem.fieldName, oItem.fieldName, desc);
-        if (constantInitializersAreInvalid) {
-          _assertUnresolvedIdentifier(rItem.expression, desc);
-        } else {
-          compareConstAsts(rItem.expression, oItem.expression, desc);
-        }
+        compareConstAsts(rItem.expression, oItem.expression, desc);
       } else if (oItem is SuperConstructorInvocation &&
           rItem is SuperConstructorInvocation) {
         compareElements(rItem.staticElement, oItem.staticElement, desc);
@@ -411,9 +406,13 @@
         compareConstAsts(r.identifier, o.identifier, desc);
       } else if (o is PropertyAccess && r is PropertyAccess) {
         compareConstAsts(r.target, o.target, desc);
-        expect(r.propertyName.name, o.propertyName.name, reason: desc);
-        compareElements(
-            r.propertyName.staticElement, o.propertyName.staticElement, desc);
+        String oName = o.propertyName.name;
+        String rName = r.propertyName.name;
+        expect(rName, oName, reason: desc);
+        if (oName == 'length') {
+          compareElements(
+              r.propertyName.staticElement, o.propertyName.staticElement, desc);
+        }
       } else if (o is PropertyAccess &&
           o.target is PrefixedIdentifier &&
           r is SimpleIdentifier) {
@@ -648,7 +647,7 @@
       return;
     }
     expect(original, isNotNull);
-    expect(resynthesized, isNotNull);
+    expect(resynthesized, isNotNull, reason: desc);
     expect(rImpl.runtimeType, oImpl.runtimeType);
     expect(resynthesized.kind, original.kind);
     expect(resynthesized.location, original.location, reason: desc);
@@ -1079,12 +1078,8 @@
             resynthesized.constantValue, original.constantValue, desc);
       } else {
         Expression initializer = resynthesizedActual.constantInitializer;
-        if (constantInitializersAreInvalid) {
-          _assertUnresolvedIdentifier(initializer, desc);
-        } else {
-          compareConstAsts(initializer, originalActual.constantInitializer,
-              '$desc initializer');
-        }
+        compareConstAsts(initializer, originalActual.constantInitializer,
+            '$desc initializer');
       }
     }
     checkPossibleMember(resynthesized, original, desc);
@@ -1200,12 +1195,6 @@
     super.setUp();
     prepareAnalysisContext(createOptions());
   }
-
-  void _assertUnresolvedIdentifier(Expression initializer, String desc) {
-    expect(initializer, new isInstanceOf<SimpleIdentifier>(), reason: desc);
-    SimpleIdentifier identifier = initializer;
-    expect(identifier.staticElement, isNull, reason: desc);
-  }
 }
 
 @reflectiveTest
@@ -1668,7 +1657,6 @@
   }
 
   test_const_invalid_field_const() {
-    constantInitializersAreInvalid = true;
     checkLibrary(
         r'''
 class C {
@@ -1680,7 +1668,6 @@
   }
 
   test_const_invalid_field_final() {
-    constantInitializersAreInvalid = true;
     checkLibrary(
         r'''
 class C {
@@ -1692,7 +1679,6 @@
   }
 
   test_const_invalid_topLevel() {
-    constantInitializersAreInvalid = true;
     checkLibrary(
         r'''
 const v = 1 + foo();
@@ -2435,7 +2421,6 @@
   }
 
   test_constructor_initializers_field_notConst() {
-    constantInitializersAreInvalid = true;
     checkLibrary(
         '''
 class C {
@@ -2931,6 +2916,20 @@
     checkLibrary('class C { var x = 0; }');
   }
 
+  test_function_async() {
+    checkLibrary(r'''
+import 'dart:async';
+Future f() async {}
+''');
+  }
+
+  test_function_asyncStar() {
+    checkLibrary(r'''
+import 'dart:async';
+Stream f() async* {}
+''');
+  }
+
   test_function_documented() {
     checkLibrary('''
 // Extra comment so doc comment offset != 0
@@ -3543,6 +3542,24 @@
     checkLibrary('export "a.dart";');
   }
 
+  test_member_function_async() {
+    checkLibrary(r'''
+import 'dart:async';
+class C {
+  Future f() async {}
+}
+''');
+  }
+
+  test_member_function_asyncStar() {
+    checkLibrary(r'''
+import 'dart:async';
+class C {
+  Stream f() async* {}
+}
+''');
+  }
+
   test_metadata_classDeclaration() {
     checkLibrary('const a = null; @a class C {}');
   }
diff --git a/pkg/analyzer/test/src/summary/summary_common.dart b/pkg/analyzer/test/src/summary/summary_common.dart
index c50e33b..7e25284 100644
--- a/pkg/analyzer/test/src/summary/summary_common.dart
+++ b/pkg/analyzer/test/src/summary/summary_common.dart
@@ -2819,6 +2819,73 @@
     ]);
   }
 
+  test_constExpr_pushReference_staticGetter() {
+    UnlinkedVariable variable = serializeVariableText('''
+class C {
+  static int get x => null;
+}
+const v = C.x;
+''');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushReference
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, null, null, 'x',
+              expectedKind: ReferenceKind.propertyAccessor,
+              prefixExpectations: [
+                new _PrefixExpectation(ReferenceKind.classOrEnum, 'C')
+              ])
+    ]);
+  }
+
+  test_constExpr_pushReference_staticGetter_imported() {
+    addNamedSource(
+        '/a.dart',
+        '''
+class C {
+  static int get x => null;
+}
+''');
+    UnlinkedVariable variable = serializeVariableText('''
+import 'a.dart';
+const v = C.x;
+''');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushReference
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, null, null, 'x',
+              expectedKind: ReferenceKind.propertyAccessor,
+              prefixExpectations: [
+                new _PrefixExpectation(ReferenceKind.classOrEnum, 'C',
+                    absoluteUri: absUri('/a.dart'), relativeUri: 'a.dart')
+              ])
+    ]);
+  }
+
+  test_constExpr_pushReference_staticGetter_imported_withPrefix() {
+    addNamedSource(
+        '/a.dart',
+        '''
+class C {
+  static int get x => null;
+}
+''');
+    UnlinkedVariable variable = serializeVariableText('''
+import 'a.dart' as p;
+const v = p.C.x;
+''');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushReference
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, null, null, 'x',
+              expectedKind: ReferenceKind.propertyAccessor,
+              prefixExpectations: [
+                new _PrefixExpectation(ReferenceKind.classOrEnum, 'C',
+                    absoluteUri: absUri('/a.dart'), relativeUri: 'a.dart'),
+                new _PrefixExpectation(ReferenceKind.prefix, 'p')
+              ])
+    ]);
+  }
+
   test_constExpr_pushReference_staticMethod() {
     UnlinkedVariable variable = serializeVariableText('''
 class C {
@@ -2956,6 +3023,48 @@
     ]);
   }
 
+  test_constExpr_pushReference_topLevelGetter() {
+    UnlinkedVariable variable = serializeVariableText('''
+int get x => null;
+const v = x;
+''');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushReference
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, null, null, 'x',
+          expectedKind: ReferenceKind.topLevelPropertyAccessor)
+    ]);
+  }
+
+  test_constExpr_pushReference_topLevelGetter_imported() {
+    addNamedSource('/a.dart', 'int get x => null;');
+    UnlinkedVariable variable = serializeVariableText('''
+import 'a.dart';
+const v = x;
+''');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushReference
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, absUri('/a.dart'), 'a.dart', 'x',
+          expectedKind: ReferenceKind.topLevelPropertyAccessor)
+    ]);
+  }
+
+  test_constExpr_pushReference_topLevelGetter_imported_withPrefix() {
+    addNamedSource('/a.dart', 'int get x => null;');
+    UnlinkedVariable variable = serializeVariableText('''
+import 'a.dart' as p;
+const v = p.x;
+''');
+    _assertUnlinkedConst(variable.constExpr, operators: [
+      UnlinkedConstOperation.pushReference
+    ], referenceValidators: [
+      (EntityRef r) => checkTypeRef(r, absUri('/a.dart'), 'a.dart', 'x',
+          expectedKind: ReferenceKind.topLevelPropertyAccessor,
+          expectedPrefix: 'p')
+    ]);
+  }
+
   test_constExpr_pushReference_topLevelVariable() {
     UnlinkedVariable variable = serializeVariableText('''
 const int a = 1;
@@ -3142,7 +3251,9 @@
         findExecutable('', executables: serializeClassText(text).executables);
     expect(executable.kind, UnlinkedExecutableKind.constructor);
     expect(executable.returnType, isNull);
+    expect(executable.isAsynchronous, isFalse);
     expect(executable.isExternal, isFalse);
+    expect(executable.isGenerator, isFalse);
     expect(executable.nameOffset, text.indexOf('C();'));
     expect(executable.periodOffset, 0);
     expect(executable.nameEnd, 0);
@@ -4738,7 +4849,9 @@
     UnlinkedExecutable executable = serializeExecutableText(text);
     expect(executable.kind, UnlinkedExecutableKind.functionOrMethod);
     expect(executable.returnType, isNull);
+    expect(executable.isAsynchronous, isFalse);
     expect(executable.isExternal, isFalse);
+    expect(executable.isGenerator, isFalse);
     expect(executable.nameOffset, text.indexOf('f'));
     expect(executable.visibleOffset, 0);
     expect(executable.visibleLength, 0);
@@ -4749,6 +4862,24 @@
     expect(unlinkedUnits[0].publicNamespace.names[0].numTypeParameters, 0);
   }
 
+  test_executable_function_async() {
+    UnlinkedExecutable executable = serializeExecutableText(r'''
+import 'dart:async';
+Future f() async {}
+''');
+    expect(executable.isAsynchronous, isTrue);
+    expect(executable.isGenerator, isFalse);
+  }
+
+  test_executable_function_asyncStar() {
+    UnlinkedExecutable executable = serializeExecutableText(r'''
+import 'dart:async';
+Stream f() async* {}
+''');
+    expect(executable.isAsynchronous, isTrue);
+    expect(executable.isGenerator, isTrue);
+  }
+
   test_executable_function_explicit_return() {
     UnlinkedExecutable executable =
         serializeExecutableText('dynamic f() => null;');
@@ -4770,7 +4901,9 @@
     UnlinkedExecutable executable = serializeExecutableText(text);
     expect(executable.kind, UnlinkedExecutableKind.getter);
     expect(executable.returnType, isNotNull);
+    expect(executable.isAsynchronous, isFalse);
     expect(executable.isExternal, isFalse);
+    expect(executable.isGenerator, isFalse);
     expect(executable.nameOffset, text.indexOf('f'));
     expect(findVariable('f'), isNull);
     expect(findExecutable('f='), isNull);
@@ -5203,12 +5336,38 @@
         executables: serializeClassText('class C { f() {} }').executables);
     expect(executable.kind, UnlinkedExecutableKind.functionOrMethod);
     expect(executable.returnType, isNull);
+    expect(executable.isAsynchronous, isFalse);
     expect(executable.isExternal, isFalse);
+    expect(executable.isGenerator, isFalse);
     expect(executable.visibleOffset, 0);
     expect(executable.visibleLength, 0);
     _assertCodeRange(executable.codeRange, 10, 6);
   }
 
+  test_executable_member_function_async() {
+    UnlinkedExecutable executable =
+        findExecutable('f', executables: serializeClassText(r'''
+import 'dart:async';
+class C {
+  Future f() async {}
+}
+''').executables);
+    expect(executable.isAsynchronous, isTrue);
+    expect(executable.isGenerator, isFalse);
+  }
+
+  test_executable_member_function_asyncStar() {
+    UnlinkedExecutable executable =
+        findExecutable('f', executables: serializeClassText(r'''
+import 'dart:async';
+class C {
+  Stream f() async* {}
+}
+''').executables);
+    expect(executable.isAsynchronous, isTrue);
+    expect(executable.isGenerator, isTrue);
+  }
+
   test_executable_member_function_explicit_return() {
     UnlinkedExecutable executable = findExecutable('f',
         executables:
@@ -5229,10 +5388,16 @@
         findExecutable('f', executables: cls.executables, failIfAbsent: true);
     expect(executable.kind, UnlinkedExecutableKind.getter);
     expect(executable.returnType, isNotNull);
+    expect(executable.isAsynchronous, isFalse);
     expect(executable.isExternal, isFalse);
+    expect(executable.isGenerator, isFalse);
+    expect(executable.isStatic, isFalse);
     _assertCodeRange(executable.codeRange, 10, 15);
     expect(findVariable('f', variables: cls.fields), isNull);
     expect(findExecutable('f=', executables: cls.executables), isNull);
+    expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
+    expect(unlinkedUnits[0].publicNamespace.names[0].name, 'C');
+    expect(unlinkedUnits[0].publicNamespace.names[0].members, isEmpty);
   }
 
   test_executable_member_getter_external() {
@@ -5242,13 +5407,34 @@
     expect(executable.isExternal, isTrue);
   }
 
+  test_executable_member_getter_static() {
+    UnlinkedClass cls =
+        serializeClassText('class C { static int get f => 1; }');
+    UnlinkedExecutable executable =
+        findExecutable('f', executables: cls.executables, failIfAbsent: true);
+    expect(executable.isStatic, isTrue);
+    expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
+    expect(unlinkedUnits[0].publicNamespace.names[0].name, 'C');
+    expect(unlinkedUnits[0].publicNamespace.names[0].members, hasLength(1));
+    expect(unlinkedUnits[0].publicNamespace.names[0].members[0].name, 'f');
+    expect(unlinkedUnits[0].publicNamespace.names[0].members[0].kind,
+        ReferenceKind.propertyAccessor);
+    expect(
+        unlinkedUnits[0].publicNamespace.names[0].members[0].numTypeParameters,
+        0);
+    expect(
+        unlinkedUnits[0].publicNamespace.names[0].members[0].members, isEmpty);
+  }
+
   test_executable_member_setter() {
     UnlinkedClass cls = serializeClassText('class C { void set f(value) {} }');
     UnlinkedExecutable executable =
         findExecutable('f=', executables: cls.executables, failIfAbsent: true);
     expect(executable.kind, UnlinkedExecutableKind.setter);
     expect(executable.returnType, isNotNull);
+    expect(executable.isAsynchronous, isFalse);
     expect(executable.isExternal, isFalse);
+    expect(executable.isGenerator, isFalse);
     _assertCodeRange(executable.codeRange, 10, 20);
     expect(findVariable('f', variables: cls.fields), isNull);
     expect(findExecutable('f', executables: cls.executables), isNull);
@@ -5302,8 +5488,10 @@
     expect(executable.name, '+');
     expect(executable.returnType, isNotNull);
     expect(executable.isAbstract, false);
+    expect(executable.isAsynchronous, isFalse);
     expect(executable.isConst, false);
     expect(executable.isFactory, false);
+    expect(executable.isGenerator, isFalse);
     expect(executable.isStatic, false);
     expect(executable.parameters, hasLength(1));
     checkTypeRef(executable.returnType, null, null, 'C');
@@ -5316,7 +5504,9 @@
         serializeClassText('class C { C operator+(C c); }', allowErrors: true)
             .executables[0];
     expect(executable.isAbstract, true);
+    expect(executable.isAsynchronous, isFalse);
     expect(executable.isExternal, false);
+    expect(executable.isGenerator, isFalse);
   }
 
   test_executable_operator_equal() {
@@ -5331,7 +5521,9 @@
         serializeClassText('class C { external C operator+(C c); }')
             .executables[0];
     expect(executable.isAbstract, false);
+    expect(executable.isAsynchronous, isFalse);
     expect(executable.isExternal, true);
+    expect(executable.isGenerator, isFalse);
   }
 
   test_executable_operator_greater_equal() {
@@ -5582,7 +5774,9 @@
         serializeExecutableText(text, executableName: 'f=');
     expect(executable.kind, UnlinkedExecutableKind.setter);
     expect(executable.returnType, isNotNull);
+    expect(executable.isAsynchronous, isFalse);
     expect(executable.isExternal, isFalse);
+    expect(executable.isGenerator, isFalse);
     expect(executable.nameOffset, text.indexOf('f'));
     expect(findVariable('f'), isNull);
     expect(findExecutable('f'), isNull);
diff --git a/pkg/analyzer/test/src/task/dart_test.dart b/pkg/analyzer/test/src/task/dart_test.dart
index 4c3007b..cddc662 100644
--- a/pkg/analyzer/test/src/task/dart_test.dart
+++ b/pkg/analyzer/test/src/task/dart_test.dart
@@ -70,6 +70,7 @@
   runReflectiveTests(ResolveInstanceFieldsInUnitTaskTest);
   runReflectiveTests(ResolveLibraryTaskTest);
   runReflectiveTests(ResolveLibraryTypeNamesTaskTest);
+  runReflectiveTests(ResolveTopLevelUnitTypeBoundsTaskTest);
   runReflectiveTests(ResolveUnitTaskTest);
   runReflectiveTests(ResolveUnitTypeNamesTaskTest);
   runReflectiveTests(ResolveVariableReferencesTaskTest);
@@ -136,6 +137,8 @@
 isInstanceOf isResolveLibraryTask = new isInstanceOf<ResolveLibraryTask>();
 isInstanceOf isResolveLibraryTypeNamesTask =
     new isInstanceOf<ResolveLibraryTypeNamesTask>();
+isInstanceOf isResolveTopLevelUnitTypeBoundsTask =
+    new isInstanceOf<ResolveTopLevelUnitTypeBoundsTask>();
 isInstanceOf isResolveUnitTask = new isInstanceOf<ResolveUnitTask>();
 isInstanceOf isResolveUnitTypeNamesTask =
     new isInstanceOf<ResolveUnitTypeNamesTask>();
@@ -1499,9 +1502,9 @@
 class A {}
 ''');
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    computeResult(target, RESOLVED_UNIT6);
-    expect(outputs[RESOLVED_UNIT6], isNotNull);
-    expect(outputs[CREATED_RESOLVED_UNIT6], isTrue);
+    computeResult(target, RESOLVED_UNIT7);
+    expect(outputs[RESOLVED_UNIT7], isNotNull);
+    expect(outputs[CREATED_RESOLVED_UNIT7], isTrue);
   }
 
   test_perform() {
@@ -1512,8 +1515,8 @@
 const b = 0;
 ''');
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    computeResult(target, RESOLVED_UNIT6);
-    CompilationUnit unit = outputs[RESOLVED_UNIT6];
+    computeResult(target, RESOLVED_UNIT7);
+    CompilationUnit unit = outputs[RESOLVED_UNIT7];
     TopLevelVariableElement elementA = unit.element.topLevelVariables[0];
     TopLevelVariableElement elementB = unit.element.topLevelVariables[1];
 
@@ -2025,8 +2028,8 @@
 }
 ''');
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    computeResult(target, RESOLVED_UNIT6);
-    CompilationUnit unit = outputs[RESOLVED_UNIT6];
+    computeResult(target, RESOLVED_UNIT7);
+    CompilationUnit unit = outputs[RESOLVED_UNIT7];
     FieldElement elementA = AstFinder.getFieldInClassElement(unit, 'A', 'a');
     // compute
     computeResult(elementA, PROPAGABLE_VARIABLE_DEPENDENCIES,
@@ -2056,8 +2059,8 @@
 var   d4 = 4;
 ''');
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    computeResult(target, RESOLVED_UNIT6);
-    CompilationUnit unit = outputs[RESOLVED_UNIT6];
+    computeResult(target, RESOLVED_UNIT7);
+    CompilationUnit unit = outputs[RESOLVED_UNIT7];
     TopLevelVariableElement elementA =
         AstFinder.getTopLevelVariableElement(unit, 'a');
     // compute
@@ -2087,8 +2090,8 @@
 final d = 4;
 ''');
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    computeResult(target, RESOLVED_UNIT6);
-    CompilationUnit unit = outputs[RESOLVED_UNIT6];
+    computeResult(target, RESOLVED_UNIT7);
+    CompilationUnit unit = outputs[RESOLVED_UNIT7];
     TopLevelVariableElement elementA =
         AstFinder.getTopLevelVariableElement(unit, 'a');
     // compute
@@ -2111,8 +2114,8 @@
 const c = 2;
 ''');
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    computeResult(target, RESOLVED_UNIT6);
-    CompilationUnit unit = outputs[RESOLVED_UNIT6];
+    computeResult(target, RESOLVED_UNIT7);
+    CompilationUnit unit = outputs[RESOLVED_UNIT7];
     TopLevelVariableElement elementA =
         AstFinder.getTopLevelVariableElement(unit, 'a');
     // compute
@@ -2219,9 +2222,9 @@
 class A {}
 ''');
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    computeResult(target, RESOLVED_UNIT12);
-    expect(outputs[RESOLVED_UNIT12], isNotNull);
-    expect(outputs[CREATED_RESOLVED_UNIT12], isTrue);
+    computeResult(target, RESOLVED_UNIT13);
+    expect(outputs[RESOLVED_UNIT13], isNotNull);
+    expect(outputs[CREATED_RESOLVED_UNIT13], isTrue);
   }
 
   test_perform() {
@@ -2238,9 +2241,9 @@
 const x = const C();
 ''');
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    computeResult(target, RESOLVED_UNIT12,
+    computeResult(target, RESOLVED_UNIT13,
         matcher: isEvaluateUnitConstantsTask);
-    CompilationUnit unit = outputs[RESOLVED_UNIT12];
+    CompilationUnit unit = outputs[RESOLVED_UNIT13];
     CompilationUnitElement unitElement = unit.element;
     expect(
         (unitElement.types[0].constructors[0] as ConstructorElementImpl)
@@ -2747,9 +2750,9 @@
 class A {}
 ''');
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    computeResult(target, RESOLVED_UNIT10);
-    expect(outputs[RESOLVED_UNIT10], isNotNull);
-    expect(outputs[CREATED_RESOLVED_UNIT10], isTrue);
+    computeResult(target, RESOLVED_UNIT11);
+    expect(outputs[RESOLVED_UNIT11], isNotNull);
+    expect(outputs[CREATED_RESOLVED_UNIT11], isTrue);
   }
 
   void test_perform() {
@@ -2769,9 +2772,9 @@
 class Y {}
 class Z {}
 ''');
-    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT10,
+    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT11,
         matcher: isInferInstanceMembersInUnitTask);
-    CompilationUnit unit = outputs[RESOLVED_UNIT10];
+    CompilationUnit unit = outputs[RESOLVED_UNIT11];
     VariableDeclaration field = AstFinder.getFieldInClass(unit, 'B', 'f');
     MethodDeclaration method = AstFinder.getMethodInClass(unit, 'B', 'm');
     DartType typeX = AstFinder.getClass(unit, 'X').element.type;
@@ -2803,12 +2806,12 @@
 }
 ''');
     computeResult(
-        new LibrarySpecificUnit(firstSource, firstSource), RESOLVED_UNIT10,
+        new LibrarySpecificUnit(firstSource, firstSource), RESOLVED_UNIT11,
         matcher: isInferInstanceMembersInUnitTask);
-    CompilationUnit firstUnit = outputs[RESOLVED_UNIT10];
+    CompilationUnit firstUnit = outputs[RESOLVED_UNIT11];
     computeResult(
-        new LibrarySpecificUnit(secondSource, secondSource), RESOLVED_UNIT10);
-    CompilationUnit secondUnit = outputs[RESOLVED_UNIT10];
+        new LibrarySpecificUnit(secondSource, secondSource), RESOLVED_UNIT11);
+    CompilationUnit secondUnit = outputs[RESOLVED_UNIT11];
 
     VariableDeclaration variableA =
         AstFinder.getTopLevelVariable(firstUnit, 'a');
@@ -2835,8 +2838,8 @@
   String field = topLevel;
 }
 ''');
-    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT10);
-    CompilationUnit unit = outputs[RESOLVED_UNIT10];
+    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT11);
+    CompilationUnit unit = outputs[RESOLVED_UNIT11];
     VariableDeclaration topLevelDecl =
         AstFinder.getTopLevelVariable(unit, 'topLevel');
     VariableDeclaration fieldDecl =
@@ -2867,9 +2870,9 @@
 class A {}
 ''');
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    computeResult(target, RESOLVED_UNIT8);
-    expect(outputs[RESOLVED_UNIT8], isNotNull);
-    expect(outputs[CREATED_RESOLVED_UNIT8], isTrue);
+    computeResult(target, RESOLVED_UNIT9);
+    expect(outputs[RESOLVED_UNIT9], isNotNull);
+    expect(outputs[CREATED_RESOLVED_UNIT9], isTrue);
   }
 
   void test_perform_const_field() {
@@ -2881,9 +2884,9 @@
   static const X = "";
 }
 ''');
-    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT8,
+    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT9,
         matcher: isInferStaticVariableTypesInUnitTask);
-    CompilationUnit unit = outputs[RESOLVED_UNIT8];
+    CompilationUnit unit = outputs[RESOLVED_UNIT9];
     VariableDeclaration declaration = AstFinder.getFieldInClass(unit, 'M', 'X');
     InterfaceType stringType = context.typeProvider.stringType;
     expect(declaration.element.type, stringType);
@@ -2896,9 +2899,9 @@
 @(i $=
 ''');
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    computeResult(target, RESOLVED_UNIT8);
-    expect(outputs[RESOLVED_UNIT8], isNotNull);
-    expect(outputs[CREATED_RESOLVED_UNIT8], isTrue);
+    computeResult(target, RESOLVED_UNIT9);
+    expect(outputs[RESOLVED_UNIT9], isNotNull);
+    expect(outputs[CREATED_RESOLVED_UNIT9], isTrue);
   }
 
   void test_perform_nestedDeclarations() {
@@ -2912,7 +2915,7 @@
   return xSquared;
 };
 ''');
-    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT8,
+    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT9,
         matcher: isInferStaticVariableTypesInUnitTask);
   }
 
@@ -2935,12 +2938,12 @@
 class M {}
 ''');
     computeResult(
-        new LibrarySpecificUnit(firstSource, firstSource), RESOLVED_UNIT8,
+        new LibrarySpecificUnit(firstSource, firstSource), RESOLVED_UNIT9,
         matcher: isInferStaticVariableTypesInUnitTask);
-    CompilationUnit firstUnit = outputs[RESOLVED_UNIT8];
+    CompilationUnit firstUnit = outputs[RESOLVED_UNIT9];
     computeResult(
-        new LibrarySpecificUnit(secondSource, secondSource), RESOLVED_UNIT8);
-    CompilationUnit secondUnit = outputs[RESOLVED_UNIT8];
+        new LibrarySpecificUnit(secondSource, secondSource), RESOLVED_UNIT9);
+    CompilationUnit secondUnit = outputs[RESOLVED_UNIT9];
 
     VariableDeclaration variableA =
         AstFinder.getTopLevelVariable(firstUnit, 'a');
@@ -2969,9 +2972,9 @@
   return 1 + X;
 };
 ''');
-    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT8,
+    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT9,
         matcher: isInferStaticVariableTypesInUnitTask);
-    CompilationUnit unit = outputs[RESOLVED_UNIT8];
+    CompilationUnit unit = outputs[RESOLVED_UNIT9];
     TopLevelVariableDeclaration declaration = unit.declarations[1];
     FunctionExpression function =
         declaration.variables.variables[0].initializer;
@@ -2993,8 +2996,8 @@
   var field = '';
 }
 ''');
-    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT6);
-    CompilationUnit unit = outputs[RESOLVED_UNIT6];
+    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT7);
+    CompilationUnit unit = outputs[RESOLVED_UNIT7];
     VariableDeclaration declaration =
         AstFinder.getFieldInClass(unit, 'C', 'field');
     VariableElement variable = declaration.name.staticElement;
@@ -3009,8 +3012,8 @@
         '''
 var topLevel = '';
 ''');
-    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT6);
-    CompilationUnit unit = outputs[RESOLVED_UNIT6];
+    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT7);
+    CompilationUnit unit = outputs[RESOLVED_UNIT7];
     VariableDeclaration declaration =
         AstFinder.getTopLevelVariable(unit, 'topLevel');
     VariableElement variable = declaration.name.staticElement;
@@ -3029,8 +3032,8 @@
   var field3 = topLevel3;
 }
 ''');
-    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT6);
-    CompilationUnit unit = outputs[RESOLVED_UNIT6];
+    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT7);
+    CompilationUnit unit = outputs[RESOLVED_UNIT7];
     VariableDeclaration topLevelDecl =
         AstFinder.getTopLevelVariable(unit, 'topLevel3');
     VariableDeclaration fieldDecl =
@@ -3056,8 +3059,8 @@
   var field = topLevel;
 }
 ''');
-    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT6);
-    CompilationUnit unit = outputs[RESOLVED_UNIT6];
+    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT7);
+    CompilationUnit unit = outputs[RESOLVED_UNIT7];
     VariableElement topLevel =
         AstFinder.getTopLevelVariable(unit, 'topLevel').name.staticElement;
     VariableElement field =
@@ -3079,8 +3082,8 @@
 var pi = piFirst ? 3.14 : tau / 2;
 var tau = piFirst ? pi * 2 : 6.28;
 ''');
-    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT6);
-    CompilationUnit unit = outputs[RESOLVED_UNIT6];
+    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT7);
+    CompilationUnit unit = outputs[RESOLVED_UNIT7];
     VariableElement piFirst =
         AstFinder.getTopLevelVariable(unit, 'piFirst').name.staticElement;
     VariableElement pi =
@@ -3102,8 +3105,8 @@
         '''
 var a = '' / null;
 ''');
-    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT6);
-    CompilationUnit unit = outputs[RESOLVED_UNIT6];
+    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT7);
+    CompilationUnit unit = outputs[RESOLVED_UNIT7];
     VariableElement a =
         AstFinder.getTopLevelVariable(unit, 'a').name.staticElement;
 
@@ -3119,8 +3122,8 @@
         '''
 var a = null;
 ''');
-    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT6);
-    CompilationUnit unit = outputs[RESOLVED_UNIT6];
+    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT7);
+    CompilationUnit unit = outputs[RESOLVED_UNIT7];
     VariableElement a =
         AstFinder.getTopLevelVariable(unit, 'a').name.staticElement;
 
@@ -3434,11 +3437,11 @@
   new A<int>().m();
 }
 ''');
-    computeResult(new LibrarySpecificUnit(sourceC, sourceC), RESOLVED_UNIT6,
+    computeResult(new LibrarySpecificUnit(sourceC, sourceC), RESOLVED_UNIT7,
         matcher: isPartiallyResolveUnitReferencesTask);
     // validate
     expect(outputs[INFERABLE_STATIC_VARIABLES_IN_UNIT], hasLength(0));
-    CompilationUnit unit = outputs[RESOLVED_UNIT6];
+    CompilationUnit unit = outputs[RESOLVED_UNIT7];
     expect(unit, isNotNull);
 
     FunctionDeclaration mainFunction = unit.declarations[0];
@@ -3466,9 +3469,9 @@
 }
 ''');
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    computeResult(target, RESOLVED_UNIT6,
+    computeResult(target, RESOLVED_UNIT7,
         matcher: isPartiallyResolveUnitReferencesTask);
-    CompilationUnit unit = outputs[RESOLVED_UNIT6];
+    CompilationUnit unit = outputs[RESOLVED_UNIT7];
     // INFERABLE_STATIC_VARIABLES_IN_UNIT
     {
       List<VariableElement> variables =
@@ -3509,9 +3512,9 @@
 }
 ''');
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    computeResult(target, RESOLVED_UNIT6,
+    computeResult(target, RESOLVED_UNIT7,
         matcher: isPartiallyResolveUnitReferencesTask);
-    CompilationUnit unit = outputs[RESOLVED_UNIT6];
+    CompilationUnit unit = outputs[RESOLVED_UNIT7];
     NodeList<CompilationUnitMember> declarations = unit.declarations;
 
     void expectReference(BlockFunctionBody body, bool isResolved) {
@@ -3560,9 +3563,9 @@
 class A {}
 ''');
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    computeResult(target, RESOLVED_UNIT7);
-    expect(outputs[RESOLVED_UNIT7], isNotNull);
-    expect(outputs[CREATED_RESOLVED_UNIT7], isTrue);
+    computeResult(target, RESOLVED_UNIT8);
+    expect(outputs[RESOLVED_UNIT8], isNotNull);
+    expect(outputs[CREATED_RESOLVED_UNIT8], isTrue);
   }
 
   void test_perform_cycle() {
@@ -3574,9 +3577,9 @@
 final tau = piFirst ? pi * 2 : 6.28;
 ''');
     // compute
-    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT7,
+    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT8,
         matcher: isPropagateVariableTypesInUnitTask);
-    CompilationUnit unit = outputs[RESOLVED_UNIT7];
+    CompilationUnit unit = outputs[RESOLVED_UNIT8];
     // verify
     TopLevelVariableElement piFirst =
         AstFinder.getTopLevelVariableElement(unit, 'piFirst');
@@ -3599,9 +3602,9 @@
 final c = '2';
 ''');
     // compute
-    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT7,
+    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT8,
         matcher: isPropagateVariableTypesInUnitTask);
-    CompilationUnit unit = outputs[RESOLVED_UNIT7];
+    CompilationUnit unit = outputs[RESOLVED_UNIT8];
     // verify
     InterfaceType intType = context.typeProvider.intType;
     InterfaceType stringType = context.typeProvider.stringType;
@@ -3624,8 +3627,8 @@
 final pi = piFirst ? 3.14 : tau / 2;
 final tau = piFirst ? pi * 2 : 6.28;
 ''');
-    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT6);
-    CompilationUnit unit = outputs[RESOLVED_UNIT6];
+    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT7);
+    CompilationUnit unit = outputs[RESOLVED_UNIT7];
     TopLevelVariableElement piFirst =
         AstFinder.getTopLevelVariableElement(unit, 'piFirst');
     TopLevelVariableElement pi =
@@ -3647,8 +3650,8 @@
         '''
 var a = null;
 ''');
-    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT6);
-    CompilationUnit unit = outputs[RESOLVED_UNIT6];
+    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT7);
+    CompilationUnit unit = outputs[RESOLVED_UNIT7];
     TopLevelVariableElement a = AstFinder.getTopLevelVariableElement(unit, 'a');
     // compute
     computeResult(a, PROPAGATED_VARIABLE, matcher: isPropagateVariableTypeTask);
@@ -3663,8 +3666,8 @@
 final b = 1;
 final c = '2';
 ''');
-    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT6);
-    CompilationUnit unit = outputs[RESOLVED_UNIT6];
+    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT7);
+    CompilationUnit unit = outputs[RESOLVED_UNIT7];
     TopLevelVariableElement elementA =
         AstFinder.getTopLevelVariableElement(unit, 'a');
     TopLevelVariableElement elementB =
@@ -3749,9 +3752,9 @@
 class A {}
 ''');
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    computeResult(target, RESOLVED_UNIT9);
-    expect(outputs[RESOLVED_UNIT9], isNotNull);
-    expect(outputs[CREATED_RESOLVED_UNIT9], isTrue);
+    computeResult(target, RESOLVED_UNIT10);
+    expect(outputs[RESOLVED_UNIT10], isNotNull);
+    expect(outputs[CREATED_RESOLVED_UNIT10], isTrue);
   }
 
   // Test inference of instance fields across units
@@ -3781,16 +3784,16 @@
     DartType dynamicType = context.typeProvider.dynamicType;
 
     computeResult(
-        new LibrarySpecificUnit(sources[1], sources[1]), RESOLVED_UNIT9);
-    CompilationUnit unit1 = outputs[RESOLVED_UNIT9];
+        new LibrarySpecificUnit(sources[1], sources[1]), RESOLVED_UNIT10);
+    CompilationUnit unit1 = outputs[RESOLVED_UNIT10];
 
     // B.b2 shoud be resolved on the rhs, but not yet inferred.
     assertVariableDeclarationTypes(
         AstFinder.getFieldInClass(unit1, "B", "b2"), dynamicType, intType);
 
     computeResult(
-        new LibrarySpecificUnit(sources[0], sources[0]), RESOLVED_UNIT9);
-    CompilationUnit unit0 = outputs[RESOLVED_UNIT9];
+        new LibrarySpecificUnit(sources[0], sources[0]), RESOLVED_UNIT10);
+    CompilationUnit unit0 = outputs[RESOLVED_UNIT10];
 
     // B.b2 should now be fully resolved and inferred.
     assertVariableDeclarationTypes(
@@ -3801,7 +3804,7 @@
         AstFinder.getFieldInClass(unit0, "A", "a2"), dynamicType, intType);
 
     computeResult(
-        new LibrarySpecificUnit(sources[2], sources[2]), RESOLVED_UNIT9);
+        new LibrarySpecificUnit(sources[2], sources[2]), RESOLVED_UNIT10);
 
     // A.a2 should now be fully resolved and inferred.
     assertVariableDeclarationTypes(
@@ -3838,15 +3841,15 @@
     DartType dynamicType = context.typeProvider.dynamicType;
 
     computeResult(
-        new LibrarySpecificUnit(sources[0], sources[0]), RESOLVED_UNIT9);
-    CompilationUnit unit0 = outputs[RESOLVED_UNIT9];
+        new LibrarySpecificUnit(sources[0], sources[0]), RESOLVED_UNIT10);
+    CompilationUnit unit0 = outputs[RESOLVED_UNIT10];
 
     // A.a2 should now be resolved on the rhs, but not yet inferred.
     assertVariableDeclarationTypes(
         AstFinder.getFieldInClass(unit0, "A", "a2"), dynamicType, dynamicType);
 
     computeResult(
-        new LibrarySpecificUnit(sources[2], sources[2]), RESOLVED_UNIT9);
+        new LibrarySpecificUnit(sources[2], sources[2]), RESOLVED_UNIT10);
 
     // A.a2 should now be fully resolved and inferred (but not re-resolved).
     assertVariableDeclarationTypes(
@@ -3884,8 +3887,8 @@
     DartType dynamicType = context.typeProvider.dynamicType;
 
     computeResult(
-        new LibrarySpecificUnit(sources[1], sources[1]), RESOLVED_UNIT9);
-    CompilationUnit unit1 = outputs[RESOLVED_UNIT9];
+        new LibrarySpecificUnit(sources[1], sources[1]), RESOLVED_UNIT10);
+    CompilationUnit unit1 = outputs[RESOLVED_UNIT10];
 
     assertVariableDeclarationTypes(
         AstFinder.getFieldInClass(unit1, "B", "b1"), intType, intType);
@@ -3893,8 +3896,8 @@
         AstFinder.getFieldInClass(unit1, "B", "b2"), dynamicType, intType);
 
     computeResult(
-        new LibrarySpecificUnit(sources[0], sources[0]), RESOLVED_UNIT9);
-    CompilationUnit unit0 = outputs[RESOLVED_UNIT9];
+        new LibrarySpecificUnit(sources[0], sources[0]), RESOLVED_UNIT10);
+    CompilationUnit unit0 = outputs[RESOLVED_UNIT10];
 
     assertVariableDeclarationTypes(
         AstFinder.getFieldInClass(unit0, "A", "a1"), intType, intType);
@@ -3907,7 +3910,7 @@
         AstFinder.getFieldInClass(unit1, "B", "b2"), intType, intType);
 
     computeResult(
-        new LibrarySpecificUnit(sources[2], sources[2]), RESOLVED_UNIT9);
+        new LibrarySpecificUnit(sources[2], sources[2]), RESOLVED_UNIT10);
 
     assertVariableDeclarationTypes(
         AstFinder.getFieldInClass(unit0, "A", "a1"), intType, intType);
@@ -3946,8 +3949,8 @@
     DartType dynamicType = context.typeProvider.dynamicType;
 
     computeResult(
-        new LibrarySpecificUnit(sources[0], sources[0]), RESOLVED_UNIT9);
-    CompilationUnit unit0 = outputs[RESOLVED_UNIT9];
+        new LibrarySpecificUnit(sources[0], sources[0]), RESOLVED_UNIT10);
+    CompilationUnit unit0 = outputs[RESOLVED_UNIT10];
 
     // A.a2 should now be resolved on the rhs, but not yet inferred.
     assertVariableDeclarationTypes(
@@ -3958,7 +3961,7 @@
         AstFinder.getFieldInClass(unit0, "B", "b2"), dynamicType, intType);
 
     computeResult(
-        new LibrarySpecificUnit(sources[1], sources[1]), RESOLVED_UNIT9);
+        new LibrarySpecificUnit(sources[1], sources[1]), RESOLVED_UNIT10);
 
     // A.a2 should now be fully resolved and inferred (but not re-resolved).
     assertVariableDeclarationTypes(
@@ -4013,10 +4016,10 @@
 part of my_lib;
 class C extends A {}
 ''');
-    computeResult(sourceLib, LIBRARY_ELEMENT5,
+    computeResult(sourceLib, LIBRARY_ELEMENT6,
         matcher: isResolveLibraryTypeNamesTask);
     // validate
-    LibraryElement library = outputs[LIBRARY_ELEMENT5];
+    LibraryElement library = outputs[LIBRARY_ELEMENT6];
     {
       ClassElement classB = library.getType('B');
       expect(classB.supertype.displayName, 'A');
@@ -4044,10 +4047,10 @@
 ''');
     // The reference A to B should be resolved, but there's no requirement that
     // the full class hierarchy be resolved.
-    computeResult(sourceA, LIBRARY_ELEMENT5,
+    computeResult(sourceA, LIBRARY_ELEMENT6,
         matcher: isResolveLibraryTypeNamesTask);
     // validate
-    LibraryElement library = outputs[LIBRARY_ELEMENT5];
+    LibraryElement library = outputs[LIBRARY_ELEMENT6];
     {
       ClassElement clazz = library.getType('A');
       expect(clazz.displayName, 'A');
@@ -4058,6 +4061,134 @@
 }
 
 @reflectiveTest
+class ResolveTopLevelUnitTypeBoundsTaskTest extends _AbstractDartTaskTest {
+  test_perform_boundIsGenericType() {
+    Source source = newSource(
+        '/test.dart',
+        '''
+class C<T extends Map<String, List<int>>> {}
+''');
+    LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
+    computeResult(target, RESOLVED_UNIT4,
+        matcher: isResolveTopLevelUnitTypeBoundsTask);
+    // validate
+    CompilationUnit unit = outputs[RESOLVED_UNIT4];
+    ClassDeclaration nodeC = unit.declarations[0];
+    _assertTypeParameterBound(nodeC.typeParameters.typeParameters[0],
+        'Map<String, List<int>>', 'Map');
+  }
+
+  test_perform_errors() {
+    Source source = newSource(
+        '/test.dart',
+        '''
+class C<T extends NoSuchClass> {}
+''');
+    LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
+    computeResult(target, RESOLVE_TYPE_BOUNDS_ERRORS,
+        matcher: isResolveTopLevelUnitTypeBoundsTask);
+    // validate
+    _fillErrorListener(RESOLVE_TYPE_BOUNDS_ERRORS);
+    errorListener
+        .assertErrorsWithCodes(<ErrorCode>[StaticWarningCode.UNDEFINED_CLASS]);
+  }
+
+  test_perform_ignoreBoundsOfBounds() {
+    Source source = newSource(
+        '/test.dart',
+        '''
+class A<T1 extends num> {}
+class B<T2 extends A> {}
+''');
+    LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
+    computeResult(target, RESOLVED_UNIT4,
+        matcher: isResolveTopLevelUnitTypeBoundsTask);
+    // validate
+    CompilationUnit unit = outputs[RESOLVED_UNIT4];
+    ClassDeclaration nodeB = unit.declarations[1];
+    _assertTypeParameterBound(
+        nodeB.typeParameters.typeParameters[0], 'A<dynamic>', 'A');
+  }
+
+  test_perform_outputs() {
+    Source source = newSource(
+        '/test.dart',
+        r'''
+class C<T extends int> {}
+''');
+    LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
+    computeResult(target, RESOLVED_UNIT4);
+    expect(outputs[RESOLVED_UNIT4], isNotNull);
+    expect(outputs[CREATED_RESOLVED_UNIT4], isTrue);
+    expect(outputs[RESOLVE_TYPE_BOUNDS_ERRORS], isNotNull);
+  }
+
+  test_perform_unitMember_ClassDeclaration() {
+    Source source = newSource(
+        '/test.dart',
+        '''
+class C<T extends int> extends Object {}
+''');
+    LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
+    computeResult(target, RESOLVED_UNIT4,
+        matcher: isResolveTopLevelUnitTypeBoundsTask);
+    // validate
+    CompilationUnit unit = outputs[RESOLVED_UNIT4];
+    ClassDeclaration nodeC = unit.declarations[0];
+    // 'extends Object' is not resolved
+    expect(nodeC.extendsClause.superclass.name.staticElement, isNull);
+    // but 'T extends int' is resolved
+    _assertTypeParameterBound(
+        nodeC.typeParameters.typeParameters[0], 'int', 'int');
+  }
+
+  test_perform_unitMember_ClassTypeAlias() {
+    Source source = newSource(
+        '/test.dart',
+        '''
+class C<T extends double> = Object;
+''');
+    LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
+    computeResult(target, RESOLVED_UNIT4,
+        matcher: isResolveTopLevelUnitTypeBoundsTask);
+    // validate
+    CompilationUnit unit = outputs[RESOLVED_UNIT4];
+    ClassTypeAlias nodeC = unit.declarations[0];
+    // '= Object' is not resolved
+    expect(nodeC.superclass.name.staticElement, isNull);
+    // but 'T extends int' is resolved
+    _assertTypeParameterBound(
+        nodeC.typeParameters.typeParameters[0], 'double', 'double');
+  }
+
+  test_perform_unitMember_FunctionTypeAlias() {
+    Source source = newSource(
+        '/test.dart',
+        '''
+typedef F<T extends String>();
+''');
+    LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
+    computeResult(target, RESOLVED_UNIT4,
+        matcher: isResolveTopLevelUnitTypeBoundsTask);
+    // validate
+    CompilationUnit unit = outputs[RESOLVED_UNIT4];
+    FunctionTypeAlias nodeF = unit.declarations[0];
+    // but 'T extends String' is resolved
+    _assertTypeParameterBound(
+        nodeF.typeParameters.typeParameters[0], 'String', 'String');
+  }
+
+  void _assertTypeParameterBound(TypeParameter typeParameter,
+      String expectedBoundTypeString, String expectedBoundElementName) {
+    TypeName boundNode = typeParameter.bound;
+    Identifier boundName = boundNode.name;
+    expect(boundNode.type.toString(), expectedBoundTypeString);
+    expect(boundName.staticType.toString(), expectedBoundTypeString);
+    expect(boundName.staticElement.displayName, expectedBoundElementName);
+  }
+}
+
+@reflectiveTest
 class ResolveUnitTaskTest extends _AbstractDartTaskTest {
   test_created_resolved_unit() {
     Source source = newSource(
@@ -4067,9 +4198,9 @@
 class A {}
 ''');
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    computeResult(target, RESOLVED_UNIT11);
-    expect(outputs[RESOLVED_UNIT11], isNotNull);
-    expect(outputs[CREATED_RESOLVED_UNIT11], isTrue);
+    computeResult(target, RESOLVED_UNIT12);
+    expect(outputs[RESOLVED_UNIT12], isNotNull);
+    expect(outputs[CREATED_RESOLVED_UNIT12], isTrue);
   }
 
   void test_perform() {
@@ -4086,9 +4217,9 @@
   }
 }
 ''');
-    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT11,
+    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT12,
         matcher: isResolveUnitTask);
-    CompilationUnit unit = outputs[RESOLVED_UNIT11];
+    CompilationUnit unit = outputs[RESOLVED_UNIT12];
 
     FunctionDeclaration f = unit.declarations[0];
     _assertResolved(f.functionExpression.body);
@@ -4115,10 +4246,10 @@
   a.v.isEven;
 }
 ''');
-    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT11,
+    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT12,
         matcher: isResolveUnitTask);
     expect(outputs[RESOLVE_UNIT_ERRORS], hasLength(0));
-    CompilationUnit unit = outputs[RESOLVED_UNIT11];
+    CompilationUnit unit = outputs[RESOLVED_UNIT12];
     FunctionDeclaration main = unit.declarations[0];
     BlockFunctionBody body = main.functionExpression.body;
     ExpressionStatement statement = body.block.statements.single;
@@ -4143,9 +4274,9 @@
 class A {}
 ''');
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    computeResult(target, RESOLVED_UNIT4);
-    expect(outputs[RESOLVED_UNIT4], isNotNull);
-    expect(outputs[CREATED_RESOLVED_UNIT4], isTrue);
+    computeResult(target, RESOLVED_UNIT5);
+    expect(outputs[RESOLVED_UNIT5], isNotNull);
+    expect(outputs[CREATED_RESOLVED_UNIT5], isTrue);
   }
 
   test_perform() {
@@ -4157,9 +4288,9 @@
 int f(String p) => p.length;
 ''');
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    computeResult(target, RESOLVED_UNIT4, matcher: isResolveUnitTypeNamesTask);
+    computeResult(target, RESOLVED_UNIT5, matcher: isResolveUnitTypeNamesTask);
     // validate
-    CompilationUnit unit = outputs[RESOLVED_UNIT4];
+    CompilationUnit unit = outputs[RESOLVED_UNIT5];
     {
       ClassDeclaration nodeA = unit.declarations[0];
       ClassDeclaration nodeB = unit.declarations[1];
@@ -4199,9 +4330,9 @@
 typedef String G(int p);
 ''');
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    computeResult(target, RESOLVED_UNIT4, matcher: isResolveUnitTypeNamesTask);
+    computeResult(target, RESOLVED_UNIT5, matcher: isResolveUnitTypeNamesTask);
     // validate
-    CompilationUnit unit = outputs[RESOLVED_UNIT4];
+    CompilationUnit unit = outputs[RESOLVED_UNIT5];
     FunctionTypeAlias nodeF = unit.declarations[0];
     FunctionTypeAlias nodeG = unit.declarations[1];
     {
@@ -4255,9 +4386,9 @@
 class A {}
 ''');
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    computeResult(target, RESOLVED_UNIT5);
-    expect(outputs[RESOLVED_UNIT5], isNotNull);
-    expect(outputs[CREATED_RESOLVED_UNIT5], isTrue);
+    computeResult(target, RESOLVED_UNIT6);
+    expect(outputs[RESOLVED_UNIT6], isNotNull);
+    expect(outputs[CREATED_RESOLVED_UNIT6], isTrue);
   }
 
   test_perform_buildClosureLibraryElements() {
@@ -4268,7 +4399,7 @@
 }
 ''');
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    computeResult(target, RESOLVED_UNIT5,
+    computeResult(target, RESOLVED_UNIT6,
         matcher: isResolveVariableReferencesTask);
   }
 
@@ -4290,10 +4421,10 @@
 }
 ''');
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    computeResult(target, RESOLVED_UNIT5,
+    computeResult(target, RESOLVED_UNIT6,
         matcher: isResolveVariableReferencesTask);
     // validate
-    CompilationUnit unit = outputs[RESOLVED_UNIT5];
+    CompilationUnit unit = outputs[RESOLVED_UNIT6];
     FunctionDeclaration mainDeclaration = unit.declarations[0];
     FunctionBody body = mainDeclaration.functionExpression.body;
     FunctionElement main = mainDeclaration.element;
@@ -4317,10 +4448,10 @@
 }
 ''');
     LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    computeResult(target, RESOLVED_UNIT5,
+    computeResult(target, RESOLVED_UNIT6,
         matcher: isResolveVariableReferencesTask);
     // validate
-    CompilationUnit unit = outputs[RESOLVED_UNIT5];
+    CompilationUnit unit = outputs[RESOLVED_UNIT6];
     FunctionDeclaration mainDeclaration = unit.declarations[0];
     FunctionBody body = mainDeclaration.functionExpression.body;
     FunctionElement main = mainDeclaration.element;
@@ -4399,8 +4530,8 @@
 var pi = piFirst ? 3.14 : tau / 2;
 var tau = piFirst ? pi * 2 : 6.28;
 ''');
-    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT11);
-    CompilationUnit unit = outputs[RESOLVED_UNIT11];
+    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT12);
+    CompilationUnit unit = outputs[RESOLVED_UNIT12];
     VariableElement piFirst =
         AstFinder.getTopLevelVariable(unit, 'piFirst').name.staticElement;
     VariableElement pi =
@@ -4442,11 +4573,11 @@
           }
 ''');
     computeResult(
-        new LibrarySpecificUnit(firstSource, firstSource), RESOLVED_UNIT11);
-    CompilationUnit unit1 = outputs[RESOLVED_UNIT11];
+        new LibrarySpecificUnit(firstSource, firstSource), RESOLVED_UNIT12);
+    CompilationUnit unit1 = outputs[RESOLVED_UNIT12];
     computeResult(
-        new LibrarySpecificUnit(secondSource, secondSource), RESOLVED_UNIT11);
-    CompilationUnit unit2 = outputs[RESOLVED_UNIT11];
+        new LibrarySpecificUnit(secondSource, secondSource), RESOLVED_UNIT12);
+    CompilationUnit unit2 = outputs[RESOLVED_UNIT12];
 
     InterfaceType intType = context.typeProvider.intType;
 
@@ -4493,7 +4624,7 @@
     '''
     });
     List<dynamic> units =
-        computeLibraryResults(sources, RESOLVED_UNIT11).toList();
+        computeLibraryResults(sources, RESOLVED_UNIT12).toList();
     CompilationUnit unit0 = units[0];
     CompilationUnit unit1 = units[1];
     CompilationUnit unit2 = units[2];
@@ -4540,7 +4671,7 @@
     '''
     });
     List<dynamic> units =
-        computeLibraryResults(sources, RESOLVED_UNIT11).toList();
+        computeLibraryResults(sources, RESOLVED_UNIT12).toList();
     CompilationUnit unit0 = units[0];
     CompilationUnit unit2 = units[2];
 
@@ -4581,11 +4712,11 @@
           }
 ''');
     computeResult(
-        new LibrarySpecificUnit(firstSource, firstSource), RESOLVED_UNIT11);
-    CompilationUnit unit1 = outputs[RESOLVED_UNIT11];
+        new LibrarySpecificUnit(firstSource, firstSource), RESOLVED_UNIT12);
+    CompilationUnit unit1 = outputs[RESOLVED_UNIT12];
     computeResult(
-        new LibrarySpecificUnit(secondSource, secondSource), RESOLVED_UNIT11);
-    CompilationUnit unit2 = outputs[RESOLVED_UNIT11];
+        new LibrarySpecificUnit(secondSource, secondSource), RESOLVED_UNIT12);
+    CompilationUnit unit2 = outputs[RESOLVED_UNIT12];
 
     InterfaceType intType = context.typeProvider.intType;
     InterfaceType stringType = context.typeProvider.stringType;
@@ -4635,7 +4766,7 @@
     '''
     });
     List<dynamic> units =
-        computeLibraryResults(sources, RESOLVED_UNIT11).toList();
+        computeLibraryResults(sources, RESOLVED_UNIT12).toList();
     CompilationUnit unit0 = units[0];
     CompilationUnit unit1 = units[1];
     CompilationUnit unit2 = units[2];
@@ -4671,8 +4802,8 @@
         y = "hi";
       }
 ''');
-    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT11);
-    CompilationUnit unit = outputs[RESOLVED_UNIT11];
+    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT12);
+    CompilationUnit unit = outputs[RESOLVED_UNIT12];
 
     InterfaceType intType = context.typeProvider.intType;
     InterfaceType stringType = context.typeProvider.stringType;
@@ -4710,8 +4841,8 @@
         final z = 42; // should infer `int`
       }
 ''');
-    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT11);
-    CompilationUnit unit = outputs[RESOLVED_UNIT11];
+    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT12);
+    CompilationUnit unit = outputs[RESOLVED_UNIT12];
 
     InterfaceType intType = context.typeProvider.intType;
     InterfaceType stringType = context.typeProvider.stringType;
@@ -4759,8 +4890,8 @@
       int y = 0; // field def after use
       final z = 42; // should infer `int`
 ''');
-    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT11);
-    CompilationUnit unit = outputs[RESOLVED_UNIT11];
+    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT12);
+    CompilationUnit unit = outputs[RESOLVED_UNIT12];
 
     InterfaceType intType = context.typeProvider.intType;
     InterfaceType stringType = context.typeProvider.stringType;
@@ -4812,8 +4943,8 @@
         new A().y2 = /*severe:StaticTypeError*/"hi";
       }
 ''');
-    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT11);
-    CompilationUnit unit = outputs[RESOLVED_UNIT11];
+    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT12);
+    CompilationUnit unit = outputs[RESOLVED_UNIT12];
 
     InterfaceType intType = context.typeProvider.intType;
     InterfaceType stringType = context.typeProvider.stringType;
@@ -4854,8 +4985,8 @@
         x = "hi";
       }
 ''');
-    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT11);
-    CompilationUnit unit = outputs[RESOLVED_UNIT11];
+    computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT12);
+    CompilationUnit unit = outputs[RESOLVED_UNIT12];
 
     InterfaceType intType = context.typeProvider.intType;
     InterfaceType stringType = context.typeProvider.stringType;
diff --git a/pkg/analyzer/test/src/task/strong/checker_test.dart b/pkg/analyzer/test/src/task/strong/checker_test.dart
index 9a7b128..28ab23a 100644
--- a/pkg/analyzer/test/src/task/strong/checker_test.dart
+++ b/pkg/analyzer/test/src/task/strong/checker_test.dart
@@ -229,10 +229,8 @@
 
   test('dynamic invocation', () {
     checkFile('''
-      class A {
-        dynamic call(dynamic x) => x;
-      }
-      class B extends A {
+      typedef dynamic A(dynamic x);
+      class B {
         int call(int x) => x;
         double col(double x) => x;
       }
@@ -276,7 +274,6 @@
           /*info:DYNAMIC_INVOKE*/g.foo(42.0);
           /*info:DYNAMIC_INVOKE*/g./*info:UNDEFINED_GETTER*/x;
           A f = new B();
-          f.call(/*info:ARGUMENT_TYPE_NOT_ASSIGNABLE*/32.0);
           /*info:DYNAMIC_INVOKE*/f.col(42.0);
           /*info:DYNAMIC_INVOKE*/f.foo(42.0);
           /*info:DYNAMIC_INVOKE*/f./*warning:UNDEFINED_GETTER*/x;
@@ -2002,6 +1999,99 @@
        ''');
   });
 
+  test('method override, fuzzy arrows', () {
+    checkFile('''
+      abstract class A {
+        bool operator ==(Object object);
+      }
+
+      class B implements A {}
+
+
+      class F {
+        void f(x) {}
+        void g(int x) {}
+      }
+
+      class G extends F {
+        /*severe:INVALID_METHOD_OVERRIDE*/void f(int x) {}
+        void g(dynamic x) {}
+      }
+
+      class H implements F {
+        /*severe:INVALID_METHOD_OVERRIDE*/void f(int x) {}
+        void g(dynamic x) {}
+      }
+
+      ''');
+  });
+
+  test('getter override, fuzzy arrows', () {
+    checkFile('''
+      typedef void ToVoid<T>(T x);
+      class F {
+        ToVoid<dynamic> get f => null;
+        ToVoid<int> get g => null;
+      }
+
+      class G extends F {
+        ToVoid<int> get f => null;
+        /*severe:INVALID_METHOD_OVERRIDE*/ToVoid<dynamic> get g => null;
+      }
+
+      class H implements F {
+        ToVoid<int> get f => null;
+        /*severe:INVALID_METHOD_OVERRIDE*/ToVoid<dynamic> get g => null;
+      }
+       ''');
+  });
+
+  test('setter override, fuzzy arrows', () {
+    checkFile('''
+      typedef void ToVoid<T>(T x);
+      class F {
+        void set f(ToVoid<dynamic> x) {}
+        void set g(ToVoid<int> x) {} 
+        void set h(dynamic x) {}
+        void set i(int x) {}
+     }
+
+      class G extends F {
+        /*severe:INVALID_METHOD_OVERRIDE*/void set f(ToVoid<int> x) {}
+        void set g(ToVoid<dynamic> x) {}
+        void set h(int x) {}
+        /*severe:INVALID_METHOD_OVERRIDE*/void set i(dynamic x) {}
+      }
+
+      class H implements F {
+        /*severe:INVALID_METHOD_OVERRIDE*/void set f(ToVoid<int> x) {}
+        void set g(ToVoid<dynamic> x) {}
+        void set h(int x) {}
+        /*severe:INVALID_METHOD_OVERRIDE*/void set i(dynamic x) {}
+      }
+       ''');
+  });
+
+  test('field override, fuzzy arrows', () {
+    checkFile('''
+      typedef void ToVoid<T>(T x);
+      class F {
+        final ToVoid<dynamic> f = null;
+        final ToVoid<int> g = null;
+      }
+
+      class G extends F {
+        /*severe:INVALID_FIELD_OVERRIDE*/final ToVoid<int> f = null;
+        /*severe:INVALID_FIELD_OVERRIDE, severe:INVALID_METHOD_OVERRIDE*/final ToVoid<dynamic> g = null;
+      }
+
+      class H implements F {
+        final ToVoid<int> f = null;
+        /*severe:INVALID_METHOD_OVERRIDE*/final ToVoid<dynamic> g = null;
+      }
+       ''');
+  });
+
   test('generic class method override', () {
     checkFile('''
           class A {}
@@ -2631,7 +2721,7 @@
                 implements I1 {}
 
             class T2 extends Base implements I1 {
-                /*severe:INVALID_METHOD_OVERRIDE,severe:INVALID_METHOD_OVERRIDE*/m(a) {}
+                m(a) {}
             }
 
             class /*warning:INCONSISTENT_METHOD_INHERITANCE*/T3
@@ -2639,7 +2729,7 @@
                 implements I1 {}
 
             class T4 extends Object with Base implements I1 {
-                /*severe:INVALID_METHOD_OVERRIDE,severe:INVALID_METHOD_OVERRIDE*/m(a) {}
+                m(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 84052c4..d1ebb09 100644
--- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
+++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
@@ -20,6 +20,11 @@
 
 abstract class InferredTypeMixin {
   /**
+   * If `true` then types of local elements may be checked.
+   */
+  bool get mayCheckTypesOfLocals;
+
+  /**
    * Add a new file with the given [name] and [content].
    */
   void addFile(String content, {String name: '/main.dart'});
@@ -30,27 +35,10 @@
    */
   CompilationUnitElement checkFile(String content);
 
-  void test_blockBodiedLambdas_async_allReturnsAreValues() {
-    var mainUnit = checkFile(r'''
-import 'dart:async';
-import 'dart:math' show Random;
-main() {
-  var f = /*info:INFERRED_TYPE_CLOSURE*/() async {
-    if (new Random().nextBool()) {
-      return 1;
-    } else {
-      return 2.0;
+  void test_blockBodiedLambdas_async_allReturnsAreFutures() {
+    if (!mayCheckTypesOfLocals) {
+      return;
     }
-  };
-  Future<num> g = f();
-  Future<int> h = /*info:ASSIGNMENT_CAST*/f();
-}
-''');
-    var f = mainUnit.functions[0].localVariables[0];
-    expect(f.type.toString(), '() → Future<num>');
-  }
-
-  void test_blockBodiedLambdas_async_alReturnsAreFutures() {
     var mainUnit = checkFile(r'''
 import 'dart:async';
 import 'dart:math' show Random;
@@ -70,40 +58,130 @@
     expect(f.type.toString(), '() → Future<num>');
   }
 
-  void test_blockBodiedLambdas_async_mixOfValuesAndFutures() {
+  void test_blockBodiedLambdas_async_allReturnsAreFutures_topLevel() {
     var mainUnit = checkFile(r'''
-  import 'dart:async';
-  import 'dart:math' show Random;
-  main() {
-    var f = /*info:INFERRED_TYPE_CLOSURE*/() async {
-      if (new Random().nextBool()) {
-        return new Future<int>.value(1);
-      } else {
-        return 2.0;
-      }
-    };
-    Future<num> g = f();
-    Future<int> h = /*info:ASSIGNMENT_CAST*/f();
+import 'dart:async';
+import 'dart:math' show Random;
+var f = /*info:INFERRED_TYPE_CLOSURE*/() async {
+  if (new Random().nextBool()) {
+    return new Future<int>.value(1);
+  } else {
+    return new Future<double>.value(2.0);
   }
+};
+''');
+    var f = mainUnit.topLevelVariables[0];
+    expect(f.type.toString(), '() → Future<num>');
+  }
+
+  void test_blockBodiedLambdas_async_allReturnsAreValues() {
+    if (!mayCheckTypesOfLocals) {
+      return;
+    }
+    var mainUnit = checkFile(r'''
+import 'dart:async';
+import 'dart:math' show Random;
+main() {
+  var f = /*info:INFERRED_TYPE_CLOSURE*/() async {
+    if (new Random().nextBool()) {
+      return 1;
+    } else {
+      return 2.0;
+    }
+  };
+  Future<num> g = f();
+  Future<int> h = /*info:ASSIGNMENT_CAST*/f();
+}
 ''');
     var f = mainUnit.functions[0].localVariables[0];
     expect(f.type.toString(), '() → Future<num>');
   }
 
-  void test_blockBodiedLambdas_asyncStar() {
+  void test_blockBodiedLambdas_async_allReturnsAreValues_topLevel() {
     var mainUnit = checkFile(r'''
-  import 'dart:async';
-  main() {
-    var f = /*info:INFERRED_TYPE_CLOSURE*/() async* {
-      yield 1;
-      Stream<double> s;
-      yield* s;
-    };
-    Stream<num> g = f();
-    Stream<int> h = /*info:ASSIGNMENT_CAST*/f();
+import 'dart:async';
+import 'dart:math' show Random;
+var f = /*info:INFERRED_TYPE_CLOSURE*/() async {
+  if (new Random().nextBool()) {
+    return 1;
+  } else {
+    return 2.0;
   }
+};
+''');
+    var f = mainUnit.topLevelVariables[0];
+    expect(f.type.toString(), '() → Future<num>');
+  }
+
+  void test_blockBodiedLambdas_async_mixOfValuesAndFutures() {
+    if (!mayCheckTypesOfLocals) {
+      return;
+    }
+    var mainUnit = checkFile(r'''
+import 'dart:async';
+import 'dart:math' show Random;
+main() {
+  var f = /*info:INFERRED_TYPE_CLOSURE*/() async {
+    if (new Random().nextBool()) {
+      return new Future<int>.value(1);
+    } else {
+      return 2.0;
+    }
+  };
+  Future<num> g = f();
+  Future<int> h = /*info:ASSIGNMENT_CAST*/f();
+}
 ''');
     var f = mainUnit.functions[0].localVariables[0];
+    expect(f.type.toString(), '() → Future<num>');
+  }
+
+  void test_blockBodiedLambdas_async_mixOfValuesAndFutures_topLevel() {
+    var mainUnit = checkFile(r'''
+import 'dart:async';
+import 'dart:math' show Random;
+var f = /*info:INFERRED_TYPE_CLOSURE*/() async {
+  if (new Random().nextBool()) {
+    return new Future<int>.value(1);
+  } else {
+    return 2.0;
+  }
+};
+''');
+    var f = mainUnit.topLevelVariables[0];
+    expect(f.type.toString(), '() → Future<num>');
+  }
+
+  void test_blockBodiedLambdas_asyncStar() {
+    if (!mayCheckTypesOfLocals) {
+      return;
+    }
+    var mainUnit = checkFile(r'''
+import 'dart:async';
+main() {
+  var f = /*info:INFERRED_TYPE_CLOSURE*/() async* {
+    yield 1;
+    Stream<double> s;
+    yield* s;
+  };
+  Stream<num> g = f();
+  Stream<int> h = /*info:ASSIGNMENT_CAST*/f();
+}
+''');
+    var f = mainUnit.functions[0].localVariables[0];
+    expect(f.type.toString(), '() → Stream<num>');
+  }
+
+  void test_blockBodiedLambdas_asyncStar_topLevel() {
+    var mainUnit = checkFile(r'''
+  import 'dart:async';
+var f = /*info:INFERRED_TYPE_CLOSURE*/() async* {
+  yield 1;
+  Stream<double> s;
+  yield* s;
+};
+''');
+    var f = mainUnit.topLevelVariables[0];
     expect(f.type.toString(), '() → Stream<num>');
   }
 
@@ -126,6 +204,9 @@
   }
 
   void test_blockBodiedLambdas_doesNotInferBottom_async() {
+    if (!mayCheckTypesOfLocals) {
+      return;
+    }
     var mainUnit = checkFile(r'''
 import 'dart:async';
 main() async {
@@ -135,12 +216,23 @@
   String s = /*info:DYNAMIC_CAST*/await f();
 }
 ''');
-
     var f = mainUnit.functions[0].localVariables[0];
     expect(f.type.toString(), '() → Future<dynamic>');
   }
 
+  void test_blockBodiedLambdas_doesNotInferBottom_async_topLevel() {
+    var mainUnit = checkFile(r'''
+import 'dart:async';
+var f = () async { return null; };
+''');
+    var f = mainUnit.topLevelVariables[0];
+    expect(f.type.toString(), '() → Future<dynamic>');
+  }
+
   void test_blockBodiedLambdas_doesNotInferBottom_asyncStar() {
+    if (!mayCheckTypesOfLocals) {
+      return;
+    }
     var mainUnit = checkFile(r'''
 import 'dart:async';
 main() async {
@@ -150,12 +242,23 @@
   String s = /*info:DYNAMIC_CAST*/await f().first;
 }
 ''');
-
     var f = mainUnit.functions[0].localVariables[0];
     expect(f.type.toString(), '() → Stream<dynamic>');
   }
 
+  void test_blockBodiedLambdas_doesNotInferBottom_asyncStar_topLevel() {
+    var mainUnit = checkFile(r'''
+import 'dart:async';
+var f = () async* { yield null; };
+''');
+    var f = mainUnit.topLevelVariables[0];
+    expect(f.type.toString(), '() → Stream<dynamic>');
+  }
+
   void test_blockBodiedLambdas_doesNotInferBottom_sync() {
+    if (!mayCheckTypesOfLocals) {
+      return;
+    }
     var mainUnit = checkFile(r'''
 var h = null;
 void foo(int f(Object _)) {}
@@ -175,7 +278,18 @@
     expect(f.type.toString(), '(Object) → dynamic');
   }
 
+  void test_blockBodiedLambdas_doesNotInferBottom_sync_topLevel() {
+    var mainUnit = checkFile(r'''
+var f = (Object x) { return null; };
+''');
+    var f = mainUnit.topLevelVariables[0];
+    expect(f.type.toString(), '(Object) → dynamic');
+  }
+
   void test_blockBodiedLambdas_doesNotInferBottom_syncStar() {
+    if (!mayCheckTypesOfLocals) {
+      return;
+    }
     var mainUnit = checkFile(r'''
 main() {
   var f = () sync* { yield null; };
@@ -184,12 +298,22 @@
   String s = /*info:DYNAMIC_CAST*/f().first;
 }
 ''');
-
     var f = mainUnit.functions[0].localVariables[0];
     expect(f.type.toString(), '() → Iterable<dynamic>');
   }
 
+  void test_blockBodiedLambdas_doesNotInferBottom_syncStar_topLevel() {
+    var mainUnit = checkFile(r'''
+var f = () sync* { yield null; };
+''');
+    var f = mainUnit.topLevelVariables[0];
+    expect(f.type.toString(), '() → Iterable<dynamic>');
+  }
+
   void test_blockBodiedLambdas_downwardsIncompatibleWithUpwardsInference() {
+    if (!mayCheckTypesOfLocals) {
+      return;
+    }
     var mainUnit = checkFile(r'''
 main() {
   String f() => null;
@@ -201,6 +325,16 @@
     expect(f.type.toString(), '() → String');
   }
 
+  void
+      test_blockBodiedLambdas_downwardsIncompatibleWithUpwardsInference_topLevel() {
+    var mainUnit = checkFile(r'''
+String f() => null;
+var g = f;
+''');
+    var f = mainUnit.topLevelVariables[0];
+    expect(f.type.toString(), '() → String');
+  }
+
   void test_blockBodiedLambdas_LUB() {
     checkFile(r'''
 import 'dart:math' show Random;
@@ -236,6 +370,9 @@
   }
 
   void test_blockBodiedLambdas_nestedLambdas() {
+    if (!mayCheckTypesOfLocals) {
+      return;
+    }
     // Original feature request: https://github.com/dart-lang/sdk/issues/25487
     var mainUnit = checkFile(r'''
 main() {
@@ -248,7 +385,21 @@
     expect(f.type.toString(), '() → (int) → num');
   }
 
+  void test_blockBodiedLambdas_nestedLambdas_topLevel() {
+    // Original feature request: https://github.com/dart-lang/sdk/issues/25487
+    var mainUnit = checkFile(r'''
+var f = /*info:INFERRED_TYPE_CLOSURE*/() {
+  return /*info:INFERRED_TYPE_CLOSURE*/(int x) { return 2.0 * x; };
+};
+''');
+    var f = mainUnit.topLevelVariables[0];
+    expect(f.type.toString(), '() → (int) → num');
+  }
+
   void test_blockBodiedLambdas_noReturn() {
+    if (!mayCheckTypesOfLocals) {
+      return;
+    }
     var mainUnit = checkFile(r'''
 test1() {
   List<int> o;
@@ -260,7 +411,19 @@
     expect(f.type.toString(), 'Iterable<dynamic>');
   }
 
+  void test_blockBodiedLambdas_noReturn_topLevel() {
+    var mainUnit = checkFile(r'''
+final List<int> o = <int>[];
+var y = o.map((x) { });
+''');
+    var f = mainUnit.topLevelVariables[1];
+    expect(f.type.toString(), 'Iterable<dynamic>');
+  }
+
   void test_blockBodiedLambdas_syncStar() {
+    if (!mayCheckTypesOfLocals) {
+      return;
+    }
     var mainUnit = checkFile(r'''
 main() {
   var f = /*info:INFERRED_TYPE_CLOSURE*/() sync* {
@@ -275,6 +438,17 @@
     expect(f.type.toString(), '() → Iterable<num>');
   }
 
+  void test_blockBodiedLambdas_syncStar_topLevel() {
+    var mainUnit = checkFile(r'''
+var f = /*info:INFERRED_TYPE_CLOSURE*/() sync* {
+  yield 1;
+  yield* /*info:INFERRED_TYPE_LITERAL*/[3, 4.0];
+};
+''');
+    var f = mainUnit.topLevelVariables[0];
+    expect(f.type.toString(), '() → Iterable<num>');
+  }
+
   void test_canInferAlsoFromStaticAndInstanceFieldsFlagOn() {
     addFile(
         '''
@@ -1072,6 +1246,17 @@
   ''');
   }
 
+  void test_fieldRefersToStaticGetter() {
+    var mainUnit = checkFile('''
+class C {
+  final x = _x;
+  static int get _x => null;
+}
+''');
+    var x = mainUnit.types[0].fields[0];
+    expect(x.type.toString(), 'int');
+  }
+
   void test_genericMethods_basicDownwardInference() {
     checkFile(r'''
 /*=T*/ f/*<S, T>*/(/*=S*/ s) => null;
@@ -1086,7 +1271,7 @@
     // Regression test for https://github.com/dart-lang/sdk/issues/25740.
     checkFile(r'''
 class Foo<T extends Pattern> {
-void method/*<U extends T>*/(dynamic/*=U*/ u) {}
+  void method/*<U extends T>*/(dynamic/*=U*/ u) {}
 }
 main() {
   new Foo().method/*<String>*/("str");
@@ -1185,9 +1370,11 @@
     checkFile('''
 class C {
   m(x) => x;
+  dynamic g(int x) => x;
 }
 class D extends C {
   /*=T*/ m/*<T>*/(/*=T*/ x) => x;
+  /*=T*/ g/*<T>*/(/*=T*/ x) => x;
 }
 main() {
   int y = /*info:DYNAMIC_CAST*/(new D() as C).m(42);
@@ -2437,6 +2624,58 @@
 ''');
   }
 
+  void test_instantiateToBounds_generic2_hasBound_definedAfter() {
+    var unit = checkFile(r'''
+class B<T extends A> {}
+class A<T extends int> {}
+B v = null;
+''');
+    expect(unit.topLevelVariables[0].type.toString(), 'B<A<dynamic>>');
+  }
+
+  void test_instantiateToBounds_generic2_hasBound_definedBefore() {
+    var unit = checkFile(r'''
+class A<T extends int> {}
+class B<T extends A> {}
+B v = null;
+''');
+    expect(unit.topLevelVariables[0].type.toString(), 'B<A<dynamic>>');
+  }
+
+  void test_instantiateToBounds_generic2_noBound() {
+    var unit = checkFile(r'''
+class A<T> {}
+class B<T extends A> {}
+B v = null;
+''');
+    expect(unit.topLevelVariables[0].type.toString(), 'B<A<dynamic>>');
+  }
+
+  void test_instantiateToBounds_generic_hasBound_definedAfter() {
+    var unit = checkFile(r'''
+A v = null;
+class A<T extends int> {}
+''');
+    expect(unit.topLevelVariables[0].type.toString(), 'A<int>');
+  }
+
+  void test_instantiateToBounds_generic_hasBound_definedBefore() {
+    var unit = checkFile(r'''
+class A<T extends int> {}
+A v = null;
+''');
+    expect(unit.topLevelVariables[0].type.toString(), 'A<int>');
+  }
+
+  void test_instantiateToBounds_notGeneric() {
+    var unit = checkFile(r'''
+class A {}
+class B<T extends A> {}
+B v = null;
+''');
+    expect(unit.topLevelVariables[0].type.toString(), 'B<A>');
+  }
+
   void test_listLiterals() {
     checkFile(r'''
 test1() {
@@ -2474,6 +2713,9 @@
   }
 
   void test_listLiteralsShouldNotInferBottom() {
+    if (!mayCheckTypesOfLocals) {
+      return;
+    }
     var unit = checkFile(r'''
 test1() {
   var x = [null];
@@ -2484,6 +2726,14 @@
     expect(x.type.toString(), 'List<dynamic>');
   }
 
+  void test_listLiteralsShouldNotInferBottom_topLevel() {
+    var unit = checkFile(r'''
+var x = [null];
+''');
+    var x = unit.topLevelVariables[0];
+    expect(x.type.toString(), 'List<dynamic>');
+  }
+
   void test_mapLiterals() {
     checkFile(r'''
 test1() {
@@ -2533,6 +2783,9 @@
   }
 
   void test_mapLiteralsShouldNotInferBottom() {
+    if (!mayCheckTypesOfLocals) {
+      return;
+    }
     var unit = checkFile(r'''
 test1() {
   var x = { null: null };
@@ -2543,6 +2796,14 @@
     expect(x.type.toString(), 'Map<dynamic, dynamic>');
   }
 
+  void test_mapLiteralsShouldNotInferBottom_topLevel() {
+    var unit = checkFile(r'''
+var x = { null: null };
+''');
+    var x = unit.topLevelVariables[0];
+    expect(x.type.toString(), 'Map<dynamic, dynamic>');
+  }
+
   void test_noErrorWhenDeclaredTypeIsNumAndAssignedNull() {
     checkFile('''
 test1() {
@@ -2651,7 +2912,7 @@
 ''');
   }
 
-  void test_staticRefersToNonstaticField_inOtherLibraryCycle() {
+  void test_staticRefersToNonStaticField_inOtherLibraryCycle() {
     addFile(
         '''
 import 'b.dart';
@@ -2705,6 +2966,9 @@
 
 @reflectiveTest
 class InferredTypeTest extends InferredTypeMixin {
+  @override
+  bool get mayCheckTypesOfLocals => true;
+
   /// Adds a file to check. The file should contain:
   ///
   ///   * all expected failures are listed in the source code using comments
diff --git a/pkg/analyzer/tool/summary/dump_inferred_types.dart b/pkg/analyzer/tool/summary/dump_inferred_types.dart
index 0668513..8b38e73 100644
--- a/pkg/analyzer/tool/summary/dump_inferred_types.dart
+++ b/pkg/analyzer/tool/summary/dump_inferred_types.dart
@@ -57,6 +57,10 @@
       SummaryClass obj, Map<String, Object> properties, String path) {
     if (obj is UnlinkedVariable) {
       collectInferredType(obj.inferredTypeSlot, path);
+      // As a temporary measure, prevent recursion into the variable's
+      // initializer, since AST-based type inference doesn't infer its type
+      // correctly yet.  TODO(paulberry): fix.
+      properties.remove('initializer');
     } else if (obj is UnlinkedExecutable) {
       collectInferredType(obj.inferredReturnTypeSlot, path);
     } else if (obj is UnlinkedParam) {
@@ -246,16 +250,22 @@
       }
       Uri libraryUri = Uri.parse(libraryUriString);
       UnlinkedUnit definingUnlinkedUnit = unlinkedUnits[libraryUriString];
-      visitUnit(definingUnlinkedUnit, linkedLibrary.units[0], libraryUriString);
-      for (int i = 0;
-          i < definingUnlinkedUnit.publicNamespace.parts.length;
-          i++) {
-        Uri relativePartUri =
-            Uri.parse(definingUnlinkedUnit.publicNamespace.parts[i]);
-        String unitUriString =
-            resolveRelativeUri(libraryUri, relativePartUri).toString();
-        visitUnit(unlinkedUnits[unitUriString], linkedLibrary.units[i + 1],
-            libraryUriString);
+      if (definingUnlinkedUnit != null) {
+        visitUnit(
+            definingUnlinkedUnit, linkedLibrary.units[0], libraryUriString);
+        for (int i = 0;
+            i < definingUnlinkedUnit.publicNamespace.parts.length;
+            i++) {
+          Uri relativePartUri =
+              Uri.parse(definingUnlinkedUnit.publicNamespace.parts[i]);
+          String unitUriString =
+              resolveRelativeUri(libraryUri, relativePartUri).toString();
+          UnlinkedUnit unlinkedUnit = unlinkedUnits[unitUriString];
+          if (unlinkedUnit != null) {
+            visitUnit(
+                unlinkedUnit, linkedLibrary.units[i + 1], libraryUriString);
+          }
+        }
       }
     });
   }
diff --git a/pkg/analyzer/tool/task_dependency_graph/tasks.dot b/pkg/analyzer/tool/task_dependency_graph/tasks.dot
index 75e8989..212dc2b 100644
--- a/pkg/analyzer/tool/task_dependency_graph/tasks.dot
+++ b/pkg/analyzer/tool/task_dependency_graph/tasks.dot
@@ -47,23 +47,24 @@
   CREATED_RESOLVED_UNIT [shape=box]
   CREATED_RESOLVED_UNIT1 [shape=box]
   CREATED_RESOLVED_UNIT10 -> InferInstanceMembersInUnitTask
-  CREATED_RESOLVED_UNIT10 -> InferStaticVariableTypeTask
-  CREATED_RESOLVED_UNIT10 -> PartiallyResolveUnitReferencesTask
-  CREATED_RESOLVED_UNIT10 -> ResolveInstanceFieldsInUnitTask
-  CREATED_RESOLVED_UNIT10 -> ResolveUnitTask
   CREATED_RESOLVED_UNIT10 [shape=box]
-  CREATED_RESOLVED_UNIT11 -> ResolveConstantExpressionTask
+  CREATED_RESOLVED_UNIT11 -> InferInstanceMembersInUnitTask
+  CREATED_RESOLVED_UNIT11 -> InferStaticVariableTypeTask
+  CREATED_RESOLVED_UNIT11 -> PartiallyResolveUnitReferencesTask
+  CREATED_RESOLVED_UNIT11 -> ResolveInstanceFieldsInUnitTask
+  CREATED_RESOLVED_UNIT11 -> ResolveUnitTask
   CREATED_RESOLVED_UNIT11 [shape=box]
+  CREATED_RESOLVED_UNIT12 -> ResolveConstantExpressionTask
   CREATED_RESOLVED_UNIT12 [shape=box]
+  CREATED_RESOLVED_UNIT13 [shape=box]
   CREATED_RESOLVED_UNIT2 [shape=box]
   CREATED_RESOLVED_UNIT3 [shape=box]
   CREATED_RESOLVED_UNIT4 [shape=box]
   CREATED_RESOLVED_UNIT5 [shape=box]
   CREATED_RESOLVED_UNIT6 [shape=box]
   CREATED_RESOLVED_UNIT7 [shape=box]
-  CREATED_RESOLVED_UNIT8 -> ResolveInstanceFieldsInUnitTask
   CREATED_RESOLVED_UNIT8 [shape=box]
-  CREATED_RESOLVED_UNIT9 -> InferInstanceMembersInUnitTask
+  CREATED_RESOLVED_UNIT9 -> ResolveInstanceFieldsInUnitTask
   CREATED_RESOLVED_UNIT9 [shape=box]
   ComputeConstantDependenciesTask -> CONSTANT_DEPENDENCIES
   ComputeConstantValueTask -> CONSTANT_VALUE
@@ -83,11 +84,12 @@
   EXPORTED_LIBRARIES -> ReadyLibraryElement2Task
   EXPORTED_LIBRARIES -> ReadyLibraryElement5Task
   EXPORTED_LIBRARIES -> ReadyLibraryElement6Task
+  EXPORTED_LIBRARIES -> ResolveTopLevelLibraryTypeBoundsTask
   EXPORTED_LIBRARIES [shape=box]
   EXPORT_SOURCE_CLOSURE -> BuildExportNamespaceTask
   EXPORT_SOURCE_CLOSURE [shape=box]
-  EvaluateUnitConstantsTask -> CREATED_RESOLVED_UNIT12
-  EvaluateUnitConstantsTask -> RESOLVED_UNIT12
+  EvaluateUnitConstantsTask -> CREATED_RESOLVED_UNIT13
+  EvaluateUnitConstantsTask -> RESOLVED_UNIT13
   GatherUsedImportedElementsTask -> USED_IMPORTED_ELEMENTS
   GatherUsedLocalElementsTask -> USED_LOCAL_ELEMENTS
   GenerateHintsTask -> HINTS
@@ -98,7 +100,8 @@
   IMPORTED_LIBRARIES -> ReadyLibraryElement2Task
   IMPORTED_LIBRARIES -> ReadyLibraryElement5Task
   IMPORTED_LIBRARIES -> ReadyLibraryElement6Task
-  IMPORTED_LIBRARIES -> ResolveUnitTypeNamesTask
+  IMPORTED_LIBRARIES -> ResolveTopLevelLibraryTypeBoundsTask
+  IMPORTED_LIBRARIES -> ResolveTopLevelUnitTypeBoundsTask
   IMPORTED_LIBRARIES [shape=box]
   INCLUDED_PARTS -> BuildLibraryElementTask
   INCLUDED_PARTS [shape=box]
@@ -110,11 +113,11 @@
   INFERRED_STATIC_VARIABLE -> InferStaticVariableTypesInUnitTask
   INFERRED_STATIC_VARIABLE [shape=box]
   IS_LAUNCHABLE [shape=box]
-  InferInstanceMembersInUnitTask -> CREATED_RESOLVED_UNIT10
-  InferInstanceMembersInUnitTask -> RESOLVED_UNIT10
+  InferInstanceMembersInUnitTask -> CREATED_RESOLVED_UNIT11
+  InferInstanceMembersInUnitTask -> RESOLVED_UNIT11
   InferStaticVariableTypeTask -> INFERRED_STATIC_VARIABLE
-  InferStaticVariableTypesInUnitTask -> CREATED_RESOLVED_UNIT8
-  InferStaticVariableTypesInUnitTask -> RESOLVED_UNIT8
+  InferStaticVariableTypesInUnitTask -> CREATED_RESOLVED_UNIT9
+  InferStaticVariableTypesInUnitTask -> RESOLVED_UNIT9
   LIBRARY_CYCLE [shape=box]
   LIBRARY_CYCLE_DEPENDENCIES -> InferInstanceMembersInUnitTask
   LIBRARY_CYCLE_DEPENDENCIES -> InferStaticVariableTypeTask
@@ -139,29 +142,34 @@
   LIBRARY_ELEMENT3 -> BuildExportNamespaceTask
   LIBRARY_ELEMENT3 -> BuildTypeProviderTask
   LIBRARY_ELEMENT3 [shape=box]
-  LIBRARY_ELEMENT4 -> ResolveLibraryTypeNamesTask
-  LIBRARY_ELEMENT4 -> ResolveUnitTypeNamesTask
+  LIBRARY_ELEMENT4 -> ResolveTopLevelLibraryTypeBoundsTask
+  LIBRARY_ELEMENT4 -> ResolveTopLevelUnitTypeBoundsTask
   LIBRARY_ELEMENT4 [shape=box]
-  LIBRARY_ELEMENT5 -> PartiallyResolveUnitReferencesTask
-  LIBRARY_ELEMENT5 -> PropagateVariableTypesInLibraryTask
-  LIBRARY_ELEMENT5 -> ReadyLibraryElement5Task
-  LIBRARY_ELEMENT5 -> ResolveInstanceFieldsInUnitTask
+  LIBRARY_ELEMENT5 -> ResolveLibraryTypeNamesTask
+  LIBRARY_ELEMENT5 -> ResolveTopLevelLibraryTypeBoundsTask
+  LIBRARY_ELEMENT5 -> ResolveUnitTypeNamesTask
   LIBRARY_ELEMENT5 [shape=box]
-  LIBRARY_ELEMENT6 -> PropagateVariableTypesInLibraryClosureTask
-  LIBRARY_ELEMENT6 -> ReadyLibraryElement6Task
+  LIBRARY_ELEMENT6 -> PartiallyResolveUnitReferencesTask
+  LIBRARY_ELEMENT6 -> PropagateVariableTypesInLibraryTask
+  LIBRARY_ELEMENT6 -> ReadyLibraryElement5Task
+  LIBRARY_ELEMENT6 -> ResolveInstanceFieldsInUnitTask
   LIBRARY_ELEMENT6 [shape=box]
-  LIBRARY_ELEMENT7 -> ResolveLibraryReferencesTask
-  LIBRARY_ELEMENT7 -> ResolveUnitTask
+  LIBRARY_ELEMENT7 -> PropagateVariableTypesInLibraryClosureTask
+  LIBRARY_ELEMENT7 -> ReadyLibraryElement6Task
   LIBRARY_ELEMENT7 [shape=box]
-  LIBRARY_ELEMENT8 -> EvaluateUnitConstantsTask
-  LIBRARY_ELEMENT8 -> ResolveLibraryTask
+  LIBRARY_ELEMENT8 -> ResolveLibraryReferencesTask
+  LIBRARY_ELEMENT8 -> ResolveUnitTask
   LIBRARY_ELEMENT8 [shape=box]
+  LIBRARY_ELEMENT9 -> EvaluateUnitConstantsTask
+  LIBRARY_ELEMENT9 -> ResolveLibraryTask
+  LIBRARY_ELEMENT9 [shape=box]
   LIBRARY_ERRORS_READY [shape=box]
   LIBRARY_SPECIFIC_UNITS -> GenerateHintsTask
   LIBRARY_SPECIFIC_UNITS -> PropagateVariableTypesInLibraryTask
   LIBRARY_SPECIFIC_UNITS -> ReadyResolvedUnitTask
   LIBRARY_SPECIFIC_UNITS -> ResolveLibraryReferencesTask
   LIBRARY_SPECIFIC_UNITS -> ResolveLibraryTypeNamesTask
+  LIBRARY_SPECIFIC_UNITS -> ResolveTopLevelLibraryTypeBoundsTask
   LIBRARY_SPECIFIC_UNITS [shape=box]
   LIBRARY_UNIT_ERRORS -> dartErrorsForUnit
   LIBRARY_UNIT_ERRORS [shape=box]
@@ -199,24 +207,24 @@
   ParseDartTask -> REFERENCED_SOURCES
   ParseDartTask -> SOURCE_KIND
   ParseDartTask -> UNITS
-  PartiallyResolveUnitReferencesTask -> CREATED_RESOLVED_UNIT6
+  PartiallyResolveUnitReferencesTask -> CREATED_RESOLVED_UNIT7
   PartiallyResolveUnitReferencesTask -> INFERABLE_STATIC_VARIABLES_IN_UNIT
   PartiallyResolveUnitReferencesTask -> PROPAGABLE_VARIABLES_IN_UNIT
-  PartiallyResolveUnitReferencesTask -> RESOLVED_UNIT6
+  PartiallyResolveUnitReferencesTask -> RESOLVED_UNIT7
   PropagateVariableTypeTask -> PROPAGATED_VARIABLE
-  PropagateVariableTypesInLibraryClosureTask -> LIBRARY_ELEMENT7
-  PropagateVariableTypesInLibraryTask -> LIBRARY_ELEMENT6
-  PropagateVariableTypesInUnitTask -> CREATED_RESOLVED_UNIT7
-  PropagateVariableTypesInUnitTask -> RESOLVED_UNIT7
+  PropagateVariableTypesInLibraryClosureTask -> LIBRARY_ELEMENT8
+  PropagateVariableTypesInLibraryTask -> LIBRARY_ELEMENT7
+  PropagateVariableTypesInUnitTask -> CREATED_RESOLVED_UNIT8
+  PropagateVariableTypesInUnitTask -> RESOLVED_UNIT8
   READY_LIBRARY_ELEMENT2 -> ComputeLibraryCycleTask
   READY_LIBRARY_ELEMENT2 -> ReadyLibraryElement2Task
   READY_LIBRARY_ELEMENT2 [shape=box]
-  READY_LIBRARY_ELEMENT5 -> PartiallyResolveUnitReferencesTask
-  READY_LIBRARY_ELEMENT5 -> ReadyLibraryElement5Task
-  READY_LIBRARY_ELEMENT5 [shape=box]
-  READY_LIBRARY_ELEMENT6 -> PropagateVariableTypesInLibraryClosureTask
-  READY_LIBRARY_ELEMENT6 -> ReadyLibraryElement6Task
+  READY_LIBRARY_ELEMENT6 -> PartiallyResolveUnitReferencesTask
+  READY_LIBRARY_ELEMENT6 -> ReadyLibraryElement5Task
   READY_LIBRARY_ELEMENT6 [shape=box]
+  READY_LIBRARY_ELEMENT7 -> PropagateVariableTypesInLibraryClosureTask
+  READY_LIBRARY_ELEMENT7 -> ReadyLibraryElement6Task
+  READY_LIBRARY_ELEMENT7 [shape=box]
   READY_RESOLVED_UNIT -> ResolveLibraryTask
   READY_RESOLVED_UNIT -> VerifyUnitTask
   READY_RESOLVED_UNIT [shape=box]
@@ -233,63 +241,72 @@
   RESOLVED_UNIT1 -> BuildLibraryElementTask
   RESOLVED_UNIT1 -> ResolveDirectiveElementsTask
   RESOLVED_UNIT1 [shape=box]
-  RESOLVED_UNIT10 -> ResolveUnitTask
+  RESOLVED_UNIT10 -> InferInstanceMembersInUnitTask
   RESOLVED_UNIT10 [shape=box]
-  RESOLVED_UNIT11 -> EvaluateUnitConstantsTask
-  RESOLVED_UNIT11 -> GatherUsedImportedElementsTask
-  RESOLVED_UNIT11 -> GatherUsedLocalElementsTask
-  RESOLVED_UNIT11 -> ResolveLibraryReferencesTask
+  RESOLVED_UNIT11 -> ResolveUnitTask
   RESOLVED_UNIT11 [shape=box]
-  RESOLVED_UNIT12 -> StrongModeVerifyUnitTask
+  RESOLVED_UNIT12 -> EvaluateUnitConstantsTask
+  RESOLVED_UNIT12 -> GatherUsedImportedElementsTask
+  RESOLVED_UNIT12 -> GatherUsedLocalElementsTask
+  RESOLVED_UNIT12 -> ResolveLibraryReferencesTask
   RESOLVED_UNIT12 [shape=box]
+  RESOLVED_UNIT13 -> StrongModeVerifyUnitTask
+  RESOLVED_UNIT13 [shape=box]
   RESOLVED_UNIT2 -> BuildEnumMemberElementsTask
   RESOLVED_UNIT2 [shape=box]
-  RESOLVED_UNIT3 -> ResolveUnitTypeNamesTask
+  RESOLVED_UNIT3 -> ResolveTopLevelUnitTypeBoundsTask
   RESOLVED_UNIT3 [shape=box]
-  RESOLVED_UNIT4 -> ResolveLibraryTypeNamesTask
-  RESOLVED_UNIT4 -> ResolveVariableReferencesTask
+  RESOLVED_UNIT4 -> ResolveTopLevelLibraryTypeBoundsTask
+  RESOLVED_UNIT4 -> ResolveUnitTypeNamesTask
   RESOLVED_UNIT4 [shape=box]
-  RESOLVED_UNIT5 -> PartiallyResolveUnitReferencesTask
+  RESOLVED_UNIT5 -> ResolveLibraryTypeNamesTask
+  RESOLVED_UNIT5 -> ResolveVariableReferencesTask
   RESOLVED_UNIT5 [shape=box]
-  RESOLVED_UNIT6 -> ComputeInferableStaticVariableDependenciesTask
-  RESOLVED_UNIT6 -> ComputePropagableVariableDependenciesTask
-  RESOLVED_UNIT6 -> PropagateVariableTypeTask
-  RESOLVED_UNIT6 -> PropagateVariableTypesInUnitTask
+  RESOLVED_UNIT6 -> PartiallyResolveUnitReferencesTask
   RESOLVED_UNIT6 [shape=box]
-  RESOLVED_UNIT7 -> InferStaticVariableTypeTask
-  RESOLVED_UNIT7 -> InferStaticVariableTypesInUnitTask
-  RESOLVED_UNIT7 -> PropagateVariableTypesInLibraryTask
+  RESOLVED_UNIT7 -> ComputeInferableStaticVariableDependenciesTask
+  RESOLVED_UNIT7 -> ComputePropagableVariableDependenciesTask
+  RESOLVED_UNIT7 -> PropagateVariableTypeTask
+  RESOLVED_UNIT7 -> PropagateVariableTypesInUnitTask
   RESOLVED_UNIT7 [shape=box]
-  RESOLVED_UNIT8 -> ResolveInstanceFieldsInUnitTask
+  RESOLVED_UNIT8 -> InferStaticVariableTypeTask
+  RESOLVED_UNIT8 -> InferStaticVariableTypesInUnitTask
+  RESOLVED_UNIT8 -> PropagateVariableTypesInLibraryTask
   RESOLVED_UNIT8 [shape=box]
-  RESOLVED_UNIT9 -> InferInstanceMembersInUnitTask
+  RESOLVED_UNIT9 -> ResolveInstanceFieldsInUnitTask
   RESOLVED_UNIT9 [shape=box]
+  RESOLVE_TYPE_BOUNDS_ERRORS -> LibraryUnitErrorsTask
+  RESOLVE_TYPE_BOUNDS_ERRORS [shape=box]
   RESOLVE_TYPE_NAMES_ERRORS -> LibraryUnitErrorsTask
   RESOLVE_TYPE_NAMES_ERRORS [shape=box]
   RESOLVE_UNIT_ERRORS -> LibraryUnitErrorsTask
   RESOLVE_UNIT_ERRORS [shape=box]
   ReadyLibraryElement2Task -> READY_LIBRARY_ELEMENT2
-  ReadyLibraryElement5Task -> READY_LIBRARY_ELEMENT5
-  ReadyLibraryElement6Task -> READY_LIBRARY_ELEMENT6
+  ReadyLibraryElement5Task -> READY_LIBRARY_ELEMENT6
+  ReadyLibraryElement6Task -> READY_LIBRARY_ELEMENT7
   ReadyResolvedUnitTask -> READY_RESOLVED_UNIT
   ResolveConstantExpressionTask -> CONSTANT_EXPRESSION_RESOLVED
   ResolveDirectiveElementsTask -> CREATED_RESOLVED_UNIT2
   ResolveDirectiveElementsTask -> RESOLVED_UNIT2
-  ResolveInstanceFieldsInUnitTask -> CREATED_RESOLVED_UNIT9
-  ResolveInstanceFieldsInUnitTask -> RESOLVED_UNIT9
-  ResolveLibraryReferencesTask -> LIBRARY_ELEMENT8
+  ResolveInstanceFieldsInUnitTask -> CREATED_RESOLVED_UNIT10
+  ResolveInstanceFieldsInUnitTask -> RESOLVED_UNIT10
+  ResolveLibraryReferencesTask -> LIBRARY_ELEMENT9
   ResolveLibraryReferencesTask -> REFERENCED_NAMES
   ResolveLibraryTask -> LIBRARY_ELEMENT
-  ResolveLibraryTypeNamesTask -> LIBRARY_ELEMENT5
+  ResolveLibraryTypeNamesTask -> LIBRARY_ELEMENT6
+  ResolveTopLevelLibraryTypeBoundsTask -> LIBRARY_ELEMENT5
+  ResolveTopLevelUnitTypeBoundsTask -> CREATED_RESOLVED_UNIT4
+  ResolveTopLevelUnitTypeBoundsTask -> RESOLVED_UNIT4
+  ResolveTopLevelUnitTypeBoundsTask -> RESOLVE_TYPE_BOUNDS_ERRORS
   ResolveUnitTask -> CONSTANT_EXPRESSIONS_DEPENDENCIES
-  ResolveUnitTask -> CREATED_RESOLVED_UNIT11
-  ResolveUnitTask -> RESOLVED_UNIT11
+  ResolveUnitTask -> CREATED_RESOLVED_UNIT12
+  ResolveUnitTask -> RESOLVED_UNIT12
   ResolveUnitTask -> RESOLVE_UNIT_ERRORS
-  ResolveUnitTypeNamesTask -> CREATED_RESOLVED_UNIT4
-  ResolveUnitTypeNamesTask -> RESOLVED_UNIT4
+  ResolveUnitTypeNamesTask -> CREATED_RESOLVED_UNIT5
+  ResolveUnitTypeNamesTask -> RESOLVED_UNIT5
   ResolveUnitTypeNamesTask -> RESOLVE_TYPE_NAMES_ERRORS
-  ResolveVariableReferencesTask -> CREATED_RESOLVED_UNIT5
-  ResolveVariableReferencesTask -> RESOLVED_UNIT5
+  ResolveVariableReferencesTask -> CREATED_RESOLVED_UNIT6
+  ResolveVariableReferencesTask -> RESOLVED_UNIT6
   ResolveVariableReferencesTask -> VARIABLE_REFERENCE_ERRORS
   SCAN_ERRORS -> dartErrorsForSource
   SCAN_ERRORS [shape=box]
@@ -315,6 +332,7 @@
   TYPE_PROVIDER -> PropagateVariableTypeTask
   TYPE_PROVIDER -> ResolveInstanceFieldsInUnitTask
   TYPE_PROVIDER -> ResolveLibraryTypeNamesTask
+  TYPE_PROVIDER -> ResolveTopLevelUnitTypeBoundsTask
   TYPE_PROVIDER -> ResolveUnitTask
   TYPE_PROVIDER -> ResolveUnitTypeNamesTask
   TYPE_PROVIDER -> ResolveVariableReferencesTask
diff --git a/pkg/compiler/lib/src/apiimpl.dart b/pkg/compiler/lib/src/apiimpl.dart
index 173c27c..e802bd4 100644
--- a/pkg/compiler/lib/src/apiimpl.dart
+++ b/pkg/compiler/lib/src/apiimpl.dart
@@ -258,8 +258,7 @@
       Duration duration = task.duration;
       if (duration != Duration.ZERO) {
         cumulatedDuration += duration;
-        timings.writeln(
-            '    $running${task.name} took'
+        timings.writeln('    $running${task.name} took'
             ' ${duration.inMilliseconds}msec');
         for (String subtask in task.subtasks) {
           int subtime = task.getSubtaskTime(subtask);
@@ -271,10 +270,9 @@
     }
     Duration unaccountedDuration =
         totalDuration - cumulatedDuration - setupDuration - asyncDuration;
-    double percent = unaccountedDuration.inMilliseconds * 100
-        / totalDuration.inMilliseconds;
-    timings.write(
-        '    Total compile-time ${totalDuration.inMilliseconds}msec;'
+    double percent =
+        unaccountedDuration.inMilliseconds * 100 / totalDuration.inMilliseconds;
+    timings.write('    Total compile-time ${totalDuration.inMilliseconds}msec;'
         ' setup ${setupDuration.inMilliseconds}msec;'
         ' async ${asyncDuration.inMilliseconds}msec;'
         ' unaccounted ${unaccountedDuration.inMilliseconds}msec'
diff --git a/pkg/compiler/lib/src/closure.dart b/pkg/compiler/lib/src/closure.dart
index dfb5ba9..0e9f37f 100644
--- a/pkg/compiler/lib/src/closure.dart
+++ b/pkg/compiler/lib/src/closure.dart
@@ -55,10 +55,10 @@
         return new ClosureClassMap(null, null, null, new ThisLocal(element));
       } else {
         assert(element.isField);
-        VariableElement field = element;
-        if (field.initializer != null) {
+        Node initializer = resolvedAst.body;
+        if (initializer != null) {
           // The lazy initializer of a static.
-          translator.translateLazyInitializer(element, node, field.initializer);
+          translator.translateLazyInitializer(element, node, initializer);
         } else {
           assert(element.isInstanceMember);
           closureMappingCache[node] =
@@ -131,7 +131,8 @@
   bool get hasResolvedAst => hasTreeElements;
 
   ResolvedAst get resolvedAst {
-    return new ParsedResolvedAst(this, null, null, treeElements);
+    return new ParsedResolvedAst(this, null, null, treeElements,
+        memberContext.compilationUnit.script.resourceUri);
   }
 
   Expression get initializer {
@@ -320,11 +321,13 @@
 class SynthesizedCallMethodElementX extends BaseFunctionElementX
     implements MethodElement {
   final LocalFunctionElement expression;
+  final FunctionExpression node;
+  final TreeElements treeElements;
 
-  SynthesizedCallMethodElementX(
-      String name, LocalFunctionElementX other, ClosureClassElement enclosing)
+  SynthesizedCallMethodElementX(String name, LocalFunctionElement other,
+      ClosureClassElement enclosing, this.node, this.treeElements)
       : expression = other,
-        super(name, other.kind, other.modifiers, enclosing) {
+        super(name, other.kind, Modifiers.EMPTY, enclosing) {
     asyncMarker = other.asyncMarker;
     functionSignature = other.functionSignature;
   }
@@ -339,18 +342,17 @@
     return closureClass.methodElement.memberContext;
   }
 
-  bool get hasNode => expression.hasNode;
-
-  FunctionExpression get node => expression.node;
+  bool get hasNode => node != null;
 
   FunctionExpression parseNode(ParsingContext parsing) => node;
 
-  ResolvedAst get resolvedAst {
-    return new ParsedResolvedAst(this, node, node.body, treeElements);
-  }
-
   Element get analyzableElement => closureClass.methodElement.analyzableElement;
 
+  ResolvedAst get resolvedAst {
+    return new ParsedResolvedAst(this, node, node.body, treeElements,
+        expression.compilationUnit.script.resourceUri);
+  }
+
   accept(ElementVisitor visitor, arg) {
     return visitor.visitMethodElement(this, arg);
   }
@@ -1032,7 +1034,7 @@
     compiler.world
         .registerClass(globalizedElement, isDirectlyInstantiated: true);
     FunctionElement callElement = new SynthesizedCallMethodElementX(
-        Identifiers.call, element, globalizedElement);
+        Identifiers.call, element, globalizedElement, node, elements);
     backend.maybeMarkClosureAsNeededForReflection(
         globalizedElement, callElement, element);
     MemberElement enclosing = element.memberContext;
diff --git a/pkg/compiler/lib/src/common/codegen.dart b/pkg/compiler/lib/src/common/codegen.dart
index 4640bdb..8ad503c 100644
--- a/pkg/compiler/lib/src/common/codegen.dart
+++ b/pkg/compiler/lib/src/common/codegen.dart
@@ -234,9 +234,8 @@
     // missing call of form registry.registerXXX. Alternatively, the code
     // generation could spuriously be adding dependencies on things we know we
     // don't need.
-    assert(invariant(
-        element, compiler.enqueuer.resolution.hasBeenProcessed(element),
-        message: "$element has not been resolved."));
+    assert(invariant(element, compiler.backend.frontend.hasResolvedAst(element),
+        message: "$element has no resolved ast."));
     ResolvedAst resolvedAst = compiler.backend.frontend.getResolvedAst(element);
     return new CodegenWorkItem.internal(resolvedAst, compilationContext);
   }
diff --git a/pkg/compiler/lib/src/common/resolution.dart b/pkg/compiler/lib/src/common/resolution.dart
index d049471..0b9f990 100644
--- a/pkg/compiler/lib/src/common/resolution.dart
+++ b/pkg/compiler/lib/src/common/resolution.dart
@@ -14,6 +14,7 @@
         AstElement,
         ClassElement,
         Element,
+        ExecutableElement,
         FunctionElement,
         FunctionSignature,
         MetadataAnnotation,
@@ -188,8 +189,11 @@
 /// Interface for the accessing the front-end analysis.
 // TODO(johnniwinther): Find a better name for this.
 abstract class Frontend {
+  /// Returns `true` if [element] has a [ResolvedAst].
+  bool hasResolvedAst(ExecutableElement element);
+
   /// Returns the `ResolvedAst` for the [element].
-  ResolvedAst getResolvedAst(Element element);
+  ResolvedAst getResolvedAst(ExecutableElement element);
 
   /// Returns the [ResolutionImpact] for [element].
   ResolutionImpact getResolutionImpact(Element element);
@@ -225,10 +229,10 @@
       Element element, ItemCompilationContext compilationContext);
 
   /// Returns `true` if [element] as a fully computed [ResolvedAst].
-  bool hasResolvedAst(Element element);
+  bool hasResolvedAst(ExecutableElement element);
 
   /// Returns the `ResolvedAst` for the [element].
-  ResolvedAst getResolvedAst(Element element);
+  ResolvedAst getResolvedAst(ExecutableElement element);
 
   /// Returns `true` if the [ResolutionImpact] for [element] is cached.
   bool hasResolutionImpact(Element element);
diff --git a/pkg/compiler/lib/src/common/tasks.dart b/pkg/compiler/lib/src/common/tasks.dart
index c5a77d3..42d5e7b 100644
--- a/pkg/compiler/lib/src/common/tasks.dart
+++ b/pkg/compiler/lib/src/common/tasks.dart
@@ -4,12 +4,8 @@
 
 library dart2js.common.tasks;
 
-import 'dart:async' show
-    Future,
-    Zone,
-    ZoneDelegate,
-    ZoneSpecification,
-    runZoned;
+import 'dart:async'
+    show Future, Zone, ZoneDelegate, ZoneSpecification, runZoned;
 
 import '../common.dart';
 import '../compiler.dart' show Compiler;
@@ -149,9 +145,8 @@
       }
     }
 
-    return runZoned(
-        action,
-        zoneValues: { measurer: this },
+    return runZoned(action,
+        zoneValues: {measurer: this},
         zoneSpecification: new ZoneSpecification(
             run: run, runUnary: runUnary, runBinary: runBinary));
   }
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index 4020814..4aa08fd 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -403,17 +403,17 @@
   // The resulting future will complete with true if the compilation
   // succeeded.
   Future<bool> run(Uri uri) => selfTask.measureSubtask("Compiler.run", () {
-    measurer.startWallClock();
+        measurer.startWallClock();
 
-    return new Future.sync(() => runInternal(uri))
-        .catchError((error) => _reporter.onError(uri, error))
-        .whenComplete(() {
-      tracer.close();
-      measurer.stopWallClock();
-    }).then((_) {
-      return !compilationFailed;
-    });
-  });
+        return new Future.sync(() => runInternal(uri))
+            .catchError((error) => _reporter.onError(uri, error))
+            .whenComplete(() {
+          tracer.close();
+          measurer.stopWallClock();
+        }).then((_) {
+          return !compilationFailed;
+        });
+      });
 
   /// This method is called immediately after the [LibraryElement] [library] has
   /// been created.
@@ -449,9 +449,7 @@
     //
     // This could for example happen if dart:async is disabled, then loading it
     // should not try to find the given element.
-    // TODO(johnniwinther): This should just be library.isSynthesized, but that
-    // does not work yet for deserialized elements.
-    if (!library.compilationUnit.script.isSynthesized) {
+    if (!library.isSynthesized) {
       if (uri == Uris.dart_core) {
         initializeCoreClasses();
         identicalFunction = coreLibrary.find('identical');
@@ -809,112 +807,112 @@
   }
 
   /// Performs the compilation when all libraries have been loaded.
-  void compileLoadedLibraries()
-      => selfTask.measureSubtask("Compiler.compileLoadedLibraries", () {
+  void compileLoadedLibraries() =>
+      selfTask.measureSubtask("Compiler.compileLoadedLibraries", () {
+        computeMain();
 
-    computeMain();
+        mirrorUsageAnalyzerTask.analyzeUsage(mainApp);
 
-    mirrorUsageAnalyzerTask.analyzeUsage(mainApp);
+        // In order to see if a library is deferred, we must compute the
+        // compile-time constants that are metadata.  This means adding
+        // something to the resolution queue.  So we cannot wait with
+        // this until after the resolution queue is processed.
+        deferredLoadTask.beforeResolution(this);
+        impactStrategy = backend.createImpactStrategy(
+            supportDeferredLoad: deferredLoadTask.isProgramSplit,
+            supportDumpInfo: options.dumpInfo,
+            supportSerialization: serialization.supportSerialization);
 
-    // In order to see if a library is deferred, we must compute the
-    // compile-time constants that are metadata.  This means adding
-    // something to the resolution queue.  So we cannot wait with
-    // this until after the resolution queue is processed.
-    deferredLoadTask.beforeResolution(this);
-    impactStrategy = backend.createImpactStrategy(
-        supportDeferredLoad: deferredLoadTask.isProgramSplit,
-        supportDumpInfo: options.dumpInfo,
-        supportSerialization: serialization.supportSerialization);
-
-    phase = PHASE_RESOLVING;
-    if (analyzeAll) {
-      libraryLoader.libraries.forEach((LibraryElement library) {
-        reporter.log('Enqueuing ${library.canonicalUri}');
-        fullyEnqueueLibrary(library, enqueuer.resolution);
-      });
-    } else if (options.analyzeMain) {
-      if (mainApp != null) {
-        fullyEnqueueLibrary(mainApp, enqueuer.resolution);
-      }
-      if (librariesToAnalyzeWhenRun != null) {
-        for (Uri libraryUri in librariesToAnalyzeWhenRun) {
-          fullyEnqueueLibrary(
-              libraryLoader.lookupLibrary(libraryUri), enqueuer.resolution);
+        phase = PHASE_RESOLVING;
+        if (analyzeAll) {
+          libraryLoader.libraries.forEach((LibraryElement library) {
+            reporter.log('Enqueuing ${library.canonicalUri}');
+            fullyEnqueueLibrary(library, enqueuer.resolution);
+          });
+        } else if (options.analyzeMain) {
+          if (mainApp != null) {
+            fullyEnqueueLibrary(mainApp, enqueuer.resolution);
+          }
+          if (librariesToAnalyzeWhenRun != null) {
+            for (Uri libraryUri in librariesToAnalyzeWhenRun) {
+              fullyEnqueueLibrary(
+                  libraryLoader.lookupLibrary(libraryUri), enqueuer.resolution);
+            }
+          }
         }
-      }
-    }
-    // Elements required by enqueueHelpers are global dependencies
-    // that are not pulled in by a particular element.
-    backend.enqueueHelpers(enqueuer.resolution, globalDependencies);
-    resolveLibraryMetadata();
-    reporter.log('Resolving...');
-    processQueue(enqueuer.resolution, mainFunction);
-    enqueuer.resolution.logSummary(reporter.log);
+        // Elements required by enqueueHelpers are global dependencies
+        // that are not pulled in by a particular element.
+        backend.enqueueHelpers(enqueuer.resolution, globalDependencies);
+        resolveLibraryMetadata();
+        reporter.log('Resolving...');
+        processQueue(enqueuer.resolution, mainFunction);
+        enqueuer.resolution.logSummary(reporter.log);
 
-    _reporter.reportSuppressedMessagesSummary();
+        _reporter.reportSuppressedMessagesSummary();
 
-    if (compilationFailed) {
-      if (!options.generateCodeWithCompileTimeErrors) return;
-      if (!backend.enableCodegenWithErrorsIfSupported(NO_LOCATION_SPANNABLE)) {
-        return;
-      }
-    }
+        if (compilationFailed) {
+          if (!options.generateCodeWithCompileTimeErrors) return;
+          if (!backend
+              .enableCodegenWithErrorsIfSupported(NO_LOCATION_SPANNABLE)) {
+            return;
+          }
+        }
 
-    if (options.analyzeOnly) {
-      if (!analyzeAll && !compilationFailed) {
-        // No point in reporting unused code when [analyzeAll] is true: all
-        // code is artificially used.
-        // If compilation failed, it is possible that the error prevents the
-        // compiler from analyzing all the code.
-        // TODO(johnniwinther): Reenable this when the reporting is more
-        // precise.
-        //reportUnusedCode();
-      }
-      return;
-    }
-    assert(mainFunction != null);
-    phase = PHASE_DONE_RESOLVING;
+        if (options.analyzeOnly) {
+          if (!analyzeAll && !compilationFailed) {
+            // No point in reporting unused code when [analyzeAll] is true: all
+            // code is artificially used.
+            // If compilation failed, it is possible that the error prevents the
+            // compiler from analyzing all the code.
+            // TODO(johnniwinther): Reenable this when the reporting is more
+            // precise.
+            //reportUnusedCode();
+          }
+          return;
+        }
+        assert(mainFunction != null);
+        phase = PHASE_DONE_RESOLVING;
 
-    world.populate();
-    // Compute whole-program-knowledge that the backend needs. (This might
-    // require the information computed in [world.populate].)
-    backend.onResolutionComplete();
+        world.populate();
+        // Compute whole-program-knowledge that the backend needs. (This might
+        // require the information computed in [world.populate].)
+        backend.onResolutionComplete();
 
-    deferredLoadTask.onResolutionComplete(mainFunction);
+        deferredLoadTask.onResolutionComplete(mainFunction);
 
-    reporter.log('Inferring types...');
-    typesTask.onResolutionComplete(mainFunction);
+        reporter.log('Inferring types...');
+        typesTask.onResolutionComplete(mainFunction);
 
-    if (stopAfterTypeInference) return;
+        if (stopAfterTypeInference) return;
 
-    backend.onTypeInferenceComplete();
+        backend.onTypeInferenceComplete();
 
-    reporter.log('Compiling...');
-    phase = PHASE_COMPILING;
-    backend.onCodegenStart();
-    // TODO(johnniwinther): Move these to [CodegenEnqueuer].
-    if (hasIsolateSupport) {
-      backend.enableIsolateSupport(enqueuer.codegen);
-    }
-    if (compileAll) {
-      libraryLoader.libraries.forEach((LibraryElement library) {
-        fullyEnqueueLibrary(library, enqueuer.codegen);
+        reporter.log('Compiling...');
+        phase = PHASE_COMPILING;
+        backend.onCodegenStart();
+        // TODO(johnniwinther): Move these to [CodegenEnqueuer].
+        if (hasIsolateSupport) {
+          backend.enableIsolateSupport(enqueuer.codegen);
+        }
+        if (compileAll) {
+          libraryLoader.libraries.forEach((LibraryElement library) {
+            fullyEnqueueLibrary(library, enqueuer.codegen);
+          });
+        }
+        processQueue(enqueuer.codegen, mainFunction);
+        enqueuer.codegen.logSummary(reporter.log);
+
+        int programSize = backend.assembleProgram();
+
+        if (options.dumpInfo) {
+          dumpInfoTask.reportSize(programSize);
+          dumpInfoTask.dumpInfo();
+        }
+
+        backend.sourceInformationStrategy.onComplete();
+
+        checkQueues();
       });
-    }
-    processQueue(enqueuer.codegen, mainFunction);
-    enqueuer.codegen.logSummary(reporter.log);
-
-    int programSize = backend.assembleProgram();
-
-    if (options.dumpInfo) {
-      dumpInfoTask.reportSize(programSize);
-      dumpInfoTask.dumpInfo();
-    }
-
-    backend.sourceInformationStrategy.onComplete();
-
-    checkQueues();
-  });
 
   void fullyEnqueueLibrary(LibraryElement library, Enqueuer world) {
     void enqueueAll(Element element) {
@@ -950,48 +948,53 @@
   /**
    * Empty the [world] queue.
    */
-  void emptyQueue(Enqueuer world)
-      => selfTask.measureSubtask("Compiler.emptyQueue", () {
-    world.forEach((WorkItem work) {
-      reporter.withCurrentElement(
-          work.element, () => selfTask.measureSubtask("world.applyImpact", () {
-        world.applyImpact(
-            work.element,
-            selfTask.measureSubtask("work.run", () => work.run(this, world)));
-      }));
-    });
-  });
+  void emptyQueue(Enqueuer world) =>
+      selfTask.measureSubtask("Compiler.emptyQueue", () {
+        world.forEach((WorkItem work) {
+          reporter.withCurrentElement(
+              work.element,
+              () => selfTask.measureSubtask("world.applyImpact", () {
+                    world.applyImpact(
+                        work.element,
+                        selfTask.measureSubtask(
+                            "work.run", () => work.run(this, world)));
+                  }));
+        });
+      });
 
-  void processQueue(Enqueuer world, Element main)
-      => selfTask.measureSubtask("Compiler.processQueue", () {
-    world.nativeEnqueuer.processNativeClasses(libraryLoader.libraries);
-    if (main != null && !main.isMalformed) {
-      FunctionElement mainMethod = main;
-      mainMethod.computeType(resolution);
-      if (mainMethod.functionSignature.parameterCount != 0) {
-        // The first argument could be a list of strings.
-        backend.listImplementation.ensureResolved(resolution);
-        backend.registerInstantiatedType(
-            backend.listImplementation.rawType, world, globalDependencies);
-        backend.stringImplementation.ensureResolved(resolution);
-        backend.registerInstantiatedType(
-            backend.stringImplementation.rawType, world, globalDependencies);
+  void processQueue(Enqueuer world, Element main) =>
+      selfTask.measureSubtask("Compiler.processQueue", () {
+        world.nativeEnqueuer.processNativeClasses(libraryLoader.libraries);
+        if (main != null && !main.isMalformed) {
+          FunctionElement mainMethod = main;
+          mainMethod.computeType(resolution);
+          if (mainMethod.functionSignature.parameterCount != 0) {
+            // The first argument could be a list of strings.
+            backend.listImplementation.ensureResolved(resolution);
+            backend.registerInstantiatedType(
+                backend.listImplementation.rawType, world, globalDependencies);
+            backend.stringImplementation.ensureResolved(resolution);
+            backend.registerInstantiatedType(
+                backend.stringImplementation.rawType,
+                world,
+                globalDependencies);
 
-        backend.registerMainHasArguments(world);
-      }
-      world.addToWorkList(main);
-    }
-    if (options.verbose) {
-      progress.reset();
-    }
-    emptyQueue(world);
-    world.queueIsClosed = true;
-    // Notify the impact strategy impacts are no longer needed for this
-    // enqueuer.
-    impactStrategy.onImpactUsed(world.impactUse);
-    backend.onQueueClosed();
-    assert(compilationFailed || world.checkNoEnqueuedInvokedInstanceMethods());
-  });
+            backend.registerMainHasArguments(world);
+          }
+          world.addToWorkList(main);
+        }
+        if (options.verbose) {
+          progress.reset();
+        }
+        emptyQueue(world);
+        world.queueIsClosed = true;
+        // Notify the impact strategy impacts are no longer needed for this
+        // enqueuer.
+        impactStrategy.onImpactUsed(world.impactUse);
+        backend.onQueueClosed();
+        assert(
+            compilationFailed || world.checkNoEnqueuedInvokedInstanceMethods());
+      });
 
   /**
    * Perform various checks of the queues. This includes checking that
@@ -1032,47 +1035,47 @@
     }
   }
 
-  WorldImpact analyzeElement(Element element)
-      => selfTask.measureSubtask("Compiler.analyzeElement", () {
-    assert(invariant(
-        element,
-        element.impliesType ||
-            element.isField ||
-            element.isFunction ||
-            element.isConstructor ||
-            element.isGetter ||
-            element.isSetter,
-        message: 'Unexpected element kind: ${element.kind}'));
-    assert(invariant(element, element is AnalyzableElement,
-        message: 'Element $element is not analyzable.'));
-    assert(invariant(element, element.isDeclaration));
-    return resolution.computeWorldImpact(element);
-  });
+  WorldImpact analyzeElement(Element element) =>
+      selfTask.measureSubtask("Compiler.analyzeElement", () {
+        assert(invariant(
+            element,
+            element.impliesType ||
+                element.isField ||
+                element.isFunction ||
+                element.isConstructor ||
+                element.isGetter ||
+                element.isSetter,
+            message: 'Unexpected element kind: ${element.kind}'));
+        assert(invariant(element, element is AnalyzableElement,
+            message: 'Element $element is not analyzable.'));
+        assert(invariant(element, element.isDeclaration));
+        return resolution.computeWorldImpact(element);
+      });
 
-  WorldImpact analyze(ResolutionWorkItem work,
-                      ResolutionEnqueuer world)
-      => selfTask.measureSubtask("Compiler.analyze", () {
-    assert(invariant(work.element, identical(world, enqueuer.resolution)));
-    assert(invariant(work.element, !work.isAnalyzed,
-        message: 'Element ${work.element} has already been analyzed'));
-    if (shouldPrintProgress) {
-      // TODO(ahe): Add structured diagnostics to the compiler API and
-      // use it to separate this from the --verbose option.
-      if (phase == PHASE_RESOLVING) {
-        reporter.log('Resolved ${enqueuer.resolution.processedElements.length} '
-            'elements.');
-        progress.reset();
-      }
-    }
-    AstElement element = work.element;
-    if (world.hasBeenProcessed(element)) {
-      return const WorldImpact();
-    }
-    WorldImpact worldImpact = analyzeElement(element);
-    backend.onElementResolved(element);
-    world.registerProcessedElement(element);
-    return worldImpact;
-  });
+  WorldImpact analyze(ResolutionWorkItem work, ResolutionEnqueuer world) =>
+      selfTask.measureSubtask("Compiler.analyze", () {
+        assert(invariant(work.element, identical(world, enqueuer.resolution)));
+        assert(invariant(work.element, !work.isAnalyzed,
+            message: 'Element ${work.element} has already been analyzed'));
+        if (shouldPrintProgress) {
+          // TODO(ahe): Add structured diagnostics to the compiler API and
+          // use it to separate this from the --verbose option.
+          if (phase == PHASE_RESOLVING) {
+            reporter
+                .log('Resolved ${enqueuer.resolution.processedElements.length} '
+                    'elements.');
+            progress.reset();
+          }
+        }
+        AstElement element = work.element;
+        if (world.hasBeenProcessed(element)) {
+          return const WorldImpact();
+        }
+        WorldImpact worldImpact = analyzeElement(element);
+        backend.onElementResolved(element);
+        world.registerProcessedElement(element);
+        return worldImpact;
+      });
 
   WorldImpact codegen(CodegenWorkItem work, CodegenEnqueuer world) {
     assert(invariant(work.element, identical(world, enqueuer.codegen)));
@@ -1915,27 +1918,25 @@
   }
 
   @override
-  bool hasResolvedAst(Element element) {
+  bool hasResolvedAst(ExecutableElement element) {
     assert(invariant(element, element.isDeclaration,
         message: "Element $element must be the declaration."));
     if (compiler.serialization.isDeserialized(element)) {
       return compiler.serialization.hasResolvedAst(element);
     }
-    return element is AstElement &&
-        hasBeenResolved(element) &&
+    return hasBeenResolved(element.memberContext.declaration) &&
         element.hasResolvedAst;
   }
 
   @override
-  ResolvedAst getResolvedAst(Element element) {
+  ResolvedAst getResolvedAst(ExecutableElement element) {
     assert(invariant(element, element.isDeclaration,
         message: "Element $element must be the declaration."));
     if (hasResolvedAst(element)) {
       if (compiler.serialization.isDeserialized(element)) {
         return compiler.serialization.getResolvedAst(element);
       }
-      AstElement astElement = element;
-      return astElement.resolvedAst;
+      return element.resolvedAst;
     }
     assert(invariant(element, hasResolvedAst(element),
         message: "ResolvedAst not available for $element."));
diff --git a/pkg/compiler/lib/src/constant_system_dart.dart b/pkg/compiler/lib/src/constant_system_dart.dart
index 60e8899..a19e003 100644
--- a/pkg/compiler/lib/src/constant_system_dart.dart
+++ b/pkg/compiler/lib/src/constant_system_dart.dart
@@ -450,6 +450,11 @@
         compiler.backend.typeImplementation.computeType(compiler.resolution));
   }
 
+  @override
+  ConstantValue createSymbol(Compiler compiler, String text) {
+    throw new UnsupportedError('DartConstantSystem.evaluate');
+  }
+
   bool isInt(ConstantValue constant) => constant.isInt;
   bool isDouble(ConstantValue constant) => constant.isDouble;
   bool isString(ConstantValue constant) => constant.isString;
diff --git a/pkg/compiler/lib/src/constants/constant_system.dart b/pkg/compiler/lib/src/constants/constant_system.dart
index aae267f..e278612 100644
--- a/pkg/compiler/lib/src/constants/constant_system.dart
+++ b/pkg/compiler/lib/src/constants/constant_system.dart
@@ -68,6 +68,8 @@
       List<ConstantValue> keys, List<ConstantValue> values);
   // TODO(johnniwinther): Remove the need for [compiler].
   ConstantValue createType(Compiler compiler, DartType type);
+  // TODO(johnniwinther): Remove the need for [compiler].
+  ConstantValue createSymbol(Compiler compiler, String text);
 
   // We need to special case the subtype check for JavaScript constant
   // system because an int is a double at runtime.
diff --git a/pkg/compiler/lib/src/constants/expressions.dart b/pkg/compiler/lib/src/constants/expressions.dart
index aa284cd..4019e16 100644
--- a/pkg/compiler/lib/src/constants/expressions.dart
+++ b/pkg/compiler/lib/src/constants/expressions.dart
@@ -680,8 +680,7 @@
   @override
   ConstantValue evaluate(
       Environment environment, ConstantSystem constantSystem) {
-    // TODO(johnniwinther): Implement this.
-    throw new UnsupportedError('SymbolConstantExpression.evaluate');
+    return constantSystem.createSymbol(environment.compiler, name);
   }
 
   @override
@@ -1261,7 +1260,11 @@
     sb.write('bool.fromEnvironment(name=');
     name._createStructuredText(sb);
     sb.write(',defaultValue=');
-    defaultValue._createStructuredText(sb);
+    if (defaultValue != null) {
+      defaultValue._createStructuredText(sb);
+    } else {
+      sb.write('null');
+    }
     sb.write(')');
   }
 
@@ -1320,7 +1323,11 @@
     sb.write('int.fromEnvironment(name=');
     name._createStructuredText(sb);
     sb.write(',defaultValue=');
-    defaultValue._createStructuredText(sb);
+    if (defaultValue != null) {
+      defaultValue._createStructuredText(sb);
+    } else {
+      sb.write('null');
+    }
     sb.write(')');
   }
 
@@ -1381,7 +1388,11 @@
     sb.write('String.fromEnvironment(name=');
     name._createStructuredText(sb);
     sb.write(',defaultValue=');
-    defaultValue._createStructuredText(sb);
+    if (defaultValue != null) {
+      defaultValue._createStructuredText(sb);
+    } else {
+      sb.write('null');
+    }
     sb.write(')');
   }
 
@@ -1438,7 +1449,8 @@
   @override
   ConstantValue evaluate(
       Environment environment, ConstantSystem constantSystem) {
-    return expression.evaluate(environment, constantSystem);
+    return new DeferredConstantValue(
+        expression.evaluate(environment, constantSystem), prefix);
   }
 
   @override
diff --git a/pkg/compiler/lib/src/constants/values.dart b/pkg/compiler/lib/src/constants/values.dart
index fd0f5dd..37f5646 100644
--- a/pkg/compiler/lib/src/constants/values.dart
+++ b/pkg/compiler/lib/src/constants/values.dart
@@ -159,7 +159,7 @@
   /** The value a Dart null is compiled to in JavaScript. */
   static const String JsNull = "null";
 
-  factory NullConstantValue() => const NullConstantValue._internal();
+  const factory NullConstantValue() = NullConstantValue._internal;
 
   const NullConstantValue._internal();
 
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
index 49d3353..c382e4e 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
@@ -78,7 +78,7 @@
       element = element.implementation;
       return reporter.withCurrentElement(element, () {
         SourceInformationBuilder sourceInformationBuilder =
-            sourceInformationStrategy.createBuilderForContext(element);
+            sourceInformationStrategy.createBuilderForContext(resolvedAst);
 
         IrBuilderVisitor builder = new IrBuilderVisitor(
             resolvedAst, compiler, sourceInformationBuilder, typeMaskSystem);
@@ -502,8 +502,9 @@
   /// Every visitor can only be applied to nodes in one context, because
   /// the [elements] field is specific to that context.
   IrBuilderVisitor makeVisitorForContext(AstElement context) {
-    return new IrBuilderVisitor(context.resolvedAst, compiler,
-        sourceInformationBuilder.forContext(context), typeMaskSystem);
+    ResolvedAst resolvedAst = backend.frontend.getResolvedAst(context);
+    return new IrBuilderVisitor(resolvedAst, compiler,
+        sourceInformationBuilder.forContext(resolvedAst), typeMaskSystem);
   }
 
   /// Builds the IR for an [expression] taken from a different [context].
@@ -1681,7 +1682,11 @@
   }
 
   ConstantValue getConstantForVariable(VariableElement element) {
-    return irBuilder.state.constants.getConstantValue(element.constant);
+    ConstantExpression constant = element.constant;
+    if (constant != null) {
+      return irBuilder.state.constants.getConstantValue(constant);
+    }
+    return null;
   }
 
   ir.Primitive buildConstantExpression(
diff --git a/pkg/compiler/lib/src/dart_backend/backend_ast_to_frontend_ast.dart b/pkg/compiler/lib/src/dart_backend/backend_ast_to_frontend_ast.dart
index 81eae70..03f0ba1 100644
--- a/pkg/compiler/lib/src/dart_backend/backend_ast_to_frontend_ast.dart
+++ b/pkg/compiler/lib/src/dart_backend/backend_ast_to_frontend_ast.dart
@@ -495,6 +495,8 @@
           : makeFunctionBody(exp.body);
       result = new tree.FunctionExpression(
           constructorName(exp),
+          // TODO(eernst): retrieve and pass the actual type variables.
+          null, // typeVariables
           parameters,
           body,
           null, // return type
@@ -514,6 +516,8 @@
       tree.Node body = makeFunctionBody(exp.body);
       result = new tree.FunctionExpression(
           functionName(exp),
+          // TODO(eernst): retrieve and pass the actual type variables.
+          null, // typeVariables
           parameters,
           body,
           exp.returnType == null || exp.element.isConstructor
@@ -798,6 +802,8 @@
     } else if (stmt is FunctionDeclaration) {
       tree.FunctionExpression function = new tree.FunctionExpression(
           stmt.name != null ? makeIdentifier(stmt.name) : null,
+          // TODO(eernst): retrieve and pass the actual type variables.
+          null, // typeVariables
           makeParameters(stmt.parameters),
           makeFunctionBody(stmt.body),
           stmt.returnType != null ? makeType(stmt.returnType) : null,
@@ -965,6 +971,8 @@
     if (param.isFunction) {
       tree.Node definition = new tree.FunctionExpression(
           makeIdentifier(param.name),
+          // TODO(eernst): retrieve and pass the actual type variables.
+          null, // typeVariables
           makeParameters(param.parameters),
           null, // body
               param.type == null ? null : makeType(param.type),
diff --git a/pkg/compiler/lib/src/deferred_load.dart b/pkg/compiler/lib/src/deferred_load.dart
index db57839..b75a6ab 100644
--- a/pkg/compiler/lib/src/deferred_load.dart
+++ b/pkg/compiler/lib/src/deferred_load.dart
@@ -8,6 +8,8 @@
 import 'common/tasks.dart' show CompilerTask;
 import 'common.dart';
 import 'compiler.dart' show Compiler;
+import 'constants/expressions.dart'
+    show ConstantExpression, ConstantExpressionKind;
 import 'constants/values.dart'
     show
         ConstantValue,
@@ -334,15 +336,14 @@
         TreeElements treeElements = analyzableElement.resolvedAst.elements;
         assert(treeElements != null);
 
-        treeElements.forEachConstantNode((Node node, _) {
+        treeElements
+            .forEachConstantNode((Node node, ConstantExpression expression) {
           // Explicitly depend on the backend constants.
-          ConstantValue value =
-              backend.constants.getConstantValueForNode(node, treeElements);
-          if (value != null) {
-            // TODO(johnniwinther): Assert that all constants have values when
-            // these are directly evaluated.
-            constants.add(value);
-          }
+          ConstantValue value = backend.constants.getConstantValue(expression);
+          assert(invariant(node, value != null,
+              message:
+                  "No constant value for ${expression.toStructuredText()}."));
+          constants.add(value);
         });
       }
     }
diff --git a/pkg/compiler/lib/src/diagnostics/messages.dart b/pkg/compiler/lib/src/diagnostics/messages.dart
index 083068e..bbe777e 100644
--- a/pkg/compiler/lib/src/diagnostics/messages.dart
+++ b/pkg/compiler/lib/src/diagnostics/messages.dart
@@ -3240,10 +3240,9 @@
 """
           ]),
 
-      MessageKind.ASYNC_AWAIT_NOT_SUPPORTED:
-        const MessageTemplate(MessageKind.ASYNC_AWAIT_NOT_SUPPORTED,
-            "The async/sync* syntax is not supported on the current platform."),
-
+      MessageKind.ASYNC_AWAIT_NOT_SUPPORTED: const MessageTemplate(
+          MessageKind.ASYNC_AWAIT_NOT_SUPPORTED,
+          "The async/sync* syntax is not supported on the current platform."),
 
       MessageKind.ASYNC_MODIFIER_ON_ABSTRACT_METHOD: const MessageTemplate(
           MessageKind.ASYNC_MODIFIER_ON_ABSTRACT_METHOD,
diff --git a/pkg/compiler/lib/src/elements/common.dart b/pkg/compiler/lib/src/elements/common.dart
index 9cdce47..6c9a013 100644
--- a/pkg/compiler/lib/src/elements/common.dart
+++ b/pkg/compiler/lib/src/elements/common.dart
@@ -151,6 +151,13 @@
     }
     return null;
   }
+
+  Element get enclosingClassOrCompilationUnit {
+    for (Element e = this; e != null; e = e.enclosingElement) {
+      if (e.isClass || e.isCompilationUnit) return e;
+    }
+    return null;
+  }
 }
 
 abstract class LibraryElementCommon implements LibraryElement {
@@ -465,6 +472,36 @@
   bool get isNamedMixinApplication {
     return isMixinApplication && !isUnnamedMixinApplication;
   }
+
+  // backendMembers are members that have been added by the backend to simplify
+  // compilation. They don't have any user-side counter-part.
+  Link<Element> backendMembers = const Link<Element>();
+
+  bool get hasBackendMembers => !backendMembers.isEmpty;
+
+  void addBackendMember(Element member) {
+    // TODO(ngeoffray): Deprecate this method.
+    assert(member.isGenerativeConstructorBody);
+    backendMembers = backendMembers.prepend(member);
+  }
+
+  void reverseBackendMembers() {
+    backendMembers = backendMembers.reverse();
+  }
+
+  /// Lookup a synthetic element created by the backend.
+  Element lookupBackendMember(String memberName) {
+    for (Element element in backendMembers) {
+      if (element.name == memberName) {
+        return element;
+      }
+    }
+    return null;
+  }
+
+  void forEachBackendMember(void f(Element member)) {
+    backendMembers.forEach(f);
+  }
 }
 
 abstract class FunctionSignatureCommon implements FunctionSignature {
diff --git a/pkg/compiler/lib/src/elements/elements.dart b/pkg/compiler/lib/src/elements/elements.dart
index a6683cf..2e6adb0 100644
--- a/pkg/compiler/lib/src/elements/elements.dart
+++ b/pkg/compiler/lib/src/elements/elements.dart
@@ -329,6 +329,12 @@
 
   bool get impliesType;
 
+  /// The character offset of the declaration of this element within its
+  /// compilation unit, if available.
+  ///
+  /// This is used to sort the elements.
+  int get sourceOffset;
+
   // TODO(johnniwinther): Remove this.
   Token get position;
 
@@ -480,7 +486,12 @@
     return true;
   }
 
-  static bool hasAccessToTypeVariables(Element element) {
+  static bool hasAccessToTypeVariable(
+      Element element, TypeVariableElement typeVariable) {
+    GenericElement declaration = typeVariable.typeDeclaration;
+    if (declaration is FunctionElement || declaration is ParameterElement) {
+      return true;
+    }
     Element outer = element.outermostEnclosingMemberOrTopLevel;
     return (outer != null && outer.isFactoryConstructor) ||
         !isInStaticContext(element);
@@ -683,10 +694,8 @@
     if (r != 0) return r;
     r = a.compilationUnit.compareTo(b.compilationUnit);
     if (r != 0) return r;
-    Token positionA = a.position;
-    Token positionB = b.position;
-    int offsetA = positionA == null ? -1 : positionA.charOffset;
-    int offsetB = positionB == null ? -1 : positionB.charOffset;
+    int offsetA = a.sourceOffset ?? -1;
+    int offsetB = b.sourceOffset ?? -1;
     r = offsetA.compareTo(offsetB);
     if (r != 0) return r;
     r = a.name.compareTo(b.name);
@@ -1103,6 +1112,7 @@
 
 abstract class FunctionSignature {
   FunctionType get type;
+  List<DartType> get typeVariables;
   List<FormalElement> get requiredParameters;
   List<FormalElement> get optionalParameters;
 
@@ -1130,7 +1140,8 @@
         AstElement,
         TypedElement,
         FunctionTypedElement,
-        ExecutableElement {
+        ExecutableElement,
+        GenericElement {
   FunctionExpression get node;
 
   FunctionElement get patch;
@@ -1138,7 +1149,7 @@
 
   bool get hasFunctionSignature;
 
-  /// The parameters of this functions.
+  /// The parameters of this function.
   List<ParameterElement> get parameters;
 
   /// The type of this function.
@@ -1228,7 +1239,7 @@
   /// The effective target of this constructor, that is the non-redirecting
   /// constructor that is called on invocation of this constructor.
   ///
-  /// Consider for instance this hierachy:
+  /// Consider for instance this hierarchy:
   ///
   ///     class C { factory C.c() = D.d; }
   ///     class D { factory D.d() = E.e2; }
@@ -1241,7 +1252,7 @@
 
   /// The immediate redirection target of a redirecting factory constructor.
   ///
-  /// Consider for instance this hierachy:
+  /// Consider for instance this hierarchy:
   ///
   ///     class C { factory C() = D; }
   ///     class D { factory D() = E; }
@@ -1318,9 +1329,20 @@
   FunctionElement get constructor;
 }
 
+/// [GenericElement] defines the common interface for generic functions and
+/// [TypeDeclarationElement].
+abstract class GenericElement extends Element implements AstElement {
+  /**
+   * The type variables declared on this declaration. The type variables are not
+   * available until the type of the element has been computed through
+   * [computeType].
+   */
+  List<DartType> get typeVariables;
+}
+
 /// [TypeDeclarationElement] defines the common interface for class/interface
 /// declarations and typedefs.
-abstract class TypeDeclarationElement extends Element implements AstElement {
+abstract class TypeDeclarationElement extends GenericElement {
   /// The name of this type declaration, taking privacy into account.
   Name get memberName;
 
@@ -1362,13 +1384,6 @@
    */
   GenericType get rawType;
 
-  /**
-   * The type variables declared on this declaration. The type variables are not
-   * available until the type of the element has been computed through
-   * [computeType].
-   */
-  List<DartType> get typeVariables;
-
   bool get isResolved;
 
   void ensureResolved(Resolution resolution);
@@ -1565,8 +1580,9 @@
   @deprecated
   get enclosingElement;
 
-  /// The class or typedef on which this type variable is defined.
-  TypeDeclarationElement get typeDeclaration;
+  /// The class, typedef, function, method, or function typed parameter on
+  /// which this type variable is defined.
+  GenericElement get typeDeclaration;
 
   /// The index of this type variable within its type declaration.
   int get index;
@@ -1608,7 +1624,7 @@
 }
 
 /// An [Element] that can define a function type.
-abstract class FunctionTypedElement extends Element {
+abstract class FunctionTypedElement extends Element implements GenericElement {
   /// The function signature for the function type defined by this element,
   /// if any.
   FunctionSignature get functionSignature;
@@ -1682,6 +1698,10 @@
   /// The [TreeElements] containing the resolution data for [node]. This only
   /// available of [kind] is `ResolvedAstKind.PARSED`.
   TreeElements get elements;
+
+  /// Returns the uri for the source file defining [node] and [body]. This
+  /// only available if [kind] is `ResolvedAstKind.PARSED`.
+  Uri get sourceUri;
 }
 
 /// [ResolvedAst] implementation used for elements whose semantics is defined in
@@ -1691,8 +1711,10 @@
   final Node node;
   final Node body;
   final TreeElements elements;
+  final Uri sourceUri;
 
-  ParsedResolvedAst(this.element, this.node, this.body, this.elements);
+  ParsedResolvedAst(
+      this.element, this.node, this.body, this.elements, this.sourceUri);
 
   ResolvedAstKind get kind => ResolvedAstKind.PARSED;
 
@@ -1722,6 +1744,11 @@
     throw new UnsupportedError('$this does not have a body AST node');
   }
 
+  @override
+  Uri get sourceUri {
+    throw new UnsupportedError('$this does not have a source URI');
+  }
+
   String toString() => '$kind:$element';
 }
 
diff --git a/pkg/compiler/lib/src/elements/modelx.dart b/pkg/compiler/lib/src/elements/modelx.dart
index 3a1e981..74ac6ad 100644
--- a/pkg/compiler/lib/src/elements/modelx.dart
+++ b/pkg/compiler/lib/src/elements/modelx.dart
@@ -109,13 +109,15 @@
     return enclosingElement != null && enclosingElement.isCompilationUnit;
   }
 
+  @override
+  int get sourceOffset => position?.charOffset;
+
   Token get position => null;
 
   SourceSpan get sourcePosition {
     if (position == null) return null;
     Uri uri = compilationUnit.script.resourceUri;
-    return new SourceSpan(
-        uri, position.charOffset, position.charOffset + position.charCount);
+    return new SourceSpan(uri, position.charOffset, position.charEnd);
   }
 
   Token findMyName(Token token) {
@@ -149,7 +151,7 @@
 
   Name get memberName => new Name(name, library);
 
-  LibraryElementX get implementationLibrary {
+  LibraryElement get implementationLibrary {
     Element element = this;
     while (!identical(element.kind, ElementKind.LIBRARY)) {
       element = element.enclosingElement;
@@ -164,13 +166,6 @@
     return null;
   }
 
-  Element get enclosingClassOrCompilationUnit {
-    for (Element e = this; e != null; e = e.enclosingElement) {
-      if (e.isClass || e.isCompilationUnit) return e;
-    }
-    return null;
-  }
-
   /**
    * Creates the scope for this element.
    */
@@ -288,6 +283,9 @@
 
   @override
   bool get isFromEnvironmentConstructor => false;
+
+  @override
+  List<DartType> get typeVariables => unsupported();
 }
 
 /// A constructor that was synthesized to recover from a compile-time error.
@@ -721,7 +719,8 @@
     localMembers = localMembers.prepend(element);
     // Provide the member to the library to build scope.
     if (enclosingElement.isPatch) {
-      implementationLibrary.addMember(element, reporter);
+      LibraryElementX library = implementationLibrary;
+      library.addMember(element, reporter);
     } else {
       library.addMember(element, reporter);
     }
@@ -1408,11 +1407,17 @@
       originVariable.constant = value;
       return;
     }
+    if (constantCache != null &&
+        constantCache.kind == ConstantExpressionKind.ERRONEOUS) {
+      // TODO(johnniwinther): Find out why we sometimes compute a non-erroneous
+      // constant for a variable already known to be erroneous.
+      return;
+    }
     assert(invariant(this, constantCache == null || constantCache == value,
         message: "Constant has already been computed for $this. "
             "Existing constant: "
-            "${constantCache != null ? constantCache.toDartText() : ''}, "
-            "New constant: ${value != null ? value.toDartText() : ''}."));
+            "${constantCache != null ? constantCache.toStructuredText() : ''}, "
+            "New constant: ${value != null ? value.toStructuredText() : ''}."));
     constantCache = value;
   }
 }
@@ -1663,6 +1668,9 @@
   final Identifier identifier;
   DartType typeCache;
 
+  @override
+  List<DartType> get typeVariables => functionSignature.typeVariables;
+
   /**
    * Function signature for a variable with a function type. The signature is
    * kept to provide full information about parameter names through the mirror
@@ -1892,6 +1900,7 @@
 // TODO(karlklose): all these lists should have element type [FormalElement].
 class FunctionSignatureX extends FunctionSignatureCommon
     implements FunctionSignature {
+  final List<DartType> typeVariables;
   final List<Element> requiredParameters;
   final List<Element> optionalParameters;
   final int requiredParameterCount;
@@ -1902,7 +1911,8 @@
   final bool hasOptionalParameters;
 
   FunctionSignatureX(
-      {this.requiredParameters: const <Element>[],
+      {this.typeVariables: const <DartType>[],
+      this.requiredParameters: const <Element>[],
       this.requiredParameterCount: 0,
       List<Element> optionalParameters: const <Element>[],
       this.optionalParameterCount: 0,
@@ -1983,6 +1993,9 @@
 
   FunctionElement asFunctionElement() => this;
 
+  @override
+  Scope buildScope() => new TypeDeclarationScope(super.buildScope(), this);
+
   String toString() {
     if (isPatch) {
       return 'patch ${super.toString()}';
@@ -1997,6 +2010,9 @@
 
   // A function is defined by the implementation element.
   AstElement get definingElement => implementation;
+
+  @override
+  List<DartType> get typeVariables => functionSignature.typeVariables;
 }
 
 abstract class FunctionElementX extends BaseFunctionElementX
@@ -2154,6 +2170,10 @@
             enclosingClass.name == 'int' ||
             enclosingClass.name == 'String');
   }
+
+  /// Returns the empty list of type variables by default.
+  @override
+  List<DartType> get typeVariables => functionSignature.typeVariables;
 }
 
 abstract class ConstructorElementX extends FunctionElementX
@@ -2487,10 +2507,6 @@
   bool isProxy = false;
   bool hasIncompleteHierarchy = false;
 
-  // backendMembers are members that have been added by the backend to simplify
-  // compilation. They don't have any user-side counter-part.
-  Link<Element> backendMembers = const Link<Element>();
-
   OrderedTypeSet allSupertypesAndSelf;
 
   BaseClassElementX(String name, Element enclosing, this.id, int initialState)
@@ -2500,8 +2516,6 @@
 
   int get hashCode => id;
 
-  bool get hasBackendMembers => !backendMembers.isEmpty;
-
   bool get isUnnamedMixinApplication => false;
 
   @override
@@ -2554,26 +2568,6 @@
   void setDefaultConstructor(
       FunctionElement constructor, DiagnosticReporter reporter);
 
-  void addBackendMember(Element member) {
-    // TODO(ngeoffray): Deprecate this method.
-    assert(member.isGenerativeConstructorBody);
-    backendMembers = backendMembers.prepend(member);
-  }
-
-  void reverseBackendMembers() {
-    backendMembers = backendMembers.reverse();
-  }
-
-  /// Lookup a synthetic element created by the backend.
-  Element lookupBackendMember(String memberName) {
-    for (Element element in backendMembers) {
-      if (element.name == memberName) {
-        return element;
-      }
-    }
-    return null;
-  }
-
   ConstructorElement lookupDefaultConstructor() {
     ConstructorElement constructor = lookupConstructor("");
     // This method might be called on constructors that have not been
@@ -2598,10 +2592,6 @@
     return supertype == null ? null : supertype.element;
   }
 
-  void forEachBackendMember(void f(Element member)) {
-    backendMembers.forEach(f);
-  }
-
   // TODO(johnniwinther): Remove these when issue 18630 is fixed.
   ClassElement get patch => super.patch;
   ClassElement get origin => super.origin;
@@ -3114,10 +3104,10 @@
   DartType boundCache;
 
   TypeVariableElementX(
-      String name, TypeDeclarationElement enclosing, this.index, this.node)
+      String name, GenericElement enclosing, this.index, this.node)
       : super(name, ElementKind.TYPE_VARIABLE, enclosing);
 
-  TypeDeclarationElement get typeDeclaration => enclosingElement;
+  GenericElement get typeDeclaration => enclosingElement;
 
   TypeVariableType computeType(Resolution resolution) => type;
 
@@ -3278,6 +3268,10 @@
       body = node.asFunctionExpression().body;
     }
     return new ParsedResolvedAst(
-        declaration, node, body, definingElement.treeElements);
+        declaration,
+        node,
+        body,
+        definingElement.treeElements,
+        definingElement.compilationUnit.script.resourceUri);
   }
 }
diff --git a/pkg/compiler/lib/src/enqueue.dart b/pkg/compiler/lib/src/enqueue.dart
index 8f1f1b7..f619520 100644
--- a/pkg/compiler/lib/src/enqueue.dart
+++ b/pkg/compiler/lib/src/enqueue.dart
@@ -309,7 +309,8 @@
         recentClasses.add(superclass);
         superclass.ensureResolved(resolution);
         superclass.implementation.forEachMember(processInstantiatedClassMember);
-        if (isResolutionQueue && !superclass.isSynthesized) {
+        if (isResolutionQueue &&
+            !compiler.serialization.isDeserialized(superclass)) {
           compiler.resolver.checkClass(superclass);
         }
         // We only tell the backend once that [superclass] was instantiated, so
diff --git a/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart b/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart
index 78ef6bb..65e7439 100644
--- a/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart
+++ b/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart
@@ -741,7 +741,10 @@
       : this.analyzedElement = analyzedElement,
         this.locals = handler {
     if (handler != null) return;
-    Node node = analyzedElement.node;
+    Node node;
+    if (resolvedAst.kind == ResolvedAstKind.PARSED) {
+      node = resolvedAst.node;
+    }
     FieldInitializationScope<T> fieldScope =
         analyzedElement.isGenerativeConstructor
             ? new FieldInitializationScope<T>(types)
diff --git a/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart b/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart
index d13b124..e800c0f 100644
--- a/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart
+++ b/pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart
@@ -47,6 +47,10 @@
 
   CoreTypes get coreTypes => compiler.coreTypes;
 
+  ResolvedAst getResolvedAst(Element element) {
+    return compiler.backend.frontend.getResolvedAst(element.declaration);
+  }
+
   /**
    * Records the default type of parameter [parameter].
    */
@@ -256,6 +260,7 @@
     return returnType;
   }
 
+  // TODO(johnniwinther): Pass the [ResolvedAst] instead of [owner].
   void updateSelectorInTree(
       AstElement owner, Spannable node, Selector selector, TypeMask mask) {
     if (node is cps_ir.Node) {
@@ -263,7 +268,7 @@
       throw "updateSelector for IR node $node";
     }
     ast.Node astNode = node;
-    TreeElements elements = owner.resolvedAst.elements;
+    TreeElements elements = getResolvedAst(owner).elements;
     if (astNode.asSendSet() != null) {
       if (selector.isSetter || selector.isIndexSet) {
         elements.setTypeMask(node, mask);
@@ -295,7 +300,7 @@
         element.isField;
   }
 
-  void analyze(Element element, ArgumentsTypes arguments);
+  void analyze(ResolvedAst resolvedAst, ArgumentsTypes arguments);
 
   bool checkIfExposesThis(Element element) {
     element = element.implementation;
@@ -354,17 +359,24 @@
             compiler,
             handler);
 
+  ResolvedAst getResolvedAst(Element element) {
+    return compiler.backend.frontend.getResolvedAst(element.declaration);
+  }
+
   void analyzeSuperConstructorCall(Element target, ArgumentsTypes arguments) {
-    inferrer.analyze(target, arguments);
+    ResolvedAst resolvedAst = getResolvedAst(target);
+    inferrer.analyze(resolvedAst, arguments);
     isThisExposed = isThisExposed || inferrer.checkIfExposesThis(target);
   }
 
   T run() {
-    var node = analyzedElement.node;
+    var node;
+    if (resolvedAst.kind == ResolvedAstKind.PARSED) {
+      node = resolvedAst.node;
+    }
     ast.Expression initializer;
     if (analyzedElement.isField) {
-      VariableElement fieldElement = analyzedElement;
-      initializer = fieldElement.initializer;
+      initializer = resolvedAst.body;
       if (initializer == null) {
         // Eagerly bailout, because computing the closure data only
         // works for functions and field assignments.
@@ -475,7 +487,8 @@
         cls.forEachInstanceField((_, FieldElement field) {
           if (field.isFinal) return;
           T type = locals.fieldScope.readField(field);
-          if (type == null && field.initializer == null) {
+          ResolvedAst resolvedAst = getResolvedAst(field);
+          if (type == null && resolvedAst.body == null) {
             inferrer.recordTypeOfNonFinalField(
                 spannable, field, types.nullType);
           }
@@ -552,7 +565,7 @@
     LocalsHandler closureLocals =
         new LocalsHandler<T>.from(locals, node, useOtherTryBlock: false);
     SimpleTypeInferrerVisitor visitor = new SimpleTypeInferrerVisitor<T>(
-        element, element.resolvedAst, compiler, inferrer, closureLocals);
+        element, getResolvedAst(element), compiler, inferrer, closureLocals);
     visitor.run();
     inferrer.recordReturnType(element, visitor.returnType);
 
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
index 2936432..62a9efd 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
@@ -9,6 +9,7 @@
 import '../common.dart';
 import '../common/names.dart' show Identifiers;
 import '../compiler.dart' show Compiler;
+import '../constants/expressions.dart' show ConstantExpression;
 import '../constants/values.dart';
 import '../dart_types.dart' show DartType;
 import '../elements/elements.dart';
@@ -663,15 +664,15 @@
     if (compiler.options.verbose) {
       compiler.progress.reset();
     }
-    sortResolvedElements().forEach((Element element) {
-      assert(compiler.enqueuer.resolution.hasBeenProcessed(element));
+    sortResolvedAsts().forEach((ResolvedAst resolvedAst) {
       if (compiler.shouldPrintProgress) {
         reporter.log('Added $addedInGraph elements in inferencing graph.');
         compiler.progress.reset();
       }
       // This also forces the creation of the [ElementTypeInformation] to ensure
       // it is in the graph.
-      types.withMember(element, () => analyze(element, null));
+      types.withMember(
+          resolvedAst.element.implementation, () => analyze(resolvedAst, null));
     });
     reporter.log('Added $addedInGraph elements in inferencing graph.');
 
@@ -827,13 +828,13 @@
     processLoopInformation();
   }
 
-  void analyze(AstElement element, ArgumentsTypes arguments) {
-    element = element.implementation;
+  void analyze(ResolvedAst resolvedAst, ArgumentsTypes arguments) {
+    AstElement element = resolvedAst.element.implementation;
     if (analyzedElements.contains(element)) return;
     analyzedElements.add(element);
 
-    SimpleTypeInferrerVisitor visitor = new SimpleTypeInferrerVisitor(
-        element, element.resolvedAst, compiler, this);
+    SimpleTypeInferrerVisitor visitor =
+        new SimpleTypeInferrerVisitor(element, resolvedAst, compiler, this);
     TypeInformation type;
     reporter.withCurrentElement(element, () {
       type = visitor.run();
@@ -842,17 +843,19 @@
 
     if (element.isField) {
       VariableElement fieldElement = element;
-      ast.Node node = fieldElement.node;
+      ast.Node node = resolvedAst.node;
+      ast.Node initializer = resolvedAst.body;
       if (element.isFinal || element.isConst) {
         // If [element] is final and has an initializer, we record
         // the inferred type.
-        if (fieldElement.initializer != null) {
+        if (resolvedAst.body != null) {
           if (type is! ListTypeInformation && type is! MapTypeInformation) {
             // For non-container types, the constant handler does
             // constant folding that could give more precise results.
-            ConstantValue value = compiler.backend.constants
-                .getConstantValue(fieldElement.constant);
-            if (value != null) {
+            ConstantExpression constant = fieldElement.constant;
+            if (constant != null) {
+              ConstantValue value =
+                  compiler.backend.constants.getConstantValue(constant);
               if (value.isFunction) {
                 FunctionConstantValue functionConstant = value;
                 type = types.allocateClosure(node, functionConstant.element);
@@ -871,7 +874,7 @@
         } else if (!element.isInstanceMember) {
           recordType(element, types.nullType);
         }
-      } else if (fieldElement.initializer == null) {
+      } else if (initializer == null) {
         // Only update types of static fields if there is no
         // assignment. Instance fields are dealt with in the constructor.
         if (Elements.isStaticOrTopLevelField(element)) {
@@ -881,9 +884,9 @@
         recordTypeOfNonFinalField(node, element, type);
       }
       if (Elements.isStaticOrTopLevelField(element) &&
-          fieldElement.initializer != null &&
+          resolvedAst.body != null &&
           !element.isConst) {
-        var argument = fieldElement.initializer;
+        var argument = resolvedAst.body;
         // TODO(13429): We could do better here by using the
         // constant handler to figure out if it's a lazy field or not.
         if (argument.asSend() != null ||
@@ -1228,15 +1231,15 @@
   // Sorts the resolved elements by size. We do this for this inferrer
   // to get the same results for [ListTracer] compared to the
   // [SimpleTypesInferrer].
-  Iterable<Element> sortResolvedElements() {
+  Iterable<ResolvedAst> sortResolvedAsts() {
     int max = 0;
-    Map<int, Setlet<Element>> methodSizes = new Map<int, Setlet<Element>>();
+    Map<int, Setlet<ResolvedAst>> methodSizes = <int, Setlet<ResolvedAst>>{};
     compiler.enqueuer.resolution.processedElements
         .forEach((AstElement element) {
       // TODO(ngeoffray): Not sure why the resolver would put a null
       // mapping.
       if (!compiler.enqueuer.resolution.hasBeenProcessed(element)) return;
-      ResolvedAst resolvedAst = element.resolvedAst;
+      ResolvedAst resolvedAst = getResolvedAst(element);
       element = element.implementation;
       if (element.impliesType) return;
       assert(invariant(
@@ -1256,14 +1259,14 @@
         length = mapping.getSelectorCount();
       }
       max = length > max ? length : max;
-      Setlet<Element> set =
-          methodSizes.putIfAbsent(length, () => new Setlet<Element>());
-      set.add(element);
+      Setlet<ResolvedAst> set =
+          methodSizes.putIfAbsent(length, () => new Setlet<ResolvedAst>());
+      set.add(resolvedAst);
     });
 
-    List<Element> result = <Element>[];
+    List<ResolvedAst> result = <ResolvedAst>[];
     for (int i = 0; i <= max; i++) {
-      Setlet<Element> set = methodSizes[i];
+      Setlet<ResolvedAst> set = methodSizes[i];
       if (set != null) result.addAll(set);
     }
     return result;
diff --git a/pkg/compiler/lib/src/io/position_information.dart b/pkg/compiler/lib/src/io/position_information.dart
index 3b01a6f..321943f 100644
--- a/pkg/compiler/lib/src/io/position_information.dart
+++ b/pkg/compiler/lib/src/io/position_information.dart
@@ -101,8 +101,8 @@
   const PositionSourceInformationStrategy();
 
   @override
-  SourceInformationBuilder createBuilderForContext(AstElement element) {
-    return new PositionSourceInformationBuilder(element);
+  SourceInformationBuilder createBuilderForContext(ResolvedAst resolvedAst) {
+    return new PositionSourceInformationBuilder(resolvedAst);
   }
 
   @override
@@ -141,12 +141,12 @@
 class PositionSourceInformationBuilder implements SourceInformationBuilder {
   final SourceFile sourceFile;
   final String name;
-  final AstElement element;
+  final ResolvedAst resolvedAst;
 
-  PositionSourceInformationBuilder(AstElement element)
-      : this.element = element,
-        sourceFile = element.implementation.compilationUnit.script.file,
-        name = computeElementNameForSourceMaps(element);
+  PositionSourceInformationBuilder(ResolvedAst resolvedAst)
+      : this.resolvedAst = resolvedAst,
+        sourceFile = computeSourceFile(resolvedAst),
+        name = computeElementNameForSourceMaps(resolvedAst.element);
 
   SourceInformation buildDeclaration(ResolvedAst resolvedAst) {
     if (resolvedAst.kind != ResolvedAstKind.PARSED) {
@@ -238,15 +238,10 @@
 
   @override
   SourceInformation buildVariableDeclaration() {
-    if (element.hasNode) {
-      Node node = element.node;
-      if (node is FunctionExpression) {
-        return buildBegin(node.body);
-      } else if (element.isField) {
-        FieldElement field = element;
-        if (field.initializer != null) {
-          return buildBegin(field.initializer);
-        }
+    if (resolvedAst.kind == ResolvedAstKind.PARSED) {
+      Node body = resolvedAst.body;
+      if (body != null) {
+        return buildBegin(body);
       }
       // TODO(johnniwinther): Are there other cases?
     }
@@ -254,8 +249,8 @@
   }
 
   @override
-  SourceInformationBuilder forContext(AstElement element) {
-    return new PositionSourceInformationBuilder(element);
+  SourceInformationBuilder forContext(ResolvedAst resolvedAst) {
+    return new PositionSourceInformationBuilder(resolvedAst);
   }
 
   @override
diff --git a/pkg/compiler/lib/src/io/source_information.dart b/pkg/compiler/lib/src/io/source_information.dart
index cf3872c..a84d8bf 100644
--- a/pkg/compiler/lib/src/io/source_information.dart
+++ b/pkg/compiler/lib/src/io/source_information.dart
@@ -5,8 +5,15 @@
 library dart2js.source_information;
 
 import '../common.dart';
-import '../elements/elements.dart' show AstElement, LocalElement, ResolvedAst;
+import '../elements/elements.dart'
+    show
+        AstElement,
+        CompilationUnitElement,
+        LocalElement,
+        ResolvedAst,
+        ResolvedAstKind;
 import '../js/js.dart' show JavaScriptNodeSourceInformation;
+import '../script.dart';
 import '../tree/tree.dart' show Node;
 import 'source_file.dart';
 
@@ -37,8 +44,8 @@
 class SourceInformationStrategy {
   const SourceInformationStrategy();
 
-  /// Create a [SourceInformationBuilder] for [element].
-  SourceInformationBuilder createBuilderForContext(AstElement element) {
+  /// Create a [SourceInformationBuilder] for [resolvedAst].
+  SourceInformationBuilder createBuilderForContext(ResolvedAst resolvedAst) {
     return const SourceInformationBuilder();
   }
 
@@ -53,8 +60,8 @@
 class SourceInformationBuilder {
   const SourceInformationBuilder();
 
-  /// Create a [SourceInformationBuilder] for [element].
-  SourceInformationBuilder forContext(AstElement element) => this;
+  /// Create a [SourceInformationBuilder] for [resolvedAst].
+  SourceInformationBuilder forContext(ResolvedAst resolvedAst) => this;
 
   /// Generate [SourceInformation] the declaration of the element in
   /// [resolvedAst].
@@ -151,7 +158,9 @@
   int _line;
 
   SourceLocation(this._sourceFile) {
-    assert(isValid);
+    assert(invariant(new SourceSpan(sourceUri, 0, 0), isValid,
+        message: "Invalid source location in ${sourceUri}: "
+            "offset=$offset, length=${_sourceFile.length}."));
   }
 
   /// The absolute URI of the source file of this source location.
@@ -244,3 +253,32 @@
     return element.name;
   }
 }
+
+/// Computes the [SourceFile] for the source code of [resolvedAst].
+SourceFile computeSourceFile(ResolvedAst resolvedAst) {
+  SourceFile sourceFile;
+  if (resolvedAst.kind != ResolvedAstKind.PARSED) {
+    // Synthesized node. Use the enclosing element for the location.
+    sourceFile = resolvedAst.element.compilationUnit.script.file;
+  } else {
+    Uri uri = resolvedAst.sourceUri;
+    AstElement implementation = resolvedAst.element.implementation;
+    Script script = implementation.compilationUnit.script;
+    if (uri == script.resourceUri) {
+      sourceFile = script.file;
+    } else {
+      // Slow path, happens only for deserialized elements.
+      // TODO(johnniwinther): Support a way to get a [SourceFile] from a
+      // [Uri].
+      for (CompilationUnitElement compilationUnit
+          in implementation.library.compilationUnits) {
+        Script script = compilationUnit.script;
+        if (uri == script.resourceUri) {
+          sourceFile = script.file;
+          break;
+        }
+      }
+    }
+  }
+  return sourceFile;
+}
diff --git a/pkg/compiler/lib/src/io/start_end_information.dart b/pkg/compiler/lib/src/io/start_end_information.dart
index ccc4d6b..1734aa9 100644
--- a/pkg/compiler/lib/src/io/start_end_information.dart
+++ b/pkg/compiler/lib/src/io/start_end_information.dart
@@ -63,16 +63,13 @@
   static StartEndSourceInformation _computeSourceInformation(
       ResolvedAst resolvedAst) {
     String name = computeElementNameForSourceMaps(resolvedAst.element);
-    SourceFile sourceFile;
+    SourceFile sourceFile = computeSourceFile(resolvedAst);
     int begin;
     int end;
     if (resolvedAst.kind != ResolvedAstKind.PARSED) {
       // Synthesized node. Use the enclosing element for the location.
-      sourceFile = resolvedAst.element.compilationUnit.script.file;
       begin = end = resolvedAst.element.sourcePosition.begin;
     } else {
-      AstElement implementation = resolvedAst.element.implementation;
-      sourceFile = implementation.compilationUnit.script.file;
       Node node = resolvedAst.node;
       begin = node.getBeginToken().charOffset;
       end = node.getEndToken().charOffset;
@@ -116,8 +113,8 @@
   const StartEndSourceInformationStrategy();
 
   @override
-  SourceInformationBuilder createBuilderForContext(AstElement element) {
-    return new StartEndSourceInformationBuilder(element);
+  SourceInformationBuilder createBuilderForContext(ResolvedAst resolvedAst) {
+    return new StartEndSourceInformationBuilder(resolvedAst);
   }
 
   @override
@@ -158,9 +155,9 @@
   final SourceFile sourceFile;
   final String name;
 
-  StartEndSourceInformationBuilder(AstElement element)
-      : sourceFile = element.compilationUnit.script.file,
-        name = computeElementNameForSourceMaps(element);
+  StartEndSourceInformationBuilder(ResolvedAst resolvedAst)
+      : sourceFile = computeSourceFile(resolvedAst),
+        name = computeElementNameForSourceMaps(resolvedAst.element);
 
   SourceInformation buildDeclaration(ResolvedAst resolvedAst) {
     return StartEndSourceInformation._computeSourceInformation(resolvedAst);
@@ -219,8 +216,8 @@
   SourceInformation buildIf(Node node) => buildGeneric(node);
 
   @override
-  SourceInformationBuilder forContext(AstElement element,
+  SourceInformationBuilder forContext(ResolvedAst resolvedAst,
       {SourceInformation sourceInformation}) {
-    return new StartEndSourceInformationBuilder(element);
+    return new StartEndSourceInformationBuilder(resolvedAst);
   }
 }
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index 83cab66..f5eac4a 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -1474,9 +1474,9 @@
     }
     if (kind.category == ElementCategory.VARIABLE) {
       VariableElement variableElement = element;
-      ConstantValue initialValue =
-          constants.getConstantValue(variableElement.constant);
-      if (initialValue != null) {
+      ConstantExpression constant = variableElement.constant;
+      if (constant != null) {
+        ConstantValue initialValue = constants.getConstantValue(constant);
         registerCompileTimeConstant(initialValue, work.registry);
         addCompileTimeConstantForEmission(initialValue);
         // We don't need to generate code for static or top-level
@@ -1851,7 +1851,9 @@
       if (library.isPlatformLibrary &&
           // Don't patch library currently disallowed.
           !library.isSynthesized &&
-          !library.isPatched) {
+          !library.isPatched &&
+          // Don't patch deserialized libraries.
+          !compiler.serialization.isDeserialized(library)) {
         // Apply patch, if any.
         Uri patchUri = compiler.resolvePatchUri(library.canonicalUri.path);
         if (patchUri != null) {
@@ -2505,11 +2507,33 @@
   }
 
   @override
-  ResolvedAst getResolvedAst(Element element) {
+  bool hasResolvedAst(ExecutableElement element) {
+    if (element is SynthesizedCallMethodElementX) {
+      return true;
+    } else if (element is ConstructorBodyElementX) {
+      return true;
+    } else if (element is FieldElementX) {
+      return true;
+    } else if (element is DeferredLoaderGetterElementX) {
+      return true;
+    } else {
+      return resolution.hasResolvedAst(element);
+    }
+  }
+
+  @override
+  ResolvedAst getResolvedAst(ExecutableElement element) {
     if (element is SynthesizedCallMethodElementX) {
       return element.resolvedAst;
     } else if (element is ConstructorBodyElementX) {
       return element.resolvedAst;
+    } else if (element is DeferredLoaderGetterElementX) {
+      return element.resolvedAst;
+    } else if (element is FieldElementX) {
+      // TODO(johnniwinther): Find a good invariant for resolution of fields.
+      // Currently some but not all are resolved (maybe it has to do with
+      // initializers?)
+      return element.resolvedAst;
     } else {
       assert(invariant(element, resolution.hasResolvedAst(element.declaration),
           message: 'No ResolvedAst for $element'));
diff --git a/pkg/compiler/lib/src/js_backend/backend_serialization.dart b/pkg/compiler/lib/src/js_backend/backend_serialization.dart
index cc7cc03f..d0594f4 100644
--- a/pkg/compiler/lib/src/js_backend/backend_serialization.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_serialization.dart
@@ -140,9 +140,9 @@
         .getStrings(SPECIAL_TYPES_RETURNED, isOptional: true)
         .map(SpecialType.fromName));
 
-    behavior.typesReturned
+    behavior.typesInstantiated
         .addAll(decoder.getTypes(DART_TYPES_INSTANTIATED, isOptional: true));
-    behavior.typesReturned.addAll(decoder
+    behavior.typesInstantiated.addAll(decoder
         .getStrings(SPECIAL_TYPES_INSTANTIATED, isOptional: true)
         .map(SpecialType.fromName));
 
diff --git a/pkg/compiler/lib/src/js_backend/codegen/task.dart b/pkg/compiler/lib/src/js_backend/codegen/task.dart
index cf21b0b..c293d5a 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/task.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/task.dart
@@ -336,7 +336,7 @@
       code = backend.rewriteAsync(element, code);
       work.registry.registerAsyncMarker(element);
     }
-    return attachPosition(code, element);
+    return attachPosition(code, work.resolvedAst);
   }
 
   Iterable<CompilerTask> get tasks {
@@ -348,9 +348,9 @@
     ]..addAll(fallbackCompiler.tasks);
   }
 
-  js.Node attachPosition(js.Node node, AstElement element) {
+  js.Node attachPosition(js.Node node, ResolvedAst resolvedAst) {
     return node.withSourceInformation(sourceInformationFactory
-        .createBuilderForContext(element)
-        .buildDeclaration(backend.frontend.getResolvedAst(element)));
+        .createBuilderForContext(resolvedAst)
+        .buildDeclaration(resolvedAst));
   }
 }
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 3bc94e5..2383662 100644
--- a/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart
@@ -245,7 +245,11 @@
     }
   }
 
+  @override
   ConstantValue getConstantValue(ConstantExpression expression) {
+    assert(invariant(CURRENT_ELEMENT_SPANNABLE, expression != null,
+        message: "ConstantExpression is null in getConstantValue."));
+    evaluate(expression);
     ConstantValue value = super.getConstantValue(expression);
     if (value == null &&
         expression != null &&
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 add7563..f3d2b4c 100644
--- a/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart
@@ -10,7 +10,7 @@
 import '../constant_system_dart.dart';
 import '../core_types.dart' show CoreTypes;
 import '../dart_types.dart';
-import '../elements/elements.dart' show ClassElement;
+import '../elements/elements.dart' show ClassElement, FieldElement;
 import '../tree/tree.dart' show DartString, LiteralDartString;
 import 'js_backend.dart';
 
@@ -345,6 +345,21 @@
     return new JavaScriptMapConstant(
         type, keysList, values, protoValue, onlyStringKeys);
   }
+
+  @override
+  ConstantValue createSymbol(Compiler compiler, String text) {
+    // TODO(johnniwinther): Create a backend agnostic value.
+    InterfaceType type = compiler.coreTypes.symbolType;
+    ConstantValue argument = createString(new DartString.literal(text));
+    Map<FieldElement, ConstantValue> fields = <FieldElement, ConstantValue>{};
+    JavaScriptBackend backend = compiler.backend;
+    backend.helpers.symbolImplementationClass.forEachInstanceField(
+        (ClassElement enclosingClass, FieldElement field) {
+      fields[field] = argument;
+    });
+    assert(fields.length == 1);
+    return new ConstructedConstantValue(type, fields);
+  }
 }
 
 class JavaScriptMapConstant extends MapConstantValue {
diff --git a/pkg/compiler/lib/src/js_backend/js_backend.dart b/pkg/compiler/lib/src/js_backend/js_backend.dart
index 6be55db..900a965 100644
--- a/pkg/compiler/lib/src/js_backend/js_backend.dart
+++ b/pkg/compiler/lib/src/js_backend/js_backend.dart
@@ -38,7 +38,8 @@
 import '../diagnostics/invariant.dart' show DEBUG_MODE;
 import '../dump_info.dart' show DumpInfoTask;
 import '../elements/elements.dart';
-import '../elements/modelx.dart' show ConstructorBodyElementX;
+import '../elements/modelx.dart'
+    show ConstructorBodyElementX, FieldElementX, DeferredLoaderGetterElementX;
 import '../elements/visitor.dart' show BaseElementVisitor;
 import '../enqueue.dart' show Enqueuer, ResolutionEnqueuer;
 import '../io/code_output.dart';
diff --git a/pkg/compiler/lib/src/parser/node_listener.dart b/pkg/compiler/lib/src/parser/node_listener.dart
index 9f6e18b..b5cb91d 100644
--- a/pkg/compiler/lib/src/parser/node_listener.dart
+++ b/pkg/compiler/lib/src/parser/node_listener.dart
@@ -344,13 +344,13 @@
     AsyncModifier asyncModifier = popNode();
     NodeList initializers = popNode();
     NodeList formals = popNode();
-    popNode(); // typeVariables
+    NodeList typeVariables = popNode();
     // The name can be an identifier or a send in case of named constructors.
     Expression name = popNode();
     TypeAnnotation type = popNode();
     Modifiers modifiers = popNode();
-    pushNode(new FunctionExpression(name, formals, body, type, modifiers,
-        initializers, getOrSet, asyncModifier));
+    pushNode(new FunctionExpression(name, typeVariables, formals, body, type,
+        modifiers, initializers, getOrSet, asyncModifier));
   }
 
   void endFunctionDeclaration(Token endToken) {
@@ -493,12 +493,12 @@
     AsyncModifier asyncModifier = popNode();
     NodeList initializers = popNode();
     NodeList formalParameters = popNode();
-    popNode(); // typeVariables
+    NodeList typeVariables = popNode();
     Expression name = popNode();
     TypeAnnotation returnType = popNode();
     Modifiers modifiers = popNode();
-    pushNode(new FunctionExpression(name, formalParameters, body, returnType,
-        modifiers, initializers, getOrSet, asyncModifier));
+    pushNode(new FunctionExpression(name, typeVariables, formalParameters, body,
+        returnType, modifiers, initializers, getOrSet, asyncModifier));
   }
 
   void handleLiteralMap(
@@ -564,12 +564,12 @@
 
   void handleFunctionTypedFormalParameter(Token endToken) {
     NodeList formals = popNode();
-    popNode(); // typeVariables
+    NodeList typeVariables = popNode();
     Identifier name = popNode();
     TypeAnnotation returnType = popNode();
     pushNode(null); // Signal "no type" to endFormalParameter.
-    pushNode(new FunctionExpression(
-        name, formals, null, returnType, Modifiers.EMPTY, null, null, null));
+    pushNode(new FunctionExpression(name, typeVariables, formals, null,
+        returnType, Modifiers.EMPTY, null, null, null));
   }
 
   void handleValuedFormalParameter(Token equals, Token token) {
@@ -675,7 +675,7 @@
     Modifiers modifiers = popNode();
 
     pushNode(new FunctionExpression(
-        name, formals, body, null, modifiers, null, null, asyncModifier));
+        name, null, formals, body, null, modifiers, null, null, asyncModifier));
   }
 
   void endForIn(
@@ -754,9 +754,9 @@
     Statement body = popNode();
     AsyncModifier asyncModifier = popNode();
     NodeList formals = popNode();
-    popNode(); // typeVariables
-    pushNode(new FunctionExpression(
-        null, formals, body, null, Modifiers.EMPTY, null, null, asyncModifier));
+    NodeList typeVariables = popNode();
+    pushNode(new FunctionExpression(null, typeVariables, formals, body, null,
+        Modifiers.EMPTY, null, null, asyncModifier));
   }
 
   void handleIsOperator(Token operathor, Token not, Token endToken) {
diff --git a/pkg/compiler/lib/src/resolution/enum_creator.dart b/pkg/compiler/lib/src/resolution/enum_creator.dart
index 6b0acfa..0dd861a 100644
--- a/pkg/compiler/lib/src/resolution/enum_creator.dart
+++ b/pkg/compiler/lib/src/resolution/enum_creator.dart
@@ -82,11 +82,12 @@
         symbolToken(Precedence.SEMICOLON_INFO), expression);
   }
 
-  FunctionExpression functionExpression(
-      Modifiers modifiers, String name, NodeList argumentList, Statement body,
+  FunctionExpression functionExpression(Modifiers modifiers, String name,
+      NodeList typeVariables, NodeList argumentList, Statement body,
       [TypeAnnotation returnType]) {
     return new FunctionExpression(
         identifier(name),
+        typeVariables,
         argumentList,
         body,
         returnType,
@@ -229,6 +230,7 @@
     FunctionExpression constructorNode = builder.functionExpression(
         builder.modifiers(isConst: true),
         enumClass.name,
+        null, // typeVariables
         builder.argumentList([indexDefinition]),
         builder.emptyStatement());
 
@@ -247,15 +249,15 @@
     enumClass.addMember(constructor, reporter);
 
     List<EnumConstantElement> enumValues = <EnumConstantElement>[];
-    VariableList variableList =
-        new VariableList(builder.modifiers(isStatic: true, isConst: true));
-    variableList.type = enumType;
     int index = 0;
     List<Node> valueReferences = <Node>[];
     List<LiteralMapEntry> mapEntries = <LiteralMapEntry>[];
     for (Link<Node> link = node.names.nodes; !link.isEmpty; link = link.tail) {
       Identifier name = link.head;
       AstBuilder valueBuilder = new AstBuilder(name.token.charOffset);
+      VariableList variableList = new VariableList(
+          valueBuilder.modifiers(isStatic: true, isConst: true));
+      variableList.type = enumType;
 
       // Add reference for the `values` field.
       valueReferences.add(valueBuilder.reference(name));
@@ -298,6 +300,7 @@
     FunctionExpression toStringNode = builder.functionExpression(
         Modifiers.EMPTY,
         'toString',
+        null, // typeVariables
         builder.argumentList([]),
         builder.returnStatement(builder.indexGet(
             builder.mapLiteral(mapEntries, isConst: true),
diff --git a/pkg/compiler/lib/src/resolution/members.dart b/pkg/compiler/lib/src/resolution/members.dart
index c8d9293..68f6f31 100644
--- a/pkg/compiler/lib/src/resolution/members.dart
+++ b/pkg/compiler/lib/src/resolution/members.dart
@@ -17,6 +17,7 @@
 import '../elements/elements.dart';
 import '../elements/modelx.dart'
     show
+        BaseFunctionElementX,
         ConstructorElementX,
         ErroneousElementX,
         FunctionElementX,
@@ -143,7 +144,7 @@
 
   ResolverVisitor(
       Compiler compiler, Element element, ResolutionRegistry registry,
-      {bool useEnclosingScope: false})
+      {Scope scope, bool useEnclosingScope: false})
       : this.enclosingElement = element,
         // When the element is a field, we are actually resolving its
         // initial value, which should not have access to instance
@@ -153,9 +154,10 @@
         this.currentClass =
             element.isClassMember ? element.enclosingClass : null,
         this.statementScope = new StatementScope(),
-        scope = useEnclosingScope
-            ? Scope.buildEnclosingScope(element)
-            : element.buildScope(),
+        this.scope = scope ??
+            (useEnclosingScope
+                ? Scope.buildEnclosingScope(element)
+                : element.buildScope()),
         // The type annotations on a typedef do not imply type checks.
         // TODO(karlklose): clean this up (dartbug.com/8870).
         inCheckContext = compiler.options.enableTypeAssertions &&
@@ -408,16 +410,21 @@
     if (node.modifiers.isStatic && enclosingElement.kind != ElementKind.CLASS) {
       reporter.reportErrorMessage(node, MessageKind.ILLEGAL_STATIC);
     }
+    FunctionSignature functionSignature = function.functionSignature;
 
+    // Create the scope where the type variables are introduced, if any.
     scope = new MethodScope(scope, function);
-    // Put the parameters in scope.
-    FunctionSignature functionParameters = function.functionSignature;
+    functionSignature.typeVariables
+        .forEach((DartType type) => addToScope(type.element));
+
+    // Create the scope for the function body, and put the parameters in scope.
+    scope = new BlockScope(scope);
     Link<Node> parameterNodes =
         (node.parameters == null) ? const Link<Node>() : node.parameters.nodes;
-    functionParameters.forEachParameter((ParameterElementX element) {
+    functionSignature.forEachParameter((ParameterElementX element) {
       // TODO(karlklose): should be a list of [FormalElement]s, but the actual
       // implementation uses [Element].
-      List<Element> optionals = functionParameters.optionalParameters;
+      List<Element> optionals = functionSignature.optionalParameters;
       if (!optionals.isEmpty && element == optionals.first) {
         NodeList nodes = parameterNodes.head;
         parameterNodes = nodes.nodes;
@@ -446,14 +453,13 @@
       parameterNodes = parameterNodes.tail;
     });
     addDeferredAction(enclosingElement, () {
-      functionParameters
-          .forEachOptionalParameter((ParameterElementX parameter) {
+      functionSignature.forEachOptionalParameter((ParameterElementX parameter) {
         parameter.constant =
             compiler.resolver.constantCompiler.compileConstant(parameter);
       });
     });
     if (inCheckContext) {
-      functionParameters.forEachParameter((ParameterElement element) {
+      functionSignature.forEachParameter((ParameterElement element) {
         registry.registerTypeUse(new TypeUse.checkedModeCheck(element.type));
       });
     }
@@ -570,7 +576,13 @@
         name, node, ElementKind.FUNCTION, Modifiers.EMPTY, enclosingElement);
     ResolverTask.processAsyncMarker(compiler, function, registry);
     function.functionSignature = SignatureResolver.analyze(
-        compiler, node.parameters, node.returnType, function, registry,
+        compiler,
+        scope,
+        node.typeVariables,
+        node.parameters,
+        node.returnType,
+        function,
+        registry,
         createRealParameters: true,
         isFunctionExpression: !inFunctionDeclaration);
     checkLocalDefinitionName(node, function);
@@ -1864,7 +1876,7 @@
   ResolutionResult handleTypeVariableTypeLiteralAccess(
       Send node, Name name, TypeVariableElement element) {
     AccessSemantics semantics;
-    if (!Elements.hasAccessToTypeVariables(enclosingElement)) {
+    if (!Elements.hasAccessToTypeVariable(enclosingElement, element)) {
       // TODO(johnniwinther): Add another access semantics for this.
       ErroneousElement error = reportAndCreateErroneousElement(
           node,
@@ -1905,7 +1917,7 @@
   ResolutionResult handleTypeVariableTypeLiteralUpdate(
       SendSet node, Name name, TypeVariableElement element) {
     AccessSemantics semantics;
-    if (!Elements.hasAccessToTypeVariables(enclosingElement)) {
+    if (!Elements.hasAccessToTypeVariable(enclosingElement, element)) {
       // TODO(johnniwinther): Add another access semantics for this.
       ErroneousElement error = reportAndCreateErroneousElement(
           node,
@@ -3537,8 +3549,8 @@
 
   ResolutionResult visitYield(Yield node) {
     if (!compiler.backend.supportsAsyncAwait) {
-      reporter.reportErrorMessage(node.yieldToken,
-          MessageKind.ASYNC_AWAIT_NOT_SUPPORTED);
+      reporter.reportErrorMessage(
+          node.yieldToken, MessageKind.ASYNC_AWAIT_NOT_SUPPORTED);
     } else {
       if (!currentAsyncMarker.isYielding) {
         reporter.reportErrorMessage(node, MessageKind.INVALID_YIELD);
@@ -3678,8 +3690,8 @@
 
   ResolutionResult visitAwait(Await node) {
     if (!compiler.backend.supportsAsyncAwait) {
-      reporter.reportErrorMessage(node.awaitToken,
-          MessageKind.ASYNC_AWAIT_NOT_SUPPORTED);
+      reporter.reportErrorMessage(
+          node.awaitToken, MessageKind.ASYNC_AWAIT_NOT_SUPPORTED);
     } else {
       if (!currentAsyncMarker.isAsync) {
         reporter.reportErrorMessage(node, MessageKind.INVALID_AWAIT);
@@ -4205,18 +4217,16 @@
 
   ResolutionResult visitAsyncForIn(AsyncForIn node) {
     if (!compiler.backend.supportsAsyncAwait) {
-      reporter.reportErrorMessage(node.awaitToken,
-          MessageKind.ASYNC_AWAIT_NOT_SUPPORTED);
+      reporter.reportErrorMessage(
+          node.awaitToken, MessageKind.ASYNC_AWAIT_NOT_SUPPORTED);
     } else {
       if (!currentAsyncMarker.isAsync) {
         reporter.reportErrorMessage(
             node.awaitToken, MessageKind.INVALID_AWAIT_FOR_IN);
       }
       registry.registerFeature(Feature.ASYNC_FOR_IN);
-      registry.registerDynamicUse(
-          new DynamicUse(Selectors.current, null));
-      registry.registerDynamicUse(
-          new DynamicUse(Selectors.moveNext, null));
+      registry.registerDynamicUse(new DynamicUse(Selectors.current, null));
+      registry.registerDynamicUse(new DynamicUse(Selectors.moveNext, null));
     }
     visit(node.expression);
 
diff --git a/pkg/compiler/lib/src/resolution/resolution.dart b/pkg/compiler/lib/src/resolution/resolution.dart
index 1439518..0676ba6 100644
--- a/pkg/compiler/lib/src/resolution/resolution.dart
+++ b/pkg/compiler/lib/src/resolution/resolution.dart
@@ -979,6 +979,8 @@
       FunctionExpression node = element.parseNode(parsingContext);
       return measure(() => SignatureResolver.analyze(
           compiler,
+          element.enclosingElement.buildScope(),
+          node.typeVariables,
           node.parameters,
           node.returnType,
           element,
diff --git a/pkg/compiler/lib/src/resolution/scope.dart b/pkg/compiler/lib/src/resolution/scope.dart
index 41df803..75c3de9 100644
--- a/pkg/compiler/lib/src/resolution/scope.dart
+++ b/pkg/compiler/lib/src/resolution/scope.dart
@@ -58,17 +58,14 @@
   }
 }
 
-/**
- * [TypeDeclarationScope] defines the outer scope of a type declaration in
- * which the declared type variables and the entities in the enclosing scope are
- * available but where declared and inherited members are not available. This
- * scope is only used for class declarations during resolution of the
- * class hierarchy. In all other cases [ClassScope] is used.
- */
-class TypeDeclarationScope extends NestedScope {
-  final TypeDeclarationElement element;
+/// [TypeVariablesScope] defines the outer scope in a context where some type
+/// variables are declared and the entities in the enclosing scope are
+/// available, but where locally declared and inherited members are not
+/// available.
+abstract class TypeVariablesScope extends NestedScope {
+  List<DartType> get typeVariables;
 
-  TypeDeclarationScope(parent, this.element) : super(parent) {
+  TypeVariablesScope(Scope parent) : super(parent) {
     assert(parent != null);
   }
 
@@ -77,7 +74,6 @@
   }
 
   Element lookupTypeVariable(String name) {
-    List<DartType> typeVariables = element.typeVariables;
     for (TypeVariableType type in typeVariables) {
       if (type.name == name) {
         return type.element;
@@ -87,6 +83,22 @@
   }
 
   Element localLookup(String name) => lookupTypeVariable(name);
+}
+
+/**
+ * [TypeDeclarationScope] defines the outer scope of a type declaration in
+ * which the declared type variables and the entities in the enclosing scope are
+ * available but where declared and inherited members are not available. This
+ * scope is used for class declarations during resolution of the class hierarchy
+ * and when resolving typedef signatures. In other cases [ClassScope] is used.
+ */
+class TypeDeclarationScope extends TypeVariablesScope {
+  final GenericElement element;
+
+  @override
+  List<DartType> get typeVariables => element.typeVariables;
+
+  TypeDeclarationScope(Scope parent, this.element) : super(parent);
 
   String toString() => 'TypeDeclarationScope($element)';
 }
diff --git a/pkg/compiler/lib/src/resolution/signatures.dart b/pkg/compiler/lib/src/resolution/signatures.dart
index 36ea970..33a8f2f 100644
--- a/pkg/compiler/lib/src/resolution/signatures.dart
+++ b/pkg/compiler/lib/src/resolution/signatures.dart
@@ -15,14 +15,15 @@
         FormalElementX,
         FunctionSignatureX,
         InitializingFormalElementX,
-        LocalParameterElementX;
+        LocalParameterElementX,
+        TypeVariableElementX;
 import '../tree/tree.dart';
 import '../universe/use.dart' show TypeUse;
 import '../util/util.dart' show Link, LinkBuilder;
 import 'members.dart' show ResolverVisitor;
 import 'registry.dart' show ResolutionRegistry;
 import 'resolution_common.dart' show MappingVisitor;
-import 'scope.dart' show Scope;
+import 'scope.dart' show Scope, TypeVariablesScope;
 
 /**
  * [SignatureResolver] resolves function signatures.
@@ -40,12 +41,13 @@
   VariableDefinitions currentDefinitions;
 
   SignatureResolver(Compiler compiler, FunctionTypedElement enclosingElement,
-      ResolutionRegistry registry,
+      Scope scope, ResolutionRegistry registry,
       {this.defaultValuesError, this.createRealParameters})
-      : this.enclosingElement = enclosingElement,
-        this.scope = enclosingElement.buildScope(),
-        this.resolver =
-            new ResolverVisitor(compiler, enclosingElement, registry),
+      : this.scope = scope,
+        this.enclosingElement = enclosingElement,
+        this.resolver = new ResolverVisitor(
+            compiler, enclosingElement, registry,
+            scope: scope),
         super(compiler, registry);
 
   bool get defaultValuesAllowed => defaultValuesError == null;
@@ -110,6 +112,8 @@
     void computeFunctionType(FunctionExpression functionExpression) {
       FunctionSignature functionSignature = SignatureResolver.analyze(
           compiler,
+          scope,
+          functionExpression.typeVariables,
           functionExpression.parameters,
           functionExpression.returnType,
           element,
@@ -287,6 +291,8 @@
    */
   static FunctionSignature analyze(
       Compiler compiler,
+      Scope scope,
+      NodeList typeVariables,
       NodeList formalParameters,
       Node returnNode,
       FunctionTypedElement element,
@@ -296,8 +302,32 @@
       bool isFunctionExpression: false}) {
     DiagnosticReporter reporter = compiler.reporter;
 
+    List<DartType> createTypeVariables(NodeList typeVariableNodes) {
+      if (typeVariableNodes == null) return const <DartType>[];
+
+      // Create the types and elements corresponding to [typeVariableNodes].
+      Link<Node> nodes = typeVariableNodes.nodes;
+      List<DartType> arguments =
+          new List.generate(nodes.slowLength(), (int index) {
+        TypeVariable node = nodes.head;
+        String variableName = node.name.source;
+        nodes = nodes.tail;
+        TypeVariableElementX variableElement =
+            new TypeVariableElementX(variableName, element, index, node);
+        // TODO(eernst): When type variables are implemented fully we will need
+        // to resolve the actual bounds; currently we just claim [dynamic].
+        variableElement.boundCache = const DynamicType();
+        TypeVariableType variableType = new TypeVariableType(variableElement);
+        variableElement.typeCache = variableType;
+        return variableType;
+      }, growable: false);
+      return arguments;
+    }
+
+    List<DartType> typeVariableTypes = createTypeVariables(typeVariables);
+    scope = new FunctionSignatureBuildingScope(scope, typeVariableTypes);
     SignatureResolver visitor = new SignatureResolver(
-        compiler, element, registry,
+        compiler, element, scope, registry,
         defaultValuesError: defaultValuesError,
         createRealParameters: createRealParameters);
     List<Element> parameters = const <Element>[];
@@ -411,6 +441,7 @@
         namedParameters,
         namedParameterTypes);
     return new FunctionSignatureX(
+        typeVariables: typeVariableTypes,
         requiredParameters: parameters,
         optionalParameters: visitor.optionalParameters,
         requiredParameterCount: requiredParameterCount,
@@ -437,3 +468,15 @@
     return result;
   }
 }
+
+/// Used during `SignatureResolver.analyze` to provide access to the type
+/// variables of the function signature itself when its signature is analyzed.
+class FunctionSignatureBuildingScope extends TypeVariablesScope {
+  @override
+  final List<DartType> typeVariables;
+
+  FunctionSignatureBuildingScope(Scope parent, this.typeVariables)
+      : super(parent);
+
+  String toString() => 'FunctionSignatureBuildingScope($typeVariables)';
+}
diff --git a/pkg/compiler/lib/src/resolution/tree_elements.dart b/pkg/compiler/lib/src/resolution/tree_elements.dart
index 9c60745..1e52fca 100644
--- a/pkg/compiler/lib/src/resolution/tree_elements.dart
+++ b/pkg/compiler/lib/src/resolution/tree_elements.dart
@@ -365,7 +365,7 @@
   }
 
   @override
-  FunctionElement getFunctionDefinition(FunctionExpression node) {
+  Element getFunctionDefinition(FunctionExpression node) {
     return this[node];
   }
 
diff --git a/pkg/compiler/lib/src/resolution/type_resolver.dart b/pkg/compiler/lib/src/resolution/type_resolver.dart
index 832279b..e1a076d 100644
--- a/pkg/compiler/lib/src/resolution/type_resolver.dart
+++ b/pkg/compiler/lib/src/resolution/type_resolver.dart
@@ -18,6 +18,7 @@
         ErroneousElement,
         PrefixElement,
         TypedefElement,
+        TypeDeclarationElement,
         TypeVariableElement;
 import '../elements/modelx.dart' show ErroneousElementX;
 import '../tree/tree.dart';
@@ -205,12 +206,17 @@
           }
         }
       } else if (element.isTypeVariable) {
+        // FIXME: check enclosing, which may be not class, not typedef (so
+        // it's a generic method) then set the type to `const DynamicType()`.
+        // This should later be fixed such that we don't tell the user that they
+        // wrote `dynamic` anywhere.
         TypeVariableElement typeVariable = element;
         Element outer =
             visitor.enclosingElement.outermostEnclosingMemberOrTopLevel;
         if (!outer.isClass &&
             !outer.isTypedef &&
-            !Elements.hasAccessToTypeVariables(visitor.enclosingElement)) {
+            !Elements.hasAccessToTypeVariable(
+                visitor.enclosingElement, typeVariable)) {
           registry.registerFeature(Feature.THROW_RUNTIME_ERROR);
           type = reportFailureAndCreateType(
               MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER,
diff --git a/pkg/compiler/lib/src/resolution/typedefs.dart b/pkg/compiler/lib/src/resolution/typedefs.dart
index ed6f741..cee72df 100644
--- a/pkg/compiler/lib/src/resolution/typedefs.dart
+++ b/pkg/compiler/lib/src/resolution/typedefs.dart
@@ -31,7 +31,13 @@
     resolveTypeVariableBounds(node.typeParameters);
 
     FunctionSignature signature = SignatureResolver.analyze(
-        compiler, node.formals, node.returnType, element, registry,
+        compiler,
+        scope,
+        null /* typeVariables */,
+        node.formals,
+        node.returnType,
+        element,
+        registry,
         defaultValuesError: MessageKind.TYPEDEF_FORMAL_WITH_DEFAULT);
     element.functionSignature = signature;
 
diff --git a/pkg/compiler/lib/src/serialization/element_serialization.dart b/pkg/compiler/lib/src/serialization/element_serialization.dart
index 6f5dc4d..ebb179a 100644
--- a/pkg/compiler/lib/src/serialization/element_serialization.dart
+++ b/pkg/compiler/lib/src/serialization/element_serialization.dart
@@ -13,6 +13,7 @@
 import 'keys.dart';
 import 'modelz.dart';
 import 'serialization.dart';
+import 'serialization_util.dart';
 
 /// Enum kinds used for encoding [Element]s.
 enum SerializedElementKind {
@@ -22,7 +23,9 @@
   ENUM,
   NAMED_MIXIN_APPLICATION,
   GENERATIVE_CONSTRUCTOR,
+  DEFAULT_CONSTRUCTOR,
   FACTORY_CONSTRUCTOR,
+  REDIRECTING_FACTORY_CONSTRUCTOR,
   FORWARDING_CONSTRUCTOR,
   TOPLEVEL_FIELD,
   STATIC_FIELD,
@@ -340,13 +343,21 @@
 
   SerializedElementKind getSerializedKind(Element element) {
     if (element.isGenerativeConstructor) {
-      if (element.enclosingClass.isNamedMixinApplication) {
+      ConstructorElement constructor = element;
+      if (constructor.enclosingClass.isNamedMixinApplication) {
         return SerializedElementKind.FORWARDING_CONSTRUCTOR;
+      } else if (constructor.definingConstructor != null) {
+        return SerializedElementKind.DEFAULT_CONSTRUCTOR;
       } else {
         return SerializedElementKind.GENERATIVE_CONSTRUCTOR;
       }
     } else if (element.isFactoryConstructor) {
-      return SerializedElementKind.FACTORY_CONSTRUCTOR;
+      ConstructorElement constructor = element;
+      if (constructor.isRedirectingFactory) {
+        return SerializedElementKind.REDIRECTING_FACTORY_CONSTRUCTOR;
+      } else {
+        return SerializedElementKind.FACTORY_CONSTRUCTOR;
+      }
     }
     return null;
   }
@@ -363,13 +374,27 @@
       SerializerUtil.serializeParameters(element, encoder);
       encoder.setBool(Key.IS_CONST, element.isConst);
       encoder.setBool(Key.IS_EXTERNAL, element.isExternal);
-      if (element.isExternal) return;
       if (element.isConst && !element.isFromEnvironmentConstructor) {
         ConstantConstructor constantConstructor = element.constantConstructor;
         ObjectEncoder constantEncoder = encoder.createObject(Key.CONSTRUCTOR);
         const ConstantConstructorSerializer()
             .visit(constantConstructor, constantEncoder);
       }
+      if (kind == SerializedElementKind.GENERATIVE_CONSTRUCTOR) {
+        encoder.setBool(Key.IS_REDIRECTING, element.isRedirectingGenerative);
+      }
+      encoder.setElement(Key.EFFECTIVE_TARGET, element.effectiveTarget);
+      if (kind == SerializedElementKind.REDIRECTING_FACTORY_CONSTRUCTOR) {
+        encoder.setType(
+            Key.EFFECTIVE_TARGET_TYPE,
+            element
+                .computeEffectiveTargetType(element.enclosingClass.thisType));
+        encoder.setElement(Key.IMMEDIATE_REDIRECTION_TARGET,
+            element.immediateRedirectionTarget);
+        if (element.redirectionDeferredPrefix != null) {
+          encoder.setElement(Key.PREFIX, element.redirectionDeferredPrefix);
+        }
+      }
     }
   }
 }
@@ -658,8 +683,12 @@
         return new InstanceFieldElementZ(decoder);
       case SerializedElementKind.GENERATIVE_CONSTRUCTOR:
         return new GenerativeConstructorElementZ(decoder);
+      case SerializedElementKind.DEFAULT_CONSTRUCTOR:
+        return new DefaultConstructorElementZ(decoder);
       case SerializedElementKind.FACTORY_CONSTRUCTOR:
         return new FactoryConstructorElementZ(decoder);
+      case SerializedElementKind.REDIRECTING_FACTORY_CONSTRUCTOR:
+        return new RedirectingFactoryConstructorElementZ(decoder);
       case SerializedElementKind.FORWARDING_CONSTRUCTOR:
         return new ForwardingConstructorElementZ(
             decoder.getElement(Key.CLASS), decoder.getElement(Key.ELEMENT));
diff --git a/pkg/compiler/lib/src/serialization/equivalence.dart b/pkg/compiler/lib/src/serialization/equivalence.dart
index acf3e71..969ef40 100644
--- a/pkg/compiler/lib/src/serialization/equivalence.dart
+++ b/pkg/compiler/lib/src/serialization/equivalence.dart
@@ -6,6 +6,7 @@
 
 library dart2js.serialization.equivalence;
 
+import '../common.dart';
 import '../common/resolution.dart';
 import '../constants/expressions.dart';
 import '../dart_types.dart';
@@ -770,7 +771,9 @@
           'node', resolvedAst1.node, resolvedAst2.node) &&
       new NodeEquivalenceVisitor(strategy).testNodes(resolvedAst1, resolvedAst2,
           'body', resolvedAst1.body, resolvedAst2.body) &&
-      testTreeElementsEquivalence(resolvedAst1, resolvedAst2, strategy);
+      testTreeElementsEquivalence(resolvedAst1, resolvedAst2, strategy) &&
+      strategy.test(resolvedAst1, resolvedAst2, 'sourceUri',
+          resolvedAst1.sourceUri, resolvedAst2.sourceUri);
 }
 
 /// Tests the equivalence of the data stored in the [TreeElements] of
@@ -1054,30 +1057,39 @@
 
   bool testNodes(
       var object1, var object2, String property, Node node1, Node node2) {
-    if (node1 == node2) return true;
-    if (node1 == null || node2 == null) return false;
-    return node1.accept1(this, node2);
+    return strategy.test(object1, object2, property, node1, node2,
+        (Node n1, Node n2) {
+      if (n1 == n2) return true;
+      if (n1 == null || n2 == null) return false;
+      return n1.accept1(this, n2);
+    });
   }
 
   bool testNodeLists(var object1, var object2, String property,
       Link<Node> list1, Link<Node> list2) {
-    if (list1 == list2) return true;
-    if (list1 == null || list2 == null) return false;
-    while (list1.isNotEmpty && list2.isNotEmpty) {
-      if (!list1.head.accept1(this, list2.head)) {
-        return false;
+    return strategy.test(object1, object2, property, list1, list2,
+        (Link<Node> l1, Link<Node> l2) {
+      if (l1 == l2) return true;
+      if (l1 == null || l2 == null) return false;
+      while (l1.isNotEmpty && l2.isNotEmpty) {
+        if (!l1.head.accept1(this, l2.head)) {
+          return false;
+        }
+        l1 = l1.tail;
+        l2 = l2.tail;
       }
-      list1 = list1.tail;
-      list2 = list2.tail;
-    }
-    return list1.isEmpty && list2.isEmpty;
+      return l1.isEmpty && l2.isEmpty;
+    });
   }
 
   bool testTokens(
       var object1, var object2, String property, Token token1, Token token2) {
-    if (token1 == token2) return true;
-    if (token1 == null || token2 == null) return false;
-    return token1.hashCode == token2.hashCode;
+    return strategy.test(object1, object2, property, token1, token2,
+        (Token t1, Token t2) {
+      if (t1 == t2) return true;
+      if (t1 == null || t2 == null) return false;
+      return strategy.test(t1, t2, 'hashCode', t1.hashCode, t2.hashCode);
+    });
   }
 
   @override
diff --git a/pkg/compiler/lib/src/serialization/keys.dart b/pkg/compiler/lib/src/serialization/keys.dart
index c7599b2..de805fe 100644
--- a/pkg/compiler/lib/src/serialization/keys.dart
+++ b/pkg/compiler/lib/src/serialization/keys.dart
@@ -26,6 +26,8 @@
   static const Key DEFAULT = const Key('default');
   static const Key DEFAULTS = const Key('defaults');
   static const Key DYNAMIC_USES = const Key('dynamic-uses');
+  static const Key EFFECTIVE_TARGET = const Key('effectiveTarget');
+  static const Key EFFECTIVE_TARGET_TYPE = const Key('effectiveTargetType');
   static const Key ELEMENT = const Key('element');
   static const Key ELEMENTS = const Key('elements');
   static const Key EXECUTABLE_CONTEXT = const Key('executable-context');
@@ -40,6 +42,8 @@
   static const Key GET_OR_SET = const Key('getOrSet');
   static const Key GETTER = const Key('getter');
   static const Key ID = const Key('id');
+  static const Key IMMEDIATE_REDIRECTION_TARGET =
+      const Key('immediateRedirectionTarget');
   static const Key IMPACTS = const Key('impacts');
   static const Key IMPORT = const Key('import');
   static const Key IMPORTS = const Key('imports');
@@ -58,6 +62,7 @@
   static const Key IS_OPERATOR = const Key('isOperator');
   static const Key IS_OPTIONAL = const Key('isOptional');
   static const Key IS_PROXY = const Key('isProxy');
+  static const Key IS_REDIRECTING = const Key('isRedirecting');
   static const Key IS_SETTER = const Key('isSetter');
   static const Key IS_UNNAMED_MIXIN_APPLICATION =
       const Key('isUnnamedMixinApplication');
diff --git a/pkg/compiler/lib/src/serialization/modelz.dart b/pkg/compiler/lib/src/serialization/modelz.dart
index e77d5c0..b280d69 100644
--- a/pkg/compiler/lib/src/serialization/modelz.dart
+++ b/pkg/compiler/lib/src/serialization/modelz.dart
@@ -30,6 +30,7 @@
 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) {
@@ -63,17 +64,12 @@
   FunctionElement asFunctionElement() => null;
 
   @override
-  Scope buildScope() => _unsupported('analyzableElement');
+  Scope buildScope() => _unsupported('buildScope');
 
   @override
   ClassElement get enclosingClass => null;
 
   @override
-  Element get enclosingClassOrCompilationUnit {
-    return _unsupported('enclosingClassOrCompilationUnit');
-  }
-
-  @override
   LibraryElement get implementationLibrary => library;
 
   @override
@@ -109,9 +105,8 @@
   @override
   bool get isStatic => false;
 
-  // TODO(johnniwinther): Find a more precise semantics for this.
   @override
-  bool get isSynthesized => true;
+  bool get isSynthesized => false;
 
   @override
   bool get isTopLevel => false;
@@ -132,10 +127,14 @@
   @override
   String get name => _decoder.getString(Key.NAME);
 
+  // TODO(johnniwinther): Should this be cached?
+  @override
+  int get sourceOffset => _decoder.getInt(Key.OFFSET, isOptional: true);
+
   @override
   SourceSpan get sourcePosition {
     // TODO(johnniwinther): Should this be cached?
-    int offset = _decoder.getInt(Key.OFFSET, isOptional: true);
+    int offset = sourceOffset;
     if (offset == null) return null;
     Uri uri = _decoder.getUri(Key.URI, isOptional: true);
     if (uri == null) {
@@ -327,6 +326,9 @@
   Element get enclosingElement => _canonicalElement.enclosingElement;
 
   @override
+  int get sourceOffset => _canonicalElement.sourceOffset;
+
+  @override
   SourceSpan get sourcePosition => _canonicalElement.sourcePosition;
 
   @override
@@ -746,9 +748,6 @@
 abstract class FunctionTypedElementMixin
     implements FunctionElement, DeserializedElementZ {
   @override
-  AsyncMarker get asyncMarker => _unsupported('asyncMarker');
-
-  @override
   FunctionElement asFunctionElement() => this;
 
   @override
@@ -756,6 +755,9 @@
     return _decoder.getBool(Key.IS_EXTERNAL,
         isOptional: true, defaultValue: false);
   }
+
+  @override
+  List<DartType> get typeVariables => functionSignature.typeVariables;
 }
 
 abstract class ClassElementMixin implements ElementZ, ClassElement {
@@ -767,23 +769,9 @@
   ElementKind get kind => ElementKind.CLASS;
 
   @override
-  void addBackendMember(Element element) => _unsupported('addBackendMember');
-
-  @override
-  void forEachBackendMember(void f(Element member)) {
-    _unsupported('forEachBackendMember');
-  }
-
-  @override
-  bool get hasBackendMembers => _unsupported('hasBackendMembers');
-
-  @override
   bool get hasConstructor => _unsupported('hasConstructor');
 
   @override
-  bool hasFieldShadowedBy(Element fieldMember) => _unsupported('');
-
-  @override
   bool get hasIncompleteHierarchy => _unsupported('hasIncompleteHierarchy');
 
   @override
@@ -793,11 +781,6 @@
   bool get isEnumClass => false;
 
   @override
-  Element lookupBackendMember(String memberName) {
-    return _unsupported('lookupBackendMember');
-  }
-
-  @override
   ConstructorElement lookupDefaultConstructor() {
     ConstructorElement constructor = lookupConstructor("");
     if (constructor != null && constructor.parameters.isEmpty) {
@@ -807,9 +790,6 @@
   }
 
   @override
-  void reverseBackendMembers() => _unsupported('reverseBackendMembers');
-
-  @override
   ClassElement get superclass => supertype != null ? supertype.element : null;
 
   @override
@@ -1034,6 +1014,9 @@
   InterfaceType get mixinType => interfaces.head;
 
   @override
+  int get sourceOffset => _subclass.sourceOffset;
+
+  @override
   SourceSpan get sourcePosition => _subclass.sourcePosition;
 }
 
@@ -1063,8 +1046,12 @@
         ParametersMixin,
         TypedElementMixin,
         MemberElementMixin
-    implements ConstructorElement {
+    implements
+        ConstructorElement,
+        // TODO(johnniwinther): Sort out whether a constructor is a method.
+        MethodElement {
   ConstantConstructor _constantConstructor;
+  ConstructorElement _effectiveTarget;
 
   ConstructorElementZ(ObjectDecoder decoder) : super(decoder);
 
@@ -1103,43 +1090,42 @@
   AsyncMarker get asyncMarker => AsyncMarker.SYNC;
 
   @override
-  InterfaceType computeEffectiveTargetType(InterfaceType newType) {
-    return _unsupported('computeEffectiveTargetType');
-  }
-
-  @override
-  ConstructorElement get definingConstructor {
-    return _unsupported('definingConstructor');
-  }
+  ConstructorElement get definingConstructor => null;
 
   @override
   ConstructorElement get effectiveTarget {
-    return _unsupported('effectiveTarget');
+    if (_effectiveTarget == null) {
+      _effectiveTarget =
+          _decoder.getElement(Key.EFFECTIVE_TARGET, isOptional: true);
+      if (_effectiveTarget == null) {
+        _effectiveTarget = this;
+      }
+    }
+    return _effectiveTarget;
   }
 
   @override
-  ConstructorElement get immediateRedirectionTarget {
-    return _unsupported('immediateRedirectionTarget');
-  }
+  ConstructorElement get immediateRedirectionTarget => null;
+
+  // TODO(johnniwinther): Should serialization support erroneous element
+  // relations?
+  @override
+  bool get isEffectiveTargetMalformed => false;
 
   @override
-  bool get isEffectiveTargetMalformed {
-    return _unsupported('isEffectiveTargetMalformed');
-  }
+  bool get isCyclicRedirection => false;
 
   @override
-  bool get isRedirectingFactory => _unsupported('isRedirectingFactory');
+  bool get isRedirectingFactory => false;
 
   @override
-  bool get isRedirectingGenerative => _unsupported('isRedirectingGenerative');
+  bool get isRedirectingGenerative => false;
 
   @override
-  bool get isCyclicRedirection => _unsupported('isCyclicRedirection');
+  PrefixElement get redirectionDeferredPrefix => null;
 
   @override
-  PrefixElement get redirectionDeferredPrefix {
-    return _unsupported('redirectionDeferredPrefix');
-  }
+  InterfaceType computeEffectiveTargetType(InterfaceType newType) => newType;
 }
 
 class GenerativeConstructorElementZ extends ConstructorElementZ {
@@ -1149,8 +1135,22 @@
   ElementKind get kind => ElementKind.GENERATIVE_CONSTRUCTOR;
 
   @override
-  bool get isEffectiveTargetMalformed =>
-      _unsupported('isEffectiveTargetMalformed');
+  bool get isRedirectingGenerative => _decoder.getBool(Key.IS_REDIRECTING);
+}
+
+class DefaultConstructorElementZ extends ConstructorElementZ {
+  DefaultConstructorElementZ(ObjectDecoder decoder) : super(decoder);
+
+  @override
+  ElementKind get kind => ElementKind.GENERATIVE_CONSTRUCTOR;
+
+  @override
+  bool get isSynthesized => true;
+
+  @override
+  ConstructorElement get definingConstructor {
+    return enclosingClass.superclass.lookupConstructor('');
+  }
 }
 
 class FactoryConstructorElementZ extends ConstructorElementZ {
@@ -1158,10 +1158,66 @@
 
   @override
   ElementKind get kind => ElementKind.FACTORY_CONSTRUCTOR;
+}
+
+class RedirectingFactoryConstructorElementZ extends ConstructorElementZ {
+  InterfaceType _effectiveTargetType;
+  ConstructorElement _immediateRedirectionTarget;
+  PrefixElement _redirectionDeferredPrefix;
+
+  RedirectingFactoryConstructorElementZ(ObjectDecoder decoder) : super(decoder);
 
   @override
-  bool get isEffectiveTargetMalformed =>
-      _unsupported('isEffectiveTargetMalformed');
+  ElementKind get kind => ElementKind.FACTORY_CONSTRUCTOR;
+
+  @override
+  bool get isRedirectingFactory => true;
+
+  void _ensureEffectiveTarget() {
+    if (_effectiveTarget == null) {
+      _effectiveTarget =
+          _decoder.getElement(Key.EFFECTIVE_TARGET, isOptional: true);
+      if (_effectiveTarget == null) {
+        _effectiveTarget = this;
+        _effectiveTargetType = enclosingClass.thisType;
+      } else {
+        _effectiveTargetType = _decoder.getType(Key.EFFECTIVE_TARGET_TYPE);
+      }
+    }
+  }
+
+  @override
+  ConstructorElement get effectiveTarget {
+    _ensureEffectiveTarget();
+    return _effectiveTarget;
+  }
+
+  @override
+  InterfaceType computeEffectiveTargetType(InterfaceType newType) {
+    _ensureEffectiveTarget();
+    return _effectiveTargetType.substByContext(newType);
+  }
+
+  void _ensureRedirection() {
+    if (_immediateRedirectionTarget == null) {
+      _immediateRedirectionTarget =
+          _decoder.getElement(Key.IMMEDIATE_REDIRECTION_TARGET);
+      _redirectionDeferredPrefix =
+          _decoder.getElement(Key.PREFIX, isOptional: true);
+    }
+  }
+
+  @override
+  ConstructorElement get immediateRedirectionTarget {
+    _ensureRedirection();
+    return _immediateRedirectionTarget;
+  }
+
+  @override
+  PrefixElement get redirectionDeferredPrefix {
+    _ensureRedirection();
+    return _redirectionDeferredPrefix;
+  }
 }
 
 class ForwardingConstructorElementZ extends ElementZ
@@ -1235,6 +1291,9 @@
   bool get isRedirectingGenerative => false;
 
   @override
+  bool get isSynthesized => true;
+
+  @override
   ElementKind get kind => ElementKind.GENERATIVE_CONSTRUCTOR;
 
   @override
@@ -1264,6 +1323,9 @@
   PrefixElement get redirectionDeferredPrefix => null;
 
   @override
+  int get sourceOffset => enclosingClass.sourceOffset;
+
+  @override
   SourceSpan get sourcePosition => enclosingClass.sourcePosition;
 
   @override
@@ -1272,6 +1334,9 @@
     // variables correctly.
     return definingConstructor.type;
   }
+
+  @override
+  List<DartType> get typeVariables => _unsupported("typeVariables");
 }
 
 abstract class MemberElementMixin
@@ -1283,7 +1348,7 @@
   Name get memberName => new Name(name, library);
 
   @override
-  List<FunctionElement> get nestedClosures => const <FunctionElement>[];
+  List<FunctionElement> get nestedClosures => <FunctionElement>[];
 }
 
 abstract class FieldElementZ extends DeserializedElementZ
@@ -1449,6 +1514,11 @@
 
   @override
   ElementKind get kind => ElementKind.FUNCTION;
+
+  @override
+  AsyncMarker get asyncMarker {
+    return _decoder.getEnum(Key.ASYNC_MARKER, AsyncMarker.values);
+  }
 }
 
 abstract class GetterElementZ extends DeserializedElementZ
@@ -1743,6 +1813,9 @@
   LibraryElement get library => typeDeclaration.library;
 
   @override
+  int get sourceOffset => typeDeclaration.sourceOffset;
+
+  @override
   SourceSpan get sourcePosition => typeDeclaration.sourcePosition;
 }
 
@@ -1794,8 +1867,13 @@
   @override
   FunctionSignature get functionSignature => _unsupported('functionSignature');
 
+  // TODO(johnniwinther): HACK. Remove [initializer] and [node] on
+  // [ParameterElementZ] when the inference does need these.
   @override
-  Expression get initializer => _unsupported('initializer');
+  Expression get initializer => null;
+
+  @override
+  Node get node => null;
 
   @override
   bool get isNamed => _decoder.getBool(Key.IS_NAMED);
@@ -1808,6 +1886,9 @@
 
   @override
   MemberElement get memberContext => executableContext.memberContext;
+
+  @override
+  List<DartType> get typeVariables => functionSignature.typeVariables;
 }
 
 class LocalParameterElementZ extends ParameterElementZ
diff --git a/pkg/compiler/lib/src/serialization/resolved_ast_serialization.dart b/pkg/compiler/lib/src/serialization/resolved_ast_serialization.dart
index eb03860..613bd61 100644
--- a/pkg/compiler/lib/src/serialization/resolved_ast_serialization.dart
+++ b/pkg/compiler/lib/src/serialization/resolved_ast_serialization.dart
@@ -110,9 +110,6 @@
         Key.URI,
         elements.analyzedElement.compilationUnit.script.resourceUri,
         elements.analyzedElement.compilationUnit.script.resourceUri);
-    if (resolvedAst.body != null) {
-      objectEncoder.setInt(Key.BODY, nodeIndices[resolvedAst.body]);
-    }
     AstKind kind;
     if (element.enclosingClass is EnumClassElement) {
       if (element.name == 'index') {
@@ -148,6 +145,13 @@
     }
     objectEncoder.setEnum(Key.SUB_KIND, kind);
     root.accept(indexComputer);
+    if (resolvedAst.body != null) {
+      int index = nodeIndices[resolvedAst.body];
+      assert(invariant(element, index != null,
+          message:
+              "No index for body of $element: ${resolvedAst.body} ($nodeIndices)."));
+      objectEncoder.setInt(Key.BODY, index);
+    }
     root.accept(this);
     if (jumpTargetMap.isNotEmpty) {
       ListEncoder list = objectEncoder.createList(Key.JUMP_TARGETS);
@@ -290,6 +294,16 @@
           .setInt(Key.LABEL_DEFINITION, getLabelDefinitionId(labelDefinition));
     }
   }
+
+  @override
+  visitFunctionExpression(FunctionExpression node) {
+    visitExpression(node);
+    Element function = elements.getFunctionDefinition(node);
+    if (function != null && function.isFunction && function.isLocal) {
+      // Mark root nodes of local functions; these need their own ResolvedAst.
+      getNodeDataEncoder(node).setElement(Key.FUNCTION, function);
+    }
+  }
 }
 
 class ResolvedAstDeserializer {
@@ -304,41 +318,47 @@
     return null;
   }
 
-  /// Deserializes the [ResolvedAst] for [element] from [objectDecoder].
+  /// Deserializes the [ResolvedAst]s for [element] and its nested local
+  /// functions from [objectDecoder] and adds these to [resolvedAstMap].
   /// [parsing] and [getBeginToken] are used for parsing the [Node] for
   /// [element] from its source code.
-  static ResolvedAst deserialize(
+  static void deserialize(
       Element element,
       ObjectDecoder objectDecoder,
       ParsingContext parsing,
       Token getBeginToken(Uri uri, int charOffset),
-      DeserializerPlugin nativeDataDeserializer) {
+      DeserializerPlugin nativeDataDeserializer,
+      Map<Element, ResolvedAst> resolvedAstMap) {
     ResolvedAstKind kind =
         objectDecoder.getEnum(Key.KIND, ResolvedAstKind.values);
     switch (kind) {
       case ResolvedAstKind.PARSED:
-        return deserializeParsed(element, objectDecoder, parsing, getBeginToken,
-            nativeDataDeserializer);
+        deserializeParsed(element, objectDecoder, parsing, getBeginToken,
+            nativeDataDeserializer, resolvedAstMap);
+        break;
       case ResolvedAstKind.DEFAULT_CONSTRUCTOR:
       case ResolvedAstKind.FORWARDING_CONSTRUCTOR:
-        return new SynthesizedResolvedAst(element, kind);
+        resolvedAstMap[element] = new SynthesizedResolvedAst(element, kind);
+        break;
     }
   }
 
-  /// Deserialize a [ResolvedAst] that is defined in terms of an AST together
-  /// with [TreeElements].
-  static ResolvedAst deserializeParsed(
+  /// Deserialize the [ResolvedAst]s for the member [element] (constructor,
+  /// method, or field) and its nested closures. The [ResolvedAst]s are added
+  /// to [resolvedAstMap].
+  static void deserializeParsed(
       Element element,
       ObjectDecoder objectDecoder,
       ParsingContext parsing,
       Token getBeginToken(Uri uri, int charOffset),
-      DeserializerPlugin nativeDataDeserializer) {
+      DeserializerPlugin nativeDataDeserializer,
+      Map<Element, ResolvedAst> resolvedAstMap) {
     CompilationUnitElement compilationUnit = element.compilationUnit;
     DiagnosticReporter reporter = parsing.reporter;
+    Uri uri = objectDecoder.getUri(Key.URI);
 
     /// Returns the first [Token] for parsing the [Node] for [element].
     Token readBeginToken() {
-      Uri uri = objectDecoder.getUri(Key.URI);
       int charOffset = objectDecoder.getInt(Key.OFFSET);
       Token beginToken = getBeginToken(uri, charOffset);
       if (beginToken == null) {
@@ -425,6 +445,7 @@
           FunctionExpression toStringNode = builder.functionExpression(
               Modifiers.EMPTY,
               'toString',
+              null,
               builder.argumentList([]),
               builder.returnStatement(builder.indexGet(
                   builder.mapLiteral(mapEntries, isConst: true),
@@ -437,6 +458,7 @@
           FunctionExpression constructorNode = builder.functionExpression(
               builder.modifiers(isConst: true),
               element.enclosingClass.name,
+              null,
               builder.argumentList([indexDefinition]),
               builder.emptyStatement());
           return constructorNode;
@@ -489,12 +511,15 @@
     AstIndexComputer indexComputer = new AstIndexComputer();
     Map<Node, int> nodeIndices = indexComputer.nodeIndices;
     List<Node> nodeList = indexComputer.nodeList;
+    root.accept(indexComputer);
     Node body;
     int bodyNodeIndex = objectDecoder.getInt(Key.BODY, isOptional: true);
     if (bodyNodeIndex != null) {
+      assert(invariant(element, bodyNodeIndex < nodeList.length,
+          message: "Body node index ${bodyNodeIndex} out of range. "
+              "Node count: ${nodeList.length}"));
       body = nodeList[bodyNodeIndex];
     }
-    root.accept(indexComputer);
 
     List<JumpTarget> jumpTargets = <JumpTarget>[];
     Map<JumpTarget, List<int>> jumpTargetLabels = <JumpTarget, List<int>>{};
@@ -545,7 +570,7 @@
       jumpTarget.labels = linkBuilder.toLink();
     });
 
-    ListDecoder dataDecoder = objectDecoder.getList(Key.DATA);
+    ListDecoder dataDecoder = objectDecoder.getList(Key.DATA, isOptional: true);
     if (dataDecoder != null) {
       for (int i = 0; i < dataDecoder.length; i++) {
         ObjectDecoder objectDecoder = dataDecoder.getObject(i);
@@ -616,8 +641,20 @@
             elements.registerNativeData(node, nativeData);
           }
         }
+        FunctionElement function =
+            objectDecoder.getElement(Key.FUNCTION, isOptional: true);
+        if (function != null) {
+          FunctionExpression functionExpression = node;
+          assert(invariant(function, !resolvedAstMap.containsKey(function),
+              message: "ResolvedAst has already been computed for $function."));
+          resolvedAstMap[function] = new ParsedResolvedAst(function,
+              functionExpression, functionExpression.body, elements, uri);
+        }
       }
     }
-    return new ParsedResolvedAst(element, root, body, elements);
+    assert(invariant(element, !resolvedAstMap.containsKey(element),
+        message: "ResolvedAst has already been computed for $element."));
+    resolvedAstMap[element] =
+        new ParsedResolvedAst(element, root, body, elements, uri);
   }
 }
diff --git a/pkg/compiler/lib/src/serialization/task.dart b/pkg/compiler/lib/src/serialization/task.dart
index 0eb9db0..1639c32 100644
--- a/pkg/compiler/lib/src/serialization/task.dart
+++ b/pkg/compiler/lib/src/serialization/task.dart
@@ -65,11 +65,11 @@
         element, context, deserializer.computeWorldImpact(element));
   }
 
-  bool hasResolvedAst(Element element) {
+  bool hasResolvedAst(ExecutableElement element) {
     return deserializer != null ? deserializer.hasResolvedAst(element) : false;
   }
 
-  ResolvedAst getResolvedAst(Element element) {
+  ResolvedAst getResolvedAst(ExecutableElement element) {
     return deserializer != null ? deserializer.getResolvedAst(element) : null;
   }
 }
@@ -102,8 +102,8 @@
 abstract class DeserializerSystem {
   Future<LibraryElement> readLibrary(Uri resolvedUri);
   bool isDeserialized(Element element);
-  bool hasResolvedAst(Element element);
-  ResolvedAst getResolvedAst(Element element);
+  bool hasResolvedAst(ExecutableElement element);
+  ResolvedAst getResolvedAst(ExecutableElement element);
   bool hasResolutionImpact(Element element);
   ResolutionImpact getResolutionImpact(Element element);
   WorldImpact computeWorldImpact(Element element);
diff --git a/pkg/compiler/lib/src/ssa/builder.dart b/pkg/compiler/lib/src/ssa/builder.dart
index e927971..50db1bf 100644
--- a/pkg/compiler/lib/src/ssa/builder.dart
+++ b/pkg/compiler/lib/src/ssa/builder.dart
@@ -1134,7 +1134,7 @@
     localsHandler = new LocalsHandler(this, target, null);
     sourceElementStack.add(target);
     sourceInformationBuilder =
-        sourceInformationFactory.createBuilderForContext(target);
+        sourceInformationFactory.createBuilderForContext(resolvedAst);
     graph.sourceInformation =
         sourceInformationBuilder.buildVariableDeclaration();
   }
@@ -1182,7 +1182,7 @@
     // that it can never be null (see result in buildFactory for instance).
     var result;
     if (target.isGenerativeConstructor) {
-      result = buildFactory(target);
+      result = buildFactory(resolvedAst);
     } else if (target.isGenerativeConstructorBody ||
         target.isFactoryConstructor ||
         target.isFunction ||
@@ -1535,11 +1535,11 @@
           function, selector, providedArguments, currentNode);
       enterInlinedMethod(function, functionResolvedAst, compiledArguments,
           instanceType: instanceType);
-      inlinedFrom(function, () {
+      inlinedFrom(functionResolvedAst, () {
         if (!isReachable) {
           emitReturn(graph.addConstantNull(compiler), null);
         } else {
-          doInline(function);
+          doInline(functionResolvedAst);
         }
       });
       leaveInlinedMethod();
@@ -1572,14 +1572,15 @@
     return allInlinedFunctionsCalledOnce && isFunctionCalledOnce(element);
   }
 
-  inlinedFrom(Element element, f()) {
+  inlinedFrom(ResolvedAst resolvedAst, f()) {
+    Element element = resolvedAst.element;
     assert(element is FunctionElement || element is VariableElement);
-    return reporter.withCurrentElement(element, () {
+    return reporter.withCurrentElement(element.implementation, () {
       // The [sourceElementStack] contains declaration elements.
       SourceInformationBuilder oldSourceInformationBuilder =
           sourceInformationBuilder;
       sourceInformationBuilder =
-          sourceInformationBuilder.forContext(element.implementation);
+          sourceInformationBuilder.forContext(resolvedAst);
       sourceElementStack.add(element.declaration);
       var result = f();
       sourceInformationBuilder = oldSourceInformationBuilder;
@@ -1753,12 +1754,15 @@
   }
 
   HGraph buildLazyInitializer(VariableElement variable) {
+    assert(invariant(variable, resolvedAst.element == variable,
+        message: "Unexpected variable $variable for $resolvedAst."));
     inLazyInitializerExpression = true;
-    assert(invariant(variable, variable.initializer != null,
+    ast.VariableDefinitions node = resolvedAst.node;
+    ast.Node initializer = resolvedAst.body;
+    assert(invariant(variable, initializer != null,
         message: "Non-constant variable $variable has no initializer."));
-    ast.VariableDefinitions node = variable.node;
     openFunction(variable, node);
-    visit(variable.initializer);
+    visit(initializer);
     HInstruction value = pop();
     value = potentiallyCheckOrTrustType(value, variable.type);
     ast.SendSet sendSet = node.definitions.nodes.head;
@@ -1773,11 +1777,14 @@
    *
    * Returns [:null:] if the constructor does not have a body.
    */
-  ConstructorBodyElement getConstructorBody(FunctionElement constructor) {
+  ConstructorBodyElement getConstructorBody(
+      ResolvedAst constructorResolvedAst) {
+    ConstructorElement constructor =
+        constructorResolvedAst.element.implementation;
     assert(constructor.isGenerativeConstructor);
-    assert(invariant(constructor, constructor.isImplementation));
-    if (constructor.isSynthesized) return null;
-    ast.FunctionExpression node = constructor.node;
+    if (constructorResolvedAst.kind != ResolvedAstKind.PARSED) return null;
+
+    ast.FunctionExpression node = constructorResolvedAst.node;
     // If we know the body doesn't have any code, we don't generate it.
     if (!node.hasBody) return null;
     if (node.hasEmptyBody) return null;
@@ -1888,13 +1895,13 @@
   /**
    * Run this builder on the body of the [function] to be inlined.
    */
-  void visitInlinedFunction(FunctionElement function) {
-    potentiallyCheckInlinedParameterTypes(function);
+  void visitInlinedFunction(ResolvedAst resolvedAst) {
+    potentiallyCheckInlinedParameterTypes(resolvedAst.element.implementation);
 
-    if (function.isGenerativeConstructor) {
-      buildFactory(function);
+    if (resolvedAst.element.isGenerativeConstructor) {
+      buildFactory(resolvedAst);
     } else {
-      ast.FunctionExpression functionNode = function.node;
+      ast.FunctionExpression functionNode = resolvedAst.node;
       functionNode.body.accept(this);
     }
   }
@@ -1941,14 +1948,14 @@
    * Invariant: [constructors] must contain only implementation elements.
    */
   void inlineSuperOrRedirect(
-      ConstructorElement callee,
+      ResolvedAst constructorRecolvedAst,
       List<HInstruction> compiledArguments,
-      List<FunctionElement> constructors,
+      List<ResolvedAst> constructorResolvedAsts,
       Map<Element, HInstruction> fieldValues,
       FunctionElement caller) {
-    callee = callee.implementation;
+    ConstructorElement callee = constructorRecolvedAst.element.implementation;
     reporter.withCurrentElement(callee, () {
-      constructors.add(callee);
+      constructorResolvedAsts.add(constructorRecolvedAst);
       ClassElement enclosingClass = callee.enclosingClass;
       if (backend.classNeedsRti(enclosingClass)) {
         // If [enclosingClass] needs RTI, we have to give a value to its
@@ -1986,7 +1993,7 @@
       // For redirecting constructors, the fields will be initialized later
       // by the effective target.
       if (!callee.isRedirectingGenerative) {
-        inlinedFrom(callee, () {
+        inlinedFrom(constructorRecolvedAst, () {
           buildFieldInitializers(
               callee.enclosingClass.implementation, fieldValues);
         });
@@ -2019,7 +2026,7 @@
       if (resolvedAst.kind == ResolvedAstKind.PARSED) {
         localsHandler.enterScope(resolvedAst.node, callee);
       }
-      buildInitializers(callee, constructors, fieldValues);
+      buildInitializers(callee, constructorResolvedAsts, fieldValues);
       localsHandler.closureData = oldClosureData;
       resolvedAst = oldResolvedAst;
     });
@@ -2027,24 +2034,26 @@
 
   void buildInitializers(
       ConstructorElement constructor,
-      List<FunctionElement> constructors,
+      List<ResolvedAst> constructorResolvedAsts,
       Map<Element, HInstruction> fieldValues) {
     assert(invariant(
         constructor, resolvedAst.element == constructor.declaration,
         message: "Expected ResolvedAst for $constructor, found $resolvedAst"));
     if (resolvedAst.kind == ResolvedAstKind.PARSED) {
-      buildParsedInitializers(constructor, constructors, fieldValues);
+      buildParsedInitializers(
+          constructor, constructorResolvedAsts, fieldValues);
     } else {
       buildSynthesizedConstructorInitializers(
-          constructor, constructors, fieldValues);
+          constructor, constructorResolvedAsts, fieldValues);
     }
   }
 
   void buildSynthesizedConstructorInitializers(
       ConstructorElement constructor,
-      List<FunctionElement> constructors,
+      List<ResolvedAst> constructorResolvedAsts,
       Map<Element, HInstruction> fieldValues) {
-    assert(invariant(constructor, constructor.isSynthesized));
+    assert(invariant(constructor, constructor.isSynthesized,
+        message: "Unexpected unsynthesized constructor: $constructor"));
     List<HInstruction> arguments = <HInstruction>[];
     HInstruction compileArgument(ParameterElement parameter) {
       return localsHandler.readLocal(parameter);
@@ -2069,8 +2078,8 @@
       reporter.internalError(
           constructor, 'forwarding constructor call does not match');
     }
-    inlineSuperOrRedirect(
-        target, arguments, constructors, fieldValues, constructor);
+    inlineSuperOrRedirect(backend.frontend.getResolvedAst(target), arguments,
+        constructorResolvedAsts, fieldValues, constructor);
   }
 
   /**
@@ -2085,12 +2094,14 @@
    */
   void buildParsedInitializers(
       ConstructorElement constructor,
-      List<FunctionElement> constructors,
+      List<ResolvedAst> constructorResolvedAsts,
       Map<Element, HInstruction> fieldValues) {
+    assert(
+        invariant(constructor, resolvedAst.element == constructor.declaration));
     assert(invariant(constructor, constructor.isImplementation));
     assert(invariant(constructor, !constructor.isSynthesized,
         message: "Unexpected synthesized constructor: $constructor"));
-    ast.FunctionExpression functionNode = constructor.node;
+    ast.FunctionExpression functionNode = resolvedAst.node;
 
     bool foundSuperOrRedirect = false;
     if (functionNode.initializers != null) {
@@ -2110,18 +2121,22 @@
               elements.getSelector(call).callStructure;
           Link<ast.Node> arguments = call.arguments;
           List<HInstruction> compiledArguments;
-          inlinedFrom(constructor, () {
+          inlinedFrom(resolvedAst, () {
             compiledArguments =
                 makeStaticArgumentList(callStructure, arguments, target);
           });
-          inlineSuperOrRedirect(target, compiledArguments, constructors,
-              fieldValues, constructor);
+          inlineSuperOrRedirect(
+              backend.frontend.getResolvedAst(target.declaration),
+              compiledArguments,
+              constructorResolvedAsts,
+              fieldValues,
+              constructor);
         } else {
           // A field initializer.
           ast.SendSet init = link.head;
           Link<ast.Node> arguments = init.arguments;
           assert(!arguments.isEmpty && arguments.tail.isEmpty);
-          inlinedFrom(constructor, () {
+          inlinedFrom(resolvedAst, () {
             visit(arguments.head);
           });
           fieldValues[elements[init]] = pop();
@@ -2149,7 +2164,11 @@
             null,
             handleConstantForOptionalParameter);
         inlineSuperOrRedirect(
-            target, arguments, constructors, fieldValues, constructor);
+            backend.frontend.getResolvedAst(target.declaration),
+            arguments,
+            constructorResolvedAsts,
+            fieldValues,
+            constructor);
       }
     }
   }
@@ -2164,11 +2183,12 @@
       ClassElement classElement, Map<Element, HInstruction> fieldValues) {
     assert(invariant(classElement, classElement.isImplementation));
     classElement.forEachInstanceField(
-        (ClassElement enclosingClass, VariableElement member) {
+        (ClassElement enclosingClass, FieldElement member) {
       if (compiler.elementHasCompileTimeError(member)) return;
       reporter.withCurrentElement(member, () {
-        ast.Node node = member.node;
-        ast.Expression initializer = member.initializer;
+        ResolvedAst fieldResolvedAst = backend.frontend.getResolvedAst(member);
+        ast.Node node = fieldResolvedAst.node;
+        ast.Expression initializer = fieldResolvedAst.body;
         if (initializer == null) {
           // Unassigned fields of native classes are not initialized to
           // prevent overwriting pre-initialized native properties.
@@ -2178,12 +2198,12 @@
         } else {
           ast.Node right = initializer;
           ResolvedAst savedResolvedAst = resolvedAst;
-          resolvedAst = backend.frontend.getResolvedAst(member);
+          resolvedAst = fieldResolvedAst;
           // In case the field initializer uses closures, run the
           // closure to class mapper.
           compiler.closureToClassMapper
               .computeClosureToClassMapping(resolvedAst);
-          inlinedFrom(member, () => right.accept(this));
+          inlinedFrom(fieldResolvedAst, () => right.accept(this));
           resolvedAst = savedResolvedAst;
           fieldValues[member] = pop();
         }
@@ -2200,13 +2220,18 @@
    *  - Call the constructor bodies, starting from the constructor(s) in the
    *    super class(es).
    */
-  HGraph buildFactory(ConstructorElement functionElement) {
+  HGraph buildFactory(ResolvedAst resolvedAst) {
+    ConstructorElement functionElement = resolvedAst.element;
     functionElement = functionElement.implementation;
     ClassElement classElement = functionElement.enclosingClass.implementation;
     bool isNativeUpgradeFactory =
         backend.isNativeOrExtendsNative(classElement) &&
             !backend.isJsInterop(classElement);
-    ast.FunctionExpression function = functionElement.node;
+    ast.FunctionExpression function;
+    if (resolvedAst.kind == ResolvedAstKind.PARSED) {
+      function = resolvedAst.node;
+    }
+
     // Note that constructors (like any other static function) do not need
     // to deal with optional arguments. It is the callers job to provide all
     // arguments as if they were positional.
@@ -2239,8 +2264,8 @@
 
     // Analyze the constructor and all referenced constructors and collect
     // initializers and constructor bodies.
-    List<FunctionElement> constructors = <FunctionElement>[functionElement];
-    buildInitializers(functionElement, constructors, fieldValues);
+    List<ResolvedAst> constructorResolvedAsts = <ResolvedAst>[resolvedAst];
+    buildInitializers(functionElement, constructorResolvedAsts, fieldValues);
 
     // Call the JavaScript constructor with the fields as argument.
     List<HInstruction> constructorArguments = <HInstruction>[];
@@ -2369,10 +2394,9 @@
 
     // Generate calls to the constructor bodies.
     HInstruction interceptor = null;
-    for (int index = constructors.length - 1; index >= 0; index--) {
-      FunctionElement constructor = constructors[index];
-      assert(invariant(functionElement, constructor.isImplementation));
-      ConstructorBodyElement body = getConstructorBody(constructor);
+    for (int index = constructorResolvedAsts.length - 1; index >= 0; index--) {
+      ResolvedAst constructorResolvedAst = constructorResolvedAsts[index];
+      ConstructorBodyElement body = getConstructorBody(constructorResolvedAst);
       if (body == null) continue;
 
       List bodyCallInputs = <HInstruction>[];
@@ -2385,8 +2409,7 @@
         bodyCallInputs.add(interceptor);
       }
       bodyCallInputs.add(newObject);
-      ResolvedAst resolvedAst = backend.frontend.getResolvedAst(constructor);
-      ast.Node node = resolvedAst.node;
+      ast.Node node = constructorResolvedAst.node;
       ClosureClassMap parameterClosureData =
           compiler.closureToClassMapper.getMappingForNestedFunction(node);
 
@@ -2409,6 +2432,8 @@
       }
 
       // Type variables arguments must come after the box (if there is one).
+      ConstructorElement constructor =
+          constructorResolvedAst.element.implementation;
       ClassElement currentClass = constructor.enclosingClass;
       if (backend.classNeedsRti(currentClass)) {
         // If [currentClass] needs RTI, we add the type variables as
@@ -7913,8 +7938,8 @@
     stack.add(result);
   }
 
-  void doInline(FunctionElement function) {
-    visitInlinedFunction(function);
+  void doInline(ResolvedAst resolvedAst) {
+    visitInlinedFunction(resolvedAst);
   }
 
   void emitReturn(HInstruction value, ast.Node node) {
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index 5938e1c..8b9ab16 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -51,7 +51,7 @@
 
     return new js.Fun(parameters, body, asyncModifier: asyncModifier)
         .withSourceInformation(sourceInformationFactory
-            .createBuilderForContext(resolvedAst.element)
+            .createBuilderForContext(resolvedAst)
             .buildDeclaration(resolvedAst));
   }
 
@@ -67,7 +67,7 @@
     return measure(() {
       compiler.tracer.traceGraph("codegen", graph);
       SourceInformation sourceInformation = sourceInformationFactory
-          .createBuilderForContext(work.element)
+          .createBuilderForContext(work.resolvedAst)
           .buildDeclaration(work.resolvedAst);
       SsaCodeGenerator codegen = new SsaCodeGenerator(backend, work);
       codegen.visitGraph(graph);
diff --git a/pkg/compiler/lib/src/ssa/nodes.dart b/pkg/compiler/lib/src/ssa/nodes.dart
index c9a4c2a..3b119bd 100644
--- a/pkg/compiler/lib/src/ssa/nodes.dart
+++ b/pkg/compiler/lib/src/ssa/nodes.dart
@@ -198,6 +198,10 @@
     HConstant result = constants[constant];
     // TODO(johnniwinther): Support source information per constant reference.
     if (result == null) {
+      if (!constant.isConstant) {
+        // We use `null` as the value for invalid constant expressions.
+        constant = const NullConstantValue();
+      }
       TypeMask type = computeTypeMask(compiler, constant);
       result = new HConstant.internal(constant, type)
         ..sourceInformation = sourceInformation;
diff --git a/pkg/compiler/lib/src/tree/nodes.dart b/pkg/compiler/lib/src/tree/nodes.dart
index ae8111b..d2e9d96 100644
--- a/pkg/compiler/lib/src/tree/nodes.dart
+++ b/pkg/compiler/lib/src/tree/nodes.dart
@@ -1076,6 +1076,7 @@
 
 class FunctionExpression extends Expression with StoredTreeElementMixin {
   final Node name;
+  final NodeList typeVariables;
 
   /**
    * List of VariableDefinitions or NodeList.
@@ -1092,8 +1093,16 @@
   final Token getOrSet;
   final AsyncModifier asyncModifier;
 
-  FunctionExpression(this.name, this.parameters, this.body, this.returnType,
-      this.modifiers, this.initializers, this.getOrSet, this.asyncModifier) {
+  FunctionExpression(
+      this.name,
+      this.typeVariables,
+      this.parameters,
+      this.body,
+      this.returnType,
+      this.modifiers,
+      this.initializers,
+      this.getOrSet,
+      this.asyncModifier) {
     assert(modifiers != null);
   }
 
@@ -1111,6 +1120,7 @@
     if (modifiers != null) modifiers.accept(visitor);
     if (returnType != null) returnType.accept(visitor);
     if (name != null) name.accept(visitor);
+    if (typeVariables != null) typeVariables.accept(visitor);
     if (parameters != null) parameters.accept(visitor);
     if (initializers != null) initializers.accept(visitor);
     if (asyncModifier != null) asyncModifier.accept(visitor);
@@ -1121,6 +1131,7 @@
     if (modifiers != null) modifiers.accept1(visitor, arg);
     if (returnType != null) returnType.accept1(visitor, arg);
     if (name != null) name.accept1(visitor, arg);
+    if (typeVariables != null) typeVariables.accept1(visitor, arg);
     if (parameters != null) parameters.accept1(visitor, arg);
     if (initializers != null) initializers.accept1(visitor, arg);
     if (asyncModifier != null) asyncModifier.accept1(visitor, arg);
@@ -3102,6 +3113,7 @@
 
   // FunctionExpression.
   get asyncModifier => null;
+  get typeVariables => null;
   get parameters => null;
   get body => null;
   get returnType => null;
diff --git a/runtime/bin/log_android.cc b/runtime/bin/log_android.cc
index 6e5a621..9dbbf05 100644
--- a/runtime/bin/log_android.cc
+++ b/runtime/bin/log_android.cc
@@ -17,10 +17,18 @@
 // it when we see a '\n'.
 
 void Log::VPrint(const char* format, va_list args) {
+  // If we launch the DartVM inside "adb shell" we will only get messages
+  // (critical ones or not) if we print them to stdout/stderr.
+  // We also log using android's logging system.
+  vprintf(format, args);
   __android_log_vprint(ANDROID_LOG_INFO, "Dart", format, args);
 }
 
 void Log::VPrintErr(const char* format, va_list args) {
+  // If we launch the DartVM inside "adb shell" we will only get messages
+  // (critical ones or not) if we print them to stdout/stderr.
+  // We also log using android's logging system.
+  vfprintf(stderr, format, args);
   __android_log_vprint(ANDROID_LOG_ERROR, "Dart", format, args);
 }
 
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 0ef6653..fb8b338 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -1417,9 +1417,9 @@
       uint8_t* assembly_buffer = NULL;
       intptr_t assembly_size = 0;
       uint8_t* instructions_blob_buffer = NULL;
-      intptr_t instructions_blob_size = NULL;
+      intptr_t instructions_blob_size = 0;
       uint8_t* rodata_blob_buffer = NULL;
-      intptr_t rodata_blob_size = NULL;
+      intptr_t rodata_blob_size = 0;
       if (use_blobs) {
         result = Dart_CreatePrecompiledSnapshotBlob(
             &vm_isolate_buffer,
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index d10e066..33b61c6 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -354,8 +354,7 @@
 }
 
 
-static RawInstance* CreateLibraryMirror(const Library& lib) {
-  Thread* thread = Thread::Current();
+static RawInstance* CreateLibraryMirror(Thread* thread, const Library& lib) {
   Zone* zone = thread->zone();
   ASSERT(!lib.IsNull());
   const Array& args = Array::Handle(zone, Array::New(3));
@@ -405,14 +404,15 @@
 }
 
 
-static RawInstance* CreateLibraryDependencyMirror(const Instance& importer,
+static RawInstance* CreateLibraryDependencyMirror(Thread* thread,
+                                                  const Instance& importer,
                                                   const Namespace& ns,
                                                   const LibraryPrefix& prefix,
                                                   const bool is_import,
                                                   const bool is_deferred) {
   const Library& importee = Library::Handle(ns.library());
   const Instance& importee_mirror =
-      Instance::Handle(CreateLibraryMirror(importee));
+      Instance::Handle(CreateLibraryMirror(thread, importee));
   if (importee_mirror.IsNull()) {
     // Imported library is censored: censor the import.
     return Instance::null();
@@ -462,7 +462,7 @@
   if (!deferred_lib.Loaded()) {
     return Instance::null();
   }
-  return CreateLibraryMirror(deferred_lib);
+  return CreateLibraryMirror(thread, deferred_lib);
 }
 
 
@@ -483,7 +483,8 @@
   for (intptr_t i = 0; i < ports.Length(); i++) {
     ns ^= ports.At(i);
     if (!ns.IsNull()) {
-      dep = CreateLibraryDependencyMirror(lib_mirror, ns, prefix, true, false);
+      dep = CreateLibraryDependencyMirror(
+          thread, lib_mirror, ns, prefix, true, false);
       if (!dep.IsNull()) {
         deps.Add(dep);
       }
@@ -494,7 +495,8 @@
   ports = lib.exports();
   for (intptr_t i = 0; i < ports.Length(); i++) {
     ns ^= ports.At(i);
-    dep = CreateLibraryDependencyMirror(lib_mirror, ns, prefix, false, false);
+    dep = CreateLibraryDependencyMirror(
+        thread, lib_mirror, ns, prefix, false, false);
     if (!dep.IsNull()) {
       deps.Add(dep);
     }
@@ -511,8 +513,8 @@
       for (intptr_t i = 0; i < ports.Length(); i++) {
         ns ^= ports.At(i);
         if (!ns.IsNull()) {
-          dep = CreateLibraryDependencyMirror(lib_mirror, ns, prefix, true,
-                                              prefix.is_deferred_load());
+          dep = CreateLibraryDependencyMirror(
+              thread, lib_mirror, ns, prefix, true, prefix.is_deferred_load());
           if (!dep.IsNull()) {
             deps.Add(dep);
           }
@@ -578,7 +580,7 @@
   const Library& root_library = Library::Handle(thread->zone(),
       isolate->object_store()->root_library());
   const Instance& root_library_mirror =
-      Instance::Handle(CreateLibraryMirror(root_library));
+      Instance::Handle(CreateLibraryMirror(thread, root_library));
 
   const Array& args = Array::Handle(Array::New(2));
   args.SetAt(0, debug_name);
@@ -800,7 +802,7 @@
 
   for (int i = 0; i < num_libraries; i++) {
     library ^= libraries.At(i);
-    library_mirror = CreateLibraryMirror(library);
+    library_mirror = CreateLibraryMirror(thread, library);
     if (!library_mirror.IsNull() && library.Loaded()) {
       library_mirrors.Add(library_mirror);
     }
@@ -1931,7 +1933,7 @@
   }
   const Class& owner = Class::Handle(func.Owner());
   if (owner.IsTopLevel()) {
-    return CreateLibraryMirror(Library::Handle(owner.library()));
+    return CreateLibraryMirror(thread, Library::Handle(owner.library()));
   }
 
   AbstractType& type = AbstractType::Handle(owner.DeclarationType());
diff --git a/runtime/lib/mirrors_impl.dart b/runtime/lib/mirrors_impl.dart
index 78835a4..8fdd7ba 100644
--- a/runtime/lib/mirrors_impl.dart
+++ b/runtime/lib/mirrors_impl.dart
@@ -226,6 +226,7 @@
     if ((_libraries == null) || dirty) {
       _libraries = new Map<Uri, LibraryMirror>.fromIterable(
           _computeLibraries(), key: (e) => e.uri);
+      dirty = false;
     }
     return _libraries;
   }
diff --git a/runtime/lib/string.cc b/runtime/lib/string.cc
index 9313ce1..01f6ad0 100644
--- a/runtime/lib/string.cc
+++ b/runtime/lib/string.cc
@@ -91,7 +91,8 @@
 
 
 DEFINE_NATIVE_ENTRY(StringBase_substringUnchecked, 3) {
-  const String& receiver = String::CheckedHandle(arguments->NativeArgAt(0));
+  const String& receiver = String::CheckedHandle(zone,
+                                                 arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Smi, start_obj, arguments->NativeArgAt(1));
   GET_NON_NULL_NATIVE_ARGUMENT(Smi, end_obj, arguments->NativeArgAt(2));
 
@@ -163,7 +164,8 @@
 
 
 DEFINE_NATIVE_ENTRY(StringBase_joinReplaceAllResult, 4) {
-  const String& base = String::CheckedHandle(arguments->NativeArgAt(0));
+  const String& base = String::CheckedHandle(zone,
+                                             arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(GrowableObjectArray,
                                matches_growable, arguments->NativeArgAt(1));
   GET_NON_NULL_NATIVE_ARGUMENT(Smi, length_obj, arguments->NativeArgAt(2));
@@ -251,7 +253,8 @@
 }
 
 DEFINE_NATIVE_ENTRY(OneByteString_substringUnchecked, 3) {
-  const String& receiver = String::CheckedHandle(arguments->NativeArgAt(0));
+  const String& receiver = String::CheckedHandle(zone,
+                                                 arguments->NativeArgAt(0));
   ASSERT(receiver.IsOneByteString());
   GET_NON_NULL_NATIVE_ARGUMENT(Smi, start_obj, arguments->NativeArgAt(1));
   GET_NON_NULL_NATIVE_ARGUMENT(Smi, end_obj, arguments->NativeArgAt(2));
@@ -303,7 +306,8 @@
 
 
 DEFINE_NATIVE_ENTRY(OneByteString_allocateFromOneByteList, 3) {
-  Instance& list = Instance::CheckedHandle(arguments->NativeArgAt(0));
+  Instance& list = Instance::CheckedHandle(zone,
+                                           arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Smi, start_obj, arguments->NativeArgAt(1));
   GET_NON_NULL_NATIVE_ARGUMENT(Smi, end_obj, arguments->NativeArgAt(2));
 
@@ -406,7 +410,8 @@
 
 
 DEFINE_NATIVE_ENTRY(TwoByteString_allocateFromTwoByteList, 3) {
-  Instance& list = Instance::CheckedHandle(arguments->NativeArgAt(0));
+  Instance& list = Instance::CheckedHandle(zone,
+                                           arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Smi, start_obj, arguments->NativeArgAt(1));
   GET_NON_NULL_NATIVE_ARGUMENT(Smi, end_obj, arguments->NativeArgAt(2));
 
@@ -492,7 +497,8 @@
 
 
 DEFINE_NATIVE_ENTRY(String_getHashCode, 1) {
-  const String& receiver = String::CheckedHandle(arguments->NativeArgAt(0));
+  const String& receiver = String::CheckedHandle(zone,
+                                                 arguments->NativeArgAt(0));
   intptr_t hash_val = receiver.Hash();
   ASSERT(hash_val > 0);
   ASSERT(Smi::IsValid(hash_val));
@@ -501,7 +507,8 @@
 
 
 DEFINE_NATIVE_ENTRY(String_getLength, 1) {
-  const String& receiver = String::CheckedHandle(arguments->NativeArgAt(0));
+  const String& receiver = String::CheckedHandle(zone,
+                                                 arguments->NativeArgAt(0));
   return Smi::New(receiver.Length());
 }
 
@@ -521,7 +528,8 @@
 
 
 DEFINE_NATIVE_ENTRY(String_charAt, 2) {
-  const String& receiver = String::CheckedHandle(arguments->NativeArgAt(0));
+  const String& receiver = String::CheckedHandle(zone,
+                                                 arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Integer, index, arguments->NativeArgAt(1));
   uint16_t value = StringValueAt(receiver, index);
   return Symbols::FromCharCode(thread, static_cast<int32_t>(value));
@@ -530,7 +538,8 @@
 
 // Returns the 16-bit UTF-16 code unit at the given index.
 DEFINE_NATIVE_ENTRY(String_codeUnitAt, 2) {
-  const String& receiver = String::CheckedHandle(arguments->NativeArgAt(0));
+  const String& receiver = String::CheckedHandle(zone,
+                                                 arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Integer, index, arguments->NativeArgAt(1));
   uint16_t value = StringValueAt(receiver, index);
   return Smi::New(static_cast<intptr_t>(value));
@@ -538,21 +547,24 @@
 
 
 DEFINE_NATIVE_ENTRY(String_concat, 2) {
-  const String& receiver = String::CheckedHandle(arguments->NativeArgAt(0));
+  const String& receiver = String::CheckedHandle(zone,
+                                                 arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(String, b, arguments->NativeArgAt(1));
   return String::Concat(receiver, b);
 }
 
 
 DEFINE_NATIVE_ENTRY(String_toLowerCase, 1) {
-  const String& receiver = String::CheckedHandle(arguments->NativeArgAt(0));
+  const String& receiver = String::CheckedHandle(zone,
+                                                 arguments->NativeArgAt(0));
   ASSERT(!receiver.IsNull());
   return String::ToLowerCase(receiver);
 }
 
 
 DEFINE_NATIVE_ENTRY(String_toUpperCase, 1) {
-  const String& receiver = String::CheckedHandle(arguments->NativeArgAt(0));
+  const String& receiver = String::CheckedHandle(zone,
+                                                 arguments->NativeArgAt(0));
   ASSERT(!receiver.IsNull());
   return String::ToUpperCase(receiver);
 }
diff --git a/runtime/vm/assembler_arm64_test.cc b/runtime/vm/assembler_arm64_test.cc
index d27358e..ba0d646 100644
--- a/runtime/vm/assembler_arm64_test.cc
+++ b/runtime/vm/assembler_arm64_test.cc
@@ -1687,8 +1687,6 @@
 }
 
 
-
-
 // Loading immediate values with the object pool.
 ASSEMBLER_TEST_GENERATE(LoadImmediatePPSmall, assembler) {
   __ SetupDartSP(kTestStackSpace);
diff --git a/runtime/vm/assembler_dbc_test.cc b/runtime/vm/assembler_dbc_test.cc
new file mode 100644
index 0000000..2941f20
--- /dev/null
+++ b/runtime/vm/assembler_dbc_test.cc
@@ -0,0 +1,709 @@
+// 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.
+
+#include "vm/globals.h"
+#if defined(TARGET_ARCH_DBC)
+
+#include "vm/assembler.h"
+#include "vm/unit_test.h"
+
+namespace dart {
+
+static RawObject* ExecuteTest(const Code& code) {
+  Thread* thread = Thread::Current();
+  TransitionToGenerated transition(thread);
+  return Simulator::Current()->Call(
+      code,
+      Array::Handle(ArgumentsDescriptor::New(0)),
+      Array::Handle(Array::New(0)),
+      thread);
+}
+
+
+#define EXECUTE_TEST_CODE_INTPTR(code)                                         \
+    Smi::Value(Smi::RawCast(ExecuteTest(code)))
+#define EXECUTE_TEST_CODE_BOOL(code)                                           \
+    (Bool::RawCast(ExecuteTest(code)) == Bool::True().raw())
+#define EXECUTE_TEST_CODE_OBJECT(code)                                         \
+    Object::Handle(ExecuteTest(code))
+
+#define __ assembler->
+
+
+ASSEMBLER_TEST_GENERATE(Simple, assembler) {
+  __ PushConstant(Smi::Handle(Smi::New(42)));
+  __ ReturnTOS();
+}
+
+
+ASSEMBLER_TEST_RUN(Simple, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+//  - AddTOS; SubTOS; MulTOS; BitOrTOS; BitAndTOS; EqualTOS; LessThanTOS;
+//    GreaterThanTOS;
+//
+//    Smi fast-path for a corresponding method. Checks if SP[0] and SP[-1] are
+//    both smis and result of SP[0] <op> SP[-1] is a smi - if this is true
+//    then pops operands and pushes result on the stack and skips the next
+//    instruction (which implements a slow path fallback).
+ASSEMBLER_TEST_GENERATE(AddTOS, assembler) {
+  __ PushConstant(Smi::Handle(Smi::New(-42)));
+  __ PushConstant(Smi::Handle(Smi::New(84)));
+  __ AddTOS();
+  __ PushConstant(Smi::Handle(Smi::New(0)));  // Should be skipped.
+  __ ReturnTOS();
+}
+
+
+ASSEMBLER_TEST_RUN(AddTOS, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(AddTOSOverflow, assembler) {
+  __ PushConstant(Smi::Handle(Smi::New(Smi::kMaxValue)));
+  __ PushConstant(Smi::Handle(Smi::New(1)));
+  __ AddTOS();
+  __ PushConstant(Smi::Handle(Smi::New(42)));  // Shouldn't be skipped.
+  __ ReturnTOS();
+}
+
+
+ASSEMBLER_TEST_RUN(AddTOSOverflow, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(AddTOSNonSmi, assembler) {
+  const String& numstr =
+      String::Handle(String::New("98765432198765432100", Heap::kOld));
+  __ PushConstant(Integer::Handle(Integer::New(numstr, Heap::kOld)));
+  __ PushConstant(Smi::Handle(Smi::New(1)));
+  __ AddTOS();
+  __ PushConstant(Smi::Handle(Smi::New(42)));  // Shouldn't be skipped.
+  __ ReturnTOS();
+}
+
+
+ASSEMBLER_TEST_RUN(AddTOSNonSmi, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(SubTOS, assembler) {
+  __ PushConstant(Smi::Handle(Smi::New(30)));
+  __ PushConstant(Smi::Handle(Smi::New(-12)));
+  __ SubTOS();
+  __ PushConstant(Smi::Handle(Smi::New(0)));  // Should be skipped.
+  __ ReturnTOS();
+}
+
+
+ASSEMBLER_TEST_RUN(SubTOS, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(SubTOSOverflow, assembler) {
+  __ PushConstant(Smi::Handle(Smi::New(Smi::kMinValue)));
+  __ PushConstant(Smi::Handle(Smi::New(1)));
+  __ SubTOS();
+  __ PushConstant(Smi::Handle(Smi::New(42)));  // Shouldn't be skipped.
+  __ ReturnTOS();
+}
+
+
+ASSEMBLER_TEST_RUN(SubTOSOverflow, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(SubTOSNonSmi, assembler) {
+  const String& numstr =
+      String::Handle(String::New("98765432198765432100", Heap::kOld));
+  __ PushConstant(Integer::Handle(Integer::New(numstr, Heap::kOld)));
+  __ PushConstant(Smi::Handle(Smi::New(1)));
+  __ SubTOS();
+  __ PushConstant(Smi::Handle(Smi::New(42)));  // Shouldn't be skipped.
+  __ ReturnTOS();
+}
+
+
+ASSEMBLER_TEST_RUN(SubTOSNonSmi, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(MulTOS, assembler) {
+  __ PushConstant(Smi::Handle(Smi::New(-6)));
+  __ PushConstant(Smi::Handle(Smi::New(-7)));
+  __ MulTOS();
+  __ PushConstant(Smi::Handle(Smi::New(0)));  // Should be skipped.
+  __ ReturnTOS();
+}
+
+
+ASSEMBLER_TEST_RUN(MulTOS, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(MulTOSOverflow, assembler) {
+  __ PushConstant(Smi::Handle(Smi::New(Smi::kMaxValue)));
+  __ PushConstant(Smi::Handle(Smi::New(-8)));
+  __ MulTOS();
+  __ PushConstant(Smi::Handle(Smi::New(42)));  // Shouldn't be skipped.
+  __ ReturnTOS();
+}
+
+
+ASSEMBLER_TEST_RUN(MulTOSOverflow, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(MulTOSNonSmi, assembler) {
+  const String& numstr =
+      String::Handle(String::New("98765432198765432100", Heap::kOld));
+  __ PushConstant(Integer::Handle(Integer::New(numstr, Heap::kOld)));
+  __ PushConstant(Smi::Handle(Smi::New(1)));
+  __ MulTOS();
+  __ PushConstant(Smi::Handle(Smi::New(42)));  // Shouldn't be skipped.
+  __ ReturnTOS();
+}
+
+
+ASSEMBLER_TEST_RUN(MulTOSNonSmi, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(BitOrTOS, assembler) {
+  __ PushConstant(Smi::Handle(Smi::New(0x22)));
+  __ PushConstant(Smi::Handle(Smi::New(0x08)));
+  __ BitOrTOS();
+  __ PushConstant(Smi::Handle(Smi::New(0)));  // Should be skipped.
+  __ ReturnTOS();
+}
+
+
+ASSEMBLER_TEST_RUN(BitOrTOS, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(BitOrTOSNonSmi, assembler) {
+  const String& numstr =
+      String::Handle(String::New("98765432198765432100", Heap::kOld));
+  __ PushConstant(Integer::Handle(Integer::New(numstr, Heap::kOld)));
+  __ PushConstant(Smi::Handle(Smi::New(0x08)));
+  __ BitOrTOS();
+  __ PushConstant(Smi::Handle(Smi::New(42)));  // Shouldn't be skipped.
+  __ ReturnTOS();
+}
+
+
+ASSEMBLER_TEST_RUN(BitOrTOSNonSmi, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(BitAndTOS, assembler) {
+  __ PushConstant(Smi::Handle(Smi::New(0x2a)));
+  __ PushConstant(Smi::Handle(Smi::New(0xaa)));
+  __ BitAndTOS();
+  __ PushConstant(Smi::Handle(Smi::New(0)));  // Should be skipped.
+  __ ReturnTOS();
+}
+
+
+ASSEMBLER_TEST_RUN(BitAndTOS, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(BitAndTOSNonSmi, assembler) {
+  const String& numstr =
+      String::Handle(String::New("98765432198765432100", Heap::kOld));
+  __ PushConstant(Integer::Handle(Integer::New(numstr, Heap::kOld)));
+  __ PushConstant(Smi::Handle(Smi::New(0x08)));
+  __ BitAndTOS();
+  __ PushConstant(Smi::Handle(Smi::New(42)));  // Shouldn't be skipped.
+  __ ReturnTOS();
+}
+
+
+ASSEMBLER_TEST_RUN(BitAndTOSNonSmi, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(EqualTOSTrue, assembler) {
+  __ PushConstant(Smi::Handle(Smi::New(42)));
+  __ PushConstant(Smi::Handle(Smi::New(42)));
+  __ EqualTOS();
+  __ PushConstant(Bool::False());  // Should be skipped.
+  __ ReturnTOS();
+}
+
+
+ASSEMBLER_TEST_RUN(EqualTOSTrue, test) {
+  EXPECT(EXECUTE_TEST_CODE_BOOL(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(EqualTOSFalse, assembler) {
+  __ PushConstant(Smi::Handle(Smi::New(42)));
+  __ PushConstant(Smi::Handle(Smi::New(-42)));
+  __ EqualTOS();
+  __ PushConstant(Bool::True());  // Should be skipped.
+  __ ReturnTOS();
+}
+
+
+ASSEMBLER_TEST_RUN(EqualTOSFalse, test) {
+  EXPECT(!EXECUTE_TEST_CODE_BOOL(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(EqualTOSNonSmi, assembler) {
+  const String& numstr =
+      String::Handle(String::New("98765432198765432100", Heap::kOld));
+  __ PushConstant(Integer::Handle(Integer::New(numstr, Heap::kOld)));
+  __ PushConstant(Smi::Handle(Smi::New(-42)));
+  __ EqualTOS();
+  __ PushConstant(Bool::True());  // Shouldn't be skipped.
+  __ ReturnTOS();
+}
+
+
+ASSEMBLER_TEST_RUN(EqualTOSNonSmi, test) {
+  EXPECT(EXECUTE_TEST_CODE_BOOL(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(LessThanTOSTrue, assembler) {
+  __ PushConstant(Smi::Handle(Smi::New(-42)));
+  __ PushConstant(Smi::Handle(Smi::New(42)));
+  __ LessThanTOS();
+  __ PushConstant(Bool::False());  // Should be skipped.
+  __ ReturnTOS();
+}
+
+
+ASSEMBLER_TEST_RUN(LessThanTOSTrue, test) {
+  EXPECT(EXECUTE_TEST_CODE_BOOL(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(LessThanTOSFalse, assembler) {
+  __ PushConstant(Smi::Handle(Smi::New(42)));
+  __ PushConstant(Smi::Handle(Smi::New(-42)));
+  __ LessThanTOS();
+  __ PushConstant(Bool::False());  // Should be skipped.
+  __ ReturnTOS();
+}
+
+
+ASSEMBLER_TEST_RUN(LessThanTOSFalse, test) {
+  EXPECT(!EXECUTE_TEST_CODE_BOOL(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(LessThanTOSNonSmi, assembler) {
+  const String& numstr =
+      String::Handle(String::New("98765432198765432100", Heap::kOld));
+  __ PushConstant(Integer::Handle(Integer::New(numstr, Heap::kOld)));
+  __ PushConstant(Smi::Handle(Smi::New(-42)));
+  __ LessThanTOS();
+  __ PushConstant(Bool::True());  // Shouldn't be skipped.
+  __ ReturnTOS();
+}
+
+
+ASSEMBLER_TEST_RUN(LessThanTOSNonSmi, test) {
+  EXPECT(EXECUTE_TEST_CODE_BOOL(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(GreaterThanTOSTrue, assembler) {
+  __ PushConstant(Smi::Handle(Smi::New(42)));
+  __ PushConstant(Smi::Handle(Smi::New(-42)));
+  __ GreaterThanTOS();
+  __ PushConstant(Bool::False());  // Should be skipped.
+  __ ReturnTOS();
+}
+
+
+ASSEMBLER_TEST_RUN(GreaterThanTOSTrue, test) {
+  EXPECT(EXECUTE_TEST_CODE_BOOL(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(GreaterThanTOSFalse, assembler) {
+  __ PushConstant(Smi::Handle(Smi::New(-42)));
+  __ PushConstant(Smi::Handle(Smi::New(42)));
+  __ GreaterThanTOS();
+  __ PushConstant(Bool::False());  // Should be skipped.
+  __ ReturnTOS();
+}
+
+
+ASSEMBLER_TEST_RUN(GreaterThanTOSFalse, test) {
+  EXPECT(!EXECUTE_TEST_CODE_BOOL(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(GreaterThanTOSNonSmi, assembler) {
+  const String& numstr =
+      String::Handle(String::New("98765432198765432100", Heap::kOld));
+  __ PushConstant(Integer::Handle(Integer::New(numstr, Heap::kOld)));
+  __ PushConstant(Smi::Handle(Smi::New(-42)));
+  __ GreaterThanTOS();
+  __ PushConstant(Bool::True());  // Shouldn't be skipped.
+  __ ReturnTOS();
+}
+
+
+ASSEMBLER_TEST_RUN(GreaterThanTOSNonSmi, test) {
+  EXPECT(EXECUTE_TEST_CODE_BOOL(test->code()));
+}
+
+
+//  - IfNeStrictTOS; IfEqStrictTOS; IfNeStrictNumTOS; IfEqStrictNumTOS
+//
+//    Skips the next instruction unless the given condition holds. 'Num'
+//    variants perform number check while non-Num variants just compare
+//    RawObject pointers.
+//
+//    Used to implement conditional jump:
+//
+//        IfNeStrictTOS
+//        Jump T         ;; jump if not equal
+ASSEMBLER_TEST_GENERATE(IfNeStrictTOSTaken, assembler) {
+  Label branch_taken;
+  const Array& array1 = Array::Handle(Array::New(1, Heap::kOld));
+  const Array& array2 = Array::Handle(Array::New(2, Heap::kOld));
+  __ PushConstant(array1);
+  __ PushConstant(array2);
+  __ IfNeStrictTOS();
+  __ Jump(&branch_taken);
+  __ PushConstant(Smi::Handle(Smi::New(0)));
+  __ ReturnTOS();
+  __ Bind(&branch_taken);
+  __ PushConstant(Smi::Handle(Smi::New(42)));
+  __ ReturnTOS();
+}
+
+
+ASSEMBLER_TEST_RUN(IfNeStrictTOSTaken, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(IfNeStrictTOSNotTaken, assembler) {
+  Label branch_taken;
+  const Array& array1 = Array::Handle(Array::New(1, Heap::kOld));
+  __ PushConstant(array1);
+  __ PushConstant(array1);
+  __ IfNeStrictTOS();
+  __ Jump(&branch_taken);
+  __ PushConstant(Smi::Handle(Smi::New(42)));
+  __ ReturnTOS();
+  __ Bind(&branch_taken);
+  __ PushConstant(Smi::Handle(Smi::New(0)));
+  __ ReturnTOS();
+}
+
+ASSEMBLER_TEST_RUN(IfNeStrictTOSNotTaken, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+// TODO(zra): Also add tests that use Mint, Bignum.
+ASSEMBLER_TEST_GENERATE(IfNeStrictNumTOSTaken, assembler) {
+  Label branch_taken;
+  __ PushConstant(Smi::Handle(Smi::New(-1)));
+  __ PushConstant(Smi::Handle(Smi::New(1)));
+  __ IfNeStrictNumTOS();
+  __ Jump(&branch_taken);
+  __ PushConstant(Smi::Handle(Smi::New(0)));
+  __ ReturnTOS();
+  __ Bind(&branch_taken);
+  __ PushConstant(Smi::Handle(Smi::New(42)));
+  __ ReturnTOS();
+}
+
+
+ASSEMBLER_TEST_RUN(IfNeStrictNumTOSTaken, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(IfNeStrictNumTOSNotTaken, assembler) {
+  Label branch_taken;
+  __ PushConstant(Smi::Handle(Smi::New(1)));
+  __ PushConstant(Smi::Handle(Smi::New(1)));
+  __ IfNeStrictNumTOS();
+  __ Jump(&branch_taken);
+  __ PushConstant(Smi::Handle(Smi::New(42)));
+  __ ReturnTOS();
+  __ Bind(&branch_taken);
+  __ PushConstant(Smi::Handle(Smi::New(0)));
+  __ ReturnTOS();
+}
+
+ASSEMBLER_TEST_RUN(IfNeStrictNumTOSNotTaken, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(IfNeStrictNumTOSTakenDouble, assembler) {
+  Label branch_taken;
+  __ PushConstant(Double::Handle(Double::New(-1.0, Heap::kOld)));
+  __ PushConstant(Double::Handle(Double::New(1.0, Heap::kOld)));
+  __ IfNeStrictNumTOS();
+  __ Jump(&branch_taken);
+  __ PushConstant(Smi::Handle(Smi::New(0)));
+  __ ReturnTOS();
+  __ Bind(&branch_taken);
+  __ PushConstant(Smi::Handle(Smi::New(42)));
+  __ ReturnTOS();
+}
+
+
+ASSEMBLER_TEST_RUN(IfNeStrictNumTOSTakenDouble, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(IfNeStrictNumTOSNotTakenDouble, assembler) {
+  Label branch_taken;
+  __ PushConstant(Double::Handle(Double::New(1.0, Heap::kOld)));
+  __ PushConstant(Double::Handle(Double::New(1.0, Heap::kOld)));
+  __ IfNeStrictNumTOS();
+  __ Jump(&branch_taken);
+  __ PushConstant(Smi::Handle(Smi::New(42)));
+  __ ReturnTOS();
+  __ Bind(&branch_taken);
+  __ PushConstant(Smi::Handle(Smi::New(0)));
+  __ ReturnTOS();
+}
+
+ASSEMBLER_TEST_RUN(IfNeStrictNumTOSNotTakenDouble, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(IfEqStrictTOSTaken, assembler) {
+  Label branch_taken;
+  const Array& array1 = Array::Handle(Array::New(1, Heap::kOld));
+  __ PushConstant(array1);
+  __ PushConstant(array1);
+  __ IfEqStrictTOS();
+  __ Jump(&branch_taken);
+  __ PushConstant(Smi::Handle(Smi::New(0)));
+  __ ReturnTOS();
+  __ Bind(&branch_taken);
+  __ PushConstant(Smi::Handle(Smi::New(42)));
+  __ ReturnTOS();
+}
+
+
+ASSEMBLER_TEST_RUN(IfEqStrictTOSTaken, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(IfEqStrictTOSNotTaken, assembler) {
+  Label branch_taken;
+  const Array& array1 = Array::Handle(Array::New(1, Heap::kOld));
+  const Array& array2 = Array::Handle(Array::New(2, Heap::kOld));
+  __ PushConstant(array1);
+  __ PushConstant(array2);
+  __ IfEqStrictTOS();
+  __ Jump(&branch_taken);
+  __ PushConstant(Smi::Handle(Smi::New(42)));
+  __ ReturnTOS();
+  __ Bind(&branch_taken);
+  __ PushConstant(Smi::Handle(Smi::New(0)));
+  __ ReturnTOS();
+}
+
+ASSEMBLER_TEST_RUN(IfEqStrictTOSNotTaken, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+// TODO(zra): Also add tests that use Mint, Bignum.
+ASSEMBLER_TEST_GENERATE(IfEqStrictNumTOSTaken, assembler) {
+  Label branch_taken;
+  __ PushConstant(Smi::Handle(Smi::New(1)));
+  __ PushConstant(Smi::Handle(Smi::New(1)));
+  __ IfEqStrictNumTOS();
+  __ Jump(&branch_taken);
+  __ PushConstant(Smi::Handle(Smi::New(0)));
+  __ ReturnTOS();
+  __ Bind(&branch_taken);
+  __ PushConstant(Smi::Handle(Smi::New(42)));
+  __ ReturnTOS();
+}
+
+
+ASSEMBLER_TEST_RUN(IfEqStrictNumTOSTaken, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(IfEqStrictNumTOSNotTaken, assembler) {
+  Label branch_taken;
+  __ PushConstant(Smi::Handle(Smi::New(-1)));
+  __ PushConstant(Smi::Handle(Smi::New(1)));
+  __ IfEqStrictNumTOS();
+  __ Jump(&branch_taken);
+  __ PushConstant(Smi::Handle(Smi::New(42)));
+  __ ReturnTOS();
+  __ Bind(&branch_taken);
+  __ PushConstant(Smi::Handle(Smi::New(0)));
+  __ ReturnTOS();
+}
+
+
+ASSEMBLER_TEST_RUN(IfEqStrictNumTOSNotTaken, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(IfEqStrictNumTOSTakenDouble, assembler) {
+  Label branch_taken;
+  __ PushConstant(Double::Handle(Double::New(1.0, Heap::kOld)));
+  __ PushConstant(Double::Handle(Double::New(1.0, Heap::kOld)));
+  __ IfEqStrictNumTOS();
+  __ Jump(&branch_taken);
+  __ PushConstant(Smi::Handle(Smi::New(0)));
+  __ ReturnTOS();
+  __ Bind(&branch_taken);
+  __ PushConstant(Smi::Handle(Smi::New(42)));
+  __ ReturnTOS();
+}
+
+
+ASSEMBLER_TEST_RUN(IfEqStrictNumTOSTakenDouble, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(IfEqStrictNumTOSNotTakenDouble, assembler) {
+  Label branch_taken;
+  __ PushConstant(Double::Handle(Double::New(-1.0, Heap::kOld)));
+  __ PushConstant(Double::Handle(Double::New(1.0, Heap::kOld)));
+  __ IfEqStrictNumTOS();
+  __ Jump(&branch_taken);
+  __ PushConstant(Smi::Handle(Smi::New(42)));
+  __ ReturnTOS();
+  __ Bind(&branch_taken);
+  __ PushConstant(Smi::Handle(Smi::New(0)));
+  __ ReturnTOS();
+}
+
+
+ASSEMBLER_TEST_RUN(IfEqStrictNumTOSNotTakenDouble, test) {
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
+}
+
+
+//  - BooleanNegateTOS
+//
+//    SP[0] = !SP[0]
+ASSEMBLER_TEST_GENERATE(BooleanNegateTOSTrue, assembler) {
+  __ PushConstant(Bool::True());
+  __ BooleanNegateTOS();
+  __ ReturnTOS();
+}
+
+
+ASSEMBLER_TEST_RUN(BooleanNegateTOSTrue, test) {
+  EXPECT(!EXECUTE_TEST_CODE_BOOL(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(BooleanNegateTOSFalse, assembler) {
+  __ PushConstant(Bool::False());
+  __ BooleanNegateTOS();
+  __ ReturnTOS();
+}
+
+
+ASSEMBLER_TEST_RUN(BooleanNegateTOSFalse, test) {
+  EXPECT(EXECUTE_TEST_CODE_BOOL(test->code()));
+}
+
+
+//  - AssertBoolean A
+//
+//    Assert that TOS is a boolean (A = 1) or that TOS is not null (A = 0).
+ASSEMBLER_TEST_GENERATE(AssertBooleanTrue, assembler) {
+  __ PushConstant(Bool::True());
+  __ AssertBoolean(1);
+  __ ReturnTOS();
+}
+
+
+ASSEMBLER_TEST_RUN(AssertBooleanTrue, test) {
+  EXPECT(EXECUTE_TEST_CODE_BOOL(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(AssertBooleanFalse, assembler) {
+  __ PushConstant(Bool::False());
+  __ AssertBoolean(1);
+  __ ReturnTOS();
+}
+
+
+ASSEMBLER_TEST_RUN(AssertBooleanFalse, test) {
+  EXPECT(!EXECUTE_TEST_CODE_BOOL(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(AssertBooleanNotNull, assembler) {
+  __ PushConstant(Bool::True());
+  __ AssertBoolean(0);
+  __ ReturnTOS();
+}
+
+
+ASSEMBLER_TEST_RUN(AssertBooleanNotNull, test) {
+  EXPECT(EXECUTE_TEST_CODE_BOOL(test->code()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(AssertBooleanFail1, assembler) {
+  __ PushConstant(Smi::Handle(Smi::New(37)));
+  __ AssertBoolean(1);
+  __ ReturnTOS();
+}
+
+
+ASSEMBLER_TEST_RUN(AssertBooleanFail1, test) {
+  EXPECT(EXECUTE_TEST_CODE_OBJECT(test->code()).IsError());
+}
+
+
+ASSEMBLER_TEST_GENERATE(AssertBooleanFail2, assembler) {
+  __ PushConstant(Object::null_object());
+  __ AssertBoolean(0);
+  __ ReturnTOS();
+}
+
+
+ASSEMBLER_TEST_RUN(AssertBooleanFail2, test) {
+  EXPECT(EXECUTE_TEST_CODE_OBJECT(test->code()).IsError());
+}
+
+}  // namespace dart
+
+#endif  // defined(TARGET_ARCH_DBC)
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index 97b8fc8..1d26af8 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -1282,6 +1282,14 @@
   if (FLAG_support_debugger && do_stacktrace) {
     String& var_name = String::Handle();
     Instance& var_value = Instance::Handle();
+    // Collecting the stack trace and accessing local variables
+    // of frames may trigger parsing of functions to compute
+    // variable descriptors of functions. Parsing may trigger
+    // code execution, e.g. to compute compile-time constants. Thus,
+    // disable FLAG_stacktrace_every during trace collection to prevent
+    // recursive stack trace collection.
+    intptr_t saved_stacktrace_every = FLAG_stacktrace_every;
+    FLAG_stacktrace_every = 0;
     DebuggerStackTrace* stack = isolate->debugger()->StackTrace();
     intptr_t num_frames = stack->Length();
     for (intptr_t i = 0; i < num_frames; i++) {
@@ -1294,6 +1302,7 @@
         frame->VariableAt(v, &var_name, &unused, &unused, &var_value);
       }
     }
+    FLAG_stacktrace_every = saved_stacktrace_every;
   }
 
   const Error& error = Error::Handle(thread->HandleInterrupts());
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index 55afac1..49796c1 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -1444,9 +1444,14 @@
                                              intptr_t osr_id) {
 NOT_IN_PRODUCT(
   VMTagScope tagScope(thread, VMTag::kCompileOptimizedTagId);
-  const char* event_name = IsBackgroundCompilation()
-      ? "BackgroundCompileOptimizedFunction"
-      : "CompileOptimizedFunction";
+  const char* event_name;
+  if (osr_id != kNoOSRDeoptId) {
+    event_name = "CompileFunctionOptimizedOSR";
+  } else if (IsBackgroundCompilation()) {
+    event_name = "CompileFunctionOptimizedBackground";
+  } else {
+    event_name = "CompileFunctionOptimized";
+  }
   TIMELINE_FUNCTION_COMPILATION_DURATION(thread, event_name, function);
 )  // !PRODUCT
 
@@ -1494,9 +1499,7 @@
   const Function& function = Function::Handle(code.function());
   ParsedFunction* parsed_function = new ParsedFunction(
       Thread::Current(), Function::ZoneHandle(function.raw()));
-  LocalVarDescriptors& var_descs =
-      LocalVarDescriptors::Handle(code.var_descriptors());
-  ASSERT(var_descs.IsNull());
+  ASSERT(code.var_descriptors() == Object::null());
   // IsIrregexpFunction have eager var descriptors generation.
   ASSERT(!function.IsIrregexpFunction());
   // In background compilation, parser can produce 'errors": bailouts
@@ -1505,8 +1508,8 @@
   if (setjmp(*jump.Set()) == 0) {
     Parser::ParseFunction(parsed_function);
     parsed_function->AllocateVariables();
-    var_descs = parsed_function->node_sequence()->scope()->
-        GetVarDescriptors(function);
+    const LocalVarDescriptors& var_descs = LocalVarDescriptors::Handle(
+        parsed_function->node_sequence()->scope()->GetVarDescriptors(function));
     ASSERT(!var_descs.IsNull());
     code.set_var_descriptors(var_descs);
   } else {
diff --git a/runtime/vm/constants_dbc.h b/runtime/vm/constants_dbc.h
index 4eb7b1b..f4144d6 100644
--- a/runtime/vm/constants_dbc.h
+++ b/runtime/vm/constants_dbc.h
@@ -340,6 +340,8 @@
   V(Move,                          A_X, reg, xeg, ___) \
   V(Push,                            X, xeg, ___, ___) \
   V(LoadConstant,                  A_D, reg, lit, ___) \
+  V(LoadClassId,                   A_D, reg, reg, ___) \
+  V(LoadClassIdTOS,                  0, ___, ___, ___) \
   V(PushConstant,                    D, lit, ___, ___) \
   V(StoreLocal,                      X, xeg, ___, ___) \
   V(PopLocal,                        X, xeg, ___, ___) \
diff --git a/runtime/vm/cpu_dbc.cc b/runtime/vm/cpu_dbc.cc
index 8fcff5b..0e61fbd 100644
--- a/runtime/vm/cpu_dbc.cc
+++ b/runtime/vm/cpu_dbc.cc
@@ -6,11 +6,12 @@
 #if defined(TARGET_ARCH_DBC)
 
 #include "vm/cpu.h"
+#include "vm/cpu_dbc.h"
 
+#include "vm/cpuinfo.h"
 
 namespace dart {
 
-
 void CPU::FlushICache(uword start, uword size) {
   // Nothing to do.
 }
@@ -21,6 +22,31 @@
 }
 
 
+const char* HostCPUFeatures::hardware_ = NULL;
+#if defined(DEBUG)
+bool HostCPUFeatures::initialized_ = false;
+#endif
+
+void HostCPUFeatures::InitOnce() {
+  CpuInfo::InitOnce();
+  hardware_ = CpuInfo::GetCpuModel();
+#if defined(DEBUG)
+  initialized_ = true;
+#endif
+}
+
+
+void HostCPUFeatures::Cleanup() {
+  DEBUG_ASSERT(initialized_);
+#if defined(DEBUG)
+  initialized_ = false;
+#endif
+  ASSERT(hardware_ != NULL);
+  free(const_cast<char*>(hardware_));
+  hardware_ = NULL;
+  CpuInfo::Cleanup();
+}
+
 }  // namespace dart
 
 #endif  // defined TARGET_ARCH_DBC
diff --git a/runtime/vm/cpu_dbc.h b/runtime/vm/cpu_dbc.h
index b437beb..486acdb 100644
--- a/runtime/vm/cpu_dbc.h
+++ b/runtime/vm/cpu_dbc.h
@@ -12,13 +12,33 @@
 
 class HostCPUFeatures: public AllStatic {
  public:
-  static const char* hardware() { return "simdbc"; }
+  static void InitOnce();
+  static void Cleanup();
+
+  static const char* hardware() {
+    DEBUG_ASSERT(initialized_);
+    return hardware_;
+  }
+
+ private:
+  static const char* hardware_;
+#if defined(DEBUG)
+  static bool initialized_;
+#endif
 };
 
 class TargetCPUFeatures : public AllStatic {
  public:
-  static void InitOnce() {}
-  static void Cleanup() {}
+  static void InitOnce() {
+    HostCPUFeatures::InitOnce();
+  }
+  static void Cleanup() {
+    HostCPUFeatures::Cleanup();
+  }
+
+  static const char* hardware() {
+    return CPU::Id();
+  }
 
   static bool double_truncate_round_supported() {
     return true;
diff --git a/runtime/vm/cpuinfo_test.cc b/runtime/vm/cpuinfo_test.cc
index 2b587f1..0b6113b 100644
--- a/runtime/vm/cpuinfo_test.cc
+++ b/runtime/vm/cpuinfo_test.cc
@@ -9,13 +9,11 @@
 
 namespace dart {
 
-#if !defined(TARGET_ARCH_DBC)
 UNIT_TEST_CASE(GetCpuModelTest) {
   const char* cpumodel = CpuInfo::GetCpuModel();
   EXPECT_NE(strlen(cpumodel), 0UL);
   // caller is responsible for deleting the returned cpumodel string.
   free(const_cast<char*>(cpumodel));
 }
-#endif
 
 }  // namespace dart
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index 3fe6df5..cd7dbde 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -207,6 +207,9 @@
     if (vm_isolate_snapshot != NULL) {
       NOT_IN_PRODUCT(TimelineDurationScope tds(Timeline::GetVMStream(),
                                                "VMIsolateSnapshot"));
+      if (instructions_snapshot != NULL) {
+        vm_isolate_->SetupInstructionsSnapshotPage(instructions_snapshot);
+      }
       if (data_snapshot != NULL) {
         vm_isolate_->SetupDataSnapshotPage(data_snapshot);
       }
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index 6afad63..3cb92b2 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -1402,6 +1402,7 @@
 // that inline the function that contains the newly created breakpoint.
 // We currently don't have this info so we deoptimize all functions.
 void Debugger::DeoptimizeWorld() {
+  BackgroundCompiler::Stop(isolate_);
   DeoptimizeFunctionsOnStack();
   // Iterate over all classes, deoptimize functions.
   // TODO(hausner): Could possibly be combined with RemoveOptimizedCode()
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index 69f7f16..0a78c7b 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -3451,8 +3451,6 @@
         load->set_is_immutable(kind != MethodRecognizer::kGrowableArrayLength);
         return ReturnDefinition(load);
       }
-#if !defined(TARGET_ARCH_DBC)
-      // TODO(vegorov) add bytecode to support this method.
       case MethodRecognizer::kClassIDgetID: {
         LocalVariable* value_var =
             node->scope()->LookupVariable(Symbols::Value(), true);
@@ -3460,7 +3458,6 @@
         LoadClassIdInstr* load = new(Z) LoadClassIdInstr(value);
         return ReturnDefinition(load);
       }
-#endif
       case MethodRecognizer::kGrowableArrayCapacity: {
         Value* receiver = Bind(BuildLoadThisVar(node->scope(), token_pos));
         LoadFieldInstr* data_load = new(Z) LoadFieldInstr(
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
index 9d448ab..006053f 100644
--- a/runtime/vm/flow_graph_compiler.cc
+++ b/runtime/vm/flow_graph_compiler.cc
@@ -32,6 +32,10 @@
 
 DEFINE_FLAG(bool, enable_simd_inline, true,
     "Enable inlining of SIMD related method calls.");
+DEFINE_FLAG(bool, inline_smi_string_hashcode, true,
+    "Inline hashcode for Smi and one-byte strings in case of megamorphic call");
+DEFINE_FLAG(int, inline_smi_string_hashcode_ratio, 50,
+    "Minimal hotness (0..100) of one-byte-string before inlining its hashcode");
 DEFINE_FLAG(int, min_optimization_counter_threshold, 5000,
     "The minimum invocation count for a function.");
 DEFINE_FLAG(int, optimization_counter_scale, 2000,
@@ -156,6 +160,31 @@
 }
 
 
+// Returns true if OnebyteString is a frequent receiver class. We inline
+// Smi check as well, since a Smi check must be done anyway.
+// TODO(srdjan): Add check and code if Smi class is hot.
+bool FlowGraphCompiler::ShouldInlineSmiStringHashCode(const ICData& ic_data) {
+  if (!FLAG_inline_smi_string_hashcode ||
+     (ic_data.target_name() != Symbols::hashCode().raw())) {
+    return false;
+  }
+  // Precompiled code has no ICData, optimistically inline it.
+  if (ic_data.IsNull() || (ic_data.NumberOfChecks() == 0)) {
+    return true;
+  }
+  // Check if OneByteString is hot enough.
+  const ICData& ic_data_sorted =
+      ICData::Handle(ic_data.AsUnaryClassChecksSortedByCount());
+  ASSERT(ic_data_sorted.NumberOfChecks() > 0);
+  if (ic_data_sorted.GetReceiverClassIdAt(0) == kOneByteStringCid) {
+    const intptr_t total_count = ic_data_sorted.AggregateCount();
+    const intptr_t ratio = (ic_data_sorted.GetCountAt(0) * 100) / total_count;
+    return ratio > FLAG_inline_smi_string_hashcode_ratio;
+  }
+  return false;
+}
+
+
 FlowGraphCompiler::FlowGraphCompiler(
     Assembler* assembler,
     FlowGraph* flow_graph,
diff --git a/runtime/vm/flow_graph_compiler.h b/runtime/vm/flow_graph_compiler.h
index 586dbdb..f7aa76e 100644
--- a/runtime/vm/flow_graph_compiler.h
+++ b/runtime/vm/flow_graph_compiler.h
@@ -616,6 +616,8 @@
  private:
   friend class CheckStackOverflowSlowPath;  // For pending_deoptimization_env_.
 
+  static bool ShouldInlineSmiStringHashCode(const ICData& ic_data);
+
   void EmitFrameEntry();
 
   void AddStaticCallTarget(const Function& function);
diff --git a/runtime/vm/flow_graph_compiler_arm.cc b/runtime/vm/flow_graph_compiler_arm.cc
index 9c58044..34172891 100644
--- a/runtime/vm/flow_graph_compiler_arm.cc
+++ b/runtime/vm/flow_graph_compiler_arm.cc
@@ -1322,7 +1322,7 @@
   // Load receiver into R0.
   __ LoadFromOffset(kWord, R0, SP, (argument_count - 1) * kWordSize);
   Label done;
-  if (name.raw() == Symbols::hashCode().raw()) {
+  if (ShouldInlineSmiStringHashCode(ic_data)) {
     Label megamorphic_call;
     __ Comment("Inlined get:hashCode for Smi and OneByteString");
     __ tst(R0, Operand(kSmiTagMask));
diff --git a/runtime/vm/flow_graph_compiler_arm64.cc b/runtime/vm/flow_graph_compiler_arm64.cc
index d62a23a..07cff9e 100644
--- a/runtime/vm/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/flow_graph_compiler_arm64.cc
@@ -1303,7 +1303,7 @@
   // Load receiver into R0.
   __ LoadFromOffset(R0, SP, (argument_count - 1) * kWordSize);
   Label done;
-  if (name.raw() == Symbols::hashCode().raw()) {
+  if (ShouldInlineSmiStringHashCode(ic_data)) {
     Label megamorphic_call;
     __ Comment("Inlined get:hashCode for Smi and OneByteString");
     __ tsti(R0, Immediate(kSmiTagMask));
diff --git a/runtime/vm/flow_graph_compiler_ia32.cc b/runtime/vm/flow_graph_compiler_ia32.cc
index 8a7c349..30cff6b2 100644
--- a/runtime/vm/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/flow_graph_compiler_ia32.cc
@@ -1303,15 +1303,13 @@
   // Load receiver into EBX.
   __ movl(EBX, Address(ESP, (argument_count - 1) * kWordSize));
   Label done;
-  if (name.raw() == Symbols::hashCode().raw()) {
-    Label try_onebytestring, megamorphic_call;
+  if (ShouldInlineSmiStringHashCode(ic_data)) {
+    Label megamorphic_call;
     __ Comment("Inlined get:hashCode for Smi and OneByteString");
+    __ movl(EAX, EBX);  // Move Smi hashcode to EAX.
     __ testl(EBX, Immediate(kSmiTagMask));
-    __ j(NOT_ZERO, &try_onebytestring, Assembler::kNearJump);  // Non-smi value.
-    __ movl(EAX, EBX);
-    __ jmp(&done, Assembler::kNearJump);
+    __ j(ZERO, &done, Assembler::kNearJump);  // It is Smi, we are done.
 
-    __ Bind(&try_onebytestring);
     __ CompareClassId(EBX, kOneByteStringCid, EAX);
     __ j(NOT_EQUAL, &megamorphic_call, Assembler::kNearJump);
     __ movl(EAX, FieldAddress(EBX, String::hash_offset()));
diff --git a/runtime/vm/flow_graph_compiler_mips.cc b/runtime/vm/flow_graph_compiler_mips.cc
index 9fa5d9f..c63f850 100644
--- a/runtime/vm/flow_graph_compiler_mips.cc
+++ b/runtime/vm/flow_graph_compiler_mips.cc
@@ -1330,15 +1330,13 @@
   // Load receiver into T0,
   __ lw(T0, Address(SP, (argument_count - 1) * kWordSize));
   Label done;
-  if (name.raw() == Symbols::hashCode().raw()) {
-    Label try_onebytestring, megamorphic_call;
+  if (ShouldInlineSmiStringHashCode(ic_data)) {
+    Label megamorphic_call;
     __ Comment("Inlined get:hashCode for Smi and OneByteString");
     __ andi(CMPRES1, T0, Immediate(kSmiTagMask));
-    __ bne(CMPRES1, ZR, &try_onebytestring);  // Not Smi.
-    __ mov(V0, T0);
-    __ b(&done);
+    __ beq(CMPRES1, ZR, &done);  // Is Smi.
+    __ delay_slot()->mov(V0, T0);  // Move Smi hashcode to V0.
 
-    __ Bind(&try_onebytestring);
     __ LoadClassId(CMPRES1, T0);  // Class ID check.
     __ BranchNotEqual(
         CMPRES1, Immediate(kOneByteStringCid), &megamorphic_call);
diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc
index def75aa..c8ce4f5 100644
--- a/runtime/vm/flow_graph_compiler_x64.cc
+++ b/runtime/vm/flow_graph_compiler_x64.cc
@@ -1332,15 +1332,13 @@
   // Load receiver into RDI.
   __ movq(RDI, Address(RSP, (argument_count - 1) * kWordSize));
   Label done;
-  if (name.raw() == Symbols::hashCode().raw()) {
-    Label try_onebytestring, megamorphic_call;
+  if (ShouldInlineSmiStringHashCode(ic_data)) {
+    Label megamorphic_call;
     __ Comment("Inlined get:hashCode for Smi and OneByteString");
+    __ movq(RAX, RDI);  // Move Smi hashcode to RAX.
     __ testq(RDI, Immediate(kSmiTagMask));
-    __ j(NOT_ZERO, &try_onebytestring, Assembler::kNearJump);  // Non-smi value.
-    __ movq(RAX, RDI);
-    __ jmp(&done, Assembler::kNearJump);
+    __ j(ZERO, &done, Assembler::kNearJump);  // It is Smi, we are done.
 
-    __ Bind(&try_onebytestring);
     __ CompareClassId(RDI, kOneByteStringCid);
     __ j(NOT_EQUAL, &megamorphic_call, Assembler::kNearJump);
     __ movq(RAX, FieldAddress(RDI, String::hash_offset()));
diff --git a/runtime/vm/flow_graph_type_propagator.cc b/runtime/vm/flow_graph_type_propagator.cc
index 8accbf4..b4a5f3b 100644
--- a/runtime/vm/flow_graph_type_propagator.cc
+++ b/runtime/vm/flow_graph_type_propagator.cc
@@ -251,17 +251,8 @@
 
 
 void FlowGraphTypePropagator::VisitCheckClassId(CheckClassIdInstr* check) {
-  if (!check->Dependencies().IsNone()) {
-    // TODO(vegorov): If check is affected by side-effect we can still propagate
-    // the type further but not the cid.
-    return;
-  }
-
-  LoadClassIdInstr* load_cid =
-      check->value()->definition()->OriginalDefinition()->AsLoadClassId();
-  if (load_cid != NULL) {
-    SetCid(load_cid->object()->definition(), check->cid());
-  }
+  // Can't propagate the type/cid because it may cause illegal code motion and
+  // we don't track dependencies in all places via redefinitions.
 }
 
 
diff --git a/runtime/vm/hash_table.h b/runtime/vm/hash_table.h
index 15317a1..8408f23 100644
--- a/runtime/vm/hash_table.h
+++ b/runtime/vm/hash_table.h
@@ -85,23 +85,21 @@
 class HashTable : public ValueObject {
  public:
   typedef KeyTraits Traits;
+  // Uses the passed in handles for all handle operations.
+  // 'Release' must be called at the end to obtain the final table
+  // after potential growth/shrinkage.
+  HashTable(Object* key, Smi* index, Array* data)
+      : key_handle_(key),
+        smi_handle_(index),
+        data_(data),
+        released_data_(NULL) {}
   // Uses 'zone' for handle allocation. 'Release' must be called at the end
   // to obtain the final table after potential growth/shrinkage.
   HashTable(Zone* zone, RawArray* data)
-      : zone_(zone),
-        key_handle_(Object::Handle(zone_)),
-        smi_handle_(Smi::Handle(zone_)),
-        data_(&Array::Handle(zone_, data)),
+      : key_handle_(&Object::Handle(zone)),
+        smi_handle_(&Smi::Handle(zone)),
+        data_(&Array::Handle(zone, data)),
         released_data_(NULL) {}
-  // Like above, except uses current zone.
-  explicit HashTable(RawArray* data)
-      : zone_(Thread::Current()->zone()),
-        key_handle_(Object::Handle(zone_)),
-        smi_handle_(Smi::Handle(zone_)),
-        data_(&Array::Handle(zone_, data)),
-        released_data_(NULL) {
-    ASSERT(!data_->IsNull());
-  }
 
   // Returns the final table. The handle is cleared when this HashTable is
   // destroyed.
@@ -134,15 +132,15 @@
   // Initializes an empty table.
   void Initialize() const {
     ASSERT(data_->Length() >= ArrayLengthForNumOccupied(0));
-    smi_handle_ = Smi::New(0);
-    data_->SetAt(kOccupiedEntriesIndex, smi_handle_);
-    data_->SetAt(kDeletedEntriesIndex, smi_handle_);
+    *smi_handle_ = Smi::New(0);
+    data_->SetAt(kOccupiedEntriesIndex, *smi_handle_);
+    data_->SetAt(kDeletedEntriesIndex, *smi_handle_);
 
 NOT_IN_PRODUCT(
-    data_->SetAt(kNumGrowsIndex, smi_handle_);
-    data_->SetAt(kNumLT5LookupsIndex, smi_handle_);
-    data_->SetAt(kNumLT25LookupsIndex, smi_handle_);
-    data_->SetAt(kNumGT25LookupsIndex, smi_handle_);
+    data_->SetAt(kNumGrowsIndex, *smi_handle_);
+    data_->SetAt(kNumLT5LookupsIndex, *smi_handle_);
+    data_->SetAt(kNumLT25LookupsIndex, *smi_handle_);
+    data_->SetAt(kNumGT25LookupsIndex, *smi_handle_);
 )  // !PRODUCT
 
     for (intptr_t i = kHeaderSize; i < data_->Length(); ++i) {
@@ -171,8 +169,8 @@
         NOT_IN_PRODUCT(UpdateCollisions(collisions);)
         return -1;
       } else if (!IsDeleted(probe)) {
-        key_handle_ = GetKey(probe);
-        if (KeyTraits::IsMatch(key, key_handle_)) {
+        *key_handle_ = GetKey(probe);
+        if (KeyTraits::IsMatch(key, *key_handle_)) {
           NOT_IN_PRODUCT(UpdateCollisions(collisions);)
           return probe;
         }
@@ -210,8 +208,8 @@
           deleted = probe;
         }
       } else {
-        key_handle_ = GetKey(probe);
-        if (KeyTraits::IsMatch(key, key_handle_)) {
+        *key_handle_ = GetKey(probe);
+        if (KeyTraits::IsMatch(key, *key_handle_)) {
           *entry = probe;
           NOT_IN_PRODUCT(UpdateCollisions(collisions);)
           return true;
@@ -289,10 +287,10 @@
     return GetSmiValueAt(kDeletedEntriesIndex);
   }
   Object& KeyHandle() const {
-    return key_handle_;
+    return *key_handle_;
   }
   Smi& SmiHandle() const {
-    return smi_handle_;
+    return *smi_handle_;
   }
 
 NOT_IN_PRODUCT(
@@ -376,24 +374,21 @@
 
   intptr_t GetSmiValueAt(intptr_t index) const {
     ASSERT(!data_->IsNull());
-    ASSERT(Object::Handle(zone(), data_->At(index)).IsSmi());
+    ASSERT(!data_->At(index)->IsHeapObject());
     return Smi::Value(Smi::RawCast(data_->At(index)));
   }
 
   void SetSmiValueAt(intptr_t index, intptr_t value) const {
-    smi_handle_ = Smi::New(value);
-    data_->SetAt(index, smi_handle_);
+    *smi_handle_ = Smi::New(value);
+    data_->SetAt(index, *smi_handle_);
   }
 
   void AdjustSmiValueAt(intptr_t index, intptr_t delta) const {
     SetSmiValueAt(index, (GetSmiValueAt(index) + delta));
   }
 
-  Zone* zone() const { return zone_; }
-
-  Zone* zone_;
-  Object& key_handle_;
-  Smi& smi_handle_;
+  Object* key_handle_;
+  Smi* smi_handle_;
   // Exactly one of these is non-NULL, depending on whether Release was called.
   Array* data_;
   Array* released_data_;
@@ -408,9 +403,11 @@
  public:
   typedef HashTable<KeyTraits, kUserPayloadSize, 0> BaseTable;
   static const intptr_t kPayloadSize = kUserPayloadSize;
-  explicit UnorderedHashTable(RawArray* data) : BaseTable(data) {}
-  UnorderedHashTable(Zone* zone, RawArray* data)
-      : BaseTable(zone, data) {}
+  explicit UnorderedHashTable(RawArray* data)
+      : BaseTable(Thread::Current()->zone(), data) {}
+  UnorderedHashTable(Zone* zone, RawArray* data) : BaseTable(zone, data) {}
+  UnorderedHashTable(Object* key, Smi* value, Array* data)
+      : BaseTable(key, value, data) {}
   // Note: Does not check for concurrent modification.
   class Iterator {
    public:
@@ -447,9 +444,12 @@
   typedef HashTable<KeyTraits, kUserPayloadSize + 1, 1> BaseTable;
   static const intptr_t kPayloadSize = kUserPayloadSize;
   static const intptr_t kNextEnumIndex = BaseTable::kMetaDataIndex;
+  EnumIndexHashTable(Object* key, Smi* value, Array* data)
+      : BaseTable(key, value, data) {}
   EnumIndexHashTable(Zone* zone, RawArray* data)
       : BaseTable(zone, data) {}
-  explicit EnumIndexHashTable(RawArray* data) : BaseTable(data) {}
+  explicit EnumIndexHashTable(RawArray* data)
+      : BaseTable(Thread::Current()->zone(), data) {}
   // Note: Does not check for concurrent modification.
   class Iterator {
    public:
@@ -509,7 +509,7 @@
   template<typename Table>
   static RawArray* New(intptr_t initial_capacity,
                        Heap::Space space = Heap::kNew) {
-    Table table(Array::New(
+    Table table(Thread::Current()->zone(), Array::New(
         Table::ArrayLengthForNumOccupied(initial_capacity), space));
     table.Initialize();
     return table.Release().raw();
@@ -517,7 +517,7 @@
 
   template<typename Table>
   static RawArray* New(const Array& array) {
-    Table table(array.raw());
+    Table table(Thread::Current()->zone(), array.raw());
     table.Initialize();
     return table.Release().raw();
   }
@@ -590,8 +590,11 @@
 template<typename BaseIterTable>
 class HashMap : public BaseIterTable {
  public:
-  explicit HashMap(RawArray* data) : BaseIterTable(data) {}
+  explicit HashMap(RawArray* data)
+      : BaseIterTable(Thread::Current()->zone(), data) {}
   HashMap(Zone* zone, RawArray* data) : BaseIterTable(zone, data) {}
+  HashMap(Object* key, Smi* value, Array* data)
+      : BaseIterTable(key, value, data) {}
   template<typename Key>
   RawObject* GetOrNull(const Key& key, bool* present = NULL) const {
     intptr_t entry = BaseIterTable::FindKey(key);
@@ -676,8 +679,11 @@
 class UnorderedHashMap : public HashMap<UnorderedHashTable<KeyTraits, 1> > {
  public:
   typedef HashMap<UnorderedHashTable<KeyTraits, 1> > BaseMap;
-  explicit UnorderedHashMap(RawArray* data) : BaseMap(data) {}
+  explicit UnorderedHashMap(RawArray* data)
+      : BaseMap(Thread::Current()->zone(), data) {}
   UnorderedHashMap(Zone* zone, RawArray* data) : BaseMap(zone, data) {}
+  UnorderedHashMap(Object* key, Smi* value, Array* data)
+      : BaseMap(key, value, data) {}
 };
 
 
@@ -685,16 +691,22 @@
 class EnumIndexHashMap : public HashMap<EnumIndexHashTable<KeyTraits, 1> > {
  public:
   typedef HashMap<EnumIndexHashTable<KeyTraits, 1> > BaseMap;
-  explicit EnumIndexHashMap(RawArray* data) : BaseMap(data) {}
+  explicit EnumIndexHashMap(RawArray* data)
+      : BaseMap(Thread::Current()->zone(), data) {}
   EnumIndexHashMap(Zone* zone, RawArray* data) : BaseMap(zone, data) {}
+  EnumIndexHashMap(Object* key, Smi* value, Array* data)
+      : BaseMap(key, value, data) {}
 };
 
 
 template<typename BaseIterTable>
 class HashSet : public BaseIterTable {
  public:
-  explicit HashSet(RawArray* data) : BaseIterTable(data) {}
+  explicit HashSet(RawArray* data)
+      : BaseIterTable(Thread::Current()->zone(), data) {}
   HashSet(Zone* zone, RawArray* data) : BaseIterTable(zone, data) {}
+  HashSet(Object* key, Smi* value, Array* data)
+      : BaseIterTable(key, value, data) {}
   bool Insert(const Object& key) {
     EnsureCapacity();
     intptr_t entry = -1;
@@ -770,10 +782,13 @@
 class UnorderedHashSet : public HashSet<UnorderedHashTable<KeyTraits, 0> > {
  public:
   typedef HashSet<UnorderedHashTable<KeyTraits, 0> > BaseSet;
-  explicit UnorderedHashSet(RawArray* data) : BaseSet(data) {
+  explicit UnorderedHashSet(RawArray* data)
+      : BaseSet(Thread::Current()->zone(), data) {
     ASSERT(data != Array::null());
   }
   UnorderedHashSet(Zone* zone, RawArray* data) : BaseSet(zone, data) {}
+  UnorderedHashSet(Object* key, Smi* value, Array* data)
+      : BaseSet(key, value, data) {}
 };
 
 
@@ -781,8 +796,11 @@
 class EnumIndexHashSet : public HashSet<EnumIndexHashTable<KeyTraits, 0> > {
  public:
   typedef HashSet<EnumIndexHashTable<KeyTraits, 0> > BaseSet;
-  explicit EnumIndexHashSet(RawArray* data) : BaseSet(data) {}
+  explicit EnumIndexHashSet(RawArray* data)
+      : BaseSet(Thread::Current()->zone(), data) {}
   EnumIndexHashSet(Zone* zone, RawArray* data) : BaseSet(zone, data) {}
+  EnumIndexHashSet(Object* key, Smi* value, Array* data)
+      : BaseSet(key, value, data) {}
 };
 
 }  // namespace dart
diff --git a/runtime/vm/hash_table_test.cc b/runtime/vm/hash_table_test.cc
index 8e0ac23..158af48 100644
--- a/runtime/vm/hash_table_test.cc
+++ b/runtime/vm/hash_table_test.cc
@@ -63,7 +63,7 @@
 
 TEST_CASE(HashTable) {
   typedef HashTable<TestTraits, 2, 1> Table;
-  Table table(HashTables::New<Table>(5));
+  Table table(Thread::Current()->zone(), HashTables::New<Table>(5));
   // Ensure that we did get at least 5 entries.
   EXPECT_LE(5, table.NumEntries());
   EXPECT_EQ(0, table.NumOccupied());
diff --git a/runtime/vm/heap.cc b/runtime/vm/heap.cc
index 6fd3c3a..ef4e14c 100644
--- a/runtime/vm/heap.cc
+++ b/runtime/vm/heap.cc
@@ -369,6 +369,7 @@
 void Heap::CollectNewSpaceGarbage(Thread* thread,
                                   ApiCallbacks api_callbacks,
                                   GCReason reason) {
+  ASSERT((reason == kNewSpace) || (reason == kFull));
   if (BeginNewSpaceGC(thread)) {
     bool invoke_api_callbacks = (api_callbacks == kInvokeApiCallbacks);
     RecordBeforeGC(kNew, reason);
@@ -381,7 +382,7 @@
     RecordAfterGC(kNew);
     PrintStats();
     EndNewSpaceGC();
-    if (old_space_.NeedsGarbageCollection()) {
+    if ((reason == kNewSpace) && old_space_.NeedsGarbageCollection()) {
       // Old collections should call the API callbacks.
       CollectOldSpaceGarbage(thread, kInvokeApiCallbacks, kPromotion);
     }
@@ -392,6 +393,7 @@
 void Heap::CollectOldSpaceGarbage(Thread* thread,
                                   ApiCallbacks api_callbacks,
                                   GCReason reason) {
+  ASSERT((reason != kNewSpace));
   if (BeginOldSpaceGC(thread)) {
     bool invoke_api_callbacks = (api_callbacks == kInvokeApiCallbacks);
     RecordBeforeGC(kOld, reason);
diff --git a/runtime/vm/il_printer.cc b/runtime/vm/il_printer.cc
index cc62146..204725c 100644
--- a/runtime/vm/il_printer.cc
+++ b/runtime/vm/il_printer.cc
@@ -13,6 +13,8 @@
 
 #ifndef PRODUCT
 
+DEFINE_FLAG(bool, display_sorted_ic_data, false,
+    "Calls display a unary, sorted-by count form of ICData");
 DEFINE_FLAG(bool, print_environments, false, "Print SSA environments.");
 DEFINE_FLAG(charp, print_flow_graph_filter, NULL,
     "Print only IR of functions with matching names");
@@ -191,7 +193,9 @@
 }
 
 
-static void PrintICDataHelper(BufferFormatter* f, const ICData& ic_data) {
+static void PrintICDataHelper(BufferFormatter* f,
+                              const ICData& ic_data,
+                              intptr_t num_checks_to_print) {
   f->Print(" IC[");
   if (ic_data.HasRangeFeedback()) {
     f->Print("{%s",
@@ -205,7 +209,11 @@
   }
   f->Print("%" Pd ": ", ic_data.NumberOfChecks());
   Function& target = Function::Handle();
-  for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) {
+  if ((num_checks_to_print == FlowGraphPrinter::kPrintAll) ||
+      (num_checks_to_print > ic_data.NumberOfChecks())) {
+    num_checks_to_print = ic_data.NumberOfChecks();
+  }
+  for (intptr_t i = 0; i < num_checks_to_print; i++) {
     GrowableArray<intptr_t> class_ids;
     ic_data.GetCheckAt(i, &class_ids, &target);
     const intptr_t count = ic_data.GetCountAt(i);
@@ -222,14 +230,35 @@
     }
     f->Print(" cnt:%" Pd " trgt:'%s'", count, target.ToQualifiedCString());
   }
+  if (num_checks_to_print < ic_data.NumberOfChecks()) {
+    f->Print("...");
+  }
   f->Print("]");
 }
 
 
-void FlowGraphPrinter::PrintICData(const ICData& ic_data) {
+static void PrintICDataSortedHelper(BufferFormatter* f,
+                                    const ICData& ic_data_orig) {
+  const ICData& ic_data =
+      ICData::Handle(ic_data_orig.AsUnaryClassChecksSortedByCount());
+  f->Print(" IC[n:%" Pd"; ", ic_data.NumberOfChecks());
+  for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) {
+    const intptr_t count = ic_data.GetCountAt(i);
+    const intptr_t cid = ic_data.GetReceiverClassIdAt(i);
+    const Class& cls =
+        Class::Handle(Isolate::Current()->class_table()->At(cid));
+    f->Print("%s : %" Pd ", ",
+        String::Handle(cls.Name()).ToCString(), count);
+  }
+  f->Print("]");
+}
+
+
+void FlowGraphPrinter::PrintICData(const ICData& ic_data,
+                                   intptr_t num_checks_to_print) {
   char buffer[1024];
   BufferFormatter f(buffer, sizeof(buffer));
-  PrintICDataHelper(&f, ic_data);
+  PrintICDataHelper(&f, ic_data, num_checks_to_print);
   THR_Print("%s ", buffer);
   const Array& a = Array::Handle(ic_data.arguments_descriptor());
   THR_Print(" arg-desc %" Pd "\n", a.Length());
@@ -435,7 +464,11 @@
     PushArgumentAt(i)->value()->PrintTo(f);
   }
   if (HasICData()) {
-    PrintICDataHelper(f, *ic_data());
+    if (FLAG_display_sorted_ic_data) {
+      PrintICDataSortedHelper(f, *ic_data());
+    } else {
+      PrintICDataHelper(f, *ic_data(), FlowGraphPrinter::kPrintAll);
+    }
   }
 }
 
@@ -446,7 +479,11 @@
     f->Print(", ");
     PushArgumentAt(i)->value()->PrintTo(f);
   }
-  PrintICDataHelper(f, ic_data());
+  if (FLAG_display_sorted_ic_data) {
+    PrintICDataSortedHelper(f, ic_data());
+  } else {
+    PrintICDataHelper(f, ic_data(), FlowGraphPrinter::kPrintAll);
+  }
   if (with_checks()) {
     f->Print(" WITH-CHECKS");
   }
@@ -947,7 +984,11 @@
 
 void CheckClassInstr::PrintOperandsTo(BufferFormatter* f) const {
   value()->PrintTo(f);
-  PrintICDataHelper(f, unary_checks());
+  if (FLAG_display_sorted_ic_data) {
+    PrintICDataSortedHelper(f, unary_checks());
+  } else {
+    PrintICDataHelper(f, unary_checks(), FlowGraphPrinter::kPrintAll);
+  }
   if (IsNullCheck()) {
     f->Print(" nullcheck");
   }
@@ -1263,7 +1304,8 @@
 }
 
 
-void FlowGraphPrinter::PrintICData(const ICData& ic_data) {
+void FlowGraphPrinter::PrintICData(const ICData& ic_data,
+                                   intptr_t num_checks_to_print) {
   UNREACHABLE();
 }
 
diff --git a/runtime/vm/il_printer.h b/runtime/vm/il_printer.h
index bc19c75..b800ab7 100644
--- a/runtime/vm/il_printer.h
+++ b/runtime/vm/il_printer.h
@@ -35,6 +35,8 @@
 // Graph printing.
 class FlowGraphPrinter : public ValueObject {
  public:
+  static const intptr_t kPrintAll = -1;
+
   FlowGraphPrinter(const FlowGraph& flow_graph,
                    bool print_locations = false)
       : function_(flow_graph.function()),
@@ -57,8 +59,10 @@
 
   static void PrintGraph(const char* phase, FlowGraph* flow_graph);
 
-  // Debugging helper function.
-  static void PrintICData(const ICData& ic_data);
+  // Debugging helper function. If 'num_checks_to_print' is not specified
+  // all checks will be printed.
+  static void PrintICData(const ICData& ic_data,
+                          intptr_t num_checks_to_print = kPrintAll);
 
   static bool ShouldPrint(const Function& function);
 
diff --git a/runtime/vm/intermediate_language_dbc.cc b/runtime/vm/intermediate_language_dbc.cc
index 293d239..7c87f8e 100644
--- a/runtime/vm/intermediate_language_dbc.cc
+++ b/runtime/vm/intermediate_language_dbc.cc
@@ -108,15 +108,15 @@
   M(UnboxInteger32)                                                            \
   M(CheckedSmiOp)                                                              \
   M(CheckArrayBound)                                                           \
-  M(CheckSmi)        \
-  M(LoadClassId)     \
-  M(CheckClassId)    \
-  M(CheckClass)      \
-  M(BinarySmiOp)     \
-  M(TestSmi)         \
-  M(RelationalOp)    \
-  M(EqualityCompare) \
-  M(LoadIndexed)     \
+  M(CheckSmi)                                                                  \
+  M(CheckClassId)                                                              \
+  M(CheckClass)                                                                \
+  M(BinarySmiOp)                                                               \
+  M(TestSmi)                                                                   \
+  M(RelationalOp)                                                              \
+  M(EqualityCompare)                                                           \
+  M(LoadIndexed)
+
 // Location summaries actually are not used by the unoptimizing DBC compiler
 // because we don't allocate any registers.
 static LocationSummary* CreateLocationSummary(Zone* zone,
@@ -238,6 +238,15 @@
 }
 
 
+EMIT_NATIVE_CODE(LoadClassId, 1, true) {
+  if (compiler->is_optimizing()) {
+    __ LoadClassId(locs()->out(0).reg(), locs()->in(0).reg());
+  } else {
+    __ LoadClassIdTOS();
+  }
+}
+
+
 EMIT_NATIVE_CODE(Constant, 0, true) {
   const intptr_t kidx = __ AddConstant(value());
   if (compiler->is_optimizing()) {
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 287079a..44127c5 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -934,6 +934,23 @@
 }
 
 
+void Isolate::SetupInstructionsSnapshotPage(
+    const uint8_t* instructions_snapshot_buffer) {
+  InstructionsSnapshot snapshot(instructions_snapshot_buffer);
+#if defined(DEBUG)
+  if (FLAG_trace_isolates) {
+    OS::Print("Precompiled instructions are at [0x%" Px ", 0x%" Px ")\n",
+              reinterpret_cast<uword>(snapshot.instructions_start()),
+              reinterpret_cast<uword>(snapshot.instructions_start()) +
+              snapshot.instructions_size());
+  }
+#endif
+  heap_->SetupExternalPage(snapshot.instructions_start(),
+                           snapshot.instructions_size(),
+                           /* is_executable = */ true);
+}
+
+
 void Isolate::SetupDataSnapshotPage(const uint8_t* data_snapshot_buffer) {
   DataSnapshot snapshot(data_snapshot_buffer);
 #if defined(DEBUG)
@@ -1386,6 +1403,12 @@
 
 
 void Isolate::AddClosureFunction(const Function& function) const {
+  // TODO(regis): remove once debugging complete.
+  if (Compiler::IsBackgroundCompilation()) {
+    NOT_IN_PRODUCT(Profiler::DumpStackTrace(true /*native*/));
+    UNREACHABLE();
+  }
+  ASSERT(!Compiler::IsBackgroundCompilation());
   GrowableObjectArray& closures =
       GrowableObjectArray::Handle(object_store()->closure_functions());
   ASSERT(!closures.IsNull());
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 8061619..c2fc955 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -228,6 +228,8 @@
     library_tag_handler_ = value;
   }
 
+  void SetupInstructionsSnapshotPage(
+      const uint8_t* instructions_snapshot_buffer);
   void SetupDataSnapshotPage(
       const uint8_t* instructions_snapshot_buffer);
 
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index ff46fbf..6f48c92 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -2714,12 +2714,12 @@
 class CHACodeArray : public WeakCodeReferences {
  public:
   explicit CHACodeArray(const Class& cls)
-      : WeakCodeReferences(Array::Handle(cls.cha_codes())), cls_(cls) {
+      : WeakCodeReferences(Array::Handle(cls.dependent_code())), cls_(cls) {
   }
 
   virtual void UpdateArrayTo(const Array& value) {
     // TODO(fschneider): Fails for classes in the VM isolate.
-    cls_.set_cha_codes(value);
+    cls_.set_dependent_code(value);
   }
 
   virtual void ReportDeoptimization(const Code& code) {
@@ -2871,8 +2871,8 @@
 }
 
 
-void Class::set_cha_codes(const Array& cache) const {
-  StorePointer(&raw_ptr()->cha_codes_, cache.raw());
+void Class::set_dependent_code(const Array& array) const {
+  StorePointer(&raw_ptr()->dependent_code_, array.raw());
 }
 
 
@@ -6418,23 +6418,6 @@
     Heap::Space space) const {
   AbstractType& other_param_type =
       AbstractType::Handle(other.ParameterTypeAt(other_parameter_position));
-
-  // TODO(regis): Remove this debugging code.
-  if (other_param_type.IsNull()) {
-    const Class& owner = Class::Handle(Owner());
-    const Class& other_owner = Class::Handle(other.Owner());
-    THR_Print("*** null other_param_type ***\n");
-    THR_Print("parameter_position: %" Pd "\n", parameter_position);
-    THR_Print("other_parameter_position: %" Pd "\n", other_parameter_position);
-    THR_Print("function: %s\n", ToCString());
-    THR_Print("function owner: %s\n", owner.ToCString());
-    THR_Print("other function: %s\n", other.ToCString());
-    THR_Print("other function owner: %s\n", other_owner.ToCString());
-    AbstractType& param_type =
-        AbstractType::Handle(ParameterTypeAt(parameter_position));
-    THR_Print("param_type: %s\n", param_type.ToCString());
-  }
-
   if (!other_param_type.IsInstantiated()) {
     other_param_type =
         other_param_type.InstantiateFrom(other_type_arguments,
@@ -6452,16 +6435,40 @@
 
   // TODO(regis): Remove this debugging code.
   if (param_type.IsNull()) {
-    const Class& owner = Class::Handle(Owner());
-    const Class& other_owner = Class::Handle(other.Owner());
     THR_Print("*** null param_type ***\n");
     THR_Print("parameter_position: %" Pd "\n", parameter_position);
     THR_Print("other_parameter_position: %" Pd "\n", other_parameter_position);
-    THR_Print("function: %s\n", ToCString());
+    String& str = String::Handle();
+    str = QualifiedScrubbedName();
+    THR_Print("function name: %s\n", str.ToCString());
+    str = other.QualifiedScrubbedName();
+    THR_Print("other function name: %s\n", str.ToCString());
+    Class& owner = Class::Handle();
+    owner = Owner();
     THR_Print("function owner: %s\n", owner.ToCString());
-    THR_Print("other function: %s\n", other.ToCString());
-    THR_Print("other function owner: %s\n", other_owner.ToCString());
+    owner = other.Owner();
+    THR_Print("other function owner: %s\n", owner.ToCString());
     THR_Print("other_param_type: %s\n", other_param_type.ToCString());
+    AbstractType& type = AbstractType::Handle();
+    if (parameter_position > 0) {
+      type = ParameterTypeAt(0);
+      THR_Print("receiver type: %s\n",
+                type.IsNull()? "null" : type.ToCString());
+    }
+    THR_Print("has code: %s\n", HasCode() ? "yes" : "no");
+    str = Report::PrependSnippet(Report::kWarning,
+                                 Script::Handle(script()),
+                                 token_pos(),
+                                 Report::AtLocation,
+                                 Symbols::Empty());
+    THR_Print("function source: %s\n", str.ToCString());
+    for (intptr_t i = 0; i < NumParameters(); i++) {
+      THR_Print("function param %" Pd "\n", i);
+      str = ParameterNameAt(i);
+      THR_Print("  name: %s\n", str.IsNull() ? "null" : str.ToCString());
+      type = ParameterTypeAt(i);
+      THR_Print("  type: %s\n", type.IsNull() ? "null" : type.ToCString());
+    }
   }
 
   if (!param_type.IsInstantiated()) {
@@ -13024,6 +13031,81 @@
 }
 
 
+// (cid, count) tuple used to sort ICData by count.
+struct CidCount {
+  CidCount(intptr_t cid_, intptr_t count_, Function* f_)
+      : cid(cid_), count(count_), function(f_) {}
+
+  static int HighestCountFirst(const CidCount* a, const CidCount* b);
+
+  intptr_t cid;
+  intptr_t count;
+  Function* function;
+};
+
+
+int CidCount::HighestCountFirst(const CidCount* a, const CidCount* b) {
+  if (a->count > b->count) {
+    return -1;
+  }
+  return (a->count < b->count) ? 1 : 0;
+}
+
+
+RawICData* ICData::AsUnaryClassChecksSortedByCount() const {
+  ASSERT(!IsNull());
+  const intptr_t kNumArgsTested = 1;
+  const intptr_t len = NumberOfChecks();
+  if (len <= 1) {
+    // No sorting needed.
+    return AsUnaryClassChecks();
+  }
+  GrowableArray<CidCount> aggregate;
+  for (intptr_t i = 0; i < len; i++) {
+    const intptr_t class_id = GetClassIdAt(i, 0);
+    const intptr_t count = GetCountAt(i);
+    if (count == 0) {
+      continue;
+    }
+    bool found = false;
+    for (intptr_t r = 0; r < aggregate.length(); r++) {
+      if (aggregate[r].cid == class_id) {
+        aggregate[r].count += count;
+        found = true;
+        break;
+      }
+    }
+    if (!found) {
+      aggregate.Add(CidCount(class_id, count,
+                             &Function::ZoneHandle(GetTargetAt(i))));
+    }
+  }
+  aggregate.Sort(CidCount::HighestCountFirst);
+
+  ICData& result = ICData::Handle(ICData::NewFrom(*this, kNumArgsTested));
+  ASSERT(result.NumberOfChecks() == 0);
+  // Room for all entries and the sentinel.
+  const intptr_t data_len =
+      result.TestEntryLength() * (aggregate.length() + 1);
+  const Array& data = Array::Handle(Array::New(data_len, Heap::kOld));
+  result.set_ic_data_array(data);
+  ASSERT(result.NumberOfChecks() == aggregate.length());
+
+  intptr_t pos = 0;
+  for (intptr_t i = 0; i < aggregate.length(); i++) {
+    data.SetAt(pos + 0, Smi::Handle(Smi::New(aggregate[i].cid)));
+    data.SetAt(pos + TargetIndexFor(1), *aggregate[i].function);
+    data.SetAt(pos + CountIndexFor(1),
+        Smi::Handle(Smi::New(aggregate[i].count)));
+
+    pos += result.TestEntryLength();
+  }
+  WriteSentinel(data, result.TestEntryLength());
+  result.set_ic_data_array(data);
+  return result.raw();
+}
+
+
 bool ICData::AllTargetsHaveSameOwner(intptr_t owner_cid) const {
   if (NumberOfChecks() == 0) return false;
   Class& cls = Class::Handle();
@@ -13443,26 +13525,6 @@
 }
 
 
-uword Code::EntryPoint() const {
-  RawObject* instr = instructions();
-  if (!instr->IsHeapObject()) {
-    return active_entry_point();
-  } else {
-    return Instructions::EntryPoint(instructions());
-  }
-}
-
-
-intptr_t Code::Size() const {
-  RawObject* instr = instructions();
-  if (!instr->IsHeapObject()) {
-    return Smi::Value(raw_ptr()->precompiled_instructions_size_);
-  } else {
-    return instructions()->ptr()->size_;
-  }
-}
-
-
 bool Code::HasBreakpoint() const {
   if (!FLAG_support_debugger) {
     return false;
@@ -13808,13 +13870,10 @@
     }
 
     // Hook up Code and Instructions objects.
-    code.set_instructions(instrs.raw());
     code.SetActiveInstructions(instrs.raw());
+    code.set_instructions(instrs.raw());
     code.set_is_alive(true);
 
-    ASSERT(code.EntryPoint() == instrs.EntryPoint());
-    ASSERT(code.Size() == instrs.size());
-
     // Set object pool in Instructions object.
     INC_STAT(Thread::Current(),
              total_code_size, object_pool.Length() * sizeof(uintptr_t));
@@ -14017,10 +14076,9 @@
 void Code::DisableDartCode() const {
   DEBUG_ASSERT(IsMutatorOrAtSafepoint());
   ASSERT(IsFunctionCode());
-  ASSERT(!IsDisabled());
+  ASSERT(instructions() == active_instructions());
   const Code& new_code =
       Code::Handle(StubCode::FixCallersTarget_entry()->code());
-  ASSERT(new_code.instructions()->IsVMHeapObject());
   SetActiveInstructions(new_code.instructions());
 }
 
@@ -14029,10 +14087,9 @@
 #if !defined(TARGET_ARCH_DBC)
   ASSERT(Thread::Current()->IsMutatorThread());
   ASSERT(IsAllocationStubCode());
-  ASSERT(!IsDisabled());
+  ASSERT(instructions() == active_instructions());
   const Code& new_code =
       Code::Handle(StubCode::FixAllocationStubTarget_entry()->code());
-  ASSERT(new_code.instructions()->IsVMHeapObject());
   SetActiveInstructions(new_code.instructions());
 #else
   // DBC does not use allocation stubs.
@@ -14045,6 +14102,7 @@
   DEBUG_ASSERT(IsMutatorOrAtSafepoint() || !is_alive());
   // RawInstructions are never allocated in New space and hence a
   // store buffer update is not needed here.
+  StorePointer(&raw_ptr()->active_instructions_, instructions);
   StoreNonPointer(&raw_ptr()->entry_point_,
                   reinterpret_cast<uword>(instructions->ptr()) +
                   Instructions::HeaderSize());
@@ -19968,7 +20026,8 @@
 }
 
 
-RawString* String::SubString(const String& str,
+RawString* String::SubString(Thread* thread,
+                             const String& str,
                              intptr_t begin_index,
                              intptr_t length,
                              Heap::Space space) {
@@ -19981,7 +20040,6 @@
   if (begin_index > str.Length()) {
     return String::null();
   }
-  String& result = String::Handle();
   bool is_one_byte_string = true;
   intptr_t char_size = str.CharSize();
   if (char_size == kTwoByteChar) {
@@ -19992,6 +20050,8 @@
       }
     }
   }
+  REUSABLE_STRING_HANDLESCOPE(thread);
+  String& result = thread->StringHandle();
   if (is_one_byte_string) {
     result = OneByteString::New(length, space);
   } else {
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 53a22fc..564db72 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -1386,8 +1386,11 @@
 
   void DisableCHAOptimizedCode(const Class& subclass);
 
-  RawArray* cha_codes() const { return raw_ptr()->cha_codes_; }
-  void set_cha_codes(const Array& value) const;
+  // Return the list of code objects that were compiled using CHA of this class.
+  // These code objects will be invalidated if new subclasses of this class
+  // are finalized.
+  RawArray* dependent_code() const { return raw_ptr()->dependent_code_; }
+  void set_dependent_code(const Array& array) const;
 
   bool TraceAllocation(Isolate* isolate) const;
   void SetTraceAllocation(bool trace_allocation) const;
@@ -1960,6 +1963,12 @@
   RawICData* AsUnaryClassChecksForCid(
       intptr_t cid, const Function& target) const;
 
+  // Returns ICData with aggregated receiver count, sorted by highest count.
+  // Smi not first!! (the convention for ICData used in code generation is that
+  // Smi check is first)
+  // Used for printing and optimizations.
+  RawICData* AsUnaryClassChecksSortedByCount() const;
+
   // Consider only used entries.
   bool AllTargetsHaveSameOwner(intptr_t owner_cid) const;
   bool AllReceiversAreNumbers() const;
@@ -3955,7 +3964,8 @@
   FINAL_HEAP_OBJECT_IMPLEMENTATION(Instructions, Object);
   friend class Class;
   friend class Code;
-  friend class InstructionsWriter;
+  friend class AssemblyInstructionsWriter;
+  friend class BlobInstructionsWriter;
 };
 
 
@@ -4368,7 +4378,9 @@
 
 class Code : public Object {
  public:
-  uword active_entry_point() const { return raw_ptr()->entry_point_; }
+  RawInstructions* active_instructions() const {
+    return raw_ptr()->active_instructions_;
+  }
 
   RawInstructions* instructions() const { return raw_ptr()->instructions_; }
 
@@ -4398,15 +4410,20 @@
   }
   void set_is_alive(bool value) const;
 
-  uword EntryPoint() const;
-  intptr_t Size() const;
-
+  uword EntryPoint() const {
+    return Instructions::Handle(instructions()).EntryPoint();
+  }
+  intptr_t Size() const {
+    const Instructions& instr = Instructions::Handle(instructions());
+    return instr.size();
+  }
   RawObjectPool* GetObjectPool() const {
     return object_pool();
   }
   bool ContainsInstructionAt(uword addr) const {
-    const uword offset = addr - EntryPoint();
-    return offset < static_cast<uword>(Size());
+    const Instructions& instr = Instructions::Handle(instructions());
+    const uword offset = addr - instr.EntryPoint();
+    return offset < static_cast<uword>(instr.size());
   }
 
   // Returns true if there is a debugger breakpoint set in this code object.
@@ -4645,11 +4662,12 @@
   void Enable() const {
     if (!IsDisabled()) return;
     ASSERT(Thread::Current()->IsMutatorThread());
+    ASSERT(instructions() != active_instructions());
     SetActiveInstructions(instructions());
   }
 
   bool IsDisabled() const {
-    return active_entry_point() != EntryPoint();
+    return instructions() != active_instructions();
   }
 
  private:
@@ -6125,6 +6143,8 @@
   friend class Api;  // For ValueFromRaw
   friend class Class;
   friend class Object;
+  friend class ReusableSmiHandleScope;
+  friend class Thread;
 };
 
 
@@ -6569,6 +6589,13 @@
   static RawString* SubString(const String& str,
                               intptr_t begin_index,
                               intptr_t length,
+                              Heap::Space space = Heap::kNew) {
+    return SubString(Thread::Current(), str, begin_index, length, space);
+  }
+  static RawString* SubString(Thread* thread,
+                              const String& str,
+                              intptr_t begin_index,
+                              intptr_t length,
                               Heap::Space space = Heap::kNew);
 
   static RawString* Transform(int32_t (*mapping)(int32_t ch),
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 6404df4..80c6021 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -12012,6 +12012,11 @@
 
 void Parser::CacheConstantValue(TokenPosition token_pos,
                                 const Instance& value) {
+  if (current_function().kind() == RawFunction::kImplicitStaticFinalGetter) {
+    // Don't cache constants in initializer expressions. They get
+    // evaluated only once.
+    return;
+  }
   ConstantPosKey key(String::Handle(Z, script_.url()), token_pos);
   if (isolate()->object_store()->compile_time_constants() == Array::null()) {
     const intptr_t kInitialConstMapSize = 16;
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index ff32dcd..12d5234 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -709,9 +709,22 @@
   RawArray* invocation_dispatcher_cache_;  // Cache for dispatcher functions.
   RawCode* allocation_stub_;  // Stub code for allocation of instances.
   RawGrowableObjectArray* direct_subclasses_;  // Array of Class.
-  RawArray* cha_codes_;  // CHA optimized codes.
+  RawArray* dependent_code_;  // CHA optimized codes.
   RawObject** to() {
-    return reinterpret_cast<RawObject**>(&ptr()->cha_codes_);
+    return reinterpret_cast<RawObject**>(&ptr()->dependent_code_);
+  }
+  RawObject** to_snapshot(Snapshot::Kind kind) {
+    switch (kind) {
+      case Snapshot::kCore:
+      case Snapshot::kScript:
+      case Snapshot::kAppWithJIT:
+      case Snapshot::kAppNoJIT:
+        return reinterpret_cast<RawObject**>(&ptr()->direct_subclasses_);
+      case Snapshot::kMessage:
+        break;
+    }
+    UNREACHABLE();
+    return NULL;
   }
 
   cpp_vtable handle_vtable_;
@@ -922,17 +935,17 @@
     // restore the value back to the original initial value.
     RawInstance* saved_value_;  // Saved initial value - static fields.
   } initializer_;
-  RawArray* dependent_code_;
   RawSmi* guarded_list_length_;
+  RawArray* dependent_code_;
   RawObject** to() {
-    return reinterpret_cast<RawObject**>(&ptr()->guarded_list_length_);
+    return reinterpret_cast<RawObject**>(&ptr()->dependent_code_);
   }
   RawObject** to_snapshot(Snapshot::Kind kind) {
     switch (kind) {
       case Snapshot::kCore:
       case Snapshot::kScript:
-        return to();
       case Snapshot::kAppWithJIT:
+        return reinterpret_cast<RawObject**>(&ptr()->guarded_list_length_);
       case Snapshot::kAppNoJIT:
         return reinterpret_cast<RawObject**>(&ptr()->initializer_);
       case Snapshot::kMessage:
@@ -1107,12 +1120,10 @@
   uword entry_point_;
 
   RawObject** from() {
-    return reinterpret_cast<RawObject**>(&ptr()->instructions_);
+    return reinterpret_cast<RawObject**>(&ptr()->active_instructions_);
   }
-  union {
-    RawInstructions* instructions_;
-    RawSmi* precompiled_instructions_size_;
-  };
+  RawInstructions* active_instructions_;
+  RawInstructions* instructions_;
   RawObjectPool* object_pool_;
   // If owner_ is Function::null() the owner is a regular stub.
   // If owner_ is a Class the owner is the allocation stub for that class.
@@ -1630,8 +1641,8 @@
     switch (kind) {
       case Snapshot::kCore:
       case Snapshot::kScript:
-        return to();
       case Snapshot::kAppWithJIT:
+        return reinterpret_cast<RawObject**>(&ptr()->imports_);
       case Snapshot::kAppNoJIT:
         return reinterpret_cast<RawObject**>(&ptr()->importer_);
       case Snapshot::kMessage:
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index 2b715b2..eec2523 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -78,7 +78,11 @@
     cls.set_state_bits(reader->Read<uint16_t>());
 
     // Set all the object fields.
-    READ_OBJECT_FIELDS(cls, cls.raw()->from(), cls.raw()->to(), kAsReference);
+    READ_OBJECT_FIELDS(cls,
+                       cls.raw()->from(),
+                       cls.raw()->to_snapshot(kind),
+                       kAsReference);
+    cls.StorePointer(&cls.raw_ptr()->dependent_code_, Array::null());
     ASSERT(!cls.IsInFullSnapshot() || (Snapshot::IsFull(kind)));
   } else {
     cls ^= reader->ReadClassId(object_id);
@@ -130,7 +134,7 @@
 
     // Write out all the object pointer fields.
     SnapshotWriterVisitor visitor(writer, kAsReference);
-    visitor.VisitPointers(from(), to());
+    visitor.VisitPointers(from(), to_snapshot(kind));
   } else {
     if (writer->can_send_any_object() ||
         writer->AllowObjectsInDartLibrary(ptr()->library_)) {
@@ -853,7 +857,7 @@
   reader->AddBackRef(object_id, &field, kIsDeserialized);
 
   // Set all non object fields.
-  if (Snapshot::IncludesCode(kind)) {
+  if (kind == Snapshot::kAppNoJIT) {
     field.set_token_pos(TokenPosition::kNoSource);
     ASSERT(!FLAG_use_field_guards);
   } else {
@@ -869,6 +873,7 @@
                      field.raw()->from(),
                      field.raw()->to_snapshot(kind),
                      kAsReference);
+  field.StorePointer(&field.raw_ptr()->dependent_code_, Array::null());
 
   if (!FLAG_use_field_guards) {
     field.set_guarded_cid(kDynamicCid);
@@ -898,7 +903,7 @@
   writer->WriteTags(writer->GetObjectTags(this));
 
   // Write out all the non object fields.
-  if (!Snapshot::IncludesCode(kind)) {
+  if (kind != Snapshot::kAppNoJIT) {
     writer->Write<int32_t>(ptr()->token_pos_.SnapshotEncode());
     writer->Write<int32_t>(ptr()->guarded_cid_);
     writer->Write<int32_t>(ptr()->is_nullable_);
@@ -913,7 +918,7 @@
   writer->WriteObjectImpl(ptr()->type_, kAsReference);
   // Write out the initial static value or field offset.
   if (Field::StaticBit::decode(ptr()->kind_bits_)) {
-    if (Snapshot::IncludesCode(kind)) {
+    if (kind == Snapshot::kAppNoJIT) {
       // For precompiled static fields, the value was already reset and
       // initializer_ now contains a Function.
       writer->WriteObjectImpl(ptr()->value_.static_value_, kAsReference);
@@ -925,14 +930,12 @@
     writer->WriteObjectImpl(ptr()->value_.offset_, kAsReference);
   }
   // Write out the initializer function or saved initial value.
-  if (Snapshot::IncludesCode(kind)) {
+  if (kind == Snapshot::kAppNoJIT) {
     writer->WriteObjectImpl(ptr()->initializer_.precompiled_, kAsReference);
   } else {
     writer->WriteObjectImpl(ptr()->initializer_.saved_value_, kAsReference);
   }
-  if (!Snapshot::IncludesCode(kind)) {
-    // Write out the dependent code.
-    writer->WriteObjectImpl(ptr()->dependent_code_, kAsReference);
+  if (kind != Snapshot::kAppNoJIT) {
     // Write out the guarded list length.
     writer->WriteObjectImpl(ptr()->guarded_list_length_, kAsReference);
   }
@@ -1253,12 +1256,12 @@
                      prefix.raw()->from(),
                      prefix.raw()->to_snapshot(kind),
                      kAsReference);
-  if (Snapshot::IncludesCode(kind)) {
+  if (kind == Snapshot::kAppNoJIT) {
     prefix.StorePointer(&prefix.raw_ptr()->imports_,
                         Array::null());
-    prefix.StorePointer(&prefix.raw_ptr()->dependent_code_,
-                        Array::null());
   }
+  prefix.StorePointer(&prefix.raw_ptr()->dependent_code_,
+                      Array::null());
 
   return prefix.raw();
 }
@@ -1358,20 +1361,24 @@
   result.set_lazy_deopt_pc_offset(-1);
 
   int32_t text_offset = reader->Read<int32_t>();
-  int32_t instructions_size = reader->Read<int32_t>();
-  uword entry_point = reader->GetInstructionsAt(text_offset);
+  RawInstructions* instr = reinterpret_cast<RawInstructions*>(
+      reader->GetInstructionsAt(text_offset) + kHeapObjectTag);
+  uword entry_point = Instructions::EntryPoint(instr);
 
 #if defined(DEBUG)
+  ASSERT(instr->IsMarked());
+  ASSERT(instr->IsVMHeapObject());
   uword expected_check = reader->Read<uword>();
+  intptr_t instructions_size = Utils::RoundUp(instr->size_,
+                                              OS::PreferredCodeAlignment());
   uword actual_check = Checksum(entry_point, instructions_size);
   ASSERT(expected_check == actual_check);
 #endif
 
   result.StoreNonPointer(&result.raw_ptr()->entry_point_, entry_point);
 
-  result.StorePointer(reinterpret_cast<RawSmi*const*>(
-                          &result.raw_ptr()->instructions_),
-                      Smi::New(instructions_size));
+  result.StorePointer(&result.raw_ptr()->active_instructions_, instr);
+  result.StorePointer(&result.raw_ptr()->instructions_, instr);
 
   (*reader->PassiveObjectHandle()) ^= reader->ReadObjectImpl(kAsReference);
   result.StorePointer(reinterpret_cast<RawObject*const*>(
@@ -1415,9 +1422,6 @@
   result.StorePointer(&result.raw_ptr()->return_address_metadata_,
                       Object::null());
 
-  ASSERT(result.Size() == instructions_size);
-  ASSERT(result.EntryPoint() == entry_point);
-
   return result.raw();
 }
 
@@ -1446,14 +1450,18 @@
   // Write out all the non object fields.
   writer->Write<int32_t>(ptr()->state_bits_);
 
+  // No disabled code in precompilation.
+  ASSERT(ptr()->instructions_ == ptr()->active_instructions_);
+
   RawInstructions* instr = ptr()->instructions_;
-  intptr_t size = instr->ptr()->size_;
   int32_t text_offset = writer->GetInstructionsId(instr, this);
   writer->Write<int32_t>(text_offset);
-  writer->Write<int32_t>(size);
+
 #if defined(DEBUG)
   uword entry = ptr()->entry_point_;
-  uword check = Checksum(entry, size);
+  intptr_t instructions_size = Utils::RoundUp(instr->size_,
+                                              OS::PreferredCodeAlignment());
+  uword check = Checksum(entry, instructions_size);
   writer->Write<uword>(check);
 #endif
 
diff --git a/runtime/vm/reusable_handles.h b/runtime/vm/reusable_handles.h
index beae36b..25e5154 100644
--- a/runtime/vm/reusable_handles.h
+++ b/runtime/vm/reusable_handles.h
@@ -110,6 +110,8 @@
   ReusableObjectHandleScope reused_object_handle(thread);
 #define REUSABLE_PC_DESCRIPTORS_HANDLESCOPE(thread)                            \
   ReusablePcDescriptorsHandleScope reused_pc_descriptors_handle(thread);
+#define REUSABLE_SMI_HANDLESCOPE(thread)                                       \
+  ReusableSmiHandleScope reused_smi_handle(thread);
 #define REUSABLE_STRING_HANDLESCOPE(thread)                                    \
   ReusableStringHandleScope reused_string_handle(thread);
 #define REUSABLE_TYPE_ARGUMENTS_HANDLESCOPE(thread)                            \
diff --git a/runtime/vm/scanner.cc b/runtime/vm/scanner.cc
index 9cbe84a..4b1e550 100644
--- a/runtime/vm/scanner.cc
+++ b/runtime/vm/scanner.cc
@@ -329,11 +329,13 @@
 
   // We did not read a keyword.
   current_token_.kind = Token::kIDENT;
-  String& literal =
-      String::ZoneHandle(Z, Symbols::New(T, source_, ident_pos, ident_length));
+  String& literal = String::ZoneHandle(Z);
   if (ident_char0 == Library::kPrivateIdentifierStart) {
     // Private identifiers are mangled on a per library basis.
+    literal = String::SubString(T, source_, ident_pos, ident_length);
     literal = Symbols::FromConcat(T, literal, private_key_);
+  } else {
+    literal = Symbols::New(T, source_, ident_pos, ident_length);
   }
   current_token_.literal = &literal;
 }
diff --git a/runtime/vm/signal_handler.h b/runtime/vm/signal_handler.h
index b204c55..ecdfe02 100644
--- a/runtime/vm/signal_handler.h
+++ b/runtime/vm/signal_handler.h
@@ -36,6 +36,17 @@
 };
 #endif
 
+
+// Old linux kernels on ARM might require a trampoline to
+// work around incorrect Thumb -> ARM transitions. See SignalHandlerTrampoline
+// below for more details.
+#if defined(HOST_ARCH_ARM) && \
+    (defined(TARGET_OS_LINUX) || defined(TARGET_OS_ANDROID)) && \
+    !defined(__thumb__)
+#define USE_SIGNAL_HANDLER_TRAMPOLINE
+#endif
+
+
 namespace dart {
 
 typedef void (*SignalAction)(int signal, siginfo_t* info,
@@ -43,17 +54,68 @@
 
 class SignalHandler : public AllStatic {
  public:
-  static void Install(SignalAction action);
+  template<SignalAction action>
+  static void Install() {
+#if defined(USE_SIGNAL_HANDLER_TRAMPOLINE)
+    InstallImpl(SignalHandlerTrampoline<action>);
+#else
+    InstallImpl(action);
+#endif  // defined(USE_SIGNAL_HANDLER_TRAMPOLINE)
+  }
   static void Remove();
   static uintptr_t GetProgramCounter(const mcontext_t& mcontext);
   static uintptr_t GetFramePointer(const mcontext_t& mcontext);
   static uintptr_t GetCStackPointer(const mcontext_t& mcontext);
   static uintptr_t GetDartStackPointer(const mcontext_t& mcontext);
   static uintptr_t GetLinkRegister(const mcontext_t& mcontext);
+
  private:
+  static void InstallImpl(SignalAction action);
+
+#if defined(USE_SIGNAL_HANDLER_TRAMPOLINE)
+  // Work around for a bug in old kernels (only fixed in 3.18 Android kernel):
+  //
+  // Kernel does not clear If-Then execution state bits when entering ARM signal
+  // handler which violates requirements imposed by ARM architecture reference.
+  // Some CPUs look at these bits even while in ARM mode which causes them
+  // to skip some instructions in the prologue of the signal handler.
+  //
+  // To work around the issue we insert enough NOPs in the prologue to ensure
+  // that no actual instructions are skipped and then branch to the actual
+  // signal handler.
+  //
+  // For the kernel patch that fixes the issue see: http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=6ecf830e5029598732e04067e325d946097519cb
+  //
+  // Note: this function is marked "naked" because we must guarantee that
+  // our NOPs occur before any compiler generated prologue.
+  template <SignalAction action>
+  static __attribute__((naked)) void SignalHandlerTrampoline(int signal,
+                                                             siginfo_t* info,
+                                                             void* context_) {
+    // IT (If-Then) instruction makes up to four instructions that follow it
+    // conditional.
+    asm volatile("nop; nop; nop; nop" : : : "memory");
+
+    // Tail-call into the actual signal handler.
+    // Note: this code is split into a separate inline assembly block because
+    // any code that compiler generates to satisfy register constraints must
+    // be generated after four NOPs.
+    register int arg0 asm("r0") = signal;
+    register siginfo_t* arg1 asm("r1") = info;
+    register void* arg2 asm("r2") = context_;
+    asm volatile("bx %3"
+                  :
+                  : "r"(arg0), "r"(arg1), "r"(arg2),
+                    "r"(action)
+                  : "memory");
+  }
+#endif  // defined(USE_SIGNAL_HANDLER_TRAMPOLINE)
 };
 
 
+#undef USE_SIGNAL_HANDLER_TRAMPOLINE
+
+
 }  // namespace dart
 
 #endif  // VM_SIGNAL_HANDLER_H_
diff --git a/runtime/vm/signal_handler_android.cc b/runtime/vm/signal_handler_android.cc
index d41eb59..64670de 100644
--- a/runtime/vm/signal_handler_android.cc
+++ b/runtime/vm/signal_handler_android.cc
@@ -100,7 +100,7 @@
 }
 
 
-void SignalHandler::Install(SignalAction action) {
+void SignalHandler::InstallImpl(SignalAction action) {
   struct sigaction act;
   memset(&act, 0, sizeof(act));
   act.sa_sigaction = action;
diff --git a/runtime/vm/signal_handler_linux.cc b/runtime/vm/signal_handler_linux.cc
index b49f90a..1df46f0 100644
--- a/runtime/vm/signal_handler_linux.cc
+++ b/runtime/vm/signal_handler_linux.cc
@@ -99,7 +99,7 @@
 }
 
 
-void SignalHandler::Install(SignalAction action) {
+void SignalHandler::InstallImpl(SignalAction action) {
   struct sigaction act;
   act.sa_handler = NULL;
   act.sa_sigaction = action;
diff --git a/runtime/vm/signal_handler_macos.cc b/runtime/vm/signal_handler_macos.cc
index ca6e64d..bfcc42c 100644
--- a/runtime/vm/signal_handler_macos.cc
+++ b/runtime/vm/signal_handler_macos.cc
@@ -102,7 +102,7 @@
 }
 
 
-void SignalHandler::Install(SignalAction action) {
+void SignalHandler::InstallImpl(SignalAction action) {
   struct sigaction act;
   act.sa_handler = NULL;
   act.sa_sigaction = action;
diff --git a/runtime/vm/signal_handler_win.cc b/runtime/vm/signal_handler_win.cc
index e3164f4..bb6b92d 100644
--- a/runtime/vm/signal_handler_win.cc
+++ b/runtime/vm/signal_handler_win.cc
@@ -38,7 +38,7 @@
 }
 
 
-void SignalHandler::Install(SignalAction action) {
+void SignalHandler::InstallImpl(SignalAction action) {
   UNIMPLEMENTED();
 }
 
diff --git a/runtime/vm/simulator_dbc.cc b/runtime/vm/simulator_dbc.cc
index 7329114..d9ff04e 100644
--- a/runtime/vm/simulator_dbc.cc
+++ b/runtime/vm/simulator_dbc.cc
@@ -1634,6 +1634,18 @@
     BYTECODE(AssertAssignable, A_D);  // Stack: instance, type args, type, name
     RawObject** args = SP - 3;
     if (args[0] != null_value) {
+      const AbstractType& dst_type =
+          AbstractType::Handle(static_cast<RawAbstractType*>(args[2]));
+      if (dst_type.IsMalformedOrMalbounded()) {
+        SP[1] = args[0];  // instance.
+        SP[2] = args[3];  // name.
+        SP[3] = args[2];  // type.
+        Exit(thread, FP, SP + 4, pc);
+        NativeArguments args(thread, 3, SP + 1, SP - 3);
+        INVOKE_RUNTIME(DRT_BadTypeError, args);
+        UNREACHABLE();
+      }
+
       RawSubtypeTestCache* cache =
           static_cast<RawSubtypeTestCache*>(LOAD_CONSTANT(rD));
       if (cache != null_value) {
@@ -1778,6 +1790,21 @@
   }
 
   {
+    BYTECODE(LoadClassId, A_D);
+    const uint16_t object_reg = rD;
+    RawObject* obj = static_cast<RawObject*>(FP[object_reg]);
+    FP[rA] = SimulatorHelpers::GetClassIdAsSmi(obj);
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(LoadClassIdTOS, 0);
+    RawObject* obj = static_cast<RawObject*>(SP[0]);
+    SP[0] = SimulatorHelpers::GetClassIdAsSmi(obj);
+    DISPATCH();
+  }
+
+  {
     BYTECODE(StoreIndexedTOS, 0);
     SP -= 3;
     RawArray* array = static_cast<RawArray*>(SP[1]);
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index 6107c53..2f2ca6a 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -1160,13 +1160,9 @@
   }
 #endif
 
-  intptr_t payload_size = instructions->ptr()->size_;
-  payload_size = Utils::RoundUp(payload_size, OS::PreferredCodeAlignment());
-
+  intptr_t heap_size = instructions->Size();
   intptr_t offset = next_offset_;
-  ASSERT(Utils::IsAligned(next_offset_, OS::PreferredCodeAlignment()));
-  next_offset_ += payload_size;
-  ASSERT(Utils::IsAligned(next_offset_, OS::PreferredCodeAlignment()));
+  next_offset_ += heap_size;
   instructions_.Add(InstructionsData(instructions, code, offset));
 
   return offset;
@@ -1235,7 +1231,32 @@
 
     ASSERT(insns.raw()->Size() % sizeof(uint64_t) == 0);
 
-    // 1. Write a label at the entry point.
+    // 1. Write from the header to the entry point.
+    {
+      NoSafepointScope no_safepoint;
+
+      uword beginning = reinterpret_cast<uword>(insns.raw_ptr());
+      uword entry = beginning + Instructions::HeaderSize();
+
+      ASSERT(Utils::IsAligned(beginning, sizeof(uint64_t)));
+      ASSERT(Utils::IsAligned(entry, sizeof(uint64_t)));
+
+      // Write Instructions with the mark and VM heap bits set.
+      uword marked_tags = insns.raw_ptr()->tags_;
+      marked_tags = RawObject::VMHeapObjectTag::update(true, marked_tags);
+      marked_tags = RawObject::MarkBit::update(true, marked_tags);
+
+      WriteWordLiteral(marked_tags);
+      beginning += sizeof(uword);
+
+      for (uword* cursor = reinterpret_cast<uword*>(beginning);
+           cursor < reinterpret_cast<uword*>(entry);
+           cursor++) {
+        WriteWordLiteral(*cursor);
+      }
+    }
+
+    // 2. Write a label at the entry point.
     owner = code.owner();
     if (owner.IsNull()) {
       const char* name = StubCode::NameOfStub(insns.EntryPoint());
@@ -1255,7 +1276,7 @@
     }
 
     {
-      // 2. Write from the entry point to the end.
+      // 3. Write from the entry point to the end.
       NoSafepointScope no_safepoint;
       uword beginning = reinterpret_cast<uword>(insns.raw()) - kHeapObjectTag;
       uword entry = beginning + Instructions::HeaderSize();
@@ -1342,8 +1363,33 @@
   for (intptr_t i = 0; i < instructions_.length(); i++) {
     const Instructions& insns = *instructions_[i].insns_;
 
+    // 1. Write from the header to the entry point.
     {
-      // 2. Write from the entry point to the end.
+      NoSafepointScope no_safepoint;
+
+      uword beginning = reinterpret_cast<uword>(insns.raw_ptr());
+      uword entry = beginning + Instructions::HeaderSize();
+
+      ASSERT(Utils::IsAligned(beginning, sizeof(uint64_t)));
+      ASSERT(Utils::IsAligned(entry, sizeof(uint64_t)));
+
+      // Write Instructions with the mark and VM heap bits set.
+      uword marked_tags = insns.raw_ptr()->tags_;
+      marked_tags = RawObject::VMHeapObjectTag::update(true, marked_tags);
+      marked_tags = RawObject::MarkBit::update(true, marked_tags);
+
+      instructions_blob_stream_.WriteWord(marked_tags);
+      beginning += sizeof(uword);
+
+      for (uword* cursor = reinterpret_cast<uword*>(beginning);
+           cursor < reinterpret_cast<uword*>(entry);
+           cursor++) {
+        instructions_blob_stream_.WriteWord(*cursor);
+      }
+    }
+
+    // 2. Write from the entry point to the end.
+    {
       NoSafepointScope no_safepoint;
       uword beginning = reinterpret_cast<uword>(insns.raw()) - kHeapObjectTag;
       uword entry = beginning + Instructions::HeaderSize();
diff --git a/runtime/vm/stack_frame.cc b/runtime/vm/stack_frame.cc
index aac196b..28636b8 100644
--- a/runtime/vm/stack_frame.cc
+++ b/runtime/vm/stack_frame.cc
@@ -69,10 +69,10 @@
 
 
 void EntryFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) {
-#if !defined(TARGET_ARCH_DBC)
   ASSERT(thread() == Thread::Current());
   // Visit objects between SP and (FP - callee_save_area).
   ASSERT(visitor != NULL);
+#if !defined(TARGET_ARCH_DBC)
   RawObject** first = reinterpret_cast<RawObject**>(sp());
   RawObject** last = reinterpret_cast<RawObject**>(
       fp() + (kExitLinkSlotFromEntryFp - 1) * kWordSize);
@@ -87,6 +87,8 @@
 
 
 void StackFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) {
+  ASSERT(thread() == Thread::Current());
+  ASSERT(visitor != NULL);
 #if !defined(TARGET_ARCH_DBC)
   // NOTE: This code runs while GC is in progress and runs within
   // a NoHandleScope block. Hence it is not ok to use regular Zone or
@@ -94,8 +96,6 @@
   // these handles are not traversed. The use of handles is mainly to
   // be able to reuse the handle based code and avoid having to add
   // helper functions to the raw object interface.
-  ASSERT(thread() == Thread::Current());
-  ASSERT(visitor != NULL);
   NoSafepointScope no_safepoint;
   Code code;
   code = LookupDartCode();
@@ -109,7 +109,8 @@
     Array maps;
     maps = Array::null();
     Stackmap map;
-    const uword entry = code.EntryPoint();
+    const uword entry = reinterpret_cast<uword>(code.instructions()->ptr()) +
+                        Instructions::HeaderSize();
     map = code.GetStackmap(pc() - entry, &maps, &map);
     if (!map.IsNull()) {
       RawObject** first = reinterpret_cast<RawObject**>(sp());
diff --git a/runtime/vm/symbols.cc b/runtime/vm/symbols.cc
index 04d6088..a138437 100644
--- a/runtime/vm/symbols.cc
+++ b/runtime/vm/symbols.cc
@@ -11,6 +11,7 @@
 #include "vm/object.h"
 #include "vm/object_store.h"
 #include "vm/raw_object.h"
+#include "vm/reusable_handles.h"
 #include "vm/snapshot_ids.h"
 #include "vm/unicode.h"
 #include "vm/visitor.h"
@@ -602,18 +603,25 @@
 // StringType can be StringSlice, ConcatString, or {Latin1,UTF16,UTF32}Array.
 template<typename StringType>
 RawString* Symbols::NewSymbol(Thread* thread, const StringType& str) {
-  Zone* zone = thread->zone();
-  String& symbol = String::Handle(zone);
+  REUSABLE_OBJECT_HANDLESCOPE(thread);
+  REUSABLE_SMI_HANDLESCOPE(thread);
+  REUSABLE_ARRAY_HANDLESCOPE(thread);
+  String& symbol = String::Handle(thread->zone());
+  dart::Object& key = thread->ObjectHandle();
+  Smi& value = thread->SmiHandle();
+  Array& data = thread->ArrayHandle();
   {
     Isolate* vm_isolate = Dart::vm_isolate();
-    SymbolTable table(zone, vm_isolate->object_store()->symbol_table());
+    data ^= vm_isolate->object_store()->symbol_table();
+    SymbolTable table(&key, &value, &data);
     symbol ^= table.GetOrNull(str);
     table.Release();
   }
   if (symbol.IsNull()) {
     Isolate* isolate = thread->isolate();
     SafepointMutexLocker ml(isolate->symbols_mutex());
-    SymbolTable table(zone, isolate->object_store()->symbol_table());
+    data ^= isolate->object_store()->symbol_table();
+    SymbolTable table(&key, &value, &data);
     symbol ^= table.InsertNewOrGet(str);
     isolate->object_store()->set_symbol_table(table.Release());
   }
@@ -625,18 +633,25 @@
 
 template<typename StringType>
 RawString* Symbols::Lookup(Thread* thread, const StringType& str) {
-  Isolate* isolate = thread->isolate();
-  Zone* zone = thread->zone();
-  String& symbol = String::Handle(zone);
+  REUSABLE_OBJECT_HANDLESCOPE(thread);
+  REUSABLE_SMI_HANDLESCOPE(thread);
+  REUSABLE_ARRAY_HANDLESCOPE(thread);
+  String& symbol = String::Handle(thread->zone());
+  dart::Object& key = thread->ObjectHandle();
+  Smi& value = thread->SmiHandle();
+  Array& data = thread->ArrayHandle();
   {
     Isolate* vm_isolate = Dart::vm_isolate();
-    SymbolTable table(zone, vm_isolate->object_store()->symbol_table());
+    data ^= vm_isolate->object_store()->symbol_table();
+    SymbolTable table(&key, &value, &data);
     symbol ^= table.GetOrNull(str);
     table.Release();
   }
   if (symbol.IsNull()) {
+    Isolate* isolate = thread->isolate();
     SafepointMutexLocker ml(isolate->symbols_mutex());
-    SymbolTable table(zone, isolate->object_store()->symbol_table());
+    data ^= isolate->object_store()->symbol_table();
+    SymbolTable table(&key, &value, &data);
     symbol ^= table.GetOrNull(str);
     table.Release();
   }
diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h
index 4a21cc5..2201f36 100644
--- a/runtime/vm/thread.h
+++ b/runtime/vm/thread.h
@@ -45,6 +45,7 @@
 class RawGrowableObjectArray;
 class RawString;
 class RuntimeEntry;
+class Smi;
 class StackResource;
 class String;
 class TypeArguments;
@@ -65,6 +66,7 @@
   V(Library)                                                                   \
   V(Object)                                                                    \
   V(PcDescriptors)                                                             \
+  V(Smi)                                                                       \
   V(String)                                                                    \
   V(TypeArguments)                                                             \
   V(TypeParameter)                                                             \
diff --git a/runtime/vm/thread_interrupter_android.cc b/runtime/vm/thread_interrupter_android.cc
index 82be148..58f302f 100644
--- a/runtime/vm/thread_interrupter_android.cc
+++ b/runtime/vm/thread_interrupter_android.cc
@@ -57,8 +57,8 @@
 
 
 void ThreadInterrupter::InstallSignalHandler() {
-  SignalHandler::Install(
-      ThreadInterrupterAndroid::ThreadInterruptSignalHandler);
+  SignalHandler::Install<
+      ThreadInterrupterAndroid::ThreadInterruptSignalHandler>();
 }
 
 
diff --git a/runtime/vm/thread_interrupter_linux.cc b/runtime/vm/thread_interrupter_linux.cc
index 28ec681..4eb07f4 100644
--- a/runtime/vm/thread_interrupter_linux.cc
+++ b/runtime/vm/thread_interrupter_linux.cc
@@ -54,7 +54,8 @@
 
 
 void ThreadInterrupter::InstallSignalHandler() {
-  SignalHandler::Install(ThreadInterrupterLinux::ThreadInterruptSignalHandler);
+  SignalHandler::Install<
+      ThreadInterrupterLinux::ThreadInterruptSignalHandler>();
 }
 
 
diff --git a/runtime/vm/thread_interrupter_macos.cc b/runtime/vm/thread_interrupter_macos.cc
index e46dbc7..222a294 100644
--- a/runtime/vm/thread_interrupter_macos.cc
+++ b/runtime/vm/thread_interrupter_macos.cc
@@ -55,7 +55,8 @@
 
 
 void ThreadInterrupter::InstallSignalHandler() {
-  SignalHandler::Install(ThreadInterrupterMacOS::ThreadInterruptSignalHandler);
+  SignalHandler::Install<
+      ThreadInterrupterMacOS::ThreadInterruptSignalHandler>();
 }
 
 
diff --git a/runtime/vm/unit_test.cc b/runtime/vm/unit_test.cc
index 24064f0..54352e5 100644
--- a/runtime/vm/unit_test.cc
+++ b/runtime/vm/unit_test.cc
@@ -210,9 +210,19 @@
 void AssemblerTest::Assemble() {
   const String& function_name = String::ZoneHandle(
       Symbols::New(Thread::Current(), name_));
+
+  // We make a dummy script so that exception objects can be composed for
+  // assembler instructions that do runtime calls, in particular on DBC.
+  const char* kDummyScript = "assembler_test_dummy_function() {}";
+  const Script& script = Script::Handle(Script::New(
+      function_name,
+      String::Handle(String::New(kDummyScript)),
+      RawScript::kSourceTag));
+  script.Tokenize(String::Handle());
+
   const Class& cls = Class::ZoneHandle(
       Class::New(function_name,
-                 Script::Handle(),
+                 script,
                  TokenPosition::kMinSource));
   const Library& lib = Library::ZoneHandle(Library::New(function_name));
   cls.set_library(lib);
@@ -221,6 +231,8 @@
                     true, false, false, false, false, cls,
                     TokenPosition::kMinSource));
   code_ = Code::FinalizeCode(function, assembler_);
+  code_.set_owner(function);
+  code_.set_exception_handlers(Object::empty_exception_handlers());
   if (FLAG_disassemble) {
     OS::Print("Code for test '%s' {\n", name_);
     const Instructions& instructions =
diff --git a/runtime/vm/unit_test.h b/runtime/vm/unit_test.h
index f170ffc..60f4057 100644
--- a/runtime/vm/unit_test.h
+++ b/runtime/vm/unit_test.h
@@ -201,7 +201,7 @@
       bit_cast<int32_t, uword>(entry),                                         \
       bit_cast<int32_t, intptr_t>(pointer_arg),                                \
       0, 0, 0))
-#endif
+#endif  // defined(ARCH_IS_64_BIT)
 #define EXECUTE_TEST_CODE_INT64_LL(name, entry, long_arg0, long_arg1)          \
   static_cast<int64_t>(Simulator::Current()->Call(                             \
       bit_cast<int32_t, uword>(entry),                                         \
@@ -224,7 +224,7 @@
       Utils::High32Bits(bit_cast<int64_t, double>(double_arg)),                \
       0, 0, false, true))
 #endif  // defined(HOST_ARCH_ARM) || defined(HOST_ARCH_MIPS)
-#endif  // defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_MIPS)
+#endif  // defined(TARGET_ARCH_{ARM, ARM64, MIPS})
 
 
 inline Dart_Handle NewString(const char* str) {
diff --git a/runtime/vm/vm_sources.gypi b/runtime/vm/vm_sources.gypi
index fa053a3..d51185b 100644
--- a/runtime/vm/vm_sources.gypi
+++ b/runtime/vm/vm_sources.gypi
@@ -21,6 +21,7 @@
     'assembler_arm64_test.cc',
     'assembler_dbc.cc',
     'assembler_dbc.h',
+    'assembler_dbc_test.cc',
     'assembler_ia32.cc',
     'assembler_ia32.h',
     'assembler_ia32_test.cc',
diff --git a/sdk/bin/dart2js.bat b/sdk/bin/dart2js.bat
index 19f9ddb..d1a4095 100644
--- a/sdk/bin/dart2js.bat
+++ b/sdk/bin/dart2js.bat
@@ -57,7 +57,7 @@
 for %%i in (%1) do set result=%%~fi
 set current=
 for /f "usebackq tokens=2 delims=[]" %%i in (`dir /a:l "%~dp1" 2^>nul ^
-                                             ^| find ">     %~n1 ["`) do (
+                                             ^| %SystemRoot%\System32\find.exe ">     %~n1 ["`) do (
   set current=%%i
 )
 if not "%current%"=="" call :follow_links "%current%", result
diff --git a/sdk/bin/dartanalyzer.bat b/sdk/bin/dartanalyzer.bat
index a73427e..0f33752 100644
--- a/sdk/bin/dartanalyzer.bat
+++ b/sdk/bin/dartanalyzer.bat
@@ -67,7 +67,7 @@
 for %%i in (%1) do set result=%%~fi
 set current=
 for /f "usebackq tokens=2 delims=[]" %%i in (`dir /a:l "%~dp1" 2^>nul ^
-                                             ^| find ">     %~n1 ["`) do (
+                                             ^| %SystemRoot%\System32\find.exe ">     %~n1 ["`) do (
   set current=%%i
 )
 if not "%current%"=="" call :follow_links "%current%", result
diff --git a/sdk/bin/dartdoc.bat b/sdk/bin/dartdoc.bat
index c313e7f..880ae55 100644
--- a/sdk/bin/dartdoc.bat
+++ b/sdk/bin/dartdoc.bat
@@ -34,7 +34,7 @@
 for %%i in (%1) do set result=%%~fi
 set current=
 for /f "usebackq tokens=2 delims=[]" %%i in (`dir /a:l "%~dp1" 2^>nul ^
-                                             ^| find ">     %~n1 ["`) do (
+                                             ^| %SystemRoot%\System32\find.exe ">     %~n1 ["`) do (
   set current=%%i
 )
 if not "%current%"=="" call :follow_links "%current%", result
diff --git a/sdk/bin/dartfmt.bat b/sdk/bin/dartfmt.bat
index 321efe5..f063221 100644
--- a/sdk/bin/dartfmt.bat
+++ b/sdk/bin/dartfmt.bat
@@ -54,7 +54,7 @@
 for %%i in (%1) do set result=%%~fi
 set current=
 for /f "usebackq tokens=2 delims=[]" %%i in (`dir /a:l "%~dp1" 2^>nul ^
-                                             ^| find ">     %~n1 ["`) do (
+                                             ^| %SystemRoot%\System32\find.exe ">     %~n1 ["`) do (
   set current=%%i
 )
 if not "%current%"=="" call :follow_links "%current%", result
diff --git a/sdk/bin/pub.bat b/sdk/bin/pub.bat
index 06ba5f3..2b8f94b 100644
--- a/sdk/bin/pub.bat
+++ b/sdk/bin/pub.bat
@@ -47,7 +47,7 @@
 for %%i in (%1) do set result=%%~fi
 set current=
 for /f "usebackq tokens=2 delims=[]" %%i in (`dir /a:l "%~dp1" 2^>nul ^
-                                             ^| find ">     %~n1 ["`) do (
+                                             ^| %SystemRoot%\System32\find.exe ">     %~n1 ["`) do (
   set current=%%i
 )
 if not "%current%"=="" call :follow_links "%current%", result
diff --git a/sdk/lib/_internal/js_runtime/lib/core_patch.dart b/sdk/lib/_internal/js_runtime/lib/core_patch.dart
index b5ad1e8..9004574 100644
--- a/sdk/lib/_internal/js_runtime/lib/core_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/core_patch.dart
@@ -20,7 +20,8 @@
                               patch_startup,
                               Primitives,
                               readHttp,
-                              stringJoinUnchecked;
+                              stringJoinUnchecked,
+                              getTraceFromException;
 
 import 'dart:_foreign_helper' show JS;
 
@@ -743,16 +744,14 @@
   @patch
   @NoInline()
   static StackTrace get current {
-    var error = JS('', 'new Error()');
-    var stack = JS('String|Null', '#.stack', error);
-    if (stack is String) return new StackTrace.fromString(stack);
     if (JS('', 'Error.captureStackTrace') != null) {
+      var error = JS('', 'new Error()');
       JS('void', 'Error.captureStackTrace(#)', error);
-      var stack = JS('String|Null', '#.stack', error);
-      if (stack is String) return new StackTrace.fromString(stack);
+      return getTraceFromException(error);
     }
+    // Fallback if Error.captureStackTrace does not exist.
     try {
-      throw 0;
+      throw '';
     } catch (_, stackTrace) {
       return stackTrace;
     }
diff --git a/sdk/lib/async/async_error.dart b/sdk/lib/async/async_error.dart
index 650d503..2f3419e 100644
--- a/sdk/lib/async/async_error.dart
+++ b/sdk/lib/async/async_error.dart
@@ -14,11 +14,13 @@
   }
 }
 
-Function _registerErrorHandler(Function errorHandler, Zone zone) {
+Function _registerErrorHandler/*<R>*/(Function errorHandler, Zone zone) {
   if (errorHandler is ZoneBinaryCallback) {
-    return zone.registerBinaryCallback(errorHandler);
+    return zone.registerBinaryCallback/*<R, dynamic, StackTrace>*/(
+        errorHandler as dynamic/*=ZoneBinaryCallback<R, dynamic, StackTrace>*/);
   } else {
-    return zone.registerUnaryCallback(errorHandler);
+    return zone.registerUnaryCallback/*<R, dynamic>*/(
+        errorHandler as dynamic/*=ZoneUnaryCallback<R, dynamic>*/);
   }
 }
 
diff --git a/sdk/lib/async/broadcast_stream_controller.dart b/sdk/lib/async/broadcast_stream_controller.dart
index a926f1d..c34ec9f 100644
--- a/sdk/lib/async/broadcast_stream_controller.dart
+++ b/sdk/lib/async/broadcast_stream_controller.dart
@@ -5,18 +5,13 @@
 part of dart.async;
 
 class _BroadcastStream<T> extends _ControllerStream<T> {
-  _BroadcastStream(_StreamControllerLifecycle controller) : super(controller);
+  _BroadcastStream(_StreamControllerLifecycle<T> controller)
+      : super(controller);
 
   bool get isBroadcast => true;
 }
 
-abstract class _BroadcastSubscriptionLink {
-  _BroadcastSubscriptionLink _next;
-  _BroadcastSubscriptionLink _previous;
-}
-
-class _BroadcastSubscription<T> extends _ControllerSubscription<T>
-                                implements _BroadcastSubscriptionLink {
+class _BroadcastSubscription<T> extends _ControllerSubscription<T> {
   static const int _STATE_EVENT_ID = 1;
   static const int _STATE_FIRING = 2;
   static const int _STATE_REMOVE_AFTER_FIRING = 4;
@@ -25,10 +20,10 @@
   // does not assume that it's use of the state integer is the only use.
   int _eventState = 0;  // Initialized to help dart2js type inference.
 
-  _BroadcastSubscriptionLink _next;
-  _BroadcastSubscriptionLink _previous;
+  _BroadcastSubscription<T> _next;
+  _BroadcastSubscription<T> _previous;
 
-  _BroadcastSubscription(_StreamControllerLifecycle controller,
+  _BroadcastSubscription(_StreamControllerLifecycle<T> controller,
                          void onData(T data),
                          Function onError,
                          void onDone(),
@@ -37,8 +32,6 @@
     _next = _previous = this;
   }
 
-  _BroadcastStreamController get _controller => super._controller;
-
   bool _expectsEvent(int eventId) =>
       (_eventState & _STATE_EVENT_ID) == eventId;
 
@@ -70,7 +63,6 @@
 abstract class _BroadcastStreamController<T>
     implements StreamController<T>,
                _StreamControllerLifecycle<T>,
-               _BroadcastSubscriptionLink,
                _EventSink<T>,
                _EventDispatch<T> {
   static const int _STATE_INITIAL = 0;
@@ -86,8 +78,8 @@
   int _state;
 
   // Double-linked list of active listeners.
-  _BroadcastSubscriptionLink _next;
-  _BroadcastSubscriptionLink _previous;
+  _BroadcastSubscription<T> _firstSubscription;
+  _BroadcastSubscription<T> _lastSubscription;
 
   // Extra state used during an [addStream] call.
   _AddStreamState<T> _addStreamState;
@@ -108,9 +100,7 @@
   _Future _doneFuture;
 
   _BroadcastStreamController(this.onListen, this.onCancel)
-      : _state = _STATE_INITIAL {
-    _next = _previous = this;
-  }
+      : _state = _STATE_INITIAL;
 
   ControllerCallback get onPause {
     throw new UnsupportedError(
@@ -158,7 +148,7 @@
    */
   bool get _hasOneListener {
     assert(!_isEmpty);
-    return identical(_next._next, this);
+    return identical(_firstSubscription, _lastSubscription);
   }
 
   /** Whether an event is being fired (sent to some, but not all, listeners). */
@@ -175,26 +165,42 @@
 
   // Linked list helpers
 
-  bool get _isEmpty => identical(_next, this);
+  bool get _isEmpty => _firstSubscription == null;
 
   /** Adds subscription to linked list of active listeners. */
   void _addListener(_BroadcastSubscription<T> subscription) {
     assert(identical(subscription._next, subscription));
-    // Insert in linked list just before `this`.
-    subscription._previous = _previous;
-    subscription._next = this;
-    this._previous._next = subscription;
-    this._previous = subscription;
     subscription._eventState = (_state & _STATE_EVENT_ID);
+    // Insert in linked list as last subscription.
+    _BroadcastSubscription<T> oldLast = _lastSubscription;
+    _lastSubscription = subscription;
+    subscription._next = null;
+    subscription._previous = oldLast;
+    if (oldLast == null) {
+      _firstSubscription = subscription;
+    } else {
+      oldLast._next = subscription;
+    }
   }
 
   void _removeListener(_BroadcastSubscription<T> subscription) {
     assert(identical(subscription._controller, this));
     assert(!identical(subscription._next, subscription));
-    _BroadcastSubscriptionLink previous = subscription._previous;
-    _BroadcastSubscriptionLink next = subscription._next;
-    previous._next = next;
-    next._previous = previous;
+    _BroadcastSubscription<T> previous = subscription._previous;
+    _BroadcastSubscription<T> next = subscription._next;
+    if (previous == null) {
+      // This was the first subscription.
+      _firstSubscription = next;
+    } else {
+      previous._next = next;
+    }
+    if (next == null) {
+      // This was the last subscription.
+      _lastSubscription = previous;
+    } else {
+      next._previous = previous;
+    }
+
     subscription._next = subscription._previous = subscription;
   }
 
@@ -209,25 +215,24 @@
       if (onDone == null) onDone = _nullDoneHandler;
       return new _DoneStreamSubscription<T>(onDone);
     }
-    StreamSubscription subscription =
+    StreamSubscription<T> subscription =
         new _BroadcastSubscription<T>(this, onData, onError, onDone,
                                       cancelOnError);
     _addListener(subscription);
-    if (identical(_next, _previous)) {
+    if (identical(_firstSubscription, _lastSubscription)) {
       // Only one listener, so it must be the first listener.
       _runGuarded(onListen);
     }
     return subscription;
   }
 
-  Future _recordCancel(_BroadcastSubscription<T> subscription) {
+  Future _recordCancel(StreamSubscription<T> sub) {
+    _BroadcastSubscription<T> subscription = sub;
     // If already removed by the stream, don't remove it again.
     if (identical(subscription._next, subscription)) return null;
-    assert(!identical(subscription._next, subscription));
     if (subscription._isFiring) {
       subscription._setRemoveAfterFiring();
     } else {
-      assert(!identical(subscription._next, subscription));
       _removeListener(subscription);
       // If we are currently firing an event, the empty-check is performed at
       // the end of the listener loop instead of here.
@@ -323,20 +328,20 @@
     // Any listeners added while firing this event will expect the next event,
     // not this one, and won't get notified.
     _state ^= _STATE_EVENT_ID | _STATE_FIRING;
-    _BroadcastSubscriptionLink link = _next;
-    while (!identical(link, this)) {
-      _BroadcastSubscription<T> subscription = link;
+    _BroadcastSubscription<T> subscription = _firstSubscription;
+    while (subscription != null) {
       if (subscription._expectsEvent(id)) {
         subscription._eventState |= _BroadcastSubscription._STATE_FIRING;
         action(subscription);
         subscription._toggleEventId();
-        link = subscription._next;
+        _BroadcastSubscription<T> next = subscription._next;
         if (subscription._removeAfterFiring) {
           _removeListener(subscription);
         }
         subscription._eventState &= ~_BroadcastSubscription._STATE_FIRING;
+        subscription = next;
       } else {
-        link = subscription._next;
+        subscription = subscription._next;
       }
     }
     _state &= ~_STATE_FIRING;
@@ -377,7 +382,7 @@
     if (_isEmpty) return;
     if (_hasOneListener) {
       _state |= _BroadcastStreamController._STATE_FIRING;
-      _BroadcastSubscription subscription = _next;
+      _BroadcastSubscription<T> subscription = _firstSubscription;
       subscription._add(data);
       _state &= ~_BroadcastStreamController._STATE_FIRING;
       if (_isEmpty) {
@@ -399,7 +404,7 @@
 
   void _sendDone() {
     if (!_isEmpty) {
-      _forEachListener((_BroadcastSubscription<T> subscription) {
+      _forEachListener((_BufferingStreamSubscription<T> subscription) {
         subscription._close();
       });
     } else {
@@ -417,29 +422,26 @@
   // EventDispatch interface.
 
   void _sendData(T data) {
-    for (_BroadcastSubscriptionLink link = _next;
-         !identical(link, this);
-         link = link._next) {
-      _BroadcastSubscription<T> subscription = link;
-      subscription._addPending(new _DelayedData(data));
+    for (_BroadcastSubscription<T> subscription = _firstSubscription;
+         subscription != null;
+         subscription = subscription._next) {
+      subscription._addPending(new _DelayedData<T>(data));
     }
   }
 
   void _sendError(Object error, StackTrace stackTrace) {
-    for (_BroadcastSubscriptionLink link = _next;
-         !identical(link, this);
-         link = link._next) {
-      _BroadcastSubscription<T> subscription = link;
+    for (_BroadcastSubscription<T> subscription = _firstSubscription;
+         subscription != null;
+         subscription = subscription._next) {
       subscription._addPending(new _DelayedError(error, stackTrace));
     }
   }
 
   void _sendDone() {
     if (!_isEmpty) {
-      for (_BroadcastSubscriptionLink link = _next;
-           !identical(link, this);
-           link = link._next) {
-        _BroadcastSubscription<T> subscription = link;
+      for (_BroadcastSubscription<T> subscription = _firstSubscription;
+           subscription != null;
+           subscription = subscription._next) {
         subscription._addPending(const _DelayedDone());
       }
     } else {
@@ -464,7 +466,7 @@
 class _AsBroadcastStreamController<T>
     extends _SyncBroadcastStreamController<T>
     implements _EventDispatch<T> {
-  _StreamImplEvents _pending;
+  _StreamImplEvents<T> _pending;
 
   _AsBroadcastStreamController(void onListen(), void onCancel())
       : super(onListen, onCancel);
@@ -473,7 +475,7 @@
 
   void _addPendingEvent(_DelayedEvent event) {
     if (_pending == null) {
-      _pending = new _StreamImplEvents();
+      _pending = new _StreamImplEvents<T>();
     }
     _pending.add(event);
   }
@@ -538,5 +540,5 @@
   }
   Future cancel() { return new _Future.immediate(null); }
   bool get isPaused => _pauseCount > 0;
-  Future asFuture([Object value]) => new _Future();
+  Future/*<E>*/ asFuture/*<E>*/([Object/*=E*/ value]) => new _Future/*<E>*/();
 }
diff --git a/sdk/lib/async/future.dart b/sdk/lib/async/future.dart
index 9fd0ca1..23bf531 100644
--- a/sdk/lib/async/future.dart
+++ b/sdk/lib/async/future.dart
@@ -112,7 +112,7 @@
    * with that value.
    */
   factory Future(computation()) {
-    _Future result = new _Future<T>();
+    _Future<T> result = new _Future<T>();
     Timer.run(() {
       try {
         result._complete(computation());
@@ -138,7 +138,7 @@
    * the returned future is completed with that value.
    */
   factory Future.microtask(computation()) {
-    _Future result = new _Future<T>();
+    _Future<T> result = new _Future<T>();
     scheduleMicrotask(() {
       try {
         result._complete(computation());
@@ -222,7 +222,7 @@
    * later time that isn't necessarily after a known fixed duration.
    */
   factory Future.delayed(Duration duration, [computation()]) {
-    _Future result = new _Future<T>();
+    _Future<T> result = new _Future<T>();
     new Timer(duration, () {
       try {
         result._complete(computation?.call());
@@ -257,8 +257,8 @@
   static Future<List/*<T>*/> wait/*<T>*/(Iterable<Future/*<T>*/> futures,
                            {bool eagerError: false,
                             void cleanUp(/*=T*/ successValue)}) {
-    final _Future<List> result = new _Future<List>();
-    List values;  // Collects the values. Set to null on error.
+    final _Future<List/*<T>*/> result = new _Future<List/*<T>*/>();
+    List/*<T>*/ values;  // Collects the values. Set to null on error.
     int remaining = 0;  // How many futures are we waiting for.
     var error;   // The first error from a future.
     StackTrace stackTrace;  // The stackTrace that came with the error.
@@ -291,7 +291,7 @@
     // position in the list of values.
     for (Future future in futures) {
       int pos = remaining++;
-      future.then((Object value) {
+      future.then((Object/*=T*/ value) {
         remaining--;
         if (values != null) {
           values[pos] = value;
@@ -312,7 +312,7 @@
     if (remaining == 0) {
       return new Future.value(const []);
     }
-    values = new List(remaining);
+    values = new List/*<T>*/(remaining);
     return result;
   }
 
@@ -327,8 +327,8 @@
    * the returned future never completes.
    */
   static Future/*<T>*/ any/*<T>*/(Iterable<Future/*<T>*/> futures) {
-    var completer = new Completer.sync();
-    var onValue = (value) {
+    var completer = new Completer/*<T>*/.sync();
+    var onValue = (/*=T*/ value) {
       if (!completer.isCompleted) completer.complete(value);
     };
     var onError = (error, stack) {
@@ -486,8 +486,17 @@
    *     }
    *
    */
-  Future catchError(Function onError,
-                    {bool test(Object error)});
+  // The `Function` below can stand for several types:
+  // - (dynamic) -> T
+  // - (dynamic, StackTrace) -> T
+  // - (dynamic) -> Future<T>
+  // - (dynamic, StackTrace) -> Future<T>
+  // Given that there is a `test` function that is usually used to do an
+  // `isCheck` we should also expect functions that take a specific argument.
+  // Note: making `catchError` return a `Future<T>` in non-strong mode could be
+  // a breaking change.
+  Future/*<T>*/ catchError(Function onError,
+                           {bool test(Object error)});
 
   /**
    * Register a function to be called when this future completes.
diff --git a/sdk/lib/async/future_impl.dart b/sdk/lib/async/future_impl.dart
index a8e71f6..eb4d6cf 100644
--- a/sdk/lib/async/future_impl.dart
+++ b/sdk/lib/async/future_impl.dart
@@ -5,7 +5,7 @@
 part of dart.async;
 
 /** The onValue and onError handlers return either a value or a future */
-typedef dynamic _FutureOnValue<T>(T value);
+typedef dynamic/*T|Future<T>*/ _FutureOnValue<S, T>(S value);
 /** Test used by [Future.catchError] to handle skip some errors. */
 typedef bool _FutureErrorTest(var error);
 /** Used by [WhenFuture]. */
@@ -57,7 +57,7 @@
   }
 }
 
-class _FutureListener {
+class _FutureListener<S, T> {
   static const int MASK_VALUE = 1;
   static const int MASK_ERROR = 2;
   static const int MASK_TEST_ERROR = 4;
@@ -73,7 +73,7 @@
   // Listeners on the same future are linked through this link.
   _FutureListener _nextListener = null;
   // The future to complete when this listener is activated.
-  final _Future result;
+  final _Future<T> result;
   // Which fields means what.
   final int state;
   // Used for then/whenDone callback and error test
@@ -82,7 +82,7 @@
   final Function errorCallback;
 
   _FutureListener.then(this.result,
-                       _FutureOnValue onValue, Function errorCallback)
+                       _FutureOnValue<S, T> onValue, Function errorCallback)
       : callback = onValue,
         errorCallback = errorCallback,
         state = (errorCallback == null) ? STATE_THEN : STATE_THEN_ONERROR;
@@ -104,18 +104,57 @@
   bool get hasErrorTest => (state == STATE_CATCHERROR_TEST);
   bool get handlesComplete => (state == STATE_WHENCOMPLETE);
 
-  _FutureOnValue get _onValue {
+
+  _FutureOnValue<S, T> get _onValue {
     assert(handlesValue);
-    return callback;
+    return callback as Object /*=_FutureOnValue<S, T>*/;
   }
   Function get _onError => errorCallback;
   _FutureErrorTest get _errorTest {
     assert(hasErrorTest);
-    return callback;
+    return callback as Object /*=_FutureErrorTest*/;
   }
   _FutureAction get _whenCompleteAction {
     assert(handlesComplete);
-    return callback;
+    return callback as Object /*=_FutureAction*/;
+  }
+
+  /// Whether this listener has an error callback.
+  ///
+  /// This function must only be called if the listener [handlesError].
+  bool get hasErrorCallback {
+    assert(handlesError);
+    return _onError != null;
+  }
+
+  dynamic/*T|Future<T>*/ handleValue(S sourceResult) {
+    return _zone.runUnary/*<dynamic/*T|Future<T>*/, S>*/(
+        _onValue, sourceResult);
+  }
+
+  bool matchesErrorTest(AsyncError asyncError) {
+    if (!hasErrorTest) return true;
+    _FutureErrorTest test = _errorTest;
+    return _zone.runUnary/*<bool, dynamic>*/(_errorTest, asyncError.error);
+  }
+
+  dynamic/*T|Future<T>*/ handleError(AsyncError asyncError) {
+    assert(handlesError && hasErrorCallback);
+    if (errorCallback is ZoneBinaryCallback) {
+      var typedErrorCallback = errorCallback as Object
+          /*=ZoneBinaryCallback<Object/*T|Future<T>*/, Object, StackTrace>*/;
+      return _zone.runBinary(typedErrorCallback,
+          asyncError.error,
+          asyncError.stackTrace);
+    } else {
+      return _zone.runUnary/*<dynamic/*T|Future<T>*/, dynamic>*/(
+          errorCallback, asyncError.error);
+    }
+  }
+
+  dynamic handleWhenComplete() {
+    assert(!handlesError);
+    return _zone.run(_whenCompleteAction);
   }
 }
 
@@ -191,40 +230,43 @@
     _resultOrListeners = source;
   }
 
-  Future/*<S>*/ then/*<S>*/(f(T value), { Function onError }) {
+  Future/*<E>*/ then/*<E>*/(
+      /*=dynamic/*E|Future<E>*/*/ f(T value), { Function onError }) {
     Zone currentZone = Zone.current;
+    ZoneUnaryCallback registered;
     if (!identical(currentZone, _ROOT_ZONE)) {
-      f = currentZone.registerUnaryCallback(f);
+      f = currentZone.registerUnaryCallback/*<dynamic, T>*/(f);
       if (onError != null) {
-        onError = _registerErrorHandler(onError, currentZone);
+        onError = _registerErrorHandler/*<T>*/(onError, currentZone);
       }
     }
-    return _thenNoZoneRegistration(f, onError);
+    return _thenNoZoneRegistration/*<E>*/(f, onError);
   }
 
   // This method is used by async/await.
-  Future _thenNoZoneRegistration(f(T value), Function onError) {
-    _Future result = new _Future();
-    _addListener(new _FutureListener.then(result, f, onError));
+  Future/*<E>*/ _thenNoZoneRegistration/*<E>*/(f(T value), Function onError) {
+    _Future/*<E>*/ result = new _Future/*<E>*/();
+    _addListener(new _FutureListener/*<T, E>*/.then(result, f, onError));
     return result;
   }
 
-  Future catchError(Function onError, { bool test(error) }) {
-    _Future result = new _Future();
+  Future/*<T>*/ catchError(Function onError, { bool test(error) }) {
+    _Future/*<T>*/ result = new _Future/*<T>*/();
     if (!identical(result._zone, _ROOT_ZONE)) {
-      onError = _registerErrorHandler(onError, result._zone);
+      onError = _registerErrorHandler/*<T>*/(onError, result._zone);
       if (test != null) test = result._zone.registerUnaryCallback(test);
     }
-    _addListener(new _FutureListener.catchError(result, onError, test));
+    _addListener(new _FutureListener/*<T, T>*/.catchError(
+        result, onError, test));
     return result;
   }
 
   Future<T> whenComplete(action()) {
-    _Future result = new _Future<T>();
+    _Future<T> result = new _Future<T>();
     if (!identical(result._zone, _ROOT_ZONE)) {
-      action = result._zone.registerCallback(action);
+      action = result._zone.registerCallback/*<dynamic>*/(action);
     }
-    _addListener(new _FutureListener.whenComplete(result, action));
+    _addListener(new _FutureListener/*<T, T>*/.whenComplete(result, action));
     return result;
   }
 
@@ -412,12 +454,12 @@
       }
     } else {
       _FutureListener listeners = _removeListeners();
-      _setValue(value);
+      _setValue(value as Object /*=T*/);
       _propagateToListeners(this, listeners);
     }
   }
 
-  void _completeWithValue(value) {
+  void _completeWithValue(T value) {
     assert(!_isComplete);
     assert(value is! Future);
 
@@ -447,11 +489,9 @@
     // unhandled error, even though we know we are already going to listen to
     // it.
 
-    if (value == null) {
-      // No checks for `null`.
-    } else if (value is Future) {
+    if (value is Future) {
       // Assign to typed variables so we get earlier checks in checked mode.
-      Future<T> typedFuture = value;
+      Future<T> typedFuture = value as Object /*=Future<T>*/;
       if (typedFuture is _Future) {
         _Future<T> coreFuture = typedFuture;
         if (coreFuture._hasError) {
@@ -465,20 +505,18 @@
           _chainCoreFuture(coreFuture, this);
         }
       } else {
-        // Case 2 from above. Chain the future immidiately.
+        // Case 2 from above. Chain the future immediately.
         // Note that we are still completing asynchronously (through
         // _chainForeignFuture).
         _chainForeignFuture(typedFuture, this);
       }
       return;
-    } else {
-      T typedValue = value;
-      assert(typedValue is T);  // Avoid warning that typedValue is unused.
     }
+    T typedValue = value as Object /*=T*/;
 
     _setPendingComplete();
     _zone.scheduleMicrotask(() {
-      _completeWithValue(value);
+      _completeWithValue(typedValue);
     });
   }
 
@@ -547,59 +585,17 @@
           oldZone = Zone._enter(zone);
         }
 
-        void handleValueCallback() {
-          assert(!hasError);
-          try {
-            listenerValueOrError = zone.runUnary(listener._onValue,
-                                                 sourceResult);
-            listenerHasError = false;
-          } catch (e, s) {
-            listenerValueOrError = new AsyncError(e, s);
-            listenerHasError = true;
-          }
-        }
-
-        void handleError() {
-          AsyncError asyncError = source._error;
-          bool matchesTest = true;
-          if (listener.hasErrorTest) {
-            _FutureErrorTest test = listener._errorTest;
-            try {
-              matchesTest = zone.runUnary(test, asyncError.error);
-            } catch (e, s) {
-              listenerValueOrError = identical(asyncError.error, e)
-                  ? asyncError
-                  : new AsyncError(e, s);
-              listenerHasError = true;
-              return;
-            }
-          }
-          Function errorCallback = listener._onError;
-          if (matchesTest && errorCallback != null) {
-            try {
-              if (errorCallback is ZoneBinaryCallback) {
-                listenerValueOrError = zone.runBinary(errorCallback,
-                                                      asyncError.error,
-                                                      asyncError.stackTrace);
-              } else {
-                listenerValueOrError = zone.runUnary(errorCallback,
-                                                     asyncError.error);
-              }
-              listenerHasError = false;
-            } catch (e, s) {
-              listenerValueOrError = identical(asyncError.error, e)
-                  ? asyncError
-                  : new AsyncError(e, s);
-              listenerHasError = true;
-            }
-          }
-        }
-
+        // These callbacks are abstracted to isolate the try/catch blocks
+        // from the rest of the code to work around a V8 glass jaw.
         void handleWhenCompleteCallback() {
+          // The whenComplete-handler is not combined with normal value/error
+          // handling. This means at most one handleX method is called per
+          // listener.
+          assert(!listener.handlesValue);
           assert(!listener.handlesError);
           var completeResult;
           try {
-            completeResult = zone.run(listener._whenCompleteAction);
+            completeResult = listener.handleWhenComplete();
           } catch (e, s) {
             if (hasError && identical(source._error.error, e)) {
               listenerValueOrError = source._error;
@@ -627,12 +623,35 @@
           }
         }
 
+        void handleValueCallback() {
+          try {
+            listenerValueOrError = listener.handleValue(sourceResult);
+          } catch (e, s) {
+            listenerValueOrError = new AsyncError(e, s);
+            listenerHasError = true;
+          }
+        }
+
+        void handleError() {
+          try {
+            AsyncError asyncError = source._error;
+            if (listener.matchesErrorTest(asyncError) &&
+                listener.hasErrorCallback) {
+              listenerValueOrError = listener.handleError(asyncError);
+              listenerHasError = false;
+            }
+          } catch (e, s) {
+            if (identical(source._error.error, e)) {
+              listenerValueOrError = source._error;
+            } else {
+              listenerValueOrError = new AsyncError(e, s);
+            }
+            listenerHasError = true;
+          }
+        }
+
+ 
         if (listener.handlesComplete) {
-          // The whenComplete-handler is not combined with normal value/error
-          // handling. This means at most one handleX method is called per
-          // listener.
-          assert(!listener.handlesValue);
-          assert(!listener.handlesError);
           handleWhenCompleteCallback();
         } else if (!hasError) {
           if (listener.handlesValue) {
@@ -643,7 +662,7 @@
             handleError();
           }
         }
-
+        
         // If we changed zone, oldZone will not be null.
         if (oldZone != null) Zone._leave(oldZone);
 
@@ -684,7 +703,7 @@
 
   Future<T> timeout(Duration timeLimit, {onTimeout()}) {
     if (_isComplete) return new _Future.immediate(this);
-    _Future result = new _Future<T>();
+    _Future<T> result = new _Future<T>();
     Timer timer;
     if (onTimeout == null) {
       timer = new Timer(timeLimit, () {
diff --git a/sdk/lib/async/schedule_microtask.dart b/sdk/lib/async/schedule_microtask.dart
index fac3f7f..70fbeba 100644
--- a/sdk/lib/async/schedule_microtask.dart
+++ b/sdk/lib/async/schedule_microtask.dart
@@ -84,7 +84,7 @@
  *
  * Is always run in the root zone.
  */
-void _schedulePriorityAsyncCallback(callback) {
+void _schedulePriorityAsyncCallback(_AsyncCallback callback) {
   if (_nextCallback == null) {
     _scheduleAsyncCallback(callback);
     _lastPriorityCallback = _lastCallback;
diff --git a/sdk/lib/async/stream.dart b/sdk/lib/async/stream.dart
index 97b1244..6931373 100644
--- a/sdk/lib/async/stream.dart
+++ b/sdk/lib/async/stream.dart
@@ -8,6 +8,8 @@
 // Core Stream types
 // -------------------------------------------------------------------
 
+typedef void _TimerCallback();
+
 /**
  * A source of asynchronous data events.
  *
@@ -127,9 +129,9 @@
    * If no future is passed, the stream closes as soon as possible.
    */
   factory Stream.fromFutures(Iterable<Future<T>> futures) {
-    var controller = new StreamController<T>(sync: true);
+    _StreamController<T> controller = new StreamController<T>(sync: true);
     int count = 0;
-    var onValue = (value) {
+    var onValue = (T value) {
       if (!controller.isClosed) {
         controller._add(value);
         if (--count == 0) controller._closeUnchecked();
@@ -384,18 +386,20 @@
    *
    * The returned stream is a broadcast stream if this stream is.
    */
-  Stream asyncMap(convert(T event)) {
-    StreamController controller;
-    StreamSubscription subscription;
-    void onListen () {
+  Stream/*<E>*/ asyncMap/*<E>*/(convert(T event)) {
+    StreamController/*<E>*/ controller;
+    StreamSubscription/*<T>*/ subscription;
+
+    void onListen() {
       final add = controller.add;
       assert(controller is _StreamController ||
              controller is _BroadcastStreamController);
-      final eventSink = controller;
+      final _EventSink/*<E>*/ eventSink =
+          controller as Object /*=_EventSink<E>*/;
       final addError = eventSink._addError;
       subscription = this.listen(
           (T event) {
-            var newValue;
+            dynamic newValue;
             try {
               newValue = convert(event);
             } catch (e, s) {
@@ -407,21 +411,22 @@
               newValue.then(add, onError: addError)
                       .whenComplete(subscription.resume);
             } else {
-              controller.add(newValue);
+              controller.add(newValue as Object/*=E*/);
             }
           },
           onError: addError,
           onDone: controller.close
       );
     }
+
     if (this.isBroadcast) {
-      controller = new StreamController.broadcast(
+      controller = new StreamController/*<E>*/.broadcast(
         onListen: onListen,
         onCancel: () { subscription.cancel(); },
         sync: true
       );
     } else {
-      controller = new StreamController(
+      controller = new StreamController/*<E>*/(
         onListen: onListen,
         onPause: () { subscription.pause(); },
         onResume: () { subscription.resume(); },
@@ -445,16 +450,17 @@
    *
    * The returned stream is a broadcast stream if this stream is.
    */
-  Stream asyncExpand(Stream convert(T event)) {
-    StreamController controller;
-    StreamSubscription subscription;
+  Stream/*<E>*/ asyncExpand/*<E>*/(Stream/*<E>*/ convert(T event)) {
+    StreamController/*<E>*/ controller;
+    StreamSubscription<T> subscription;
     void onListen() {
       assert(controller is _StreamController ||
              controller is _BroadcastStreamController);
-      final eventSink = controller;
+      final _EventSink/*<E>*/ eventSink =
+          controller as Object /*=_EventSink<E>*/;
       subscription = this.listen(
           (T event) {
-            Stream newStream;
+            Stream/*<E>*/ newStream;
             try {
               newStream = convert(event);
             } catch (e, s) {
@@ -472,13 +478,13 @@
       );
     }
     if (this.isBroadcast) {
-      controller = new StreamController.broadcast(
+      controller = new StreamController/*<E>*/.broadcast(
         onListen: onListen,
         onCancel: () { subscription.cancel(); },
         sync: true
       );
     } else {
-      controller = new StreamController(
+      controller = new StreamController/*<E>*/(
         onListen: onListen,
         onPause: () { subscription.pause(); },
         onResume: () { subscription.resume(); },
@@ -611,14 +617,14 @@
   Future/*<S>*/ fold/*<S>*/(var/*=S*/ initialValue,
       /*=S*/ combine(var/*=S*/ previous, T element)) {
 
-    _Future result = new _Future();
-    var value = initialValue;
+    _Future/*<S>*/ result = new _Future/*<S>*/();
+    var/*=S*/ value = initialValue;
     StreamSubscription subscription;
     subscription = this.listen(
       (T element) {
         _runUserCode(
           () => combine(value, element),
-          (newValue) { value = newValue; },
+          (/*=S*/ newValue) { value = newValue; },
           _cancelAndErrorClosure(subscription, result)
         );
       },
@@ -880,8 +886,8 @@
    * In case of a `done` event the future completes with the given
    * [futureValue].
    */
-  Future drain([var futureValue]) => listen(null, cancelOnError: true)
-      .asFuture(futureValue);
+  Future/*<E>*/ drain/*<E>*/([/*=E*/ futureValue])
+      => listen(null, cancelOnError: true).asFuture/*<E>*/(futureValue);
 
   /**
    * Provides at most the first [n] values of this stream.
@@ -1292,13 +1298,13 @@
    * will have its individually timer that starts counting on listen,
    * and the subscriptions' timers can be paused individually.
    */
-  Stream timeout(Duration timeLimit, {void onTimeout(EventSink sink)}) {
-    StreamController controller;
+  Stream<T> timeout(Duration timeLimit, {void onTimeout(EventSink<T> sink)}) {
+    StreamController<T> controller;
     // The following variables are set on listen.
     StreamSubscription<T> subscription;
     Timer timer;
     Zone zone;
-    Function timeout;
+    _TimerCallback timeout;
 
     void onData(T event) {
       timer.cancel();
@@ -1309,7 +1315,7 @@
       timer.cancel();
       assert(controller is _StreamController ||
              controller is _BroadcastStreamController);
-      var eventSink = controller;
+      dynamic eventSink = controller;
       eventSink._addError(error, stackTrace);  // Avoid Zone error replacement.
       timer = zone.createTimer(timeLimit, timeout);
     }
@@ -1329,12 +1335,15 @@
                                                    timeLimit), null);
         };
       } else {
-        onTimeout = zone.registerUnaryCallback(onTimeout);
+        // TODO(floitsch): the return type should be 'void', and the type
+        // should be inferred.
+        var registeredOnTimeout =
+            zone.registerUnaryCallback/*<dynamic, EventSink<T>>*/(onTimeout);
         _ControllerEventSinkWrapper wrapper =
             new _ControllerEventSinkWrapper(null);
         timeout = () {
           wrapper._sink = controller;  // Only valid during call.
-          zone.runUnaryGuarded(onTimeout, wrapper);
+          zone.runUnaryGuarded(registeredOnTimeout, wrapper);
           wrapper._sink = null;
         };
       }
@@ -1349,8 +1358,8 @@
       return result;
     }
     controller = isBroadcast
-        ? new _SyncBroadcastStreamController(onListen, onCancel)
-        : new _SyncStreamController(
+        ? new _SyncBroadcastStreamController<T>(onListen, onCancel)
+        : new _SyncStreamController<T>(
               onListen,
               () {
                 // Don't null the timer, onCancel may call cancel again.
@@ -1473,7 +1482,7 @@
    * In case of a `done` event the future completes with the given
    * [futureValue].
    */
-  Future asFuture([var futureValue]);
+  Future/*<E>*/ asFuture/*<E>*/([var/*=E*/ futureValue]);
 }
 
 
@@ -1500,8 +1509,9 @@
 
   bool get isBroadcast => _stream.isBroadcast;
 
-  Stream<T> asBroadcastStream({void onListen(StreamSubscription subscription),
-                               void onCancel(StreamSubscription subscription)})
+  Stream<T> asBroadcastStream(
+      {void onListen(StreamSubscription<T> subscription),
+       void onCancel(StreamSubscription<T> subscription)})
       => _stream.asBroadcastStream(onListen: onListen, onCancel: onCancel);
 
   StreamSubscription<T> listen(void onData(T value),
diff --git a/sdk/lib/async/stream_controller.dart b/sdk/lib/async/stream_controller.dart
index cd69f44..87b64e8 100644
--- a/sdk/lib/async/stream_controller.dart
+++ b/sdk/lib/async/stream_controller.dart
@@ -494,37 +494,40 @@
   // stream is listened to.
   // While adding a stream, pending events are moved into the
   // state object to allow the state object to use the _varData field.
-  _PendingEvents get _pendingEvents {
+  _PendingEvents<T> get _pendingEvents {
     assert(_isInitialState);
     if (!_isAddingStream) {
-      return _varData;
+      return _varData as Object /*=_PendingEvents<T>*/;
     }
-    _StreamControllerAddStreamState state = _varData;
-    return state.varData;
+    _StreamControllerAddStreamState<T> state =
+      _varData as Object /*=_StreamControllerAddStreamState<T>*/;
+    return state.varData as Object /*=_PendingEvents<T>*/;
   }
 
   // Returns the pending events, and creates the object if necessary.
-  _StreamImplEvents _ensurePendingEvents() {
+  _StreamImplEvents<T> _ensurePendingEvents() {
     assert(_isInitialState);
     if (!_isAddingStream) {
-      if (_varData == null) _varData = new _StreamImplEvents();
-      return _varData;
+      if (_varData == null) _varData = new _StreamImplEvents<T>();
+      return _varData as Object /*=_StreamImplEvents<T>*/;
     }
-    _StreamControllerAddStreamState state = _varData;
-    if (state.varData == null) state.varData = new _StreamImplEvents();
-    return state.varData;
+    _StreamControllerAddStreamState<T> state =
+        _varData as Object /*=_StreamControllerAddStreamState<T>*/;
+    if (state.varData == null) state.varData = new _StreamImplEvents<T>();
+    return state.varData as Object /*=_StreamImplEvents<T>*/;
   }
 
   // Get the current subscription.
   // If we are adding a stream, the subscription is moved into the state
   // object to allow the state object to use the _varData field.
-  _ControllerSubscription get _subscription {
+  _ControllerSubscription<T> get _subscription {
     assert(hasListener);
     if (_isAddingStream) {
-      _StreamControllerAddStreamState addState = _varData;
-      return addState.varData;
+      _StreamControllerAddStreamState<T> addState =
+          _varData as Object /*=_StreamControllerAddStreamState<T>*/;
+      return addState.varData as Object /*=_ControllerSubscription<T>*/;
     }
-    return _varData;
+    return _varData as Object /*=_ControllerSubscription<T>*/;
   }
 
   /**
@@ -544,11 +547,11 @@
   Future addStream(Stream<T> source, {bool cancelOnError: true}) {
     if (!_mayAddEvent) throw _badEventState();
     if (_isCanceled) return new _Future.immediate(null);
-    _StreamControllerAddStreamState addState =
-        new _StreamControllerAddStreamState(this,
-                                            _varData,
-                                            source,
-                                            cancelOnError);
+    _StreamControllerAddStreamState<T> addState =
+        new _StreamControllerAddStreamState<T>(this,
+                                               _varData,
+                                               source,
+                                               cancelOnError);
     _varData = addState;
     _state |= _STATE_ADDSTREAM;
     return addState.addStreamFuture;
@@ -646,7 +649,8 @@
   void _close() {
     // End of addStream stream.
     assert(_isAddingStream);
-    _StreamControllerAddStreamState addState = _varData;
+    _StreamControllerAddStreamState<T> addState =
+        _varData as Object /*=_StreamControllerAddStreamState<T>*/;
     _varData = addState.varData;
     _state &= ~_STATE_ADDSTREAM;
     addState.complete();
@@ -662,14 +666,15 @@
     if (!_isInitialState) {
       throw new StateError("Stream has already been listened to.");
     }
-    _ControllerSubscription subscription =
+    _ControllerSubscription<T> subscription =
         new _ControllerSubscription<T>(this, onData, onError, onDone,
                                        cancelOnError);
 
-    _PendingEvents pendingEvents = _pendingEvents;
+    _PendingEvents<T> pendingEvents = _pendingEvents;
     _state |= _STATE_SUBSCRIBED;
     if (_isAddingStream) {
-      _StreamControllerAddStreamState addState = _varData;
+      _StreamControllerAddStreamState<T> addState =
+          _varData as Object /*=_StreamControllerAddStreamState<T>*/;
       addState.varData = subscription;
       addState.resume();
     } else {
@@ -694,7 +699,8 @@
     // returned future.
     Future result;
     if (_isAddingStream) {
-      _StreamControllerAddStreamState addState = _varData;
+      _StreamControllerAddStreamState<T> addState =
+          _varData as Object /*=_StreamControllerAddStreamState<T>*/;
       result = addState.cancel();
     }
     _varData = null;
@@ -736,7 +742,8 @@
 
   void _recordPause(StreamSubscription<T> subscription) {
     if (_isAddingStream) {
-      _StreamControllerAddStreamState addState = _varData;
+      _StreamControllerAddStreamState<T> addState =
+          _varData as Object /*=_StreamControllerAddStreamState<T>*/;
       addState.pause();
     }
     _runGuarded(onPause);
@@ -744,7 +751,8 @@
 
   void _recordResume(StreamSubscription<T> subscription) {
     if (_isAddingStream) {
-      _StreamControllerAddStreamState addState = _varData;
+      _StreamControllerAddStreamState<T> addState =
+          _varData as Object /*=_StreamControllerAddStreamState<T>*/;
       addState.resume();
     }
     _runGuarded(onResume);
@@ -772,7 +780,7 @@
 abstract class _AsyncStreamControllerDispatch<T>
     implements _StreamController<T> {
   void _sendData(T data) {
-    _subscription._addPending(new _DelayedData(data));
+    _subscription._addPending(new _DelayedData<dynamic /*=T*/>(data));
   }
 
   void _sendError(Object error, StackTrace stackTrace) {
@@ -928,7 +936,7 @@
   // to store this state object.
   var varData;
 
-  _StreamControllerAddStreamState(_StreamController controller,
+  _StreamControllerAddStreamState(_StreamController<T> controller,
                                   this.varData,
                                   Stream source,
                                   bool cancelOnError)
diff --git a/sdk/lib/async/stream_impl.dart b/sdk/lib/async/stream_impl.dart
index 51f8b14..dffaa12 100644
--- a/sdk/lib/async/stream_impl.dart
+++ b/sdk/lib/async/stream_impl.dart
@@ -106,7 +106,7 @@
    *
    * Is created when necessary, or set in constructor for preconfigured events.
    */
-  _PendingEvents _pending;
+  _PendingEvents<T> _pending;
 
   _BufferingStreamSubscription(void onData(T data),
                                Function onError,
@@ -124,7 +124,7 @@
    * This can only be done once. The pending events object is used for the
    * rest of the subscription's life cycle.
    */
-  void _setPendingEvents(_PendingEvents pendingEvents) {
+  void _setPendingEvents(_PendingEvents<T> pendingEvents) {
     assert(_pending == null);
     if (pendingEvents == null) return;
     _pending = pendingEvents;
@@ -134,29 +134,18 @@
     }
   }
 
-  /**
-   * Extracts the pending events from a canceled stream.
-   *
-   * This can only be done during the [_onCancel] method call. After that,
-   * any remaining pending events will be cleared.
-   */
-  _PendingEvents _extractPending() {
-    assert(_isCanceled);
-    _PendingEvents events = _pending;
-    _pending = null;
-    return events;
-  }
-
   // StreamSubscription interface.
 
   void onData(void handleData(T event)) {
     if (handleData == null) handleData = _nullDataHandler;
-    _onData = _zone.registerUnaryCallback(handleData);
+    // TODO(floitsch): the return type should be 'void', and the type
+    // should be inferred.
+    _onData = _zone.registerUnaryCallback/*<dynamic, T>*/(handleData);
   }
 
   void onError(Function handleError) {
     if (handleError == null) handleError = _nullErrorHandler;
-    _onError = _registerErrorHandler(handleError, _zone);
+    _onError = _registerErrorHandler/*<T>*/(handleError, _zone);
   }
 
   void onDone(void handleDone()) {
@@ -202,8 +191,8 @@
     return _cancelFuture;
   }
 
-  Future asFuture([var futureValue]) {
-    _Future result = new _Future();
+  Future/*<E>*/ asFuture/*<E>*/([var/*=E*/ futureValue]) {
+    _Future/*<E>*/ result = new _Future/*<E>*/();
 
     // Overwrite the onDone and onError handlers.
     _onDone = () { result._complete(futureValue); };
@@ -269,7 +258,7 @@
     if (_canFire) {
       _sendData(data);
     } else {
-      _addPending(new _DelayedData(data));
+      _addPending(new _DelayedData<dynamic /*=T*/>(data));
     }
   }
 
@@ -319,8 +308,10 @@
    * of pending events later (if necessary).
    */
   void _addPending(_DelayedEvent event) {
-    _StreamImplEvents pending = _pending;
-    if (_pending == null) pending = _pending = new _StreamImplEvents();
+    _StreamImplEvents<T> pending = _pending;
+    if (_pending == null) {
+      pending = _pending = new _StreamImplEvents<dynamic /*=T*/>();
+    }
     pending.add(event);
     if (!_hasPending) {
       _state |= _STATE_HAS_PENDING;
@@ -354,10 +345,13 @@
       // future to finish we must not report the error.
       if (_isCanceled && !_waitsForCancel) return;
       _state |= _STATE_IN_CALLBACK;
-      if (_onError is ZoneBinaryCallback) {
-        _zone.runBinaryGuarded(_onError, error, stackTrace);
+      if (_onError is ZoneBinaryCallback<dynamic, Object, StackTrace>) {
+        ZoneBinaryCallback<dynamic, Object, StackTrace> errorCallback = _onError
+            as Object /*=ZoneBinaryCallback<dynamic, Object, StackTrace>*/;
+        _zone.runBinaryGuarded(errorCallback, error, stackTrace);
       } else {
-        _zone.runUnaryGuarded(_onError, error);
+        _zone.runUnaryGuarded/*<dynamic, dynamic>*/(
+            _onError as Object /*=ZoneUnaryCallback<dynamic, dynamic>*/, error);
       }
       _state &= ~_STATE_IN_CALLBACK;
     }
@@ -470,7 +464,7 @@
                                  void onDone(),
                                  bool cancelOnError }) {
     cancelOnError = identical(true, cancelOnError);
-    StreamSubscription subscription =
+    StreamSubscription<T> subscription =
         _createSubscription(onData, onError, onDone, cancelOnError);
     _onListen(subscription);
     return subscription;
@@ -478,7 +472,7 @@
 
   // -------------------------------------------------------------------
   /** Create a subscription object. Called by [subcribe]. */
-  _BufferingStreamSubscription<T> _createSubscription(
+  StreamSubscription<T> _createSubscription(
       void onData(T data),
       Function onError,
       void onDone(),
@@ -491,11 +485,11 @@
   void _onListen(StreamSubscription subscription) {}
 }
 
-typedef _PendingEvents _EventGenerator();
+typedef _PendingEvents<T> _EventGenerator<T>();
 
 /** Stream that generates its own events. */
 class _GeneratedStreamImpl<T> extends _StreamImpl<T> {
-  final _EventGenerator _pending;
+  final _EventGenerator<T> _pending;
   bool _isUsed = false;
   /**
    * Initializes the stream to have only the events provided by a
@@ -505,7 +499,7 @@
    */
   _GeneratedStreamImpl(this._pending);
 
-  StreamSubscription _createSubscription(
+  StreamSubscription<T> _createSubscription(
       void onData(T data),
       Function onError,
       void onDone(),
@@ -519,7 +513,7 @@
 
 
 /** Pending events object that gets its events from an [Iterable]. */
-class _IterablePendingEvents<T> extends _PendingEvents {
+class _IterablePendingEvents<T> extends _PendingEvents<T> {
   // The iterator providing data for data events.
   // Set to null when iteration has completed.
   Iterator<T> _iterator;
@@ -528,7 +522,7 @@
 
   bool get isEmpty => _iterator == null;
 
-  void handleNext(_EventDispatch dispatch) {
+  void handleNext(_EventDispatch<T> dispatch) {
     if (_iterator == null) {
       throw new StateError("No events pending.");
     }
@@ -580,15 +574,15 @@
 
 
 /** A delayed event on a buffering stream subscription. */
-abstract class _DelayedEvent {
+abstract class _DelayedEvent<T> {
   /** Added as a linked list on the [StreamController]. */
   _DelayedEvent next;
   /** Execute the delayed event on the [StreamController]. */
-  void perform(_EventDispatch dispatch);
+  void perform(_EventDispatch<T> dispatch);
 }
 
 /** A delayed data event. */
-class _DelayedData<T> extends _DelayedEvent {
+class _DelayedData<T> extends _DelayedEvent<T> {
   final T value;
   _DelayedData(this.value);
   void perform(_EventDispatch<T> dispatch) {
@@ -622,7 +616,7 @@
 }
 
 /** Superclass for provider of pending events. */
-abstract class _PendingEvents {
+abstract class _PendingEvents<T> {
   // No async event has been scheduled.
   static const int _STATE_UNSCHEDULED = 0;
   // An async event has been scheduled to run a function.
@@ -656,7 +650,7 @@
    * If called more than once, it should be called with the same dispatch as
    * argument each time. It may reuse an earlier argument in some cases.
    */
-  void schedule(_EventDispatch dispatch) {
+  void schedule(_EventDispatch<T> dispatch) {
     if (isScheduled) return;
     assert(!isEmpty);
     if (_eventScheduled) {
@@ -677,7 +671,7 @@
     if (isScheduled) _state = _STATE_CANCELED;
   }
 
-  void handleNext(_EventDispatch dispatch);
+  void handleNext(_EventDispatch<T> dispatch);
 
   /** Throw away any pending events and cancel scheduled events. */
   void clear();
@@ -685,7 +679,7 @@
 
 
 /** Class holding pending events for a [_StreamImpl]. */
-class _StreamImplEvents extends _PendingEvents {
+class _StreamImplEvents<T> extends _PendingEvents<T> {
   /// Single linked list of [_DelayedEvent] objects.
   _DelayedEvent firstPendingEvent = null;
   /// Last element in the list of pending events. New events are added after it.
@@ -701,7 +695,7 @@
     }
   }
 
-  void handleNext(_EventDispatch dispatch) {
+  void handleNext(_EventDispatch<T> dispatch) {
     assert(!isScheduled);
     _DelayedEvent event = firstPendingEvent;
     firstPendingEvent = event.next;
@@ -736,7 +730,7 @@
   }
 }
 
-typedef void _broadcastCallback(StreamSubscription subscription);
+typedef void _BroadcastCallback<T>(StreamSubscription<T> subscription);
 
 /**
  * Done subscription that will send one done event as soon as possible.
@@ -784,8 +778,8 @@
 
   Future cancel() => null;
 
-  Future asFuture([futureValue]) {
-    _Future result = new _Future();
+  Future/*<E>*/ asFuture/*<E>*/([var/*=E*/ futureValue]) {
+    _Future/*<E>*/ result = new _Future/*<E>*/();
     _onDone = () { result._completeWithValue(null); };
     return result;
   }
@@ -800,18 +794,22 @@
 
 class _AsBroadcastStream<T> extends Stream<T> {
   final Stream<T> _source;
-  final _broadcastCallback _onListenHandler;
-  final _broadcastCallback _onCancelHandler;
+  final _BroadcastCallback<T> _onListenHandler;
+  final _BroadcastCallback<T> _onCancelHandler;
   final Zone _zone;
 
   _AsBroadcastStreamController<T> _controller;
   StreamSubscription<T> _subscription;
 
   _AsBroadcastStream(this._source,
-                     void onListenHandler(StreamSubscription subscription),
-                     void onCancelHandler(StreamSubscription subscription))
-      : _onListenHandler = Zone.current.registerUnaryCallback(onListenHandler),
-        _onCancelHandler = Zone.current.registerUnaryCallback(onCancelHandler),
+                     void onListenHandler(StreamSubscription<T> subscription),
+                     void onCancelHandler(StreamSubscription<T> subscription))
+      // TODO(floitsch): the return type should be void and should be
+      // inferred.
+      : _onListenHandler = Zone.current.registerUnaryCallback
+            /*<dynamic, StreamSubscription<T>>*/(onListenHandler),
+        _onCancelHandler = Zone.current.registerUnaryCallback
+            /*<dynamic, StreamSubscription<T>>*/(onCancelHandler),
         _zone = Zone.current {
     _controller = new _AsBroadcastStreamController<T>(_onListen, _onCancel);
   }
@@ -896,7 +894,7 @@
         "Cannot change handlers of asBroadcastStream source subscription.");
   }
 
-  void onError(void handleError(Object data)) {
+  void onError(Function handleError) {
     throw new UnsupportedError(
         "Cannot change handlers of asBroadcastStream source subscription.");
   }
@@ -923,7 +921,7 @@
     return _stream._isSubscriptionPaused;
   }
 
-  Future asFuture([var futureValue]) {
+  Future/*<E>*/ asFuture/*<E>*/([var/*=E*/ futureValue]) {
     throw new UnsupportedError(
         "Cannot change handlers of asBroadcastStream source subscription.");
   }
@@ -974,7 +972,7 @@
   /// Also used to store the next value/error in case the stream provides an
   /// event before [moveNext] is called again. In that case, the stream will
   /// be paused to prevent further events.
-  var _futureOrPrefetch = null;
+  var/*Future<bool> or T*/ _futureOrPrefetch = null;
 
   /// The current state.
   int _state = _STATE_FOUND;
@@ -998,14 +996,15 @@
     if (_state == _STATE_FOUND) {
       _state = _STATE_MOVING;
       _current = null;
-      _futureOrPrefetch = new _Future<bool>();
-      return _futureOrPrefetch;
+      var result = new _Future<bool>();
+      _futureOrPrefetch = result;
+      return result;
     } else {
       assert(_state >= _STATE_EXTRA_DATA);
       switch (_state) {
         case _STATE_EXTRA_DATA:
           _state = _STATE_FOUND;
-          _current = _futureOrPrefetch;
+          _current = _futureOrPrefetch as Object /*=T*/;
           _futureOrPrefetch = null;
           _subscription.resume();
           return new _Future<bool>.immediate(true);
@@ -1033,7 +1032,7 @@
     StreamSubscription subscription = _subscription;
     if (subscription == null) return null;
     if (_state == _STATE_MOVING) {
-      _Future<bool> hasNext = _futureOrPrefetch;
+      _Future<bool> hasNext = _futureOrPrefetch as Object /*=_Future<bool>*/;
       _clear();
       hasNext._complete(false);
     } else {
@@ -1045,7 +1044,7 @@
   void _onData(T data) {
     if (_state == _STATE_MOVING) {
       _current = data;
-      _Future<bool> hasNext = _futureOrPrefetch;
+      _Future<bool> hasNext = _futureOrPrefetch as Object /*=_Future<bool>*/;
       _futureOrPrefetch = null;
       _state = _STATE_FOUND;
       hasNext._complete(true);
@@ -1059,7 +1058,7 @@
 
   void _onError(Object error, [StackTrace stackTrace]) {
     if (_state == _STATE_MOVING) {
-      _Future<bool> hasNext = _futureOrPrefetch;
+      _Future<bool> hasNext = _futureOrPrefetch as Object /*=_Future<bool>*/;
       // We have cancelOnError: true, so the subscription is canceled.
       _clear();
       hasNext._completeError(error, stackTrace);
@@ -1073,7 +1072,7 @@
 
   void _onDone() {
      if (_state == _STATE_MOVING) {
-      _Future<bool> hasNext = _futureOrPrefetch;
+      _Future<bool> hasNext = _futureOrPrefetch as Object /*=_Future<bool>*/;
       _clear();
       hasNext._complete(false);
       return;
diff --git a/sdk/lib/async/stream_pipe.dart b/sdk/lib/async/stream_pipe.dart
index b3c3aaf..1125620 100644
--- a/sdk/lib/async/stream_pipe.dart
+++ b/sdk/lib/async/stream_pipe.dart
@@ -47,10 +47,15 @@
   _cancelAndError(subscription, future, error, stackTrace);
 }
 
+typedef void _ErrorCallback(error, StackTrace stackTrace);
+
 /** Helper function to make an onError argument to [_runUserCode]. */
-_cancelAndErrorClosure(StreamSubscription subscription, _Future future) =>
-  ((error, StackTrace stackTrace) => _cancelAndError(
-      subscription, future, error, stackTrace));
+_ErrorCallback _cancelAndErrorClosure(
+    StreamSubscription subscription, _Future future) {
+  return (error, StackTrace stackTrace) {
+    _cancelAndError(subscription, future, error, stackTrace);
+  };
+}
 
 /** Helper function to cancel a subscription and wait for the potential future,
   before completing with a value. */
@@ -100,8 +105,7 @@
   // Override the following methods in subclasses to change the behavior.
 
   void _handleData(S data, _EventSink<T> sink) {
-    var outputData = data;
-    sink._add(outputData);
+    sink._add(data as Object /*=T*/);
   }
 
   void _handleError(error, StackTrace stackTrace, _EventSink<T> sink) {
@@ -224,7 +228,7 @@
  * A stream pipe that converts data events before passing them on.
  */
 class _MapStream<S, T> extends _ForwardingStream<S, T> {
-  final _Transformation _transform;
+  final _Transformation<S, T> _transform;
 
   _MapStream(Stream<S> source, T transform(S event))
       : this._transform = transform, super(source);
@@ -327,7 +331,7 @@
   }
 
   void _handleData(T inputEvent, _EventSink<T> sink) {
-    _StateStreamSubscription subscription = sink;
+    _StateStreamSubscription<T> subscription = sink;
     int count = subscription._count;
     if (count > 0) {
       sink._add(inputEvent);
@@ -351,7 +355,7 @@
   // Raw state field. Typed access provided by getters and setters below.
   var _sharedState;
 
-  _StateStreamSubscription(_ForwardingStream stream, void onData(T data),
+  _StateStreamSubscription(_ForwardingStream<T, T> stream, void onData(T data),
                            Function onError, void onDone(),
                            bool cancelOnError, this._sharedState)
       : super(stream, onData, onError, onDone, cancelOnError);
@@ -407,7 +411,7 @@
   }
 
   void _handleData(T inputEvent, _EventSink<T> sink) {
-    _StateStreamSubscription subscription = sink;
+    _StateStreamSubscription<T> subscription = sink;
     int count = subscription._count;
     if (count > 0) {
       subscription._count = count - 1;
@@ -433,7 +437,7 @@
   }
 
   void _handleData(T inputEvent, _EventSink<T> sink) {
-    _StateStreamSubscription subscription = sink;
+    _StateStreamSubscription<T> subscription = sink;
     bool hasFailed = subscription._flag;
     if (hasFailed) {
       sink._add(inputEvent);
@@ -476,7 +480,7 @@
         if (_equals == null) {
           isEqual = (_previous == inputEvent);
         } else {
-          isEqual = _equals(_previous, inputEvent);
+          isEqual = _equals(_previous as Object /*=T*/, inputEvent);
         }
       } catch (e, s) {
         _addErrorWithReplacement(sink, e, s);
diff --git a/sdk/lib/async/stream_transformers.dart b/sdk/lib/async/stream_transformers.dart
index 979ce3a..e0982da 100644
--- a/sdk/lib/async/stream_transformers.dart
+++ b/sdk/lib/async/stream_transformers.dart
@@ -28,13 +28,13 @@
 class _SinkTransformerStreamSubscription<S, T>
     extends _BufferingStreamSubscription<T> {
   /// The transformer's input sink.
-  EventSink _transformerSink;
+  EventSink<S> _transformerSink;
 
   /// The subscription to the input stream.
   StreamSubscription<S> _subscription;
 
   _SinkTransformerStreamSubscription(Stream<S> source,
-                                     _SinkMapper mapper,
+                                     _SinkMapper<S, T> mapper,
                                      void onData(T data),
                                      Function onError,
                                      void onDone(),
@@ -183,8 +183,9 @@
                                  void onDone(),
                                  bool cancelOnError }) {
     cancelOnError = identical(true, cancelOnError);
-    StreamSubscription<T> subscription = new _SinkTransformerStreamSubscription(
-        _stream, _sinkMapper, onData, onError, onDone, cancelOnError);
+    StreamSubscription<T> subscription =
+        new _SinkTransformerStreamSubscription<S, T>(
+            _stream, _sinkMapper, onData, onError, onDone, cancelOnError);
     return subscription;
   }
 }
diff --git a/sdk/lib/async/timer.dart b/sdk/lib/async/timer.dart
index fafe652..1bbb65b 100644
--- a/sdk/lib/async/timer.dart
+++ b/sdk/lib/async/timer.dart
@@ -76,8 +76,11 @@
       // be invoked in the root zone.
       return Zone.current.createPeriodicTimer(duration, callback);
     }
-    return Zone.current.createPeriodicTimer(
-        duration, Zone.current.bindUnaryCallback(callback, runGuarded: true));
+    // TODO(floitsch): the return type should be 'void', and the type
+    // should be inferred.
+    var boundCallback = Zone.current.bindUnaryCallback/*<dynamic, Timer>*/(
+        callback, runGuarded: true);
+    return Zone.current.createPeriodicTimer(duration, boundCallback);
   }
 
   /**
diff --git a/sdk/lib/async/zone.dart b/sdk/lib/async/zone.dart
index 5cc4d88..24f83f8 100644
--- a/sdk/lib/async/zone.dart
+++ b/sdk/lib/async/zone.dart
@@ -4,27 +4,37 @@
 
 part of dart.async;
 
-typedef dynamic ZoneCallback();
-typedef dynamic ZoneUnaryCallback(arg);
-typedef dynamic ZoneBinaryCallback(arg1, arg2);
+typedef R ZoneCallback<R>();
+typedef R ZoneUnaryCallback<R, T>(T arg);
+typedef R ZoneBinaryCallback<R, T1, T2>(T1 arg1, T2 arg2);
 
-typedef dynamic HandleUncaughtErrorHandler(
+// TODO(floitsch): we are abusing generic typedefs as typedefs for generic
+// functions.
+/*ABUSE*/
+typedef R HandleUncaughtErrorHandler<R>(
     Zone self, ZoneDelegate parent, Zone zone, error, StackTrace stackTrace);
-typedef dynamic RunHandler(Zone self, ZoneDelegate parent, Zone zone, f());
-typedef dynamic RunUnaryHandler(
-    Zone self, ZoneDelegate parent, Zone zone, f(arg), arg);
-typedef dynamic RunBinaryHandler(
-    Zone self, ZoneDelegate parent, Zone zone, f(arg1, arg2), arg1, arg2);
-typedef ZoneCallback RegisterCallbackHandler(
-    Zone self, ZoneDelegate parent, Zone zone, f());
-typedef ZoneUnaryCallback RegisterUnaryCallbackHandler(
-    Zone self, ZoneDelegate parent, Zone zone, f(arg));
-typedef ZoneBinaryCallback RegisterBinaryCallbackHandler(
-    Zone self, ZoneDelegate parent, Zone zone, f(arg1, arg2));
+/*ABUSE*/
+typedef R RunHandler<R>(Zone self, ZoneDelegate parent, Zone zone, R f());
+/*ABUSE*/
+typedef R RunUnaryHandler<R, T>(
+    Zone self, ZoneDelegate parent, Zone zone, R f(T arg), T arg);
+/*ABUSE*/
+typedef R RunBinaryHandler<R, T1, T2>(
+    Zone self, ZoneDelegate parent, Zone zone,
+    R f(T1 arg1, T2 arg2), T1 arg1, T2 arg2);
+/*ABUSE*/
+typedef ZoneCallback<R> RegisterCallbackHandler<R>(
+    Zone self, ZoneDelegate parent, Zone zone, R f());
+/*ABUSE*/
+typedef ZoneUnaryCallback<R, T> RegisterUnaryCallbackHandler<R, T>(
+    Zone self, ZoneDelegate parent, Zone zone, R f(T arg));
+/*ABUSE*/
+typedef ZoneBinaryCallback<R, T1, T2> RegisterBinaryCallbackHandler<R, T1, T2>(
+    Zone self, ZoneDelegate parent, Zone zone, R f(T1 arg1, T2 arg2));
 typedef AsyncError ErrorCallbackHandler(Zone self, ZoneDelegate parent,
     Zone zone, Object error, StackTrace stackTrace);
 typedef void ScheduleMicrotaskHandler(
-    Zone self, ZoneDelegate parent, Zone zone, f());
+    Zone self, ZoneDelegate parent, Zone zone, void f());
 typedef Timer CreateTimerHandler(
     Zone self, ZoneDelegate parent, Zone zone, Duration duration, void f());
 typedef Timer CreatePeriodicTimerHandler(
@@ -38,7 +48,7 @@
 
 /** Pair of error and stack trace. Returned by [Zone.errorCallback]. */
 class AsyncError implements Error {
-  final error;
+  final Object error;
   final StackTrace stackTrace;
 
   AsyncError(this.error, this.stackTrace);
@@ -47,9 +57,9 @@
 }
 
 
-class _ZoneFunction {
+class _ZoneFunction<T extends Function> {
   final _Zone zone;
-  final Function function;
+  final T function;
   const _ZoneFunction(this.zone, this.function);
 }
 
@@ -77,30 +87,19 @@
    * Creates a specification with the provided handlers.
    */
   const factory ZoneSpecification({
-    dynamic handleUncaughtError(Zone self, ZoneDelegate parent, Zone zone,
-                                error, StackTrace stackTrace),
-    dynamic run(Zone self, ZoneDelegate parent, Zone zone, f()),
-    dynamic runUnary(
-        Zone self, ZoneDelegate parent, Zone zone, f(arg), arg),
-    dynamic runBinary(Zone self, ZoneDelegate parent, Zone zone,
-                      f(arg1, arg2), arg1, arg2),
-    ZoneCallback registerCallback(
-        Zone self, ZoneDelegate parent, Zone zone, f()),
-    ZoneUnaryCallback registerUnaryCallback(
-        Zone self, ZoneDelegate parent, Zone zone, f(arg)),
-    ZoneBinaryCallback registerBinaryCallback(
-        Zone self, ZoneDelegate parent, Zone zone, f(arg1, arg2)),
-    AsyncError errorCallback(Zone self, ZoneDelegate parent, Zone zone,
-                             Object error, StackTrace stackTrace),
-    void scheduleMicrotask(
-        Zone self, ZoneDelegate parent, Zone zone, f()),
-    Timer createTimer(Zone self, ZoneDelegate parent, Zone zone,
-                      Duration duration, void f()),
-    Timer createPeriodicTimer(Zone self, ZoneDelegate parent, Zone zone,
-                              Duration period, void f(Timer timer)),
-    void print(Zone self, ZoneDelegate parent, Zone zone, String line),
-    Zone fork(Zone self, ZoneDelegate parent, Zone zone,
-              ZoneSpecification specification, Map zoneValues)
+      HandleUncaughtErrorHandler handleUncaughtError,
+      RunHandler run,
+      RunUnaryHandler runUnary,
+      RunBinaryHandler runBinary,
+      RegisterCallbackHandler registerCallback,
+      RegisterUnaryCallbackHandler registerUnaryCallback,
+      RegisterBinaryCallbackHandler registerBinaryCallback,
+      ErrorCallbackHandler errorCallback,
+      ScheduleMicrotaskHandler scheduleMicrotask,
+      CreateTimerHandler createTimer,
+      CreatePeriodicTimerHandler createPeriodicTimer,
+      PrintHandler print,
+      ForkHandler fork
   }) = _ZoneSpecification;
 
   /**
@@ -108,31 +107,19 @@
    * the ones in [other].
    */
   factory ZoneSpecification.from(ZoneSpecification other, {
-    dynamic handleUncaughtError(Zone self, ZoneDelegate parent, Zone zone,
-                                error, StackTrace stackTrace): null,
-    dynamic run(Zone self, ZoneDelegate parent, Zone zone, f()): null,
-    dynamic runUnary(
-        Zone self, ZoneDelegate parent, Zone zone, f(arg), arg): null,
-    dynamic runBinary(Zone self, ZoneDelegate parent, Zone zone,
-                      f(arg1, arg2), arg1, arg2): null,
-    ZoneCallback registerCallback(
-        Zone self, ZoneDelegate parent, Zone zone, f()): null,
-    ZoneUnaryCallback registerUnaryCallback(
-        Zone self, ZoneDelegate parent, Zone zone, f(arg)): null,
-    ZoneBinaryCallback registerBinaryCallback(
-        Zone self, ZoneDelegate parent, Zone zone, f(arg1, arg2)): null,
-    AsyncError errorCallback(Zone self, ZoneDelegate parent, Zone zone,
-                             Object error, StackTrace stackTrace),
-    void scheduleMicrotask(
-        Zone self, ZoneDelegate parent, Zone zone, f()): null,
-    Timer createTimer(Zone self, ZoneDelegate parent, Zone zone,
-                      Duration duration, void f()): null,
-    Timer createPeriodicTimer(Zone self, ZoneDelegate parent, Zone zone,
-                              Duration period, void f(Timer timer)): null,
-    void print(Zone self, ZoneDelegate parent, Zone zone, String line): null,
-    Zone fork(Zone self, ZoneDelegate parent, Zone zone,
-              ZoneSpecification specification,
-              Map zoneValues): null
+      HandleUncaughtErrorHandler handleUncaughtError: null,
+      RunHandler run: null,
+      RunUnaryHandler runUnary: null,
+      RunBinaryHandler runBinary: null,
+      RegisterCallbackHandler registerCallback: null,
+      RegisterUnaryCallbackHandler registerUnaryCallback: null,
+      RegisterBinaryCallbackHandler registerBinaryCallback: null,
+      ErrorCallbackHandler errorCallback: null,
+      ScheduleMicrotaskHandler scheduleMicrotask: null,
+      CreateTimerHandler createTimer: null,
+      CreatePeriodicTimerHandler createPeriodicTimer: null,
+      PrintHandler print: null,
+      ForkHandler fork: null
   }) {
     return new ZoneSpecification(
       handleUncaughtError: handleUncaughtError ?? other.handleUncaughtError,
@@ -217,15 +204,19 @@
  * directly invoking the parent zone.
  */
 abstract class ZoneDelegate {
-  dynamic handleUncaughtError(Zone zone, error, StackTrace stackTrace);
-  dynamic run(Zone zone, f());
-  dynamic runUnary(Zone zone, f(arg), arg);
-  dynamic runBinary(Zone zone, f(arg1, arg2), arg1, arg2);
-  ZoneCallback registerCallback(Zone zone, f());
-  ZoneUnaryCallback registerUnaryCallback(Zone zone, f(arg));
-  ZoneBinaryCallback registerBinaryCallback(Zone zone, f(arg1, arg2));
+  /*=R*/ handleUncaughtError/*<R>*/(
+      Zone zone, error, StackTrace stackTrace);
+  /*=R*/ run/*<R>*/(Zone zone, /*=R*/ f());
+  /*=R*/ runUnary/*<R, T>*/(Zone zone, /*=R*/ f(/*=T*/ arg), /*=T*/ arg);
+  /*=R*/ runBinary/*<R, T1, T2>*/(Zone zone,
+      /*=R*/ f(/*=T1*/ arg1, /*=T2*/ arg2), /*=T1*/ arg1, /*=T2*/ arg2);
+  ZoneCallback/*<R>*/ registerCallback/*<R>*/(Zone zone, /*=R*/ f());
+  ZoneUnaryCallback/*<R, T>*/ registerUnaryCallback/*<R, T>*/(
+      Zone zone, /*=R*/ f(/*=T*/ arg));
+  ZoneBinaryCallback/*<R, T1, T2>*/ registerBinaryCallback/*<R, T1, T2>*/(
+      Zone zone, /*=R*/ f(/*=T1*/ arg1, /*=T2*/ arg2));
   AsyncError errorCallback(Zone zone, Object error, StackTrace stackTrace);
-  void scheduleMicrotask(Zone zone, f());
+  void scheduleMicrotask(Zone zone, void f());
   Timer createTimer(Zone zone, Duration duration, void f());
   Timer createPeriodicTimer(Zone zone, Duration period, void f(Timer timer));
   void print(Zone zone, String line);
@@ -250,7 +241,7 @@
 
   static Zone get current => _current;
 
-  dynamic handleUncaughtError(error, StackTrace stackTrace);
+  /*=R*/ handleUncaughtError/*<R>*/(error, StackTrace stackTrace);
 
   /**
    * Returns the parent zone.
@@ -294,18 +285,19 @@
   /**
    * Executes the given function [f] in this zone.
    */
-  dynamic run(f());
+  /*=R*/ run/*<R>*/(/*=R*/ f());
 
   /**
    * Executes the given callback [f] with argument [arg] in this zone.
    */
-  dynamic runUnary(f(arg), var arg);
+  /*=R*/ runUnary/*<R, T>*/(/*=R*/ f(/*=T*/ arg), /*=T*/ arg);
 
   /**
    * Executes the given callback [f] with argument [arg1] and [arg2] in this
    * zone.
    */
-  dynamic runBinary(f(arg1, arg2), var arg1, var arg2);
+  /*=R*/ runBinary/*<R, T1, T2>*/(
+      /*=R*/ f(/*=T1*/ arg1, /*=T2*/ arg2), /*=T1*/ arg1, /*=T2*/ arg2);
 
   /**
    * Executes the given function [f] in this zone.
@@ -313,7 +305,7 @@
    * Same as [run] but catches uncaught errors and gives them to
    * [handleUncaughtError].
    */
-  dynamic runGuarded(f());
+  /*=R*/ runGuarded/*<R>*/(/*=R*/ f());
 
   /**
    * Executes the given callback [f] in this zone.
@@ -321,7 +313,7 @@
    * Same as [runUnary] but catches uncaught errors and gives them to
    * [handleUncaughtError].
    */
-  dynamic runUnaryGuarded(f(arg), var arg);
+  /*=R*/ runUnaryGuarded/*<R, T>*/(/*=R*/ f(/*=T*/ arg), /*=T*/ arg);
 
   /**
    * Executes the given callback [f] in this zone.
@@ -329,7 +321,8 @@
    * Same as [runBinary] but catches uncaught errors and gives them to
    * [handleUncaughtError].
    */
-  dynamic runBinaryGuarded(f(arg1, arg2), var arg1, var arg2);
+  /*=R*/ runBinaryGuarded/*<R, T1, T2>*/(
+      /*=R*/ f(/*=T1*/ arg1, /*=T2*/ arg2), /*=T1*/ arg1, /*=T2*/ arg2);
 
   /**
    * Registers the given callback in this zone.
@@ -343,21 +336,23 @@
    * Returns a potentially new callback that should be used in place of the
    * given [callback].
    */
-  ZoneCallback registerCallback(callback());
+  ZoneCallback/*<R>*/ registerCallback/*<R>*/(/*=R*/ callback());
 
   /**
    * Registers the given callback in this zone.
    *
    * Similar to [registerCallback] but with a unary callback.
    */
-  ZoneUnaryCallback registerUnaryCallback(callback(arg));
+  ZoneUnaryCallback/*<R, T>*/ registerUnaryCallback/*<R, T>*/(
+      /*=R*/ callback(/*=T*/ arg));
 
   /**
    * Registers the given callback in this zone.
    *
    * Similar to [registerCallback] but with a unary callback.
    */
-  ZoneBinaryCallback registerBinaryCallback(callback(arg1, arg2));
+  ZoneBinaryCallback/*<R, T1, T2>*/ registerBinaryCallback/*<R, T1, T2>*/(
+      /*=R*/ callback(/*=T1*/ arg1, /*=T2*/ arg2));
 
   /**
    *  Equivalent to:
@@ -367,7 +362,8 @@
    *      return () => this.run(registered);
    *
    */
-  ZoneCallback bindCallback(f(), { bool runGuarded: true });
+  ZoneCallback/*<R>*/ bindCallback/*<R>*/(
+      /*=R*/ f(), { bool runGuarded: true });
 
   /**
    *  Equivalent to:
@@ -376,7 +372,8 @@
    *      if (runGuarded) return (arg) => this.runUnaryGuarded(registered, arg);
    *      return (arg) => thin.runUnary(registered, arg);
    */
-  ZoneUnaryCallback bindUnaryCallback(f(arg), { bool runGuarded: true });
+  ZoneUnaryCallback/*<R, T>*/ bindUnaryCallback/*<R, T>*/(
+      /*=R*/ f(/*=T*/ arg), { bool runGuarded: true });
 
   /**
    *  Equivalent to:
@@ -387,11 +384,11 @@
    *      }
    *      return (arg1, arg2) => thin.runBinary(registered, arg1, arg2);
    */
-  ZoneBinaryCallback bindBinaryCallback(
-      f(arg1, arg2), { bool runGuarded: true });
+  ZoneBinaryCallback/*<R, T1, T2>*/ bindBinaryCallback/*<R, T1, T2>*/(
+      /*=R*/ f(/*=T1*/ arg1, /*=T2*/ arg2), { bool runGuarded: true });
 
   /**
-   * Intercepts errors when added programmtically to a `Future` or `Stream`.
+   * Intercepts errors when added programmatically to a `Future` or `Stream`.
    *
    * When caling [Completer.completeError], [Stream.addError],
    * or [Future] constructors that take an error or a callback that may throw,
@@ -475,60 +472,84 @@
 
   _ZoneDelegate(this._delegationTarget);
 
-  dynamic handleUncaughtError(Zone zone, error, StackTrace stackTrace) {
-    _ZoneFunction implementation = _delegationTarget._handleUncaughtError;
+  /*=R*/ handleUncaughtError/*<R>*/(
+      Zone zone, error, StackTrace stackTrace) {
+    var implementation = _delegationTarget._handleUncaughtError;
     _Zone implZone = implementation.zone;
     HandleUncaughtErrorHandler handler = implementation.function;
+    // TODO(floitsch): make this a generic method call on '<R>' once it's
+    // supported. Remove the unnecessary cast.
     return handler(
-        implZone, _parentDelegate(implZone), zone, error, stackTrace);
+        implZone, _parentDelegate(implZone), zone, error, stackTrace)
+        as Object/*=R*/;
   }
 
-  dynamic run(Zone zone, f()) {
-    _ZoneFunction implementation = _delegationTarget._run;
+  /*=R*/ run/*<R>*/(Zone zone, /*=R*/ f()) {
+    var implementation = _delegationTarget._run;
     _Zone implZone = implementation.zone;
     RunHandler handler = implementation.function;
-    return handler(implZone, _parentDelegate(implZone), zone, f);
+    // TODO(floitsch): make this a generic method call on '<R>' once it's
+    // supported. Remove the unnecessary cast.
+    return handler(implZone, _parentDelegate(implZone), zone, f)
+        as Object/*=R*/;
   }
 
-  dynamic runUnary(Zone zone, f(arg), arg) {
-    _ZoneFunction implementation = _delegationTarget._runUnary;
+  /*=R*/ runUnary/*<R, T>*/(Zone zone, /*=R*/ f(/*=T*/ arg), /*=T*/ arg) {
+    var implementation = _delegationTarget._runUnary;
     _Zone implZone = implementation.zone;
     RunUnaryHandler handler = implementation.function;
+    // TODO(floitsch): make this a generic method call on '<R, T>' once it's
+    // supported. Remove the unnecessary cast.
     return handler(
-        implZone, _parentDelegate(implZone), zone, f, arg);
+        implZone, _parentDelegate(implZone), zone, f, arg) as Object/*=R*/;
   }
 
-  dynamic runBinary(Zone zone, f(arg1, arg2), arg1, arg2) {
-    _ZoneFunction implementation = _delegationTarget._runBinary;
+  /*=R*/ runBinary/*<R, T1, T2>*/(Zone zone,
+      /*=R*/ f(/*=T1*/ arg1, /*=T2*/ arg2), /*=T1*/ arg1, /*=T2*/ arg2) {
+    var implementation = _delegationTarget._runBinary;
     _Zone implZone = implementation.zone;
     RunBinaryHandler handler = implementation.function;
+    // TODO(floitsch): make this a generic method call on '<R, T1, T2>' once
+    // it's supported. Remove the unnecessary cast.
     return handler(
-        implZone, _parentDelegate(implZone), zone, f, arg1, arg2);
+        implZone, _parentDelegate(implZone), zone, f, arg1, arg2)
+        as Object/*=R*/;
   }
 
-  ZoneCallback registerCallback(Zone zone, f()) {
-    _ZoneFunction implementation = _delegationTarget._registerCallback;
+  ZoneCallback/*<R>*/ registerCallback/*<R>*/(Zone zone, /*=R*/ f()) {
+    var implementation = _delegationTarget._registerCallback;
     _Zone implZone = implementation.zone;
     RegisterCallbackHandler handler = implementation.function;
-    return handler(implZone, _parentDelegate(implZone), zone, f);
+    // TODO(floitsch): make this a generic method call on '<R>' once it's
+    // supported. Remove the unnecessary cast.
+    return handler(implZone, _parentDelegate(implZone), zone, f)
+        as Object/*=ZoneCallback<R>*/;
   }
 
-  ZoneUnaryCallback registerUnaryCallback(Zone zone, f(arg)) {
-    _ZoneFunction implementation = _delegationTarget._registerUnaryCallback;
+  ZoneUnaryCallback/*<R, T>*/ registerUnaryCallback/*<R, T>*/(
+      Zone zone, /*=R*/ f(/*=T*/ arg)) {
+    var implementation = _delegationTarget._registerUnaryCallback;
     _Zone implZone = implementation.zone;
     RegisterUnaryCallbackHandler handler = implementation.function;
-    return handler(implZone, _parentDelegate(implZone), zone, f);
+    // TODO(floitsch): make this a generic method call on '<R, T>' once it's
+    // supported. Remove the unnecessary cast.
+    return handler(implZone, _parentDelegate(implZone), zone, f)
+        as Object/*=ZoneUnaryCallback<R, T>*/;
   }
 
-  ZoneBinaryCallback registerBinaryCallback(Zone zone, f(arg1, arg2)) {
-    _ZoneFunction implementation = _delegationTarget._registerBinaryCallback;
+  ZoneBinaryCallback/*<R, T1, T2>*/ registerBinaryCallback/*<R, T1, T2>*/(
+      Zone zone, /*=R*/ f(/*=T1*/ arg1, /*=T2*/ arg2)) {
+    var implementation = _delegationTarget._registerBinaryCallback;
     _Zone implZone = implementation.zone;
     RegisterBinaryCallbackHandler handler = implementation.function;
-    return handler(implZone, _parentDelegate(implZone), zone, f);
+    // TODO(floitsch): make this a generic method call on '<R, T1, T2>' once
+    // it's supported. Remove the unnecessary cast.
+    return handler(implZone, _parentDelegate(implZone), zone, f)
+        as Object/*=ZoneBinaryCallback<R, T1, T2>*/;
   }
 
   AsyncError errorCallback(Zone zone, Object error, StackTrace stackTrace) {
-    _ZoneFunction implementation = _delegationTarget._errorCallback;
+    var implementation = _delegationTarget._errorCallback;
     _Zone implZone = implementation.zone;
     if (identical(implZone, _ROOT_ZONE)) return null;
     ErrorCallbackHandler handler = implementation.function;
@@ -537,28 +558,28 @@
   }
 
   void scheduleMicrotask(Zone zone, f()) {
-    _ZoneFunction implementation = _delegationTarget._scheduleMicrotask;
+    var implementation = _delegationTarget._scheduleMicrotask;
     _Zone implZone = implementation.zone;
     ScheduleMicrotaskHandler handler = implementation.function;
     handler(implZone, _parentDelegate(implZone), zone, f);
   }
 
   Timer createTimer(Zone zone, Duration duration, void f()) {
-    _ZoneFunction implementation = _delegationTarget._createTimer;
+    var implementation = _delegationTarget._createTimer;
     _Zone implZone = implementation.zone;
     CreateTimerHandler handler = implementation.function;
     return handler(implZone, _parentDelegate(implZone), zone, duration, f);
   }
 
   Timer createPeriodicTimer(Zone zone, Duration period, void f(Timer timer)) {
-    _ZoneFunction implementation = _delegationTarget._createPeriodicTimer;
+    var implementation = _delegationTarget._createPeriodicTimer;
     _Zone implZone = implementation.zone;
     CreatePeriodicTimerHandler handler = implementation.function;
     return handler(implZone, _parentDelegate(implZone), zone, period, f);
   }
 
   void print(Zone zone, String line) {
-    _ZoneFunction implementation = _delegationTarget._print;
+    var implementation = _delegationTarget._print;
     _Zone implZone = implementation.zone;
     PrintHandler handler = implementation.function;
     handler(implZone, _parentDelegate(implZone), zone, line);
@@ -566,7 +587,7 @@
 
   Zone fork(Zone zone, ZoneSpecification specification,
             Map zoneValues) {
-    _ZoneFunction implementation = _delegationTarget._fork;
+    var implementation = _delegationTarget._fork;
     _Zone implZone = implementation.zone;
     ForkHandler handler = implementation.function;
     return handler(
@@ -581,21 +602,21 @@
 abstract class _Zone implements Zone {
   const _Zone();
 
-  _ZoneFunction get _runUnary;
-  _ZoneFunction get _run;
-  _ZoneFunction get _runBinary;
-  _ZoneFunction get _registerCallback;
-  _ZoneFunction get _registerUnaryCallback;
-  _ZoneFunction get _registerBinaryCallback;
-  _ZoneFunction get _errorCallback;
-  _ZoneFunction get _scheduleMicrotask;
-  _ZoneFunction get _createTimer;
-  _ZoneFunction get _createPeriodicTimer;
-  _ZoneFunction get _print;
-  _ZoneFunction get _fork;
-  _ZoneFunction get _handleUncaughtError;
+  _ZoneFunction<RunHandler> get _run;
+  _ZoneFunction<RunUnaryHandler> get _runUnary;
+  _ZoneFunction<RunBinaryHandler> get _runBinary;
+  _ZoneFunction<RegisterCallbackHandler> get _registerCallback;
+  _ZoneFunction<RegisterUnaryCallbackHandler> get _registerUnaryCallback;
+  _ZoneFunction<RegisterBinaryCallbackHandler> get _registerBinaryCallback;
+  _ZoneFunction<ErrorCallbackHandler> get _errorCallback;
+  _ZoneFunction<ScheduleMicrotaskHandler> get _scheduleMicrotask;
+  _ZoneFunction<CreateTimerHandler> get _createTimer;
+  _ZoneFunction<CreatePeriodicTimerHandler> get _createPeriodicTimer;
+  _ZoneFunction<PrintHandler> get _print;
+  _ZoneFunction<ForkHandler> get _fork;
+  _ZoneFunction<HandleUncaughtErrorHandler> get _handleUncaughtError;
   _Zone get parent;
-  _ZoneDelegate get _delegate;
+  ZoneDelegate get _delegate;
   Map get _map;
 
   bool inSameErrorZone(Zone otherZone) {
@@ -607,19 +628,19 @@
 class _CustomZone extends _Zone {
   // The actual zone and implementation of each of these
   // inheritable zone functions.
-  _ZoneFunction _runUnary;
-  _ZoneFunction _run;
-  _ZoneFunction _runBinary;
-  _ZoneFunction _registerCallback;
-  _ZoneFunction _registerUnaryCallback;
-  _ZoneFunction _registerBinaryCallback;
-  _ZoneFunction _errorCallback;
-  _ZoneFunction _scheduleMicrotask;
-  _ZoneFunction _createTimer;
-  _ZoneFunction _createPeriodicTimer;
-  _ZoneFunction _print;
-  _ZoneFunction _fork;
-  _ZoneFunction _handleUncaughtError;
+  _ZoneFunction<RunHandler> _run;
+  _ZoneFunction<RunUnaryHandler> _runUnary;
+  _ZoneFunction<RunBinaryHandler> _runBinary;
+  _ZoneFunction<RegisterCallbackHandler> _registerCallback;
+  _ZoneFunction<RegisterUnaryCallbackHandler> _registerUnaryCallback;
+  _ZoneFunction<RegisterBinaryCallbackHandler> _registerBinaryCallback;
+  _ZoneFunction<ErrorCallbackHandler> _errorCallback;
+  _ZoneFunction<ScheduleMicrotaskHandler> _scheduleMicrotask;
+  _ZoneFunction<CreateTimerHandler> _createTimer;
+  _ZoneFunction<CreatePeriodicTimerHandler> _createPeriodicTimer;
+  _ZoneFunction<PrintHandler> _print;
+  _ZoneFunction<ForkHandler> _fork;
+  _ZoneFunction<HandleUncaughtErrorHandler> _handleUncaughtError;
 
   // A cached delegate to this zone.
   ZoneDelegate _delegateCache;
@@ -643,43 +664,50 @@
     // specification, so it will never try to access the (null) parent.
     // All other zones have a non-null parent.
     _run = (specification.run != null)
-        ? new _ZoneFunction(this, specification.run)
+        ? new _ZoneFunction<RunHandler>(this, specification.run)
         : parent._run;
     _runUnary = (specification.runUnary != null)
-        ? new _ZoneFunction(this, specification.runUnary)
+        ? new _ZoneFunction<RunUnaryHandler>(this, specification.runUnary)
         : parent._runUnary;
     _runBinary = (specification.runBinary != null)
-        ? new _ZoneFunction(this, specification.runBinary)
+        ? new _ZoneFunction<RunBinaryHandler>(this, specification.runBinary)
         : parent._runBinary;
     _registerCallback = (specification.registerCallback != null)
-        ? new _ZoneFunction(this, specification.registerCallback)
+        ? new _ZoneFunction<RegisterCallbackHandler>(
+            this, specification.registerCallback)
         : parent._registerCallback;
     _registerUnaryCallback = (specification.registerUnaryCallback != null)
-        ? new _ZoneFunction(this, specification.registerUnaryCallback)
+        ? new _ZoneFunction<RegisterUnaryCallbackHandler>(
+            this, specification.registerUnaryCallback)
         : parent._registerUnaryCallback;
     _registerBinaryCallback = (specification.registerBinaryCallback != null)
-        ? new _ZoneFunction(this, specification.registerBinaryCallback)
+        ? new _ZoneFunction<RegisterBinaryCallbackHandler>(
+            this, specification.registerBinaryCallback)
         : parent._registerBinaryCallback;
     _errorCallback = (specification.errorCallback != null)
-        ? new _ZoneFunction(this, specification.errorCallback)
+        ? new _ZoneFunction<ErrorCallbackHandler>(
+            this, specification.errorCallback)
         : parent._errorCallback;
     _scheduleMicrotask = (specification.scheduleMicrotask != null)
-        ? new _ZoneFunction(this, specification.scheduleMicrotask)
+        ? new _ZoneFunction<ScheduleMicrotaskHandler>(
+            this, specification.scheduleMicrotask)
         : parent._scheduleMicrotask;
     _createTimer = (specification.createTimer != null)
-        ? new _ZoneFunction(this, specification.createTimer)
+        ? new _ZoneFunction<CreateTimerHandler>(this, specification.createTimer)
         : parent._createTimer;
     _createPeriodicTimer = (specification.createPeriodicTimer != null)
-        ? new _ZoneFunction(this, specification.createPeriodicTimer)
+        ? new _ZoneFunction<CreatePeriodicTimerHandler>(
+            this, specification.createPeriodicTimer)
         : parent._createPeriodicTimer;
     _print = (specification.print != null)
-        ? new _ZoneFunction(this, specification.print)
+        ? new _ZoneFunction<PrintHandler>(this, specification.print)
         : parent._print;
     _fork = (specification.fork != null)
-        ? new _ZoneFunction(this, specification.fork)
+        ? new _ZoneFunction<ForkHandler>(this, specification.fork)
         : parent._fork;
     _handleUncaughtError = (specification.handleUncaughtError != null)
-        ? new _ZoneFunction(this, specification.handleUncaughtError)
+        ? new _ZoneFunction<HandleUncaughtErrorHandler>(
+            this, specification.handleUncaughtError)
         : parent._handleUncaughtError;
   }
 
@@ -691,7 +719,7 @@
    */
   Zone get errorZone => _handleUncaughtError.zone;
 
-  dynamic runGuarded(f()) {
+  /*=R*/ runGuarded/*<R>*/(/*=R*/ f()) {
     try {
       return run(f);
     } catch (e, s) {
@@ -699,7 +727,7 @@
     }
   }
 
-  dynamic runUnaryGuarded(f(arg), arg) {
+  /*=R*/ runUnaryGuarded/*<R, T>*/(/*=R*/ f(/*=T*/ arg), /*=T*/ arg) {
     try {
       return runUnary(f, arg);
     } catch (e, s) {
@@ -707,7 +735,8 @@
     }
   }
 
-  dynamic runBinaryGuarded(f(arg1, arg2), arg1, arg2) {
+  /*=R*/ runBinaryGuarded/*<R, T1, T2>*/(
+      /*=R*/ f(/*=T1*/ arg1, /*=T2*/ arg2), /*=T1*/ arg1, /*=T2*/ arg2) {
     try {
       return runBinary(f, arg1, arg2);
     } catch (e, s) {
@@ -715,8 +744,9 @@
     }
   }
 
-  ZoneCallback bindCallback(f(), { bool runGuarded: true }) {
-    ZoneCallback registered = registerCallback(f);
+  ZoneCallback/*<R>*/ bindCallback/*<R>*/(
+      /*=R*/ f(), { bool runGuarded: true }) {
+    var registered = registerCallback(f);
     if (runGuarded) {
       return () => this.runGuarded(registered);
     } else {
@@ -724,8 +754,9 @@
     }
   }
 
-  ZoneUnaryCallback bindUnaryCallback(f(arg), { bool runGuarded: true }) {
-    ZoneUnaryCallback registered = registerUnaryCallback(f);
+  ZoneUnaryCallback/*<R, T>*/ bindUnaryCallback/*<R, T>*/(
+      /*=R*/ f(/*=T*/ arg), { bool runGuarded: true }) {
+    var registered = registerUnaryCallback(f);
     if (runGuarded) {
       return (arg) => this.runUnaryGuarded(registered, arg);
     } else {
@@ -733,9 +764,9 @@
     }
   }
 
-  ZoneBinaryCallback bindBinaryCallback(
-      f(arg1, arg2), { bool runGuarded: true }) {
-    ZoneBinaryCallback registered = registerBinaryCallback(f);
+  ZoneBinaryCallback/*<R, T1, T2>*/ bindBinaryCallback/*<R, T1, T2>*/(
+      /*=R*/ f(/*=T1*/ arg1, /*=T2*/ arg2), { bool runGuarded: true }) {
+    var registered = registerBinaryCallback(f);
     if (runGuarded) {
       return (arg1, arg2) => this.runBinaryGuarded(registered, arg1, arg2);
     } else {
@@ -764,17 +795,20 @@
 
   // Methods that can be customized by the zone specification.
 
-  dynamic handleUncaughtError(error, StackTrace stackTrace) {
-    _ZoneFunction implementation = this._handleUncaughtError;
+  /*=R*/ handleUncaughtError/*<R>*/(error, StackTrace stackTrace) {
+    var implementation = this._handleUncaughtError;
     assert(implementation != null);
     ZoneDelegate parentDelegate = _parentDelegate(implementation.zone);
     HandleUncaughtErrorHandler handler = implementation.function;
+    // TODO(floitsch): make this a generic method call on '<R>' once it's
+    // supported. Remove the unnecessary cast.
     return handler(
-        implementation.zone, parentDelegate, this, error, stackTrace);
+        implementation.zone, parentDelegate, this, error, stackTrace)
+        as Object/*=R*/;
   }
 
   Zone fork({ZoneSpecification specification, Map zoneValues}) {
-    _ZoneFunction implementation = this._fork;
+    var implementation = this._fork;
     assert(implementation != null);
     ZoneDelegate parentDelegate = _parentDelegate(implementation.zone);
     ForkHandler handler = implementation.function;
@@ -782,57 +816,78 @@
                    specification, zoneValues);
   }
 
-  dynamic run(f()) {
-    _ZoneFunction implementation = this._run;
+  /*=R*/ run/*<R>*/(/*=R*/ f()) {
+    var implementation = this._run;
     assert(implementation != null);
     ZoneDelegate parentDelegate = _parentDelegate(implementation.zone);
     RunHandler handler = implementation.function;
-    return handler(implementation.zone, parentDelegate, this, f);
+    // TODO(floitsch): make this a generic method call on '<R>' once it's
+    // supported. Remove the unnecessary cast.
+    return handler(implementation.zone, parentDelegate, this, f)
+        as Object/*=R*/;
   }
 
-  dynamic runUnary(f(arg), arg) {
-    _ZoneFunction implementation = this._runUnary;
+  /*=R*/ runUnary/*<R, T>*/(/*=R*/ f(/*=T*/ arg), /*=T*/ arg) {
+    var implementation = this._runUnary;
     assert(implementation != null);
     ZoneDelegate parentDelegate = _parentDelegate(implementation.zone);
     RunUnaryHandler handler = implementation.function;
-    return handler(implementation.zone, parentDelegate, this, f, arg);
+    // TODO(floitsch): make this a generic method call on '<R, T>' once it's
+    // supported. Remove the unnecessary cast.
+    return handler(implementation.zone, parentDelegate, this, f, arg)
+        as Object/*=R*/;
   }
 
-  dynamic runBinary(f(arg1, arg2), arg1, arg2) {
-    _ZoneFunction implementation = this._runBinary;
+  /*=R*/ runBinary/*<R, T1, T2>*/(
+      /*=R*/ f(/*=T1*/ arg1, /*=T2*/ arg2), /*=T1*/ arg1, /*=T2*/ arg2) {
+    var implementation = this._runBinary;
     assert(implementation != null);
     ZoneDelegate parentDelegate = _parentDelegate(implementation.zone);
     RunBinaryHandler handler = implementation.function;
+    // TODO(floitsch): make this a generic method call on '<R, T1, T2>' once
+    // it's supported. Remove the unnecessary cast.
     return handler(
-        implementation.zone, parentDelegate, this, f, arg1, arg2);
+        implementation.zone, parentDelegate, this, f, arg1, arg2)
+        as Object/*=R*/;
   }
 
-  ZoneCallback registerCallback(f()) {
-    _ZoneFunction implementation = this._registerCallback;
+  ZoneCallback/*<R>*/ registerCallback/*<R>*/(/*=R*/ callback()) {
+    var implementation = this._registerCallback;
     assert(implementation != null);
     ZoneDelegate parentDelegate = _parentDelegate(implementation.zone);
     RegisterCallbackHandler handler = implementation.function;
-    return handler(implementation.zone, parentDelegate, this, f);
+    // TODO(floitsch): make this a generic method call on '<R>' once it's
+    // supported. Remove the unnecessary cast.
+    return handler(implementation.zone, parentDelegate, this, callback)
+        as Object/*=ZoneCallback<R>*/;
   }
 
-  ZoneUnaryCallback registerUnaryCallback(f(arg)) {
-    _ZoneFunction implementation = this._registerUnaryCallback;
+  ZoneUnaryCallback/*<R, T>*/ registerUnaryCallback/*<R, T>*/(
+      /*=R*/ callback(/*=T*/ arg)) {
+    var implementation = this._registerUnaryCallback;
     assert(implementation != null);
     ZoneDelegate parentDelegate = _parentDelegate(implementation.zone);
     RegisterUnaryCallbackHandler handler = implementation.function;
-    return handler(implementation.zone, parentDelegate, this, f);
+    // TODO(floitsch): make this a generic method call on '<R, T>' once it's
+    // supported. Remove the unnecessary cast.
+    return handler(implementation.zone, parentDelegate, this, callback)
+        as Object/*=ZoneUnaryCallback<R, T>*/;
   }
 
-  ZoneBinaryCallback registerBinaryCallback(f(arg1, arg2)) {
-    _ZoneFunction implementation = this._registerBinaryCallback;
+  ZoneBinaryCallback/*<R, T1, T2>*/ registerBinaryCallback/*<R, T1, T2>*/(
+      /*=R*/ callback(/*=T1*/ arg1, /*=T2*/ arg2)) {
+    var implementation = this._registerBinaryCallback;
     assert(implementation != null);
     ZoneDelegate parentDelegate = _parentDelegate(implementation.zone);
     RegisterBinaryCallbackHandler handler = implementation.function;
-    return handler(implementation.zone, parentDelegate, this, f);
+    // TODO(floitsch): make this a generic method call on '<R, T1, T2>' once
+    // it's supported. Remove the unnecessary cast.
+    return handler(implementation.zone, parentDelegate, this, callback)
+        as Object/*=ZoneBinaryCallback<R, T1, T2>*/;
   }
 
   AsyncError errorCallback(Object error, StackTrace stackTrace) {
-    final _ZoneFunction implementation = this._errorCallback;
+    var implementation = this._errorCallback;
     assert(implementation != null);
     final Zone implementationZone = implementation.zone;
     if (identical(implementationZone, _ROOT_ZONE)) return null;
@@ -843,7 +898,7 @@
   }
 
   void scheduleMicrotask(void f()) {
-    _ZoneFunction implementation = this._scheduleMicrotask;
+    var implementation = this._scheduleMicrotask;
     assert(implementation != null);
     ZoneDelegate parentDelegate = _parentDelegate(implementation.zone);
     ScheduleMicrotaskHandler handler = implementation.function;
@@ -851,7 +906,7 @@
   }
 
   Timer createTimer(Duration duration, void f()) {
-    _ZoneFunction implementation = this._createTimer;
+    var implementation = this._createTimer;
     assert(implementation != null);
     ZoneDelegate parentDelegate = _parentDelegate(implementation.zone);
     CreateTimerHandler handler = implementation.function;
@@ -859,7 +914,7 @@
   }
 
   Timer createPeriodicTimer(Duration duration, void f(Timer timer)) {
-    _ZoneFunction implementation = this._createPeriodicTimer;
+    var implementation = this._createPeriodicTimer;
     assert(implementation != null);
     ZoneDelegate parentDelegate = _parentDelegate(implementation.zone);
     CreatePeriodicTimerHandler handler = implementation.function;
@@ -868,7 +923,7 @@
   }
 
   void print(String line) {
-    _ZoneFunction implementation = this._print;
+    var implementation = this._print;
     assert(implementation != null);
     ZoneDelegate parentDelegate = _parentDelegate(implementation.zone);
     PrintHandler handler = implementation.function;
@@ -876,7 +931,7 @@
   }
 }
 
-void _rootHandleUncaughtError(
+/*=R*/ _rootHandleUncaughtError/*<R>*/(
     Zone self, ZoneDelegate parent, Zone zone, error, StackTrace stackTrace) {
   _schedulePriorityAsyncCallback(() {
     if (error == null) error = new NullThrownError();
@@ -887,7 +942,7 @@
 
 external void _rethrow(Object error, StackTrace stackTrace);
 
-dynamic _rootRun(Zone self, ZoneDelegate parent, Zone zone, f()) {
+/*=R*/ _rootRun/*<R>*/(Zone self, ZoneDelegate parent, Zone zone, /*=R*/ f()) {
   if (Zone._current == zone) return f();
 
   Zone old = Zone._enter(zone);
@@ -898,7 +953,8 @@
   }
 }
 
-dynamic _rootRunUnary(Zone self, ZoneDelegate parent, Zone zone, f(arg), arg) {
+/*=R*/ _rootRunUnary/*<R, T>*/(Zone self, ZoneDelegate parent, Zone zone,
+    /*=R*/ f(/*=T*/ arg), /*=T*/ arg) {
   if (Zone._current == zone) return f(arg);
 
   Zone old = Zone._enter(zone);
@@ -909,8 +965,8 @@
   }
 }
 
-dynamic _rootRunBinary(Zone self, ZoneDelegate parent, Zone zone,
-                       f(arg1, arg2), arg1, arg2) {
+/*=R*/ _rootRunBinary/*<R, T1, T2>*/(Zone self, ZoneDelegate parent, Zone zone,
+    /*=R*/ f(/*=T1*/ arg1, /*=T2*/ arg2), /*=T1*/ arg1, /*=T2*/ arg2) {
   if (Zone._current == zone) return f(arg1, arg2);
 
   Zone old = Zone._enter(zone);
@@ -921,18 +977,19 @@
   }
 }
 
-ZoneCallback _rootRegisterCallback(
-    Zone self, ZoneDelegate parent, Zone zone, f()) {
+ZoneCallback/*<R>*/ _rootRegisterCallback/*<R>*/(
+    Zone self, ZoneDelegate parent, Zone zone, /*=R*/ f()) {
   return f;
 }
 
-ZoneUnaryCallback _rootRegisterUnaryCallback(
-    Zone self, ZoneDelegate parent, Zone zone, f(arg)) {
+ZoneUnaryCallback/*<R, T>*/ _rootRegisterUnaryCallback/*<R, T>*/(
+    Zone self, ZoneDelegate parent, Zone zone, /*=R*/ f(/*=T*/ arg)) {
   return f;
 }
 
-ZoneBinaryCallback _rootRegisterBinaryCallback(
-    Zone self, ZoneDelegate parent, Zone zone, f(arg1, arg2)) {
+ZoneBinaryCallback/*<R, T1, T2>*/ _rootRegisterBinaryCallback/*<R, T1, T2>*/(
+    Zone self, ZoneDelegate parent, Zone zone,
+    /*=R*/ f(/*=T1*/ arg1, /*=T2*/ arg2)) {
   return f;
 }
 
@@ -961,7 +1018,8 @@
     Zone self, ZoneDelegate parent, Zone zone,
     Duration duration, void callback(Timer timer)) {
   if (!identical(_ROOT_ZONE, zone)) {
-    callback = zone.bindUnaryCallback(callback);
+    // TODO(floitsch): the return type should be 'void'.
+    callback = zone.bindUnaryCallback/*<dynamic, Timer>*/(callback);
   }
   return Timer._createPeriodicTimer(duration, callback);
 }
@@ -1004,32 +1062,37 @@
 class _RootZone extends _Zone {
   const _RootZone();
 
-  _ZoneFunction get _run =>
-      const _ZoneFunction(_ROOT_ZONE, _rootRun);
-  _ZoneFunction get _runUnary =>
-      const _ZoneFunction(_ROOT_ZONE, _rootRunUnary);
-  _ZoneFunction get _runBinary =>
-      const _ZoneFunction(_ROOT_ZONE, _rootRunBinary);
-  _ZoneFunction get _registerCallback =>
-      const _ZoneFunction(_ROOT_ZONE, _rootRegisterCallback);
-  _ZoneFunction get _registerUnaryCallback =>
-      const _ZoneFunction(_ROOT_ZONE, _rootRegisterUnaryCallback);
-  _ZoneFunction get _registerBinaryCallback =>
-      const _ZoneFunction(_ROOT_ZONE, _rootRegisterBinaryCallback);
-  _ZoneFunction get _errorCallback =>
-      const _ZoneFunction(_ROOT_ZONE, _rootErrorCallback);
-  _ZoneFunction get _scheduleMicrotask =>
-      const _ZoneFunction(_ROOT_ZONE, _rootScheduleMicrotask);
-  _ZoneFunction get _createTimer =>
-      const _ZoneFunction(_ROOT_ZONE, _rootCreateTimer);
-  _ZoneFunction get _createPeriodicTimer =>
-      const _ZoneFunction(_ROOT_ZONE, _rootCreatePeriodicTimer);
-  _ZoneFunction get _print =>
-      const _ZoneFunction(_ROOT_ZONE, _rootPrint);
-  _ZoneFunction get _fork =>
-      const _ZoneFunction(_ROOT_ZONE, _rootFork);
-  _ZoneFunction get _handleUncaughtError =>
-      const _ZoneFunction(_ROOT_ZONE, _rootHandleUncaughtError);
+  _ZoneFunction<RunHandler> get _run =>
+      const _ZoneFunction<RunHandler>(_ROOT_ZONE, _rootRun);
+  _ZoneFunction<RunUnaryHandler> get _runUnary =>
+      const _ZoneFunction<RunUnaryHandler>(_ROOT_ZONE, _rootRunUnary);
+  _ZoneFunction<RunBinaryHandler> get _runBinary =>
+      const _ZoneFunction<RunBinaryHandler>(_ROOT_ZONE, _rootRunBinary);
+  _ZoneFunction<RegisterCallbackHandler> get _registerCallback =>
+      const _ZoneFunction<RegisterCallbackHandler>(
+          _ROOT_ZONE, _rootRegisterCallback);
+  _ZoneFunction<RegisterUnaryCallbackHandler> get _registerUnaryCallback =>
+      const _ZoneFunction<RegisterUnaryCallbackHandler>(
+          _ROOT_ZONE, _rootRegisterUnaryCallback);
+  _ZoneFunction<RegisterBinaryCallbackHandler> get _registerBinaryCallback =>
+      const _ZoneFunction<RegisterBinaryCallbackHandler>(
+          _ROOT_ZONE, _rootRegisterBinaryCallback);
+  _ZoneFunction<ErrorCallbackHandler> get _errorCallback =>
+      const _ZoneFunction<ErrorCallbackHandler>(_ROOT_ZONE, _rootErrorCallback);
+  _ZoneFunction<ScheduleMicrotaskHandler> get _scheduleMicrotask =>
+      const _ZoneFunction<ScheduleMicrotaskHandler>(
+          _ROOT_ZONE, _rootScheduleMicrotask);
+  _ZoneFunction<CreateTimerHandler> get _createTimer =>
+      const _ZoneFunction<CreateTimerHandler>(_ROOT_ZONE, _rootCreateTimer);
+  _ZoneFunction<CreatePeriodicTimerHandler> get _createPeriodicTimer =>
+      const _ZoneFunction<CreatePeriodicTimerHandler>(_ROOT_ZONE, _rootCreatePeriodicTimer);
+  _ZoneFunction<PrintHandler> get _print =>
+      const _ZoneFunction<PrintHandler>(_ROOT_ZONE, _rootPrint);
+  _ZoneFunction<ForkHandler> get _fork =>
+      const _ZoneFunction<ForkHandler>(_ROOT_ZONE, _rootFork);
+  _ZoneFunction<HandleUncaughtErrorHandler> get _handleUncaughtError =>
+      const _ZoneFunction<HandleUncaughtErrorHandler>(
+          _ROOT_ZONE, _rootHandleUncaughtError);
 
   // The parent zone.
   _Zone get parent => null;
@@ -1058,61 +1121,65 @@
 
   // Zone interface.
 
-  dynamic runGuarded(f()) {
+  /*=R*/ runGuarded/*<R>*/(/*=R*/ f()) {
     try {
       if (identical(_ROOT_ZONE, Zone._current)) {
         return f();
       }
-      return _rootRun(null, null, this, f);
+      return _rootRun/*<R>*/(null, null, this, f);
     } catch (e, s) {
-      return handleUncaughtError(e, s);
+      return handleUncaughtError/*<R>*/(e, s);
     }
   }
 
-  dynamic runUnaryGuarded(f(arg), arg) {
+  /*=R*/ runUnaryGuarded/*<R, T>*/(/*=R*/ f(/*=T*/ arg), /*=T*/ arg) {
     try {
       if (identical(_ROOT_ZONE, Zone._current)) {
         return f(arg);
       }
-      return _rootRunUnary(null, null, this, f, arg);
+      return _rootRunUnary/*<R, T>*/(null, null, this, f, arg);
     } catch (e, s) {
-      return handleUncaughtError(e, s);
+      return handleUncaughtError/*<R>*/(e, s);
     }
   }
 
-  dynamic runBinaryGuarded(f(arg1, arg2), arg1, arg2) {
+  /*=R*/ runBinaryGuarded/*<R, T1, T2>*/(
+      /*=R*/ f(/*=T1*/ arg1, /*=T2*/ arg2), /*=T1*/ arg1, /*=T2*/ arg2) {
     try {
       if (identical(_ROOT_ZONE, Zone._current)) {
         return f(arg1, arg2);
       }
-      return _rootRunBinary(null, null, this, f, arg1, arg2);
+      return _rootRunBinary/*<R, T1, T2>*/(null, null, this, f, arg1, arg2);
     } catch (e, s) {
-      return handleUncaughtError(e, s);
+      return handleUncaughtError/*<R>*/(e, s);
     }
   }
 
-  ZoneCallback bindCallback(f(), { bool runGuarded: true }) {
+  ZoneCallback/*<R>*/ bindCallback/*<R>*/(
+      /*=R*/ f(), { bool runGuarded: true }) {
     if (runGuarded) {
-      return () => this.runGuarded(f);
+      return () => this.runGuarded/*<R>*/(f);
     } else {
-      return () => this.run(f);
+      return () => this.run/*<R>*/(f);
     }
   }
 
-  ZoneUnaryCallback bindUnaryCallback(f(arg), { bool runGuarded: true }) {
+  ZoneUnaryCallback/*<R, T>*/ bindUnaryCallback/*<R, T>*/(
+      /*=R*/ f(/*=T*/ arg), { bool runGuarded: true }) {
     if (runGuarded) {
-      return (arg) => this.runUnaryGuarded(f, arg);
+      return (arg) => this.runUnaryGuarded/*<R, T>*/(f, arg);
     } else {
-      return (arg) => this.runUnary(f, arg);
+      return (arg) => this.runUnary/*<R, T>*/(f, arg);
     }
   }
 
-  ZoneBinaryCallback bindBinaryCallback(
-      f(arg1, arg2), { bool runGuarded: true }) {
+  ZoneBinaryCallback/*<R, T1, T2>*/ bindBinaryCallback/*<R, T1, T2>*/(
+      /*=R*/ f(/*=T1*/ arg1, /*=T2*/ arg2), { bool runGuarded: true }) {
     if (runGuarded) {
-      return (arg1, arg2) => this.runBinaryGuarded(f, arg1, arg2);
+      return (arg1, arg2) =>
+          this.runBinaryGuarded/*<R, T1, T2>*/(f, arg1, arg2);
     } else {
-      return (arg1, arg2) => this.runBinary(f, arg1, arg2);
+      return (arg1, arg2) => this.runBinary/*<R, T1, T2>*/(f, arg1, arg2);
     }
   }
 
@@ -1120,7 +1187,7 @@
 
   // Methods that can be customized by the zone specification.
 
-  dynamic handleUncaughtError(error, StackTrace stackTrace) {
+  /*=R*/ handleUncaughtError/*<R>*/(error, StackTrace stackTrace) {
     return _rootHandleUncaughtError(null, null, this, error, stackTrace);
   }
 
@@ -1128,26 +1195,29 @@
     return _rootFork(null, null, this, specification, zoneValues);
   }
 
-  dynamic run(f()) {
+  /*=R*/ run/*<R>*/(/*=R*/ f()) {
     if (identical(Zone._current, _ROOT_ZONE)) return f();
     return _rootRun(null, null, this, f);
   }
 
-  dynamic runUnary(f(arg), arg) {
+  /*=R*/ runUnary/*<R, T>*/(/*=R*/ f(/*=T*/ arg), /*=T*/ arg) {
     if (identical(Zone._current, _ROOT_ZONE)) return f(arg);
     return _rootRunUnary(null, null, this, f, arg);
   }
 
-  dynamic runBinary(f(arg1, arg2), arg1, arg2) {
+  /*=R*/ runBinary/*<R, T1, T2>*/(
+      /*=R*/ f(/*=T1*/ arg1, /*=T2*/ arg2), /*=T1*/ arg1, /*=T2*/ arg2) {
     if (identical(Zone._current, _ROOT_ZONE)) return f(arg1, arg2);
     return _rootRunBinary(null, null, this, f, arg1, arg2);
   }
 
-  ZoneCallback registerCallback(f()) => f;
+  ZoneCallback/*<R>*/ registerCallback/*<R>*/(/*=R*/ f()) => f;
 
-  ZoneUnaryCallback registerUnaryCallback(f(arg)) => f;
+  ZoneUnaryCallback/*<R, T>*/ registerUnaryCallback/*<R, T>*/(
+      /*=R*/ f(/*=T*/ arg)) => f;
 
-  ZoneBinaryCallback registerBinaryCallback(f(arg1, arg2)) => f;
+  ZoneBinaryCallback/*<R, T1, T2>*/ registerBinaryCallback/*<R, T1, T2>*/(
+      /*=R*/ f(/*=T1*/ arg1, /*=T2*/ arg2)) => f;
 
   AsyncError errorCallback(Object error, StackTrace stackTrace) => null;
 
@@ -1195,7 +1265,7 @@
  *       new Future(() { throw "asynchronous error"; });
  *     }, onError: print);  // Will print "asynchronous error".
  */
-dynamic runZoned(body(),
+/*=R*/ runZoned/*<R>*/(/*=R*/ body(),
                  { Map zoneValues,
                    ZoneSpecification zoneSpecification,
                    Function onError }) {
@@ -1204,7 +1274,7 @@
     errorHandler = (Zone self, ZoneDelegate parent, Zone zone,
                     error, StackTrace stackTrace) {
       try {
-        if (onError is ZoneBinaryCallback) {
+        if (onError is ZoneBinaryCallback<dynamic/*=R*/, dynamic, StackTrace>) {
           return self.parent.runBinary(onError, error, stackTrace);
         }
         return self.parent.runUnary(onError, error);
diff --git a/sdk/lib/collection/linked_hash_set.dart b/sdk/lib/collection/linked_hash_set.dart
index a149692..e087b5f 100644
--- a/sdk/lib/collection/linked_hash_set.dart
+++ b/sdk/lib/collection/linked_hash_set.dart
@@ -102,7 +102,7 @@
    *     Iterable<SuperType> tmp = superSet.where((e) => e is SubType);
    *     Set<SubType> subSet = new LinkedHashSet<SubType>.from(tmp);
    */
-  factory LinkedHashSet.from(Iterable<E> elements) {
+  factory LinkedHashSet.from(Iterable elements) {
     LinkedHashSet<E> result = new LinkedHashSet<E>();
     for (final E element in elements) {
       result.add(element);
diff --git a/sdk/lib/convert/base64.dart b/sdk/lib/convert/base64.dart
index ff3a439..f3d7019 100644
--- a/sdk/lib/convert/base64.dart
+++ b/sdk/lib/convert/base64.dart
@@ -28,9 +28,9 @@
  *
  * Examples:
  *
- *     var encoded = BASE64.encode([0x62, 0x6c, 0xc3, 0xa5, 0x62, 0xc3, 0xa6,
- *                                  0x72, 0x67, 0x72, 0xc3, 0xb8, 0x64]);
- *     var decoded = BASE64.decode("YmzDpWLDpnJncsO4ZAo=");
+ *     var encoded = BASE64URL.encode([0x62, 0x6c, 0xc3, 0xa5, 0x62, 0xc3, 0xa6,
+ *                                     0x72, 0x67, 0x72, 0xc3, 0xb8, 0x64]);
+ *     var decoded = BASE64URL.decode("YmzDpWLDpnJncsO4ZAo=");
  */
 const Base64Codec BASE64URL = const Base64Codec.urlSafe();
 
diff --git a/sdk/lib/convert/chunked_conversion.dart b/sdk/lib/convert/chunked_conversion.dart
index a36c505..95e561c 100644
--- a/sdk/lib/convert/chunked_conversion.dart
+++ b/sdk/lib/convert/chunked_conversion.dart
@@ -122,7 +122,7 @@
    * The input sink for new data. All data that is received with
    * [handleData] is added into this sink.
    */
-  ChunkedConversionSink<S> _chunkedSink;
+  final ChunkedConversionSink<S> _chunkedSink;
 
   _ConverterStreamEventSink(
       Converter/*=ChunkedConverter<dynamic, dynamic, S, T>*/ converter,
diff --git a/sdk/lib/core/iterable.dart b/sdk/lib/core/iterable.dart
index 4f45744..a1967b7 100644
--- a/sdk/lib/core/iterable.dart
+++ b/sdk/lib/core/iterable.dart
@@ -106,9 +106,6 @@
    *
    * The empty iterable has no elements, and iterating it always stops
    * immediately.
-   *
-   * An empty iterable can be used in places where you always that
-   * the iterable you would otherwise create is empty.
    */
   const factory Iterable.empty() = EmptyIterable<E>;
 
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 4ca1158..7be7e5d 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -43374,7 +43374,10 @@
   if (callback == null) return null;
   // TODO(jacobr): we cast to _wrapZoneCallback/*<A, R>*/ to hack around missing
   // generic method support in zones.
-  return Zone.current.bindUnaryCallback(callback, runGuarded: true) as _wrapZoneCallback/*<A, R>*/;
+  // ignore: STRONG_MODE_DOWN_CAST_COMPOSITE
+  _wrapZoneCallback/*<A, R>*/ wrapped =
+      Zone.current.bindUnaryCallback(callback, runGuarded: true);
+  return wrapped;
 }
 
 _wrapZoneBinaryCallback/*<A, B, R>*/ _wrapBinaryZone/*<A, B, R>*/(_wrapZoneBinaryCallback/*<A, B, R>*/ callback) {
@@ -43382,7 +43385,10 @@
   if (callback == null) return null;
   // We cast to _wrapZoneBinaryCallback/*<A, B, R>*/ to hack around missing
   // generic method support in zones.
-  return Zone.current.bindBinaryCallback(callback, runGuarded: true) as _wrapZoneBinaryCallback/*<A, B, R>*/;
+  // ignore: STRONG_MODE_DOWN_CAST_COMPOSITE
+  _wrapZoneBinaryCallback/*<A, B, R>*/ wrapped =
+      Zone.current.bindBinaryCallback(callback, runGuarded: true);
+  return wrapped;
 }
 
 /**
@@ -43613,10 +43619,21 @@
       sanitizeNode(node, parent);
 
       var child = node.lastChild;
-      while (child != null) {
-        // Child may be removed during the walk.
-        var nextChild = child.previousNode;
-        walk(child, node);
+      while (null != child) {
+        var nextChild;
+        try {
+          // Child may be removed during the walk, and we may not
+          // even be able to get its previousNode.
+          nextChild = child.previousNode;
+        } catch (e) {
+          // Child appears bad, remove it. We want to check the rest of the
+          // children of node and, but we have no way of getting to the next
+          // child, so start again from the last child.
+          _removeNode(child, node);
+          child = null;
+          nextChild = node.lastChild;
+        }
+        if (child != null) walk(child, node);
         child = nextChild;
       }
     }
diff --git a/sdk/lib/html/dartium/html_dartium.dart b/sdk/lib/html/dartium/html_dartium.dart
index 78de601..6d8873e 100644
--- a/sdk/lib/html/dartium/html_dartium.dart
+++ b/sdk/lib/html/dartium/html_dartium.dart
@@ -47194,10 +47194,21 @@
       sanitizeNode(node, parent);
 
       var child = node.lastChild;
-      while (child != null) {
-        // Child may be removed during the walk.
-        var nextChild = child.previousNode;
-        walk(child, node);
+      while (null != child) {
+        var nextChild;
+        try {
+          // Child may be removed during the walk, and we may not
+          // even be able to get its previousNode.
+          nextChild = child.previousNode;
+        } catch (e) {
+          // Child appears bad, remove it. We want to check the rest of the
+          // children of node and, but we have no way of getting to the next
+          // child, so start again from the last child.
+          _removeNode(child, node);
+          child = null;
+          nextChild = node.lastChild;
+        }
+        if (child != null) walk(child, node);
         child = nextChild;
       }
     }
@@ -47852,7 +47863,10 @@
   if (callback == null) return null;
   // TODO(jacobr): we cast to _wrapZoneCallback/*<A, R>*/ to hack around missing
   // generic method support in zones.
-  return Zone.current.bindUnaryCallback(callback, runGuarded: true) as _wrapZoneCallback/*<A, R>*/;
+  // ignore: STRONG_MODE_DOWN_CAST_COMPOSITE
+  _wrapZoneCallback/*<A, R>*/ wrapped =
+      Zone.current.bindUnaryCallback(callback, runGuarded: true);
+  return wrapped;
 }
 
 _wrapZoneBinaryCallback/*<A, B, R>*/ _wrapBinaryZone/*<A, B, R>*/(_wrapZoneBinaryCallback/*<A, B, R>*/ callback) {
@@ -47860,7 +47874,10 @@
   if (callback == null) return null;
   // We cast to _wrapZoneBinaryCallback/*<A, B, R>*/ to hack around missing
   // generic method support in zones.
-  return Zone.current.bindBinaryCallback(callback, runGuarded: true) as _wrapZoneBinaryCallback/*<A, B, R>*/;
+  // ignore: STRONG_MODE_DOWN_CAST_COMPOSITE
+  _wrapZoneBinaryCallback/*<A, B, R>*/ wrapped =
+      Zone.current.bindBinaryCallback(callback, runGuarded: true);
+  return wrapped;
 }
 
 /**
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index 0be5cac..f8105cc 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -656,7 +656,6 @@
 LayoutTests/fast/canvas/webgl/buffer-data-array-buffer_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/context-attributes-alpha-depth-stencil-antialias-t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/context-lost-restored_t01: Pass, Timeout # Please triage this failure
-LayoutTests/fast/canvas/webgl/copy-tex-image-and-sub-image-2d_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/css-webkit-canvas-repaint_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/css-webkit-canvas_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/framebuffer-bindings-unaffected-on-resize_t01: RuntimeError # Please triage this failure
@@ -1472,9 +1471,15 @@
 WebPlatformTest/shadow-dom/events/event-retargeting/test-001_t01: RuntimeError # Please triage this failure
 WebPlatformTest/shadow-dom/events/event-retargeting/test-002_t01: RuntimeError # Please triage this failure
 WebPlatformTest/shadow-dom/events/event-retargeting/test-004_t01: RuntimeError # Please triage this failure
-WebPlatformTest/shadow-dom/events/events-that-are-always-stopped/test-004_t01: RuntimeError # Please triage this failure
-WebPlatformTest/shadow-dom/events/events-that-are-always-stopped/test-005_t01: RuntimeError # Please triage this failure
-WebPlatformTest/shadow-dom/events/events-that-are-always-stopped/test-007_t01: RuntimeError # Please triage this failure
+WebPlatformTest/shadow-dom/events/events-that-are-always-stopped/test-001_t01: Pass, RuntimeError # Issue 52 
+WebPlatformTest/shadow-dom/events/events-that-are-always-stopped/test-002_t01: Pass, RuntimeError # Issue 52
+WebPlatformTest/shadow-dom/events/events-that-are-always-stopped/test-003_t01: Pass, RuntimeError # Issue 52
+WebPlatformTest/shadow-dom/events/events-that-are-always-stopped/test-004_t01: Pass, RuntimeError # Issue 52
+WebPlatformTest/shadow-dom/events/events-that-are-always-stopped/test-005_t01: Pass, RuntimeError # Issue 52
+WebPlatformTest/shadow-dom/events/events-that-are-always-stopped/test-006_t01: Pass, RuntimeError # Issue 52
+WebPlatformTest/shadow-dom/events/events-that-are-always-stopped/test-007_t01: Pass, RuntimeError # Issue 52
+WebPlatformTest/shadow-dom/events/events-that-are-always-stopped/test-008_t01: Pass, RuntimeError # Issue 52
+WebPlatformTest/shadow-dom/events/events-that-are-always-stopped/test-009_t01: Pass, RuntimeError # Issue 52
 WebPlatformTest/shadow-dom/events/retargeting-focus-events/test-001_t01: Skip # Times out. Please triage this failure
 WebPlatformTest/shadow-dom/events/retargeting-focus-events/test-001_t02: Skip # Times out. Please triage this failure
 WebPlatformTest/shadow-dom/events/retargeting-focus-events/test-001_t05: Skip # Times out. Please triage this failure
@@ -1596,6 +1601,7 @@
 LayoutTests/fast/canvas/webgl/context-destroyed-crash_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/context-lost_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/context-lost-restored_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/canvas/webgl/copy-tex-image-and-sub-image-2d_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/draw-arrays-out-of-bounds_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/draw-elements-out-of-bounds_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/draw-webgl-to-canvas-2d_t01: RuntimeError # Please triage this failure
@@ -2080,6 +2086,7 @@
 LayoutTests/fast/dom/Document/CaretRangeFromPoint/caretRangeFromPoint-in-zoom-and-scroll_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/Document/CaretRangeFromPoint/caretRangeFromPoint-with-first-letter-style_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/Document/CaretRangeFromPoint/hittest-relative-to-viewport_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/dom/Document/CaretRangeFromPoint/replace-element_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/Document/createElement-valid-names_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/Document/createElementNS-namespace-err_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/Document/document-title-get_t01: RuntimeError # Please triage this failure
@@ -3246,12 +3253,6 @@
 LayoutTests/fast/canvas/setWidthResetAfterForcedRender_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/canvas/webgl/bad-arguments-test_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/context-attributes-alpha-depth-stencil-antialias-t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/framebuffer-test_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/object-deletion-behaviour_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-canvas_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-data-rgb565_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-data-rgba4444_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-data-rgba5551_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-rgb565_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-rgba4444_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-rgba5551_t01: RuntimeError # Please triage this failure
@@ -3260,11 +3261,8 @@
 LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-video-rgba4444_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-video-rgba5551_t01: RuntimeError, Timeout # Please triage this failure
 LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-video_t01: RuntimeError, Timeout # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-input-validation_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-sub-image-2d_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/texture-transparent-pixels-initialized_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/uniform-location_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/uninitialized-test_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/webgl-depth-texture_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/webgl-large-texture_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css-generated-content/malformed-url_t01: RuntimeError # Please triage this failure
@@ -3335,6 +3333,7 @@
 LayoutTests/fast/css/deprecated-flexbox-auto-min-size_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/draggable-region-parser_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/dynamic-class-backdrop-pseudo_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/css/ex-unit-with-no-x-height_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/first-child-display-change-inverse_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/focus-display-block-inline_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/css/font-face-cache-bug_t01: RuntimeError # Please triage this failure
@@ -3450,6 +3449,7 @@
 LayoutTests/fast/dom/HTMLLinkElement/prefetch-onerror_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/dom/HTMLLinkElement/prefetch-onload_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/dom/HTMLLinkElement/prefetch_t01: Skip # Times out. Please triage this failure
+LayoutTests/fast/dom/HTMLLinkElement/resolve-url-on-insertion_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/HTMLOptionElement/collection-setter-getter_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/HTMLOutputElement/dom-settable-token-list_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/HTMLScriptElement/async-false-inside-async-false-load_t01: RuntimeError # Please triage this failure
@@ -3501,6 +3501,7 @@
 LayoutTests/fast/dom/attribute-namespaces-get-set_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/characterdata-api-arguments_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/client-width-height-quirks_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/dom/css-selectorText_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/custom/attribute-changed-callback_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/custom/constructor-calls-created-synchronously_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/custom/created-callback_t01: RuntimeError # Please triage this failure
@@ -3530,12 +3531,13 @@
 LayoutTests/fast/dom/implementation-api-args_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/importNode-unsupported-node-type_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/location-hash_t01: Skip # Times out. Please triage this failure
+LayoutTests/fast/dom/mutation-event-remove-inserted-node_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/navigatorcontentutils/is-protocol-handler-registered_t01: Skip # API not supported.
 LayoutTests/fast/dom/navigatorcontentutils/register-protocol-handler_t01: Skip # API not supported.
 LayoutTests/fast/dom/navigatorcontentutils/unregister-protocol-handler_t01: Skip # API not supported.
 LayoutTests/fast/dom/object-plugin-hides-properties_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/dom/option-properties_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/dom/partial-layout-overlay-scrollbars_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/dom/partial-layout-non-overlay-scrollbars_t01: Pass, RuntimeError # Issue 53
 LayoutTests/fast/dom/set-innerHTML_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/shadow/access-document-of-detached-stylesheetlist-crash_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/shadow/base-in-shadow-tree_t01: RuntimeError # Please triage this failure
@@ -3693,6 +3695,7 @@
 LayoutTests/fast/forms/clone-input-with-dirty-value_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/color/color-setrangetext_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/color/input-value-sanitization-color_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/forms/datalist/datalist-child-validation_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/datalist/datalist_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/datalist/input-list_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/forms/datetimelocal/input-valueasnumber-datetimelocal_t01: RuntimeError # Dartium JSInterop failure
@@ -3978,6 +3981,7 @@
 LibTest/html/Element/enteredView_A01_t01: RuntimeError # Please triage this failure
 LibTest/html/Element/getAttributeNS_A01_t01: RuntimeError # Please triage this failure
 LibTest/html/Element/getAttributeNS_A02_t01: RuntimeError # Please triage this failure
+LibTest/html/Element/getBoundingClientRect_A01_t02: Pass, RuntimeError # Issue 53
 LibTest/html/Element/getClientRects_A01_t02: RuntimeError # Please triage this failure
 LibTest/html/Element/getNamespacedAttributes_A01_t01: RuntimeError # Please triage this failure
 LibTest/html/Element/isTagSupported_A01_t01: RuntimeError # Please triage this failure
@@ -7782,7 +7786,6 @@
 LayoutTests/fast/canvas/webgl/error-reporting_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/framebuffer-bindings-unaffected-on-resize_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/framebuffer-object-attachment_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/framebuffer-test_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/functions-returning-strings_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/get-active-test_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/gl-bind-attrib-location-test_t01: Pass, RuntimeError # Please triage this failure
@@ -7828,7 +7831,6 @@
 LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-video_t01: Skip # Times out. Please triage this failure
 LayoutTests/fast/canvas/webgl/tex-image-and-uniform-binding-bugs_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/tex-image-webgl_t01: Pass, RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/tex-input-validation_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/tex-sub-image-2d-bad-args_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/tex-sub-image-2d_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/tex-sub-image-cube-maps_t01: RuntimeError # Please triage this failure
@@ -7843,7 +7845,6 @@
 LayoutTests/fast/canvas/webgl/triangle_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/uniform-location-length-limits_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/uniform-location_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/webgl/uninitialized-test_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/viewport-unchanged-upon-resize_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/webgl-composite-modes-repaint_t01: Pass, RuntimeError # Please triage this failure
 LayoutTests/fast/canvas/webgl/webgl-composite-modes_t01: Pass, RuntimeError # Please triage this failure
diff --git a/tests/co19/co19-dartium.status b/tests/co19/co19-dartium.status
index 1436313..545123a 100644
--- a/tests/co19/co19-dartium.status
+++ b/tests/co19/co19-dartium.status
@@ -1366,10 +1366,11 @@
 LayoutTests/fast/dom/computed-style-set-property_t01: RuntimeError # Issue 26134
 LayoutTests/fast/dom/custom/document-register-type-extensions_t01: RuntimeError # Issue 26134
 LayoutTests/fast/dom/custom/document-register-namespace_t01: RuntimeError # Issue 26134
+LayoutTests/fast/dom/custom/element-type_t01: RuntimeError # Issue 26134
+LayoutTests/fast/dom/custom/element-upgrade_t01: RuntimeError # Issue 26134
 LayoutTests/fast/dom/DOMException/prototype-object_t01: RuntimeError # Issue 26134
 LayoutTests/fast/dom/shadow/shadow-hierarchy-exception_t01: RuntimeError # Issue 26134
 LayoutTests/fast/dom/Node/contains-method_t01: RuntimeError # Issue 26134
-LayoutTests/fast/dom/MutationObserver/observe-attributes_t01: RuntimeError # Issue 26134
 LayoutTests/fast/events/mutation-during-append-child_t01: RuntimeError # Issue 26134
 LayoutTests/fast/events/mutation-during-insert-before_t01: RuntimeError # Issue 26134
 LayoutTests/fast/events/clipboard-dataTransferItemList-remove_t01: Skip # Issue 26134, timesout
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index 59ebaf3..d9a0814 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -168,3 +168,10 @@
 # TODO(vegorov) These tests are very slow on unoptimized SIMDBC
 LibTest/collection/ListMixin/ListMixin_class_A01_t02: Timeout
 LibTest/collection/ListBase/ListBase_class_A01_t02: Timeout
+
+[ $compiler == precompiler && $runtime == dart_precompiled && $system == android ]
+LibTest/isolate/*: Skip # Issue #26373
+Language/Expressions/Spawning_an_Isolate/new_isolate_t01: Skip # Issue #26373
+
+LibTest/math/log_A01_t01: RuntimeError # Precision of Math.log (Issue #18998)
+Language/Expressions/Object_Identity/double_t02: RuntimeError # Issue #26374
diff --git a/tests/compiler/dart2js/analyze_test_test.dart b/tests/compiler/dart2js/analyze_test_test.dart
index 93cf7b9..a38c814 100644
--- a/tests/compiler/dart2js/analyze_test_test.dart
+++ b/tests/compiler/dart2js/analyze_test_test.dart
@@ -38,17 +38,15 @@
 
 const List<String> SKIP_LIST = const <String>[
   // Helper files:
-  "dart2js_batch2_run.dart",
+  "/data/",
   "http_launch_data/",
   "mirrors_helper.dart",
   "path%20with%20spaces/",
-  "one_line_dart_program.dart",
-  "sourcemaps/invokes_test_file.dart",
   "cps_ir/input/",
   // No longer maintained:
   "backend_dart/",
   // Broken tests:
-  "http_test.dart",
+  "quarantined/http_test.dart",
   // Package directory
   "packages/",
 ];
diff --git a/tests/compiler/dart2js/dart2js.status b/tests/compiler/dart2js/dart2js.status
index 6c26bdb..e6c7b74 100644
--- a/tests/compiler/dart2js/dart2js.status
+++ b/tests/compiler/dart2js/dart2js.status
@@ -2,6 +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.
 
+packages/*: Skip # Skip packages folder
+
 compile_with_empty_libraries_test: Fail # Issue 24223
 
 boolified_operator_test: Fail # Issue 8001
@@ -34,7 +36,7 @@
 
 patch_test/bug: RuntimeError # Issue 21132
 
-http_test: Pass, Slow
+quarantined/http_test: Pass, Slow
 inference_stats_test: Pass, Slow
 
 # These tests are for the now-deleted dart2dart variant of the CPS IR.
diff --git a/tests/compiler/dart2js/dart2js_batch2_test.dart b/tests/compiler/dart2js/dart2js_batch2_test.dart
index 644c790..2bd2495 100644
--- a/tests/compiler/dart2js/dart2js_batch2_test.dart
+++ b/tests/compiler/dart2js/dart2js_batch2_test.dart
@@ -38,8 +38,8 @@
   return createTempDir().then((Directory directory) {
     tmpDir = directory;
     String newPath = path.join(directory.path, "dart2js_batch2_run.dart");
-    File source =
-        new File.fromUri(Platform.script.resolve("dart2js_batch2_run.dart"));
+    File source = new File.fromUri(
+        Platform.script.resolve("data/dart2js_batch2_run.dart"));
     source.copySync(newPath);
   });
 }
diff --git a/tests/compiler/dart2js/dart2js_batch2_run.dart b/tests/compiler/dart2js/data/dart2js_batch2_run.dart
similarity index 100%
rename from tests/compiler/dart2js/dart2js_batch2_run.dart
rename to tests/compiler/dart2js/data/dart2js_batch2_run.dart
diff --git a/tests/compiler/dart2js/exit_code_helper.dart b/tests/compiler/dart2js/data/exit_code_helper.dart
similarity index 100%
rename from tests/compiler/dart2js/exit_code_helper.dart
rename to tests/compiler/dart2js/data/exit_code_helper.dart
diff --git a/tests/compiler/dart2js/mirrors_helper.dart b/tests/compiler/dart2js/data/mirrors_helper.dart
similarity index 100%
rename from tests/compiler/dart2js/mirrors_helper.dart
rename to tests/compiler/dart2js/data/mirrors_helper.dart
diff --git a/tests/compiler/dart2js/one_line_dart_program.dart b/tests/compiler/dart2js/data/one_line_dart_program.dart
similarity index 100%
rename from tests/compiler/dart2js/one_line_dart_program.dart
rename to tests/compiler/dart2js/data/one_line_dart_program.dart
diff --git a/tests/compiler/dart2js/deferred_follow_constant_dependencies_test.dart b/tests/compiler/dart2js/deferred_follow_constant_dependencies_test.dart
index d1175e7..0f10523 100644
--- a/tests/compiler/dart2js/deferred_follow_constant_dependencies_test.dart
+++ b/tests/compiler/dart2js/deferred_follow_constant_dependencies_test.dart
@@ -5,6 +5,7 @@
 // Test that constants depended on by other constants are correctly deferred.
 
 import 'package:async_helper/async_helper.dart';
+import 'package:compiler/src/common.dart';
 import 'package:compiler/src/constants/values.dart';
 import 'package:compiler/src/compiler.dart';
 import 'package:expect/expect.dart';
@@ -34,8 +35,11 @@
         return constant.isString
             && constant.primitiveValue.slowToString() == stringValue;
       });
-      Expect.notEquals(null, outputUnitForConstant(constant));
-      Expect.notEquals(mainOutputUnit, outputUnitForConstant(constant));
+      Expect.notEquals(null, outputUnitForConstant(constant),
+          "Constant value ${constant.toStructuredText()} has no output unit.");
+      Expect.notEquals(mainOutputUnit, outputUnitForConstant(constant),
+          "Constant value ${constant.toStructuredText()} "
+              "is in the main output unit.");
     }
   });
 }
diff --git a/tests/compiler/dart2js/exit_code_test.dart b/tests/compiler/dart2js/exit_code_test.dart
index b67b026..67a04bd 100644
--- a/tests/compiler/dart2js/exit_code_test.dart
+++ b/tests/compiler/dart2js/exit_code_test.dart
@@ -242,7 +242,7 @@
     entry.compileFunc = compile;
 
     List<String> args = new List<String>.from(options)
-        ..add("tests/compiler/dart2js/exit_code_helper.dart");
+        ..add("tests/compiler/dart2js/data/exit_code_helper.dart");
     Future result = entry.internalMain(args);
     return result.catchError((e, s) {
       // Capture crashes.
diff --git a/tests/compiler/dart2js/mock_compiler.dart b/tests/compiler/dart2js/mock_compiler.dart
index 839c083..59dc3da 100644
--- a/tests/compiler/dart2js/mock_compiler.dart
+++ b/tests/compiler/dart2js/mock_compiler.dart
@@ -11,6 +11,7 @@
 import 'package:compiler/src/common/names.dart' show
     Uris;
 import 'package:compiler/src/constants/expressions.dart';
+import 'package:compiler/src/dart_types.dart' show DartType;
 import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
 import 'package:compiler/src/diagnostics/source_span.dart';
 import 'package:compiler/src/diagnostics/spannable.dart';
@@ -224,10 +225,15 @@
   TreeElementMapping resolveNodeStatement(Node tree,
                                           ExecutableElement element) {
     ResolverVisitor visitor =
-        new ResolverVisitor(this, element,
+        new ResolverVisitor(
+            this,
+            element,
             new ResolutionRegistry(this,
-                new CollectingTreeElements(element)));
-    if (visitor.scope is LibraryScope) {
+                new CollectingTreeElements(element)),
+            scope: new MockTypeVariablesScope(
+                element.enclosingElement.buildScope()));
+    if (visitor.scope is LibraryScope ||
+        visitor.scope is MockTypeVariablesScope) {
       visitor.scope = new MethodScope(visitor.scope, element);
     }
     visitor.visit(tree);
@@ -238,9 +244,12 @@
   resolverVisitor() {
     Element mockElement = new MockElement(mainApp.entryCompilationUnit);
     ResolverVisitor visitor =
-        new ResolverVisitor(this, mockElement,
-          new ResolutionRegistry(this,
-              new CollectingTreeElements(mockElement)));
+        new ResolverVisitor(
+            this,
+            mockElement,
+            new ResolutionRegistry(
+                this, new CollectingTreeElements(mockElement)),
+            scope: mockElement.enclosingElement.buildScope());
     visitor.scope = new MethodScope(visitor.scope, mockElement);
     return visitor;
   }
@@ -321,6 +330,13 @@
   }
 }
 
+class MockTypeVariablesScope extends TypeVariablesScope {
+  @override
+  List<DartType> get typeVariables => <DartType>[];
+  MockTypeVariablesScope(Scope parent) : super(parent);
+  String toString() => 'MockTypeVariablesScope($parent)';
+}
+
 // The mock compiler does not split the program in output units.
 class MockDeferredLoadTask extends DeferredLoadTask {
   MockDeferredLoadTask(Compiler compiler) : super(compiler);
diff --git a/tests/compiler/dart2js/http_test.dart b/tests/compiler/dart2js/quarantined/http_test.dart
similarity index 97%
rename from tests/compiler/dart2js/http_test.dart
rename to tests/compiler/dart2js/quarantined/http_test.dart
index aed6ddd..cdb1348 100644
--- a/tests/compiler/dart2js/http_test.dart
+++ b/tests/compiler/dart2js/quarantined/http_test.dart
@@ -15,7 +15,7 @@
 import 'package:expect/expect.dart';
 import 'package:path/path.dart' as path;
 
-Uri pathOfData = Platform.script.resolve('http_launch_data/');
+Uri pathOfData = Platform.script.resolve('../http_launch_data/');
 Directory tempDir;
 String outFilePath;
 
@@ -43,7 +43,7 @@
   String ext = Platform.isWindows ? '.bat' : '';
   String command =
       path.normalize(path.join(path.fromUri(Platform.script),
-                    '../../../../sdk/bin/dart2js${ext}'));
+                    '../../../../../sdk/bin/dart2js${ext}'));
   return Process.run(command, args);
 }
 
diff --git a/tests/compiler/dart2js/mirrors_test.dart b/tests/compiler/dart2js/quarantined/mirrors_test.dart
similarity index 99%
rename from tests/compiler/dart2js/mirrors_test.dart
rename to tests/compiler/dart2js/quarantined/mirrors_test.dart
index ef815e9..428442f 100644
--- a/tests/compiler/dart2js/mirrors_test.dart
+++ b/tests/compiler/dart2js/quarantined/mirrors_test.dart
@@ -43,9 +43,9 @@
 
 main() {
   Uri scriptUri = currentDirectory.resolveUri(Platform.script);
-  Uri packageRoot = scriptUri.resolve('./packages/');
-  Uri libUri = scriptUri.resolve('../../../sdk/');
-  Uri inputUri = scriptUri.resolve('mirrors_helper.dart');
+  Uri packageRoot = scriptUri.resolve('../packages/');
+  Uri libUri = scriptUri.resolve('../../../../sdk/');
+  Uri inputUri = scriptUri.resolve('../data/mirrors_helper.dart');
   var provider = new CompilerSourceFileProvider();
   var diagnosticHandler = new FormattingDiagnosticHandler(provider);
   asyncStart();
diff --git a/tests/compiler/dart2js/resolver_test.dart b/tests/compiler/dart2js/resolver_test.dart
index 6067a6c..2e1868a 100644
--- a/tests/compiler/dart2js/resolver_test.dart
+++ b/tests/compiler/dart2js/resolver_test.dart
@@ -222,10 +222,11 @@
     ClassElement classA = compiler.mainApp.find("A");
     FunctionElement fooA = classA.lookupLocalMember("foo");
 
-    ResolverVisitor visitor =
-        new ResolverVisitor(compiler, fooB,
-            new ResolutionRegistry(compiler,
-                new CollectingTreeElements(fooB)));
+    ResolverVisitor visitor = new ResolverVisitor(
+        compiler,
+        fooB,
+        new ResolutionRegistry(compiler, new CollectingTreeElements(fooB)),
+        scope: new MockTypeVariablesScope(classB.buildScope()));
     FunctionExpression node =
         (fooB as FunctionElementX).parseNode(compiler.parsingContext);
     visitor.visit(node.body);
@@ -266,10 +267,12 @@
       compiler.resolveStatement("Foo foo;");
       ClassElement fooElement = compiler.mainApp.find("Foo");
       FunctionElement funElement = fooElement.lookupLocalMember("foo");
-      ResolverVisitor visitor =
-          new ResolverVisitor(compiler, funElement,
-              new ResolutionRegistry(compiler,
-                  new CollectingTreeElements(funElement)));
+      ResolverVisitor visitor = new ResolverVisitor(
+          compiler,
+          funElement,
+          new ResolutionRegistry(
+              compiler, new CollectingTreeElements(funElement)),
+          scope: new MockTypeVariablesScope(fooElement.buildScope()));
       FunctionExpression function =
           (funElement as FunctionElementX).parseNode(compiler.parsingContext);
       visitor.visit(function.body);
@@ -292,9 +295,12 @@
       compiler.resolveStatement("Foo foo;");
       ClassElement fooElement = compiler.mainApp.find("Foo");
       FunctionElement funElement = fooElement.lookupLocalMember("foo");
-      ResolverVisitor visitor = new ResolverVisitor(compiler, funElement,
-          new ResolutionRegistry(compiler,
-              new CollectingTreeElements(funElement)));
+      ResolverVisitor visitor = new ResolverVisitor(
+          compiler,
+          funElement,
+          new ResolutionRegistry(
+              compiler, new CollectingTreeElements(funElement)),
+          scope: new MockTypeVariablesScope(fooElement.buildScope()));
       FunctionExpression function =
           (funElement as FunctionElementX).parseNode(compiler.parsingContext);
       visitor.visit(function.body);
@@ -581,10 +587,10 @@
     // correctly.
     compiler.parseScript("abstract class Bar {}");
 
-    ResolverVisitor visitor =
-        new ResolverVisitor(compiler, null,
-            new ResolutionRegistry(compiler,
-                new CollectingTreeElements(null)));
+    ResolverVisitor visitor = new ResolverVisitor(
+        compiler,
+        null,
+        new ResolutionRegistry(compiler, new CollectingTreeElements(null)));
     compiler.resolveStatement("Foo bar;");
 
     ClassElement fooElement = compiler.mainApp.find('Foo');
@@ -619,7 +625,6 @@
 
 Future testFunctionExpression() {
   return MockCompiler.create((MockCompiler compiler) {
-    ResolverVisitor visitor = compiler.resolverVisitor();
     Map mapping = compiler.resolveStatement("int f() {}").map;
     Expect.equals(2, mapping.length);
     Element element;
@@ -701,10 +706,11 @@
     Element element;
     element = classElement.lookupConstructor(constructor);
     FunctionExpression tree = (element as FunctionElement).node;
-    ResolverVisitor visitor =
-        new ResolverVisitor(compiler, element,
-            new ResolutionRegistry(compiler,
-                new CollectingTreeElements(element)));
+    ResolverVisitor visitor = new ResolverVisitor(
+        compiler,
+        element,
+        new ResolutionRegistry(compiler, new CollectingTreeElements(element)),
+        scope: classElement.buildScope());
     new InitializerResolver(visitor, element, tree).resolveInitializers();
     visitor.visit(tree.body);
     Expect.equals(expectedElementCount, map(visitor).length,
diff --git a/tests/compiler/dart2js/serialization_analysis_test.dart b/tests/compiler/dart2js/serialization/analysis_test.dart
similarity index 94%
rename from tests/compiler/dart2js/serialization_analysis_test.dart
rename to tests/compiler/dart2js/serialization/analysis_test.dart
index 39c46de..b1a96b5 100644
--- a/tests/compiler/dart2js/serialization_analysis_test.dart
+++ b/tests/compiler/dart2js/serialization/analysis_test.dart
@@ -12,9 +12,9 @@
 import 'package:compiler/src/common/names.dart';
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/filenames.dart';
-import 'memory_compiler.dart';
-import 'serialization_helper.dart';
-import 'serialization_test_data.dart';
+import '../memory_compiler.dart';
+import 'helper.dart';
+import 'test_data.dart';
 
 main(List<String> arguments) {
   asyncTest(() async {
diff --git a/tests/compiler/dart2js/serialization_compilation_test.dart b/tests/compiler/dart2js/serialization/compilation_test.dart
similarity index 88%
rename from tests/compiler/dart2js/serialization_compilation_test.dart
rename to tests/compiler/dart2js/serialization/compilation_test.dart
index 590f57a..e6601e1 100644
--- a/tests/compiler/dart2js/serialization_compilation_test.dart
+++ b/tests/compiler/dart2js/serialization/compilation_test.dart
@@ -12,10 +12,10 @@
 import 'package:compiler/src/common/names.dart';
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/filenames.dart';
-import 'memory_compiler.dart';
-import 'serialization_helper.dart';
-import 'serialization_test_data.dart';
-import 'output_collector.dart';
+import '../memory_compiler.dart';
+import 'helper.dart';
+import 'test_data.dart';
+import '../output_collector.dart';
 
 main(List<String> args) {
   asyncTest(() async {
@@ -29,7 +29,7 @@
     } else {
       Uri entryPoint = Uri.parse('memory:main.dart');
       // TODO(johnniwinther): Handle the remaining tests.
-      for (Test test in TESTS.sublist(0, 1)) {
+      for (Test test in TESTS.sublist(0, 5)) {
         await compile(serializedData, entryPoint, test,
                       verbose: arguments.verbose);
       }
@@ -48,8 +48,7 @@
   await runCompiler(
       entryPoint: entryPoint,
       memorySourceFiles: test != null ? test.sourceFiles : const {},
-      options: [Flags.disableTypeInference,
-                Flags.disableInlining],
+      options: [],
       outputProvider: outputCollector,
       beforeRun: (Compiler compiler) {
         deserialize(compiler, serializedData, deserializeResolvedAst: true);
diff --git a/tests/compiler/dart2js/serialization_test.dart b/tests/compiler/dart2js/serialization/equivalence_test.dart
similarity index 94%
rename from tests/compiler/dart2js/serialization_test.dart
rename to tests/compiler/dart2js/serialization/equivalence_test.dart
index 7edeb4c..32a538a 100644
--- a/tests/compiler/dart2js/serialization_test.dart
+++ b/tests/compiler/dart2js/serialization/equivalence_test.dart
@@ -5,7 +5,7 @@
 library dart2js.serialization_test;
 
 import 'dart:io';
-import 'memory_compiler.dart';
+import '../memory_compiler.dart';
 import 'package:async_helper/async_helper.dart';
 import 'package:compiler/src/commandline_options.dart';
 import 'package:compiler/src/common.dart';
@@ -21,7 +21,7 @@
 import 'package:compiler/src/serialization/equivalence.dart';
 import 'package:compiler/src/serialization/json_serializer.dart';
 import 'package:compiler/src/serialization/serialization.dart';
-import 'serialization_test_helper.dart';
+import 'test_helper.dart';
 
 main(List<String> arguments) {
   // Ensure that we can print out constant expressions.
@@ -243,6 +243,8 @@
     if (element1 == element2) return;
     check(element1, element2, 'kind', element1.kind, element2.kind);
     element1.accept(this, element2);
+    check(element1, element2, 'isSynthesized',
+        element1.isSynthesized, element2.isSynthesized);
   }
 
   @override
@@ -560,6 +562,24 @@
           element1.constantConstructor,
           element2.constantConstructor);
     }
+    check(element1, element2, 'isRedirectingGenerative',
+        element1.isRedirectingGenerative, element2.isRedirectingGenerative);
+    check(element1, element2, 'isRedirectingFactory',
+        element1.isRedirectingFactory, element2.isRedirectingFactory);
+    checkElementIdentities(element1, element2, 'effectiveTarget',
+        element1.effectiveTarget, element2.effectiveTarget);
+    checkElementIdentities(element1, element2, 'definingConstructor',
+        element1.definingConstructor, element2.definingConstructor);
+    check(
+        element1, element2, 'effectiveTargetType',
+        element1.computeEffectiveTargetType(element1.enclosingClass.thisType),
+        element2.computeEffectiveTargetType(element2.enclosingClass.thisType),
+        areTypesEquivalent);
+    checkElementIdentities(element1, element2, 'immediateRedirectionTarget',
+        element1.immediateRedirectionTarget,
+        element2.immediateRedirectionTarget);
+    checkElementIdentities(element1, element2, 'redirectionDeferredPrefix',
+        element1.redirectionDeferredPrefix, element2.redirectionDeferredPrefix);
   }
 
   @override
diff --git a/tests/compiler/dart2js/serialization_helper.dart b/tests/compiler/dart2js/serialization/helper.dart
similarity index 92%
rename from tests/compiler/dart2js/serialization_helper.dart
rename to tests/compiler/dart2js/serialization/helper.dart
index 2d1ea1f..c7719b3 100644
--- a/tests/compiler/dart2js/serialization_helper.dart
+++ b/tests/compiler/dart2js/serialization/helper.dart
@@ -28,7 +28,7 @@
 import 'package:compiler/src/universe/world_impact.dart';
 import 'package:compiler/src/universe/use.dart';
 
-import 'memory_compiler.dart';
+import '../memory_compiler.dart';
 
 class Arguments {
   final String filename;
@@ -211,7 +211,7 @@
   }
 
   @override
-  bool hasResolvedAst(Element element) {
+  bool hasResolvedAst(ExecutableElement element) {
     if (_resolvedAstDeserializer != null) {
       return _resolvedAstDeserializer.hasResolvedAst(element);
     }
@@ -219,7 +219,7 @@
   }
 
   @override
-  ResolvedAst getResolvedAst(Element element) {
+  ResolvedAst getResolvedAst(ExecutableElement element) {
     if (_resolvedAstDeserializer != null) {
       return _resolvedAstDeserializer.getResolvedAst(element);
     }
@@ -300,27 +300,30 @@
   final Backend backend;
   final Map<Uri, SourceFile> sourceFiles = <Uri, SourceFile>{};
 
-  Map<Element, ResolvedAst> _resolvedAstMap = <Element, ResolvedAst>{};
-  Map<Element, ObjectDecoder> _decoderMap = <Element, ObjectDecoder>{};
+  Map<ExecutableElement, ResolvedAst> _resolvedAstMap =
+      <ExecutableElement, ResolvedAst>{};
+  Map<MemberElement, ObjectDecoder> _decoderMap =
+      <MemberElement, ObjectDecoder>{};
   Map<Uri, Token> beginTokenMap = <Uri, Token>{};
 
   ResolvedAstDeserializerPlugin(this.parsingContext, this.backend);
 
-  bool hasResolvedAst(Element element) {
+  bool hasResolvedAst(ExecutableElement element) {
     return _resolvedAstMap.containsKey(element) ||
-        _decoderMap.containsKey(element);
+        _decoderMap.containsKey(element.memberContext);
   }
 
-  ResolvedAst getResolvedAst(Element element) {
+  ResolvedAst getResolvedAst(ExecutableElement element) {
     ResolvedAst resolvedAst = _resolvedAstMap[element];
     if (resolvedAst == null) {
-      ObjectDecoder decoder = _decoderMap[element];
+      ObjectDecoder decoder = _decoderMap[element.memberContext];
       if (decoder != null) {
-        resolvedAst = _resolvedAstMap[element] =
-            ResolvedAstDeserializer.deserialize(
-                element, decoder, parsingContext, findToken,
-                backend.serialization.deserializer);
+         ResolvedAstDeserializer.deserialize(
+             element.memberContext, decoder, parsingContext, findToken,
+             backend.serialization.deserializer,
+             _resolvedAstMap);
         _decoderMap.remove(element);
+        resolvedAst = _resolvedAstMap[element];
       }
     }
     return resolvedAst;
diff --git a/tests/compiler/dart2js/serialization_impact_test.dart b/tests/compiler/dart2js/serialization/impact_test.dart
similarity index 94%
rename from tests/compiler/dart2js/serialization_impact_test.dart
rename to tests/compiler/dart2js/serialization/impact_test.dart
index 6f5fd15..ea1d113 100644
--- a/tests/compiler/dart2js/serialization_impact_test.dart
+++ b/tests/compiler/dart2js/serialization/impact_test.dart
@@ -12,9 +12,9 @@
 import 'package:compiler/src/elements/elements.dart';
 import 'package:compiler/src/filenames.dart';
 import 'package:compiler/src/serialization/equivalence.dart';
-import 'memory_compiler.dart';
-import 'serialization_helper.dart';
-import 'serialization_test_helper.dart';
+import '../memory_compiler.dart';
+import 'helper.dart';
+import 'test_helper.dart';
 
 main(List<String> args) {
   Arguments arguments = new Arguments.from(args);
diff --git a/tests/compiler/dart2js/serialization_library_test.dart b/tests/compiler/dart2js/serialization/library_test.dart
similarity index 98%
rename from tests/compiler/dart2js/serialization_library_test.dart
rename to tests/compiler/dart2js/serialization/library_test.dart
index df59fbc..81d90cf 100644
--- a/tests/compiler/dart2js/serialization_library_test.dart
+++ b/tests/compiler/dart2js/serialization/library_test.dart
@@ -5,7 +5,7 @@
 library dart2js.serialization_library_test;
 
 import 'dart:io';
-import 'memory_compiler.dart';
+import '../memory_compiler.dart';
 import 'package:async_helper/async_helper.dart';
 import 'package:compiler/src/commandline_options.dart';
 import 'package:compiler/src/common/names.dart';
@@ -21,7 +21,7 @@
 import 'package:compiler/src/serialization/json_serializer.dart';
 import 'package:compiler/src/serialization/serialization.dart';
 
-import 'serialization_test.dart';
+import 'equivalence_test.dart';
 
 main(List<String> arguments) {
   // Ensure that we can print out constant expressions.
diff --git a/tests/compiler/dart2js/serialization_model_test.dart b/tests/compiler/dart2js/serialization/model_test.dart
similarity index 97%
rename from tests/compiler/dart2js/serialization_model_test.dart
rename to tests/compiler/dart2js/serialization/model_test.dart
index 52547ae..66ac6c5 100644
--- a/tests/compiler/dart2js/serialization_model_test.dart
+++ b/tests/compiler/dart2js/serialization/model_test.dart
@@ -25,10 +25,10 @@
 import 'package:compiler/src/universe/world_impact.dart';
 import 'package:compiler/src/universe/class_set.dart';
 import 'package:compiler/src/universe/use.dart';
-import 'memory_compiler.dart';
-import 'serialization_helper.dart';
-import 'serialization_test_data.dart';
-import 'serialization_test_helper.dart';
+import '../memory_compiler.dart';
+import 'helper.dart';
+import 'test_data.dart';
+import 'test_helper.dart';
 
 main(List<String> args) {
   asyncTest(() async {
diff --git a/tests/compiler/dart2js/serialization_resolved_ast_test.dart b/tests/compiler/dart2js/serialization/resolved_ast_test.dart
similarity index 92%
rename from tests/compiler/dart2js/serialization_resolved_ast_test.dart
rename to tests/compiler/dart2js/serialization/resolved_ast_test.dart
index 7712f9a..0ca8672 100644
--- a/tests/compiler/dart2js/serialization_resolved_ast_test.dart
+++ b/tests/compiler/dart2js/serialization/resolved_ast_test.dart
@@ -14,10 +14,10 @@
 import 'package:compiler/src/elements/elements.dart';
 import 'package:compiler/src/filenames.dart';
 import 'package:compiler/src/serialization/equivalence.dart';
-import 'memory_compiler.dart';
-import 'serialization_helper.dart';
-import 'serialization_test_data.dart';
-import 'serialization_test_helper.dart';
+import '../memory_compiler.dart';
+import 'helper.dart';
+import 'test_data.dart';
+import 'test_helper.dart';
 
 
 main(List<String> args) {
@@ -68,7 +68,8 @@
       compiler1,
       compiler2,
       (Element member1) {
-        return compiler1.resolution.hasResolvedAst(member1);
+        return member1 is ExecutableElement &&
+            compiler1.resolution.hasResolvedAst(member1);
       },
       checkResolvedAsts,
       verbose: verbose);
diff --git a/tests/compiler/dart2js/serialization_test_data.dart b/tests/compiler/dart2js/serialization/test_data.dart
similarity index 100%
rename from tests/compiler/dart2js/serialization_test_data.dart
rename to tests/compiler/dart2js/serialization/test_data.dart
diff --git a/tests/compiler/dart2js/serialization_test_helper.dart b/tests/compiler/dart2js/serialization/test_helper.dart
similarity index 99%
rename from tests/compiler/dart2js/serialization_test_helper.dart
rename to tests/compiler/dart2js/serialization/test_helper.dart
index 0c871a8..1a05c98 100644
--- a/tests/compiler/dart2js/serialization_test_helper.dart
+++ b/tests/compiler/dart2js/serialization/test_helper.dart
@@ -5,7 +5,7 @@
 library dart2js.serialization_test_helper;
 
 import 'dart:io';
-import 'memory_compiler.dart';
+import '../memory_compiler.dart';
 import 'package:async_helper/async_helper.dart';
 import 'package:compiler/src/common/resolution.dart';
 import 'package:compiler/src/commandline_options.dart';
diff --git a/tests/compiler/dart2js/sourcemaps/invokes_test_file.dart b/tests/compiler/dart2js/sourcemaps/data/invokes_test_file.dart
similarity index 100%
rename from tests/compiler/dart2js/sourcemaps/invokes_test_file.dart
rename to tests/compiler/dart2js/sourcemaps/data/invokes_test_file.dart
diff --git a/tests/compiler/dart2js/sourcemaps/operators_test_file.dart b/tests/compiler/dart2js/sourcemaps/data/operators_test_file.dart
similarity index 100%
rename from tests/compiler/dart2js/sourcemaps/operators_test_file.dart
rename to tests/compiler/dart2js/sourcemaps/data/operators_test_file.dart
diff --git a/tests/compiler/dart2js/sourcemaps/sourcemap_helper.dart b/tests/compiler/dart2js/sourcemaps/sourcemap_helper.dart
index 9bc1ac8..3a5befd 100644
--- a/tests/compiler/dart2js/sourcemaps/sourcemap_helper.dart
+++ b/tests/compiler/dart2js/sourcemaps/sourcemap_helper.dart
@@ -200,8 +200,8 @@
   RecordingSourceInformationStrategy(this.strategy);
 
   @override
-  SourceInformationBuilder createBuilderForContext(AstElement element) {
-    return strategy.createBuilderForContext(element);
+  SourceInformationBuilder createBuilderForContext(ResolvedAst resolvedAst) {
+    return strategy.createBuilderForContext(resolvedAst);
   }
 
   @override
diff --git a/tests/compiler/dart2js/zero_termination_test.dart b/tests/compiler/dart2js/zero_termination_test.dart
index 501fb42..fbfeab7 100644
--- a/tests/compiler/dart2js/zero_termination_test.dart
+++ b/tests/compiler/dart2js/zero_termination_test.dart
@@ -67,7 +67,8 @@
 }
 
 Future testFile() async {
-  String inFilePath = pathOfData.resolve('one_line_dart_program.dart').path;
+  String inFilePath =
+      pathOfData.resolve('data/one_line_dart_program.dart').path;
   List<String> args = [inFilePath, "--out=" + outFilePath];
 
   await cleanup();
@@ -77,7 +78,7 @@
 
 Future serverRunning(HttpServer server) async {
   int port = server.port;
-  String inFilePath = "http://127.0.0.1:$port/one_line_dart_program.dart";
+  String inFilePath = "http://127.0.0.1:$port/data/one_line_dart_program.dart";
   List<String> args = [inFilePath, "--out=" + outFilePath];
 
   server.listen(handleRequest);
diff --git a/tests/corelib/core_runtime_types_test.dart b/tests/corelib/core_runtime_types_test.dart
index 017df05..49b234c 100644
--- a/tests/corelib/core_runtime_types_test.dart
+++ b/tests/corelib/core_runtime_types_test.dart
@@ -262,7 +262,7 @@
     assertEquals(d.year, 1970);
 
     d = new DateTime.now();
-    assertEquals(d.year >= 2011, true);
+    assertEquals(d.year >= 1970, true);
   }
 
   static testLiterals() {
diff --git a/tests/corelib/set_test.dart b/tests/corelib/set_test.dart
index 3711449..20a136a 100644
--- a/tests/corelib/set_test.dart
+++ b/tests/corelib/set_test.dart
@@ -445,6 +445,17 @@
   Expect.isTrue(set4.isEmpty);
 }
 
+class A {}
+class B {}
+class C implements A, B {}
+
+void testASetFrom(setFrom) {
+  List<B> bList= <B>[new C()];
+  // Set.from allows to cast elements.
+  Set<A> aSet = setFrom(bList);
+  Expect.isTrue(aSet.length == 1);
+}
+
 main() {
   testMain(() => new HashSet());
   testMain(() => new LinkedHashSet());
@@ -508,4 +519,9 @@
   testCESetFrom((x) => new SplayTreeSet<CE>.from(x,
                                                  customCompare(20), validKey));
   testCESetFrom((x) => new SplayTreeSet<CE>.from(x, identityCompare));
+
+  testASetFrom((x) => new Set<A>.from(x));
+  testASetFrom((x) => new HashSet<A>.from(x));
+  testASetFrom((x) => new LinkedHashSet<A>.from(x));
+  testASetFrom((x) => new SplayTreeSet<A>.from(x));
 }
diff --git a/tests/html/html.status b/tests/html/html.status
index 2b538fc..dfd1a25 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -60,7 +60,6 @@
 fileapi_test/getFile: Pass, Fail # Issue 20488
 async_test: RuntimeError, OK  # Uses Isolate.spawn.
 isolates_test: RuntimeError, OK  # Uses Isolate.spawn.
-custom/created_callback_test: Fail # Support for created constructor. Issue 14835
 
 [ $compiler == none && ($runtime == drt || $runtime == dartium ) && $mode == debug ]
 websocket_test/websocket: Skip # Issue 17666
diff --git a/tests/isolate/isolate.status b/tests/isolate/isolate.status
index 3508c2c..157f638 100644
--- a/tests/isolate/isolate.status
+++ b/tests/isolate/isolate.status
@@ -183,3 +183,6 @@
 
 [ $compiler == dart2js && $cps_ir && $checked ]
 *: Skip # `assert` not implemented
+
+[ $compiler == precompiler && $runtime == dart_precompiled && $system == android ]
+*: Skip # Issue #26373
diff --git a/tests/language/language.status b/tests/language/language.status
index c3a14b9..ca50f91 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -219,3 +219,7 @@
 # TODO(vegorov) Encoding limitation: StoreField bytecode only supports 256
 # fields in an object.
 large_class_declaration_test: Skip
+
+[ $compiler == precompiler && $runtime == dart_precompiled && $system == android ]
+vm/optimized_guarded_field_isolates_test: Skip # Issue #26373
+issue23244_test: Skip # Issue #26373
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index 46f4331..adb3a7d 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -295,3 +295,13 @@
 
 # SIMDBC interpreter doesn't support --no_lazy_dispatchers
 no_lazy_dispatchers_test: SkipByDesign
+
+[ $compiler == precompiler && $runtime == dart_precompiled && $system == android ]
+io/*: Skip # Issue #26376
+
+typed_data_isolate_test: Skip # Issue #26376
+typed_array_test: Skip # Issue #26376
+typed_array_int64_uint64_test: Skip # Issue #26376
+
+oom_error_stacktrace_test: Skip # Issue #26377
+out_of_memory_test: Skip # Issue #26377
diff --git a/third_party/.gitignore b/third_party/.gitignore
index 074f02f..c819c4b 100644
--- a/third_party/.gitignore
+++ b/third_party/.gitignore
@@ -5,7 +5,7 @@
 !.gitignore
 !pkg
 !pkg_tested
-!boringssl
+!/boringssl
 !drt_resources
 !d8
 !7zip.tar.gz.sha1
diff --git a/third_party/boringssl/.gitignore b/third_party/boringssl/.gitignore
index 6eda124..a0cb5a8 100644
--- a/third_party/boringssl/.gitignore
+++ b/third_party/boringssl/.gitignore
@@ -1,2 +1,4 @@
 # ignore the checkout of boringssl.
 src/
+*.mk
+*.Makefile
diff --git a/tools/VERSION b/tools/VERSION
index 57ab3a2..ec6b498 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 1
 MINOR 17
 PATCH 0
-PRERELEASE 1
+PRERELEASE 2
 PRERELEASE_PATCH 0
diff --git a/tools/deps/dartium.deps/DEPS b/tools/deps/dartium.deps/DEPS
index f4ddd0c..b7500f2 100644
--- a/tools/deps/dartium.deps/DEPS
+++ b/tools/deps/dartium.deps/DEPS
@@ -9,7 +9,7 @@
 
 vars.update({
   "dartium_chromium_commit": "18554681ff1dfb53a553375c1b0c641fb3d63a1a",
-  "dartium_webkit_commit": "1ebe477439d73297f0e6090b474fd9b761407434",
+  "dartium_webkit_commit": "ef30dc04127c86283c1f5c5c6b0094d73b1e29df",
   "chromium_base_revision": "338390",
 
   # We use mirrors of all github repos to guarantee reproducibility and
diff --git a/tools/dom/src/Validators.dart b/tools/dom/src/Validators.dart
index 4dbe32c..ee42c51 100644
--- a/tools/dom/src/Validators.dart
+++ b/tools/dom/src/Validators.dart
@@ -167,10 +167,21 @@
       sanitizeNode(node, parent);
 
       var child = node.lastChild;
-      while (child != null) {
-        // Child may be removed during the walk.
-        var nextChild = child.previousNode;
-        walk(child, node);
+      while (null != child) {
+        var nextChild;
+        try {
+          // Child may be removed during the walk, and we may not
+          // even be able to get its previousNode.
+          nextChild = child.previousNode;
+        } catch (e) {
+          // Child appears bad, remove it. We want to check the rest of the
+          // children of node and, but we have no way of getting to the next
+          // child, so start again from the last child.
+          _removeNode(child, node);
+          child = null;
+          nextChild = node.lastChild;
+        }
+        if (child != null) walk(child, node);
         child = nextChild;
       }
     }
diff --git a/tools/dom/src/shared_html.dart b/tools/dom/src/shared_html.dart
index 27fa2b7..7342cdf 100644
--- a/tools/dom/src/shared_html.dart
+++ b/tools/dom/src/shared_html.dart
@@ -14,7 +14,10 @@
   if (callback == null) return null;
   // TODO(jacobr): we cast to _wrapZoneCallback/*<A, R>*/ to hack around missing
   // generic method support in zones.
-  return Zone.current.bindUnaryCallback(callback, runGuarded: true) as _wrapZoneCallback/*<A, R>*/;
+  // ignore: STRONG_MODE_DOWN_CAST_COMPOSITE
+  _wrapZoneCallback/*<A, R>*/ wrapped =
+      Zone.current.bindUnaryCallback(callback, runGuarded: true);
+  return wrapped;
 }
 
 _wrapZoneBinaryCallback/*<A, B, R>*/ _wrapBinaryZone/*<A, B, R>*/(_wrapZoneBinaryCallback/*<A, B, R>*/ callback) {
@@ -22,7 +25,10 @@
   if (callback == null) return null;
   // We cast to _wrapZoneBinaryCallback/*<A, B, R>*/ to hack around missing
   // generic method support in zones.
-  return Zone.current.bindBinaryCallback(callback, runGuarded: true) as _wrapZoneBinaryCallback/*<A, B, R>*/;
+  // ignore: STRONG_MODE_DOWN_CAST_COMPOSITE
+  _wrapZoneBinaryCallback/*<A, B, R>*/ wrapped =
+      Zone.current.bindBinaryCallback(callback, runGuarded: true);
+  return wrapped;
 }
 
 /**
diff --git a/tools/sdks/README b/tools/sdks/README
index f1f1fd3..5771731 100644
--- a/tools/sdks/README
+++ b/tools/sdks/README
@@ -8,9 +8,9 @@
 the subdirectories to have the special names "linux", "win", and "mac", which
 the download script is hardcoded to recognize.
 
-The linux SDK has had two extra dart executables added to the bin directory.
-'dart-mips' and 'dart-arm' are executables compiled to run on mips and arm
-processors, respectively.
+The linux SDK has three extra dart executables added to the bin directory.
+'dart-mips', 'dart-arm', and 'dart-arm64' are executables compiled to run on
+mips, arm, and arm64 (aarch64) processors, respectively.
 
 To upload new versions of these tar files, use the "upload_to_google_storage"
 tool in depot_tools, and download the new stable SDKs from the dartlang.org
diff --git a/tools/sdks/linux/dart-sdk.tar.gz.sha1 b/tools/sdks/linux/dart-sdk.tar.gz.sha1
index 9083f2b..3a4aab2 100644
--- a/tools/sdks/linux/dart-sdk.tar.gz.sha1
+++ b/tools/sdks/linux/dart-sdk.tar.gz.sha1
@@ -1 +1 @@
-360de5bc1ad8b525f2ccc98c80fd87131caaefe2
\ No newline at end of file
+0c27d9ced0e84a07ee98f99d5057121744138ac9
\ No newline at end of file
diff --git a/tools/sdks/mac/dart-sdk.tar.gz.sha1 b/tools/sdks/mac/dart-sdk.tar.gz.sha1
index 292199a..5e27c0c 100644
--- a/tools/sdks/mac/dart-sdk.tar.gz.sha1
+++ b/tools/sdks/mac/dart-sdk.tar.gz.sha1
@@ -1 +1 @@
-45bb23f239c67de5e01a24e7efcf4b323eb9c36c
\ No newline at end of file
+78d5d490650f7cb834a6e67ba882be106dd6324f
\ No newline at end of file
diff --git a/tools/sdks/win/dart-sdk.tar.gz.sha1 b/tools/sdks/win/dart-sdk.tar.gz.sha1
index 54587b2..060bbb7 100644
--- a/tools/sdks/win/dart-sdk.tar.gz.sha1
+++ b/tools/sdks/win/dart-sdk.tar.gz.sha1
@@ -1 +1 @@
-1264ca2ff3131284a53ccffadeb230835300c602
\ No newline at end of file
+6c0d135f57ac07f8ad70f21b29a3645bce2edb50
\ No newline at end of file
diff --git a/tools/test.dart b/tools/test.dart
index bbfdf25..e00357d 100755
--- a/tools/test.dart
+++ b/tools/test.dart
@@ -61,6 +61,9 @@
     var optionsParser = new TestOptionsParser();
     var configurations = optionsParser.parse(arguments);
     if (configurations != null && configurations.length > 0) {
+      // All the testing is carried out asynchronously in tasks created by this
+      // call.
+      // TODO(26372): Ensure that all tasks complete before the returned future.
       testConfigurations(configurations);
     }
   });
diff --git a/tools/test.py b/tools/test.py
index 9a32fa5..8db546e 100755
--- a/tools/test.py
+++ b/tools/test.py
@@ -18,6 +18,16 @@
   dart_test_script = string.join([tools_dir, dart_script_name], os.sep)
   command = [utils.CheckedInSdkExecutable(),
              '--checked', dart_test_script] + args
+
+  # The testing script potentially needs the android platform tools in PATH so
+  # we do that in ./tools/test.py (a similar logic exists in ./tools/build.py).
+  android_platform_tools = os.path.normpath(os.path.join(
+      tools_dir,
+      '../third_party/android_tools/sdk/platform-tools'))
+  if os.path.isdir(android_platform_tools):
+    os.environ['PATH'] = '%s%s%s' % (
+            os.environ['PATH'], os.pathsep, android_platform_tools)
+
   exit_code = subprocess.call(command)
   utils.DiagnoseExitCode(exit_code, command)
   return exit_code
diff --git a/tools/testing/dart/android.dart b/tools/testing/dart/android.dart
index 1d39071..bf83128 100644
--- a/tools/testing/dart/android.dart
+++ b/tools/testing/dart/android.dart
@@ -7,30 +7,44 @@
 import "dart:async";
 import "dart:convert" show LineSplitter, UTF8;
 import "dart:core";
+import "dart:collection";
 import "dart:io";
 
 import "path.dart";
 import "utils.dart";
 
-Future _executeCommand(String executable, List<String> args,
-    [String stdin = ""]) {
-  return _executeCommandRaw(executable, args, stdin).then((results) => null);
-}
+class AdbCommandResult {
+  final String command;
+  final String stdout;
+  final String stderr;
+  final int exitCode;
+  final bool timedOut;
 
-Future _executeCommandGetOutput(String executable, List<String> args,
-    [String stdin = ""]) {
-  return _executeCommandRaw(executable, args, stdin).then((output) => output);
+  AdbCommandResult(this.command, this.stdout, this.stderr, this.exitCode,
+                   this.timedOut);
+
+  void throwIfFailed() {
+    if (exitCode != 0) {
+      var error = "Running: $command failed:"
+                  "stdout:\n  ${stdout.trim()}\n"
+                  "stderr:\n  ${stderr.trim()}\n"
+                  "exitCode: $exitCode\n"
+                  "timedOut: $timedOut";
+      throw new Exception(error);
+    }
+  }
 }
 
 /**
- * [_executeCommandRaw] will write [stdin] to the standard input of the created
+ * [_executeCommand] will write [stdin] to the standard input of the created
  * process and will return a tuple (stdout, stderr).
  *
  * If the exit code of the process was nonzero it will complete with an error.
  * If starting the process failed, it will complete with an error as well.
  */
-Future _executeCommandRaw(String executable, List<String> args,
-    [String stdin = ""]) {
+Future<AdbCommandResult> _executeCommand(
+    String executable, List<String> args,
+    {String stdin, Duration timeout}) {
   Future<String> getOutput(Stream<List<int>> stream) {
     return stream
         .transform(UTF8.decoder)
@@ -38,31 +52,32 @@
         .then((data) => data.join(""));
   }
 
-  DebugLogger.info("Running: '\$ $executable ${args.join(' ')}'");
-  return Process.start(executable, args).then((Process process) {
+  return Process.start(executable, args).then((Process process) async {
     if (stdin != null && stdin != '') {
       process.stdin.write(stdin);
     }
     process.stdin.close();
 
-    var futures = [
-      getOutput(process.stdout),
-      getOutput(process.stderr),
-      process.exitCode
-    ];
-    return Future.wait(futures).then((results) {
-      bool success = results[2] == 0;
-      if (!success) {
-        var error = "Running: '\$ $executable ${args.join(' ')}' failed:"
-            "stdout: \n ${results[0]}"
-            "stderr: \n ${results[1]}"
-            "exitCode: \n ${results[2]}";
-        throw new Exception(error);
-      } else {
-        DebugLogger.info("Success: $executable finished");
-      }
-      return results[0];
-    });
+    Timer timer;
+    bool timedOut = false;
+    if (timeout != null) {
+      timer = new Timer(timeout, () {
+        timedOut = true;
+        process.kill(ProcessSignal.SIGTERM);
+        timer = null;
+      });
+    }
+
+    var results = await Future.wait([
+        getOutput(process.stdout),
+        getOutput(process.stderr),
+        process.exitCode
+    ]);
+    if (timer != null) timer.cancel();
+
+    String command = "$executable ${args.join(' ')}";
+    return new AdbCommandResult(
+        command, results[0], results[1], results[2], timedOut);
   });
 }
 
@@ -152,7 +167,7 @@
  * Helper class to create avd device configurations.
  */
 class AndroidHelper {
-  static Future createAvd(String name, String target) {
+  static Future createAvd(String name, String target) async {
     var args = [
       '--silent',
       'create',
@@ -166,7 +181,8 @@
       'armeabi-v7a'
     ];
     // We're adding newlines to stdin to simulate <enter>.
-    return _executeCommand("android", args, "\n\n\n\n");
+    var result = await _executeCommand("android", args, stdin: "\n\n\n\n");
+    result.throwIfFailed();
   }
 }
 
@@ -192,25 +208,15 @@
    * Polls the 'sys.boot_completed' property. Returns as soon as the property is
    * 1.
    */
-  Future waitForBootCompleted() {
-    var timeout = const Duration(seconds: 2);
-    var completer = new Completer();
-
-    checkUntilBooted() {
-      _adbCommandGetOutput(['shell', 'getprop', 'sys.boot_completed'])
-          .then((String stdout) {
-        stdout = stdout.trim();
-        if (stdout == '1') {
-          completer.complete();
-        } else {
-          new Timer(timeout, checkUntilBooted);
-        }
-      }).catchError((error) {
-        new Timer(timeout, checkUntilBooted);
-      });
+  Future waitForBootCompleted() async {
+    while (true) {
+      try {
+        AdbCommandResult result =
+            await _adbCommand(['shell', 'getprop', 'sys.boot_completed']);
+        if (result.stdout.trim() == '1') return;
+      } catch (_) { }
+      await new Future.delayed(const Duration(seconds: 2));
     }
-    checkUntilBooted();
-    return completer.future;
   }
 
   /**
@@ -299,22 +305,58 @@
     return _adbCommand(arguments);
   }
 
-  Future _adbCommand(List<String> adbArgs) {
-    if (_deviceId != null) {
-      var extendedAdbArgs = ['-s', _deviceId];
-      extendedAdbArgs.addAll(adbArgs);
-      adbArgs = extendedAdbArgs;
-    }
-    return _executeCommand("adb", adbArgs);
+  Future<AdbCommandResult> runAdbCommand(List<String> adbArgs,
+                                         {Duration timeout}) {
+    return _executeCommand(
+        "adb", _deviceSpecificArgs(adbArgs), timeout: timeout);
   }
 
-  Future<String> _adbCommandGetOutput(List<String> adbArgs) {
+  Future<AdbCommandResult> runAdbShellCommand(List<String> shellArgs,
+                                              {Duration timeout}) async {
+    const MARKER = 'AdbShellExitCode: ';
+
+    // The exitcode of 'adb shell ...' can be 0 even though the command failed
+    // with a non-zero exit code. We therefore explicitly print it to stdout and
+    // search for it.
+
+    var args = ['shell',
+                "${shellArgs.join(' ')} ; echo $MARKER \$?"];
+    AdbCommandResult result = await _executeCommand(
+        "adb", _deviceSpecificArgs(args), timeout: timeout);
+    int exitCode = result.exitCode;
+    var lines = result
+        .stdout.split('\n')
+        .where((line) => line.trim().length > 0)
+        .toList();
+    if (lines.length > 0) {
+      int index = lines.last.indexOf(MARKER);
+      if (index >= 0) {
+        exitCode = int.parse(
+            lines.last.substring(index + MARKER.length).trim());
+        exitCode = exitCode.toSigned(8);
+      } else {
+        // In case of timeouts, for example, we won't get the exitcode marker.
+        assert(result.exitCode != 0);
+      }
+    }
+    return new AdbCommandResult(
+        result.command, result.stdout, result.stderr, exitCode,
+        result.timedOut);
+  }
+
+  Future<AdbCommandResult> _adbCommand(List<String> adbArgs) async {
+    var result = await _executeCommand("adb", _deviceSpecificArgs(adbArgs));
+    result.throwIfFailed();
+    return result;
+  }
+
+  List<String> _deviceSpecificArgs(List<String> adbArgs) {
     if (_deviceId != null) {
       var extendedAdbArgs = ['-s', _deviceId];
       extendedAdbArgs.addAll(adbArgs);
       adbArgs = extendedAdbArgs;
     }
-    return _executeCommandGetOutput("adb", adbArgs);
+    return adbArgs;
   }
 }
 
@@ -350,3 +392,45 @@
 
   Intent(this.action, this.package, this.activity, [this.dataUri]);
 }
+
+/**
+ * Discovers all available devices and supports acquire/release.
+ */
+class AdbDevicePool {
+  final Queue<AdbDevice> _idleDevices = new Queue<AdbDevice>();
+  final Queue<Completer> _waiter = new Queue<Completer>();
+
+  AdbDevicePool(List<AdbDevice> idleDevices) {
+    _idleDevices.addAll(idleDevices);
+  }
+
+  static Future<AdbDevicePool> create() async {
+    var names = await AdbHelper.listDevices();
+    var devices = names.map((id) => new AdbDevice(id)).toList();
+    if (devices.length == 0) {
+      throw new Exception(
+          'No android devices found. '
+          'Please make sure "adb devices" shows your device!');
+    }
+    return new AdbDevicePool(devices);
+  }
+
+  Future<AdbDevice> acquireDevice() async {
+    if (_idleDevices.length > 0) {
+      return _idleDevices.removeFirst();
+    } else {
+      var completer = new Completer();
+      _waiter.add(completer);
+      return completer.future;
+    }
+  }
+
+  void releaseDevice(AdbDevice device) {
+    if (_waiter.length > 0) {
+      Completer completer = _waiter.removeFirst();
+      completer.complete(device);
+    } else {
+      _idleDevices.add(device);
+    }
+  }
+}
diff --git a/tools/testing/dart/compiler_configuration.dart b/tools/testing/dart/compiler_configuration.dart
index 161252a..7c0945e 100644
--- a/tools/testing/dart/compiler_configuration.dart
+++ b/tools/testing/dart/compiler_configuration.dart
@@ -79,7 +79,8 @@
             isDebug: isDebug,
             isChecked: isChecked,
             arch: configuration['arch'],
-            useBlobs: useBlobs);
+            useBlobs: useBlobs,
+            isAndroid: configuration['system'] == 'android');
       case 'none':
         return new NoneCompilerConfiguration(
             isDebug: isDebug,
@@ -302,11 +303,11 @@
 class PrecompilerCompilerConfiguration extends CompilerConfiguration {
   final String arch;
   final bool useBlobs;
+  final bool isAndroid;
 
-  PrecompilerCompilerConfiguration({bool isDebug, bool isChecked, String arch, bool useBlobs})
-      : super._subclass(isDebug: isDebug, isChecked: isChecked),
-        arch = arch,
-        useBlobs = useBlobs;
+  PrecompilerCompilerConfiguration({bool isDebug, bool isChecked,
+    this.arch, this.useBlobs, this.isAndroid})
+      : super._subclass(isDebug: isDebug, isChecked: isChecked);
 
   int computeTimeoutMultiplier() {
     int multiplier = 2;
@@ -345,6 +346,9 @@
     if (useBlobs) {
       args.add("--use_blobs");
     }
+    if (isAndroid && arch == 'arm') {
+      args.add('--no-sim-use-hardfp');
+    }
     args.addAll(arguments);
 
     return commandBuilder.getCompilationCommand('precompiler', tempDir, !useSdk,
@@ -357,7 +361,8 @@
       CommandBuilder commandBuilder,
       List arguments,
       Map<String, String> environmentOverrides) {
-    var cc, cc_flags, shared, libname;
+
+    var cc, shared, libname;
     if (Platform.isLinux) {
       cc = 'gcc';
       shared = '-shared';
@@ -369,17 +374,24 @@
     } else {
       throw "Platform not supported: ${Platform.operatingSystem}";
     }
+    if (isAndroid) {
+      // TODO: If we're not using "--use_blobs" we need to use the arm cross
+      // compiler instead of just 'gcc' for .
+    }
 
+    var cc_flags;
     if (arch == 'x64') {
       cc_flags = "-m64";
     } else if (arch == 'simarm64') {
       cc_flags = "-m64";
+    } else if (arch == 'ia32') {
+      cc_flags = "-m32";
     } else if (arch == 'simarm') {
       cc_flags = "-m32";
     } else if (arch == 'simmips') {
       cc_flags = "-m32";
     } else if (arch == 'arm') {
-      cc_flags = "";
+      cc_flags = null;
     } else if (arch == 'mips') {
       cc_flags = "-EL";
     } else {
@@ -387,13 +399,12 @@
     }
 
     var exec = cc;
-    var args = [
-      shared,
-      cc_flags,
+    var args = (cc_flags != null) ? [ shared, cc_flags ] : [ shared ];
+    args.addAll([
       '-o',
       '$tempDir/$libname',
       '$tempDir/precompiled.S'
-    ];
+    ]);
 
     return commandBuilder.getCompilationCommand('assemble', tempDir, !useSdk,
         bootstrapDependencies(buildDir), exec, args, environmentOverrides);
diff --git a/tools/testing/dart/runtime_configuration.dart b/tools/testing/dart/runtime_configuration.dart
index 7191342..b8e9e3d7 100644
--- a/tools/testing/dart/runtime_configuration.dart
+++ b/tools/testing/dart/runtime_configuration.dart
@@ -54,6 +54,9 @@
         return new DartProductRuntimeConfiguration();
 
       case 'dart_precompiled':
+        if (configuration['system'] == 'android') {
+          return new DartPrecompiledAdbRuntimeConfiguration(useBlobs: useBlobs);
+        }
         return new DartPrecompiledRuntimeConfiguration(useBlobs: useBlobs);
 
       case 'drt':
@@ -275,6 +278,32 @@
   }
 }
 
+class DartPrecompiledAdbRuntimeConfiguration
+      extends DartVmRuntimeConfiguration {
+  final bool useBlobs;
+  DartPrecompiledAdbRuntimeConfiguration({bool useBlobs}) : useBlobs = useBlobs;
+
+  List<Command> computeRuntimeCommands(
+      TestSuite suite,
+      CommandBuilder commandBuilder,
+      CommandArtifact artifact,
+      List<String> arguments,
+      Map<String, String> environmentOverrides) {
+    String script = artifact.filename;
+    String type = artifact.mimeType;
+    if (script != null && type != 'application/dart-precompiled') {
+      throw "dart_precompiled cannot run files of type '$type'.";
+    }
+
+    String precompiledRunner = suite.dartPrecompiledBinaryFileName;
+    return <Command>[
+      commandBuilder.getAdbPrecompiledCommand(precompiledRunner,
+                                              script,
+                                              useBlobs)
+    ];
+  }
+}
+
 /// Temporary runtime configuration for browser runtimes that haven't been
 /// migrated yet.
 // TODO(ahe): Remove this class.
diff --git a/tools/testing/dart/test_configurations.dart b/tools/testing/dart/test_configurations.dart
index ff48273..f8cd209 100644
--- a/tools/testing/dart/test_configurations.dart
+++ b/tools/testing/dart/test_configurations.dart
@@ -8,6 +8,7 @@
 import 'dart:io';
 import "dart:math" as math;
 
+import 'android.dart';
 import "browser_controller.dart";
 import "co19_test_config.dart";
 import "http_server.dart";
@@ -49,7 +50,7 @@
   new Path('utils/tests/peg'),
 ];
 
-void testConfigurations(List<Map> configurations) {
+Future testConfigurations(List<Map> configurations) async {
   var startTime = new DateTime.now();
   // Extract global options from first configuration.
   var firstConf = configurations[0];
@@ -281,26 +282,34 @@
     eventListener.add(new ExitCodeSetter());
   }
 
-  void startProcessQueue() {
-    // [firstConf] is needed here, since the ProcessQueue needs to know the
-    // settings of 'noBatch' and 'local_ip'
-    new ProcessQueue(
-        firstConf,
-        maxProcesses,
-        maxBrowserProcesses,
-        startTime,
-        testSuites,
-        eventListener,
-        allTestsFinished,
-        verbose,
-        recordingPath,
-        recordingOutputPath);
+  // If any of the configurations need to access android devices we'll first
+  // make a pool of all available adb devices.
+  AdbDevicePool adbDevicePool;
+  bool needsAdbDevicePool = configurations.any((Map conf) {
+    return conf['runtime'] == 'dart_precompiled' &&
+           conf['system'] == 'android';
+  });
+  if (needsAdbDevicePool) {
+    adbDevicePool = await AdbDevicePool.create();
   }
 
   // Start all the HTTP servers required before starting the process queue.
-  if (serverFutures.isEmpty) {
-    startProcessQueue();
-  } else {
-    Future.wait(serverFutures).then((_) => startProcessQueue());
+  if (!serverFutures.isEmpty) {
+    await Future.wait(serverFutures);
   }
+
+  // [firstConf] is needed here, since the ProcessQueue needs to know the
+  // settings of 'noBatch' and 'local_ip'
+  new ProcessQueue(
+      firstConf,
+      maxProcesses,
+      maxBrowserProcesses,
+      startTime,
+      testSuites,
+      eventListener,
+      allTestsFinished,
+      verbose,
+      recordingPath,
+      recordingOutputPath,
+      adbDevicePool);
 }
diff --git a/tools/testing/dart/test_options.dart b/tools/testing/dart/test_options.dart
index d4849a4..bc83dc0 100644
--- a/tools/testing/dart/test_options.dart
+++ b/tools/testing/dart/test_options.dart
@@ -157,7 +157,7 @@
           'system',
           'The operating system to run tests on',
           ['-s', '--system'],
-          ['linux', 'macos', 'windows'],
+          ['linux', 'macos', 'windows', 'android'],
           Platform.operatingSystem),
       new _TestOptionSpecification(
           'checked', 'Run tests in checked mode', ['--checked'], [], false,
diff --git a/tools/testing/dart/test_runner.dart b/tools/testing/dart/test_runner.dart
index 0d64136..8d189ae 100644
--- a/tools/testing/dart/test_runner.dart
+++ b/tools/testing/dart/test_runner.dart
@@ -18,6 +18,7 @@
 // CommandOutput.exitCode in subclasses of CommandOutput.
 import "dart:io" as io;
 import "dart:math" as math;
+import 'android.dart';
 import 'dependency_graph.dart' as dgraph;
 import "browser_controller.dart";
 import "path.dart";
@@ -344,6 +345,33 @@
       : super._("vm", executable, arguments, environmentOverrides);
 }
 
+class AdbPrecompilationCommand extends Command {
+  final String precompiledRunnerFilename;
+  final String precompiledTestDirectory;
+  final bool useBlobs;
+
+  AdbPrecompilationCommand._(this.precompiledRunnerFilename,
+                             this.precompiledTestDirectory,
+                             this.useBlobs)
+      : super._("adb_precompilation");
+
+  void _buildHashCode(HashCodeBuilder builder) {
+    super._buildHashCode(builder);
+    builder.add(precompiledRunnerFilename);
+    builder.add(precompiledTestDirectory);
+    builder.add(useBlobs);
+  }
+
+  bool _equal(AdbPrecompilationCommand other) =>
+      super._equal(other) &&
+      precompiledRunnerFilename == other.precompiledRunnerFilename &&
+      useBlobs == other.useBlobs &&
+      precompiledTestDirectory == other.precompiledTestDirectory;
+
+  String toString() => 'Steps to push precompiled runner and precompiled code '
+                       'to an attached device. Uses (and requires) adb.';
+}
+
 class JSCommandlineCommand extends ProcessCommand {
   JSCommandlineCommand._(
       String displayName, String executable, List<String> arguments,
@@ -610,6 +638,14 @@
     return _getUniqueCommand(command);
   }
 
+  AdbPrecompilationCommand getAdbPrecompiledCommand(String precompiledRunner,
+                                                    String testDirectory,
+                                                    bool useBlobs) {
+    var command = new AdbPrecompilationCommand._(
+        precompiledRunner, testDirectory, useBlobs);
+    return _getUniqueCommand(command);
+  }
+
   Command getJSCommandlineCommand(String displayName, executable, arguments,
       [environment = null]) {
     var command = new JSCommandlineCommand._(
@@ -1625,6 +1661,9 @@
   } else if (command is VmCommand) {
     return new VmCommandOutputImpl(
         command, exitCode, timedOut, stdout, stderr, time, pid);
+  } else if (command is AdbPrecompilationCommand) {
+    return new VmCommandOutputImpl(
+        command, exitCode, timedOut, stdout, stderr, time, pid);
   } else if (command is CompilationCommand) {
     if (command.displayName == 'precompiler' ||
         command.displayName == 'dart2snapshot') {
@@ -2396,6 +2435,7 @@
   final Map globalConfiguration;
   final int maxProcesses;
   final int maxBrowserProcesses;
+  AdbDevicePool adbDevicePool;
 
   // For dart2js and analyzer batch processing,
   // we keep a list of batch processes.
@@ -2406,7 +2446,8 @@
   bool _finishing = false;
 
   CommandExecutorImpl(
-      this.globalConfiguration, this.maxProcesses, this.maxBrowserProcesses);
+      this.globalConfiguration, this.maxProcesses, this.maxBrowserProcesses,
+      {this.adbDevicePool});
 
   Future cleanup() {
     assert(!_finishing);
@@ -2460,11 +2501,99 @@
           .runCommand(command.flavor, command, timeout, command.arguments);
     } else if (command is ScriptCommand) {
       return command.run();
+    } else if (command is AdbPrecompilationCommand) {
+      assert(adbDevicePool != null);
+      return adbDevicePool.acquireDevice().then((AdbDevice device) {
+        return _runAdbPrecompilationCommand(
+            device, command, timeout).whenComplete(() {
+          adbDevicePool.releaseDevice(device);
+        });
+      });
     } else {
       return new RunningProcess(command, timeout).run();
     }
   }
 
+  Future<CommandOutput> _runAdbPrecompilationCommand(
+      AdbDevice device, AdbPrecompilationCommand command, int timeout) async {
+    var runner = command.precompiledRunnerFilename;
+    var testdir = command.precompiledTestDirectory;
+    var devicedir = '/data/local/tmp/precompilation-testing';
+    var deviceTestDir = '/data/local/tmp/precompilation-testing/test';
+
+    // We copy all the files which the vm precompiler puts into the test
+    // directory.
+    List<String> files = new io.Directory(testdir)
+        .listSync()
+        .where((fse) => fse is io.File)
+        .map((file) => file.path)
+        .map((path) => path.substring(path.lastIndexOf('/') + 1))
+        .toList();
+
+    var timeoutDuration = new Duration(seconds: timeout);
+
+    // All closures are of type "Future<AdbCommandResult> run()"
+    List<Function> steps = [];
+
+    steps.add(() => device.runAdbShellCommand(
+          ['rm', '-Rf', deviceTestDir]));
+    steps.add(() => device.runAdbShellCommand(
+          ['mkdir', '-p', deviceTestDir]));
+    // TODO: We should find a way for us to cache the runner binary and avoid
+    // pushhing it for every single test (this is bad for SSD cycle time, test
+    // timing).
+    steps.add(() => device.runAdbCommand(
+          ['push', runner, '$devicedir/runner']));
+    steps.add(() => device.runAdbShellCommand(
+          ['chmod', '777', '$devicedir/runner']));
+
+    for (var file in files) {
+      steps.add(() => device.runAdbCommand(
+            ['push', '$testdir/$file', '$deviceTestDir/$file']));
+    }
+
+    if (command.useBlobs) {
+      steps.add(() => device.runAdbShellCommand(
+            ['$devicedir/runner', '--run-precompiled-snapshot=$deviceTestDir',
+             '--use_blobs', 'ignored.dart'], timeout: timeoutDuration));
+    } else {
+      steps.add(() => device.runAdbShellCommand(
+            ['$devicedir/runner', '--run-precompiled-snapshot=$deviceTestDir',
+             'ignored.dart'], timeout: timeoutDuration));
+    }
+
+    var stopwatch = new Stopwatch()..start();
+    var writer = new StringBuffer();
+
+    await device.waitForBootCompleted();
+    await device.waitForDevice();
+
+    AdbCommandResult result;
+    for (var i = 0; i < steps.length; i++) {
+      var fun = steps[i];
+      var commandStopwatch = new Stopwatch()..start();
+      result = await fun();
+
+      writer.writeln("Executing ${result.command}");
+      if (result.stdout.length > 0) {
+        writer.writeln("Stdout:\n${result.stdout.trim()}");
+      }
+      if (result.stderr.length > 0) {
+        writer.writeln("Stderr:\n${result.stderr.trim()}");
+      }
+      writer.writeln("ExitCode: ${result.exitCode}");
+      writer.writeln("Time: ${commandStopwatch.elapsed}");
+      writer.writeln("");
+
+      // If one command fails, we stop processing the others and return
+      // immediately.
+      if (result.exitCode != 0) break;
+    }
+    return createCommandOutput(
+        command, result.exitCode, result.timedOut, UTF8.encode('$writer'),
+        [], stopwatch.elapsed, false);
+  }
+
   BatchRunnerProcess _getBatchRunner(String identifier) {
     // Start batch processes if needed
     var runners = _batchProcesses[identifier];
@@ -2716,7 +2845,8 @@
       DateTime startTime, testSuites, this._eventListener, this._allDone,
       [bool verbose = false,
       String recordingOutputFile,
-      String recordedInputFile]) {
+      String recordedInputFile,
+      AdbDevicePool adbDevicePool]) {
     void setupForListing(TestCaseEnqueuer testCaseEnqueuer) {
       _graph.events
           .where((event) => event is dgraph.GraphSealedEvent)
@@ -2817,7 +2947,8 @@
         executor = new ReplayingCommandExecutor(new Path(recordedInputFile));
       } else {
         executor = new CommandExecutorImpl(
-            _globalConfiguration, maxProcesses, maxBrowserProcesses);
+            _globalConfiguration, maxProcesses,
+            maxBrowserProcesses, adbDevicePool: adbDevicePool);
       }
 
       // Run "runnable commands" using [executor] subject to
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index dbab65e..58b0937 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -2233,12 +2233,14 @@
   static String outputDir(Map configuration) {
     var result = '';
     var system = configuration['system'];
-    if (system == 'linux') {
+    if (system == 'linux' || system == 'android') {
       result = 'out/';
     } else if (system == 'macos') {
       result = 'xcodebuild/';
     } else if (system == 'windows') {
       result = 'build/';
+    } else {
+      throw new Exception('Unknown operating system: "$system"');
     }
     return result;
   }
@@ -2335,9 +2337,22 @@
       default:
         throw 'Unrecognized mode configuration: ${configuration['mode']}';
     }
+    var os;
+    switch (configuration['system']) {
+      case 'android':
+        os = 'Android';
+        break;
+      case 'linux':
+      case 'macos':
+      case 'windows':
+        os = '';
+        break;
+      default:
+        throw 'Unrecognized operating system: ${configuration['system']}';
+    }
     var arch = configuration['arch'].toUpperCase();
-    var normal = '$mode$arch';
-    var cross = '${mode}X$arch';
+    var normal = '$mode$os$arch';
+    var cross = '$mode${os}X$arch';
     var outDir = outputDir(configuration);
     var normalDir = new Directory(new Path('$outDir$normal').toNativePath());
     var crossDir = new Directory(new Path('$outDir$cross').toNativePath());