Version 2.0.0-dev.51.0

Merge commit 'c164f923970465e393b18c1eb31c2b46043f464a' into dev
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 83e13f6..710c9a7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,22 @@
+## 2.0.0-dev.51.0
+
+### Tool Changes
+
+#### dartfmt
+  * Fixes a runtime error when dart_style is itself run in Dart 2.
+  * Force splitting an empty block as the then body of an if with an else.
+  * Uses the new lowercase Dart 2 constant names.
+
+#### Pub
+
+* The `build` and `serve` commands will now fail and point users to
+  https://webdev.dartlang.org/dart-2
+
+#### dart2js
+
+* `async` functions now start synchronously. This will be the default behavior
+  across all tools. To temporarily opt-out, use the `--no-sync-async` flag.
+
 ## 2.0.0-dev.50.0
 
 ## 2.0.0-dev.49.0
@@ -13,28 +32,6 @@
 
 ## 2.0.0-dev.48.0
 
-### Language
-
-#### Strong Mode
-
-### Core library changes
-
-### Dart VM
-
-### Tool Changes
-
-#### Pub
-
-#### Other Tools
-
-## 2.0.0-dev.49.0
-
-## 2.0.0-dev.47.0
-
-### Tool Changes
-
-## 2.0.0-dev.48.0
-
 ### Core library changes
 
 * `dart:core`
diff --git a/DEPS b/DEPS
index 163bf8d..b6218f0 100644
--- a/DEPS
+++ b/DEPS
@@ -81,7 +81,7 @@
   #     minutes later.
   #
   # For more details, see https://github.com/dart-lang/sdk/issues/30164
-  "dart_style_tag": "@1.0.10",  # Please see the note above before updating.
+  "dart_style_tag": "@1.0.11",  # Please see the note above before updating.
 
   "dartdoc_tag" : "@v0.18.1",
   "fixnum_tag": "@0.10.5",
@@ -114,7 +114,7 @@
   "ply_rev": "@604b32590ffad5cbb82e4afef1d305512d06ae93",
   "pool_tag": "@1.3.4",
   "protobuf_tag": "@0.7.1",
-  "pub_rev": "@4947e0b3cb3ec77e4e8fe0d3141ce4dc60f43256",
+  "pub_rev": "@2e821bff00c00889afe5200e3a33f280ce942336",
   "pub_semver_tag": "@1.3.7",
   "quiver_tag": "@5aaa3f58c48608af5b027444d561270b53f15dbf",
   "resource_rev":"@af5a5bf65511943398146cf146e466e5f0b95cb9",
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/local_constructor_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/local_constructor_contributor.dart
index 1e5973c..ec71bf9 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/local_constructor_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/local_constructor_contributor.dart
@@ -109,12 +109,8 @@
 
     ClassElement classElement =
         resolutionMap.elementDeclaredByClassDeclaration(classDecl);
-    int relevance = optype.constructorSuggestionsFilter(
+    int relevance = optype.returnValueSuggestionsFilter(
         classElement?.type, DART_RELEVANCE_DEFAULT);
-    if (relevance == null) {
-      return;
-    }
-
     if (constructorDecl != null) {
       // Build a suggestion for explicitly declared constructor
       ConstructorElement element = constructorDecl.element;
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart
index 7966324..d22c4f5 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart
@@ -55,11 +55,9 @@
       }
     }
     if (optype.includeConstructorSuggestions) {
-      int relevance = optype.constructorSuggestionsFilter(
+      int relevance = optype.returnValueSuggestionsFilter(
           element.type, DART_RELEVANCE_DEFAULT);
-      if (relevance != null) {
-        _addConstructorSuggestions(element, relevance);
-      }
+      _addConstructorSuggestions(element, relevance);
     }
     if (optype.includeReturnValueSuggestions) {
       if (element.isEnum) {
diff --git a/pkg/analysis_server/lib/src/services/correction/fix.dart b/pkg/analysis_server/lib/src/services/correction/fix.dart
index 051a72d..3ba57d8 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix.dart
@@ -45,6 +45,7 @@
     errorCode == CompileTimeErrorCode.INVALID_ANNOTATION ||
     errorCode == CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT ||
     errorCode == CompileTimeErrorCode.PART_OF_NON_PART ||
+    errorCode == CompileTimeErrorCode.UNDEFINED_ANNOTATION ||
     errorCode ==
         CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT ||
     errorCode == CompileTimeErrorCode.URI_DOES_NOT_EXIST ||
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 869f385..580e541 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -214,7 +214,8 @@
         errorCode == StaticWarningCode.UNDEFINED_IDENTIFIER_AWAIT) {
       await _addFix_addAsync();
     }
-    if (errorCode == CompileTimeErrorCode.INVALID_ANNOTATION) {
+    if (errorCode == CompileTimeErrorCode.INVALID_ANNOTATION ||
+        errorCode == CompileTimeErrorCode.UNDEFINED_ANNOTATION) {
       if (node is Annotation) {
         Annotation annotation = node;
         Identifier name = annotation.name;
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 6f5f0d9..558129a 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
@@ -43,6 +43,12 @@
    */
   bool get isNullExpectedReturnTypeConsideredDynamic => true;
 
+  /**
+   * Return `true` if contributors should suggest constructors in contexts where
+   * there is no `new` or `const` keyword.
+   */
+  bool get suggestConstructorsWithoutNew => false;
+
   bool get usingFastaParser => analyzer.Parser.useFasta;
 
   void addTestSource(String content) {
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 a72473f..8f6efea 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
@@ -529,7 +529,7 @@
     assertNotSuggested('a');
     assertNotSuggested('main');
     assertSuggestClass('A');
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('A');
     }
     assertSuggestClass('Object');
@@ -621,7 +621,7 @@
     assertNotSuggested('partT8');
 
     assertSuggestClass('A', elemFile: '/testAB.dart');
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('A');
     }
     assertNotSuggested('_B');
@@ -1194,7 +1194,7 @@
         class Z { }''');
     await computeSuggestions();
     assertSuggestClass('C');
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('C');
     }
     assertNotSuggested('H');
@@ -1580,7 +1580,7 @@
     assertNotSuggested('F2');
     assertNotSuggested('T2');
     assertSuggestClass('A');
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('A');
     }
     assertSuggestFunction('F1', 'dynamic');
@@ -1629,7 +1629,7 @@
     assertNotSuggested('F2');
     assertNotSuggested('T2');
     assertSuggestClass('A');
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('A');
     }
     assertSuggestFunction('F1', 'dynamic');
@@ -1802,7 +1802,7 @@
     expect(suggestion.docSummary, 'My class.\nShort description.');
     expect(suggestion.docComplete,
         'My class.\nShort description.\n\nLonger description.');
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('A');
     }
   }
@@ -1908,7 +1908,7 @@
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
     assertSuggestClass('A');
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('A');
     }
     assertSuggestFunction('F1', '_B');
@@ -2488,7 +2488,7 @@
     assertNotSuggested('F2');
     assertNotSuggested('T2');
     assertSuggestClass('A');
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('A');
     }
     assertSuggestFunction('F1', 'dynamic');
@@ -2629,7 +2629,7 @@
     assertSuggestConstructor('C',
         elemOffset: -1,
         relevance: DART_RELEVANCE_DEFAULT + DART_RELEVANCE_BOOST_SUBTYPE);
-    assertNotSuggested('D');
+    assertSuggestConstructor('D', elemOffset: -1);
   }
 
   test_InstanceCreationExpression_imported() async {
@@ -2711,7 +2711,7 @@
     await computeSuggestions();
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('Object');
       assertSuggestConstructor('C1');
     } else {
@@ -2995,7 +2995,7 @@
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
     assertSuggestClass('Object');
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('Object');
     }
     // Simulate unresolved imported library,
@@ -3246,7 +3246,7 @@
     assertNotSuggested('f');
     assertNotSuggested('_g');
     assertSuggestClass('bool');
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       // TODO(brianwilkerson) Should not suggest constructors for classes that
       // cannot be instantiated.
       assertSuggestConstructor('bool');
@@ -3494,7 +3494,7 @@
 
     await computeSuggestions();
     assertSuggestClass('ClassInLocalContext');
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('ClassInLocalContext');
     }
     // Assert contributor does not include results from 2nd context.
@@ -3876,7 +3876,7 @@
     expect(replacementOffset, completionOffset - 1);
     expect(replacementLength, 1);
     assertSuggestClass('A');
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('A');
     }
     assertNotSuggested('X');
diff --git a/pkg/analysis_server/test/services/completion/dart/local_constructor_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/local_constructor_contributor_test.dart
index e6dfb14..473e297 100644
--- a/pkg/analysis_server/test/services/completion/dart/local_constructor_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/local_constructor_contributor_test.dart
@@ -91,7 +91,7 @@
     assertNotSuggested('bar');
     assertNotSuggested('hasLength');
     assertNotSuggested('identical');
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('B');
     } else {
       assertNotSuggested('B');
@@ -122,7 +122,7 @@
     assertNotSuggested('bar');
     assertNotSuggested('hasLength');
     assertNotSuggested('identical');
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('B');
     } else {
       assertNotSuggested('B');
@@ -154,7 +154,7 @@
     assertNotSuggested('bar');
     assertNotSuggested('hasLength');
     assertNotSuggested('identical');
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('B');
     } else {
       assertNotSuggested('B');
@@ -188,7 +188,7 @@
     assertNotSuggested('bar');
     assertNotSuggested('hasLength');
     assertNotSuggested('identical');
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('B');
     } else {
       assertNotSuggested('B');
@@ -220,7 +220,7 @@
     assertNotSuggested('bar');
     assertNotSuggested('hasLength');
     assertNotSuggested('identical');
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('B');
     } else {
       assertNotSuggested('B');
@@ -251,7 +251,7 @@
     assertNotSuggested('bar');
     assertNotSuggested('hasLength');
     assertNotSuggested('identical');
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('B');
     } else {
       assertNotSuggested('B');
@@ -283,7 +283,7 @@
     assertNotSuggested('bar');
     assertNotSuggested('hasLength');
     assertNotSuggested('identical');
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('B');
     } else {
       assertNotSuggested('B');
@@ -314,7 +314,7 @@
     assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
     assertNotSuggested('hasLength');
     assertNotSuggested('identical');
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('B');
     } else {
       assertNotSuggested('B');
@@ -379,7 +379,7 @@
     expect(replacementLength, 0);
     assertNotSuggested('a');
     assertNotSuggested('main');
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('A');
     } else {
       assertNotSuggested('A');
@@ -399,7 +399,7 @@
 
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('A');
     } else {
       assertNotSuggested('A');
@@ -428,7 +428,7 @@
 
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('A');
     } else {
       assertNotSuggested('A');
@@ -454,7 +454,7 @@
 
     expect(replacementOffset, completionOffset - 3);
     expect(replacementLength, 3);
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('A');
     } else {
       assertNotSuggested('A');
@@ -483,7 +483,7 @@
 
     expect(replacementOffset, completionOffset - 1);
     expect(replacementLength, 1);
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('A');
     } else {
       assertNotSuggested('A');
@@ -508,7 +508,7 @@
     expect(replacementLength, 0);
     assertNotSuggested('a');
     assertNotSuggested('main');
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('A');
     } else {
       assertNotSuggested('A');
@@ -589,7 +589,7 @@
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
 
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('X');
       assertSuggestConstructor('Z');
     } else {
@@ -987,7 +987,7 @@
     expect(replacementOffset, completionOffset - 1);
     expect(replacementLength, 1);
 
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('X');
       assertSuggestConstructor('Z');
     } else {
@@ -1241,7 +1241,7 @@
     assertNotSuggested('b');
     assertNotSuggested('_c');
     assertNotSuggested('a');
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('A');
       assertSuggestConstructor('X');
     } else {
@@ -1518,7 +1518,7 @@
     assertNotSuggested('x');
     assertNotSuggested('f');
     assertNotSuggested('foo');
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('C');
     } else {
       assertNotSuggested('C');
@@ -1568,7 +1568,7 @@
     assertNotSuggested('x');
     assertNotSuggested('f');
     assertNotSuggested('foo');
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('C');
     } else {
       assertNotSuggested('C');
@@ -1758,7 +1758,7 @@
     expect(replacementLength, 0);
     assertNotSuggested('foo');
     assertNotSuggested('a');
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('A');
     } else {
       assertNotSuggested('A');
@@ -1801,7 +1801,7 @@
     expect(replacementLength, 0);
     assertNotSuggested('A');
     assertNotSuggested('F1');
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('C');
     } else {
       assertNotSuggested('C');
@@ -2190,7 +2190,7 @@
     assertNotSuggested('b');
     assertNotSuggested('_c');
     assertNotSuggested('Object');
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('A');
     } else {
       assertNotSuggested('A');
@@ -2209,7 +2209,7 @@
     expect(replacementLength, 0);
     assertNotSuggested('a');
     assertNotSuggested('main');
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('A');
     } else {
       assertNotSuggested('A');
@@ -2228,7 +2228,7 @@
     assertNotSuggested('b');
     assertNotSuggested('_c');
     assertNotSuggested('Object');
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('A');
     } else {
       assertNotSuggested('A');
@@ -2316,7 +2316,7 @@
     assertNotSuggested('x');
     assertNotSuggested('f');
     assertNotSuggested('foo');
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('C');
     } else {
       assertNotSuggested('C');
@@ -2439,7 +2439,7 @@
     assertSuggestConstructor('C',
         elemOffset: -1,
         relevance: DART_RELEVANCE_DEFAULT + DART_RELEVANCE_BOOST_SUBTYPE);
-    assertNotSuggested('D');
+    assertSuggestConstructor('D', elemOffset: -1);
   }
 
   test_InstanceCreationExpression_assignment_expression_filter2() async {
@@ -2460,7 +2460,7 @@
     assertSuggestConstructor('C',
         elemOffset: -1,
         relevance: DART_RELEVANCE_DEFAULT + DART_RELEVANCE_BOOST_SUBTYPE);
-    assertNotSuggested('D');
+    assertSuggestConstructor('D', elemOffset: -1);
   }
 
   test_InstanceCreationExpression_imported() async {
@@ -2509,7 +2509,7 @@
     assertSuggestConstructor('B',
         elemOffset: -1,
         relevance: DART_RELEVANCE_DEFAULT + DART_RELEVANCE_BOOST_SUBTYPE);
-    assertNotSuggested('C');
+    assertSuggestConstructor('C', elemOffset: -1);
   }
 
   test_InstanceCreationExpression_invocationArgument_named() async {
@@ -2527,7 +2527,7 @@
     assertSuggestConstructor('B',
         elemOffset: -1,
         relevance: DART_RELEVANCE_DEFAULT + DART_RELEVANCE_BOOST_SUBTYPE);
-    assertNotSuggested('C');
+    assertSuggestConstructor('C', elemOffset: -1);
   }
 
   test_InstanceCreationExpression_unimported() async {
@@ -2559,7 +2559,7 @@
     assertSuggestConstructor('C',
         elemOffset: -1,
         relevance: DART_RELEVANCE_DEFAULT + DART_RELEVANCE_BOOST_SUBTYPE);
-    assertNotSuggested('D');
+    assertSuggestConstructor('D', elemOffset: -1);
   }
 
   test_InstanceCreationExpression_variable_declaration_filter2() async {
@@ -2579,7 +2579,7 @@
     assertSuggestConstructor('C',
         elemOffset: -1,
         relevance: DART_RELEVANCE_DEFAULT + DART_RELEVANCE_BOOST_SUBTYPE);
-    assertNotSuggested('D');
+    assertSuggestConstructor('D', elemOffset: -1);
   }
 
   test_InterpolationExpression() async {
@@ -2608,7 +2608,7 @@
     assertNotSuggested('T2');
     assertNotSuggested('F2');
     assertNotSuggested('D2');
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('C2');
     } else {
       assertNotSuggested('C2');
@@ -2642,7 +2642,7 @@
     assertNotSuggested('T2');
     assertNotSuggested('F2');
     assertNotSuggested('D2');
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('C2');
     } else {
       assertNotSuggested('C2');
@@ -2728,7 +2728,7 @@
     assertNotSuggested('main');
     assertNotSuggested('foo');
     assertNotSuggested('bar');
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('A');
     } else {
       assertNotSuggested('A');
@@ -2853,7 +2853,7 @@
     assertNotSuggested('T2');
     assertNotSuggested('F2');
     assertNotSuggested('D2');
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('C2');
     } else {
       assertNotSuggested('C2');
@@ -3579,7 +3579,7 @@
     expect(replacementOffset, completionOffset - 1);
     expect(replacementLength, 1);
     assertNotSuggested('A');
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('X');
     } else {
       assertNotSuggested('X');
@@ -3785,7 +3785,7 @@
     addTestSource('class A {String g(int x) {var t; switch(x) {case 0: ^}}}');
     await computeSuggestions();
 
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('A');
     } else {
       assertNotSuggested('A');
@@ -4135,7 +4135,7 @@
     assertNotSuggested('X');
     assertNotSuggested('_B');
     assertNotSuggested('Y');
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('C');
     } else {
       assertNotSuggested('C');
@@ -4171,7 +4171,7 @@
     assertNotSuggested('bar2');
     assertNotSuggested('_B');
     assertNotSuggested('Y');
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('C');
     } else {
       assertNotSuggested('C');
diff --git a/pkg/analysis_server/test/services/completion/dart/local_library_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/local_library_contributor_test.dart
index 0df1a0b..e3d07b2 100644
--- a/pkg/analysis_server/test/services/completion/dart/local_library_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/local_library_contributor_test.dart
@@ -128,8 +128,8 @@
     assertSuggestConstructor('C',
         elemOffset: -1,
         relevance: DART_RELEVANCE_DEFAULT + DART_RELEVANCE_BOOST_SUBTYPE);
-    // D is sorted out
-    assertNotSuggested('D');
+    // D has the default relevance
+    assertSuggestConstructor('D', elemOffset: -1);
 
     // Suggested by ConstructorContributor
     assertNotSuggested('Local');
@@ -179,8 +179,8 @@
     assertSuggestConstructor('C',
         elemOffset: -1,
         relevance: DART_RELEVANCE_DEFAULT + DART_RELEVANCE_BOOST_SUBTYPE);
-    // D is sorted out
-    assertNotSuggested('D');
+    // D has the default relevance
+    assertSuggestConstructor('D', elemOffset: -1);
 
     // Suggested by ConstructorContributor
     assertNotSuggested('Local');
@@ -219,7 +219,7 @@
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
     assertSuggestClass('A');
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('A');
     }
     assertSuggestFunction('af', 'int',
@@ -266,7 +266,7 @@
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
     assertSuggestClass('B');
-    if (previewDart2) {
+    if (suggestConstructorsWithoutNew) {
       assertSuggestConstructor('B');
     }
     assertSuggestFunction('bf', 'int',
diff --git a/pkg/analysis_server/test/services/completion/dart/override_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/override_contributor_test.dart
index 9b27990..73bc6b4 100644
--- a/pkg/analysis_server/test/services/completion/dart/override_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/override_contributor_test.dart
@@ -176,6 +176,53 @@
         selectionLength: 22);
   }
 
+  @failingTest
+  test_withOverrideAnnotation() async {
+    addTestSource('''
+class A {
+  method() {}
+  int age;
+}
+
+class B extends A {
+  @override
+  ^
+}
+''');
+    await computeSuggestions();
+    _assertOverride('''
+method() {
+    // TODO: implement method
+    return super.method();
+  }''',
+        displayText: 'method() { … }',
+        selectionOffset: 45,
+        selectionLength: 22);
+  }
+
+  @failingTest
+  test_insideBareClass() async {
+    addTestSource('''
+class A {
+  method() {}
+  int age;
+}
+
+class B extends A {
+  ^
+}
+''');
+    await computeSuggestions();
+    _assertOverride('''
+method() {
+    // TODO: implement method
+    return super.method();
+  }''',
+        displayText: 'method() { … }',
+        selectionOffset: 45,
+        selectionLength: 22);
+  }
+
   CompletionSuggestion _assertOverride(String completion,
       {String displayText, int selectionOffset, int selectionLength}) {
     CompletionSuggestion cs = getSuggest(
diff --git a/pkg/analysis_server/test/services/correction/assist_test.dart b/pkg/analysis_server/test/services/correction/assist_test.dart
index 6600839e..72e36b6 100644
--- a/pkg/analysis_server/test/services/correction/assist_test.dart
+++ b/pkg/analysis_server/test/services/correction/assist_test.dart
@@ -38,6 +38,8 @@
   String resultCode;
   LinkedEditGroup linkedPositionGroup;
 
+  bool get omitNew => false;
+
   /**
    * Asserts that there is an [Assist] of the given [kind] at [offset] which
    * produces the [expected] code when applied to [testCode].
@@ -3538,7 +3540,7 @@
 }
 ''');
     _setCaretLocation();
-    if (previewDart2) {
+    if (omitNew) {
       await assertHasAssist(DartAssistKind.FLUTTER_WRAP_CENTER, '''
 import 'package:flutter/widgets.dart';
 class FakeFlutter {
@@ -3595,7 +3597,7 @@
 }
 ''');
     _setCaretLocation();
-    if (previewDart2) {
+    if (omitNew) {
       await assertHasAssist(DartAssistKind.FLUTTER_WRAP_COLUMN, '''
 import 'package:flutter/widgets.dart';
 
@@ -3649,7 +3651,7 @@
 }
 ''');
     _setStartEndSelection();
-    if (previewDart2) {
+    if (omitNew) {
       await assertHasAssist(DartAssistKind.FLUTTER_WRAP_COLUMN, '''
 import 'package:flutter/widgets.dart';
 
@@ -3747,7 +3749,7 @@
 }
 ''');
     _setCaretLocation();
-    if (previewDart2) {
+    if (omitNew) {
       await assertHasAssist(DartAssistKind.FLUTTER_WRAP_PADDING, '''
 import 'package:flutter/widgets.dart';
 class FakeFlutter {
@@ -3793,7 +3795,7 @@
 }
 ''');
     _setStartEndSelection();
-    if (previewDart2) {
+    if (omitNew) {
       await assertHasAssist(DartAssistKind.FLUTTER_WRAP_ROW, '''
 import 'package:flutter/widgets.dart';
 
@@ -3950,7 +3952,7 @@
 }
 ''');
     _setCaretLocation();
-    if (previewDart2) {
+    if (omitNew) {
       await assertHasAssist(DartAssistKind.FLUTTER_WRAP_GENERIC, '''
 import 'package:flutter/widgets.dart';
 class FakeFlutter {
@@ -4019,7 +4021,7 @@
 }\r
 ''');
     _setCaretLocation();
-    if (previewDart2) {
+    if (omitNew) {
       await assertHasAssist(DartAssistKind.FLUTTER_WRAP_GENERIC, '''
 import 'package:flutter/widgets.dart';
 class FakeFlutter {\r
@@ -4079,7 +4081,7 @@
 }
 ''');
     _setCaretLocation();
-    if (previewDart2) {
+    if (omitNew) {
       await assertHasAssist(DartAssistKind.FLUTTER_WRAP_GENERIC, '''
 import 'package:flutter/widgets.dart';
 class FakeFlutter {
@@ -4115,7 +4117,7 @@
 }
 ''');
     _setCaretLocation();
-    if (previewDart2) {
+    if (omitNew) {
       await assertHasAssist(DartAssistKind.FLUTTER_WRAP_GENERIC, '''
 import 'package:flutter/widgets.dart';
 class FakeFlutter {
@@ -4148,7 +4150,7 @@
 }
 ''');
     _setCaretLocation();
-    if (previewDart2) {
+    if (omitNew) {
       await assertHasAssist(DartAssistKind.FLUTTER_WRAP_GENERIC, '''
 import 'package:flutter/widgets.dart';
 class FakeFlutter {
diff --git a/pkg/analyzer/doc/tasks.html b/pkg/analyzer/doc/tasks.html
index 960dc69..e2de682 100644
--- a/pkg/analyzer/doc/tasks.html
+++ b/pkg/analyzer/doc/tasks.html
@@ -344,7 +344,6 @@
   TYPE_PROVIDER -> PartiallyResolveUnitReferencesTask
   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/analysis/session.dart b/pkg/analyzer/lib/dart/analysis/session.dart
index 8e58253..a39a2f7 100644
--- a/pkg/analyzer/lib/dart/analysis/session.dart
+++ b/pkg/analyzer/lib/dart/analysis/session.dart
@@ -59,6 +59,12 @@
   Future<ParseResult> getParsedAst(String path);
 
   /**
+   * Return information about the results of parsing the file with the given
+   * absolute, normalized [path].
+   */
+  ParseResult getParsedAstSync(String path);
+
+  /**
    * Return a future that will complete with information about the results of
    * resolving the file with the given absolute, normalized [path].
    */
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index beb7369..b2743a7 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -151,6 +151,7 @@
   CompileTimeErrorCode.INTEGER_LITERAL_OUT_OF_RANGE,
   CompileTimeErrorCode.INVALID_ANNOTATION,
   CompileTimeErrorCode.INVALID_ANNOTATION_FROM_DEFERRED_LIBRARY,
+  CompileTimeErrorCode.INVALID_ANNOTATION_GETTER,
   CompileTimeErrorCode.INVALID_CONSTANT,
   CompileTimeErrorCode.INVALID_CONSTRUCTOR_NAME,
   CompileTimeErrorCode.INVALID_FACTORY_NAME_NOT_A_CLASS,
@@ -231,6 +232,7 @@
   CompileTimeErrorCode.SUPER_IN_REDIRECTING_CONSTRUCTOR,
   CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF,
   CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS,
+  CompileTimeErrorCode.UNDEFINED_ANNOTATION,
   CompileTimeErrorCode.UNDEFINED_CLASS,
   CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER,
   CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT,
diff --git a/pkg/analyzer/lib/src/command_line/arguments.dart b/pkg/analyzer/lib/src/command_line/arguments.dart
index c4f50a40..263d250 100644
--- a/pkg/analyzer/lib/src/command_line/arguments.dart
+++ b/pkg/analyzer/lib/src/command_line/arguments.dart
@@ -65,10 +65,8 @@
     options.implicitDynamic = !args[noImplicitDynamicFlag];
     verbose('$noImplicitDynamicFlag = ${options.implicitDynamic}');
   }
-  if (args.wasParsed(strongModeFlag)) {
-    options.strongMode = args[strongModeFlag];
-    verbose('$strongModeFlag = ${options.strongMode}');
-  }
+  options.strongMode = args[strongModeFlag];
+  verbose('$strongModeFlag = ${options.strongMode}');
   try {
     if (args.wasParsed(lintsFlag)) {
       options.lint = args[lintsFlag];
@@ -178,8 +176,9 @@
       hide: ddc && hide);
   parser.addFlag(strongModeFlag,
       help: 'Enable strong static checks (https://goo.gl/DqcBsw).',
-      defaultsTo: ddc,
-      hide: ddc);
+      defaultsTo: true,
+      hide: ddc,
+      negatable: true);
   parser.addFlag(declarationCastsFlag,
       negatable: true,
       help: 'Disable declaration casts in strong mode (https://goo.gl/cTLz40).',
@@ -294,6 +293,9 @@
     if (abbreviation != null) {
       knownAbbreviations.add(abbreviation);
     }
+    if (option.negatable) {
+      knownOptions.add('no-$name');
+    }
   });
   String optionName(int prefixLength, String argument) {
     int equalsOffset = argument.lastIndexOf('=');
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index d48b1d6..8085a6b 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -855,6 +855,21 @@
    * resolved unit).
    */
   Future<ParseResult> parseFile(String path) async {
+    return parseFileSync(path);
+  }
+
+  /**
+   * Return a [ParseResult] for the file with the given [path].
+   *
+   * The [path] must be absolute and normalized.
+   *
+   * The [path] can be any file - explicitly or implicitly analyzed, or neither.
+   *
+   * The parsing is performed in the method itself, and the result is not
+   * produced through the [results] stream (just because it is not a fully
+   * resolved unit).
+   */
+  ParseResult parseFileSync(String path) {
     _throwIfNotAbsolutePath(path);
     FileState file = _fileTracker.verifyApiSignature(path);
     RecordingErrorListener listener = new RecordingErrorListener();
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
index e16375c..b3b5230 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -34,6 +34,8 @@
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:analyzer/src/kernel/resynthesize.dart';
+import 'package:analyzer/src/lint/linter.dart';
+import 'package:analyzer/src/lint/linter_visitor.dart';
 import 'package:analyzer/src/services/lint.dart';
 import 'package:analyzer/src/task/dart.dart';
 import 'package:analyzer/src/task/strong/checker.dart';
@@ -353,22 +355,34 @@
 
     ErrorReporter errorReporter = _getErrorReporter(file);
 
-    List<AstVisitor> visitors = <AstVisitor>[];
+    var nodeRegistry = new NodeLintRegistry(_analysisOptions.enableTiming);
+    var visitors = <AstVisitor>[];
     for (Linter linter in _analysisOptions.lintRules) {
-      AstVisitor visitor = linter.getVisitor();
-      if (visitor != null) {
-        linter.reporter = errorReporter;
-        if (_analysisOptions.enableTiming) {
-          visitor = new TimedAstVisitor(visitor, lintRegistry.getTimer(linter));
+      linter.reporter = errorReporter;
+      if (linter is NodeLintRule) {
+        (linter as NodeLintRule).registerNodeProcessors(nodeRegistry);
+      } else {
+        AstVisitor visitor = linter.getVisitor();
+        if (visitor != null) {
+          if (_analysisOptions.enableTiming) {
+            var timer = lintRegistry.getTimer(linter);
+            visitor = new TimedAstVisitor(visitor, timer);
+          }
+          visitors.add(visitor);
         }
-        visitors.add(visitor);
       }
     }
 
-    AstVisitor visitor = new ExceptionHandlingDelegatingAstVisitor(
-        visitors, ExceptionHandlingDelegatingAstVisitor.logException);
+    // Run lints that handle specific node types.
+    unit.accept(new LinterVisitor(
+        nodeRegistry, ExceptionHandlingDelegatingAstVisitor.logException));
 
-    unit.accept(visitor);
+    // Run visitor based lints.
+    if (visitors.isNotEmpty) {
+      AstVisitor visitor = new ExceptionHandlingDelegatingAstVisitor(
+          visitors, ExceptionHandlingDelegatingAstVisitor.logException);
+      unit.accept(visitor);
+    }
   }
 
   void _computePendingMissingRequiredParameters(
diff --git a/pkg/analyzer/lib/src/dart/analysis/session.dart b/pkg/analyzer/lib/src/dart/analysis/session.dart
index caadbdb..37ad32e 100644
--- a/pkg/analyzer/lib/src/dart/analysis/session.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/session.dart
@@ -86,9 +86,14 @@
   }
 
   @override
-  Future<ParseResult> getParsedAst(String path) {
+  Future<ParseResult> getParsedAst(String path) async {
+    return getParsedAstSync(path);
+  }
+
+  @override
+  ParseResult getParsedAstSync(String path) {
     _checkConsistency();
-    return _driver.parseFile(path);
+    return _driver.parseFileSync(path);
   }
 
   @override
diff --git a/pkg/analyzer/lib/src/dart/ast/token.dart b/pkg/analyzer/lib/src/dart/ast/token.dart
index 09da763..4b0b503 100644
--- a/pkg/analyzer/lib/src/dart/ast/token.dart
+++ b/pkg/analyzer/lib/src/dart/ast/token.dart
@@ -12,6 +12,8 @@
         KeywordToken,
         SimpleToken,
         StringToken,
+        SyntheticBeginToken,
         SyntheticKeywordToken,
         SyntheticStringToken,
+        SyntheticToken,
         TokenClass;
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
index c3dba9c..1ee3f0b 100644
--- a/pkg/analyzer/lib/src/dart/ast/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -2768,8 +2768,8 @@
    * A function that can be used with instances of this class to log and then
    * ignore any exceptions that are thrown by any of the delegates.
    */
-  static void logException(AstNode node, AstVisitor visitor, dynamic exception,
-      StackTrace stackTrace) {
+  static void logException(
+      AstNode node, Object visitor, dynamic exception, StackTrace stackTrace) {
     StringBuffer buffer = new StringBuffer();
     buffer.write('Exception while using a ${visitor.runtimeType} to visit a ');
     AstNode currentNode = node;
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index 63cfad3..4be6d72 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -1408,6 +1408,17 @@
               "changing the import to not be deferred.");
 
   /**
+   * 15 Metadata: Metadata consists of a series of annotations, each of which
+   * begin with the character @, followed by a constant expression that must be
+   * either a reference to a compile-time constant variable, or a call to a
+   * constant constructor.
+   */
+  static const CompileTimeErrorCode INVALID_ANNOTATION_GETTER =
+      const CompileTimeErrorCode(
+          'INVALID_ANNOTATION_GETTER', "Getters cannot be used as annotations.",
+          correction: "Try using a top-level variable or a field.");
+
+  /**
    * 15.31 Identifier Reference: It is a compile-time error if any of the
    * identifiers async, await or yield is used as an identifier in a function
    * body marked with either async, async* or sync*.
@@ -2399,6 +2410,19 @@
           "another typedef.");
 
   /**
+   * 15 Metadata: Metadata consists of a series of annotations, each of which
+   * begin with the character @, followed by a constant expression that must be
+   * either a reference to a compile-time constant variable, or a call to a
+   * constant constructor.
+   */
+  static const CompileTimeErrorCode UNDEFINED_ANNOTATION =
+      const CompileTimeErrorCode(
+          'UNDEFINED_ANNOTATION', "Undefined name '{0}' used as an annotation.",
+          correction:
+              "Try defining the name or importing it from another library.",
+          isUnresolvedIdentifier: true);
+
+  /**
    * 16.12.2 Const: It is a compile-time error if <i>T</i> is not a class
    * accessible in the current scope, optionally followed by type arguments.
    */
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index bb67cb9..9c01d75 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -526,8 +526,14 @@
     Statement elsePart = popIfNotNull(elseToken);
     Statement thenPart = pop();
     ParenthesizedExpression condition = pop();
-    push(ast.ifStatement(ifToken, condition.leftParenthesis, condition,
-        condition.rightParenthesis, thenPart, elseToken, elsePart));
+    push(ast.ifStatement(
+        ifToken,
+        condition.leftParenthesis,
+        condition.expression,
+        condition.rightParenthesis,
+        thenPart,
+        elseToken,
+        elsePart));
   }
 
   void handleNoInitializers() {
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index 0e14ee2..94c6855 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -953,7 +953,9 @@
         AstNode parent = node.parent;
         if (parent is Annotation) {
           _resolver.errorReporter.reportErrorForNode(
-              CompileTimeErrorCode.INVALID_ANNOTATION, parent);
+              CompileTimeErrorCode.UNDEFINED_ANNOTATION,
+              parent,
+              [identifier.name]);
         } else {
           _resolver.errorReporter.reportErrorForNode(
               StaticWarningCode.UNDEFINED_GETTER,
@@ -1148,7 +1150,7 @@
             CompileTimeErrorCode.INVALID_CONSTRUCTOR_NAME, node);
       } else if (parent is Annotation) {
         _resolver.errorReporter.reportErrorForNode(
-            CompileTimeErrorCode.INVALID_ANNOTATION, parent);
+            CompileTimeErrorCode.UNDEFINED_ANNOTATION, parent, [node.name]);
       } else if (element != null) {
         _resolver.errorReporter.reportErrorForNode(
             CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
@@ -1989,7 +1991,8 @@
       }
     }
     SimpleIdentifier nameNode3 = annotation.constructorName;
-    ConstructorElement constructor = null;
+    ConstructorElement constructor;
+    bool undefined = false;
     //
     // CONST or Class(args)
     //
@@ -2004,6 +2007,8 @@
       if (element1 is ClassElement) {
         constructor = new InterfaceTypeImpl(element1)
             .lookUpConstructor(null, _definingLibrary);
+      } else if (element1 == null) {
+        undefined = true;
       }
     }
     //
@@ -2033,6 +2038,9 @@
             .lookUpConstructor(nameNode2.name, _definingLibrary);
         nameNode2.staticElement = constructor;
       }
+      if (element1 == null && element2 == null) {
+        undefined = true;
+      }
     }
     //
     // prefix.Class.CONST or prefix.Class.constructor(args)
@@ -2055,12 +2063,17 @@
         constructor = new InterfaceTypeImpl(element2)
             .lookUpConstructor(name3, _definingLibrary);
         nameNode3.staticElement = constructor;
+      } else if (element2 == null) {
+        undefined = true;
       }
     }
     // we need constructor
     if (constructor == null) {
-      _resolver.errorReporter.reportErrorForNode(
-          CompileTimeErrorCode.INVALID_ANNOTATION, annotation);
+      if (!undefined) {
+        // If the class was not found then we've already reported the error.
+        _resolver.errorReporter.reportErrorForNode(
+            CompileTimeErrorCode.INVALID_ANNOTATION, annotation);
+      }
       return;
     }
     // record element
@@ -2074,7 +2087,7 @@
     // accessor should be synthetic
     if (!accessorElement.isSynthetic) {
       _resolver.errorReporter.reportErrorForNode(
-          CompileTimeErrorCode.INVALID_ANNOTATION, annotation);
+          CompileTimeErrorCode.INVALID_ANNOTATION_GETTER, annotation);
       return;
     }
     // variable should be constant
@@ -2082,6 +2095,7 @@
     if (!variableElement.isConst) {
       _resolver.errorReporter.reportErrorForNode(
           CompileTimeErrorCode.INVALID_ANNOTATION, annotation);
+      return;
     }
     // no arguments
     if (annotation.arguments != null) {
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index 56d147d..d04d6ad 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -1440,7 +1440,7 @@
   @override
   bool preserveComments = true;
 
-  bool _strongMode = false;
+  bool _strongMode = true;
 
   /**
    * A flag indicating whether strong-mode inference hints should be
@@ -1457,7 +1457,7 @@
   bool useFastaParser = false;
 
   @override
-  bool previewDart2 = false;
+  bool previewDart2 = true;
 
   @override
   bool disableCacheFlushing = false;
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 281110b..f13507a 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -2321,7 +2321,7 @@
       if (_inGenerator) {
         return;
       } else if (_inAsync) {
-        if (expectedReturnType.isDynamic) {
+        if (expectedReturnType.isDynamic || expectedReturnType.isVoid) {
           return;
         }
         if (expectedReturnType is InterfaceType &&
@@ -2329,6 +2329,7 @@
           DartType futureArgument = expectedReturnType.typeArguments[0];
           if (futureArgument.isDynamic ||
               futureArgument.isDartCoreNull ||
+              futureArgument.isVoid ||
               futureArgument.isObject) {
             return;
           }
diff --git a/pkg/analyzer/lib/src/lint/linter.dart b/pkg/analyzer/lib/src/lint/linter.dart
index 8f774d5..92e25c4 100644
--- a/pkg/analyzer/lib/src/lint/linter.dart
+++ b/pkg/analyzer/lib/src/lint/linter.dart
@@ -16,6 +16,7 @@
 import 'package:analyzer/src/lint/analysis.dart';
 import 'package:analyzer/src/lint/config.dart';
 import 'package:analyzer/src/lint/io.dart';
+import 'package:analyzer/src/lint/linter_visitor.dart' show NodeLintRegistry;
 import 'package:analyzer/src/lint/project.dart';
 import 'package:analyzer/src/lint/pub.dart';
 import 'package:analyzer/src/lint/registry.dart';
@@ -23,6 +24,8 @@
 import 'package:glob/glob.dart';
 import 'package:path/path.dart' as p;
 
+export 'package:analyzer/src/lint/linter_visitor.dart' show NodeLintRegistry;
+
 typedef Printer(String msg);
 
 /// Describes a String in valid camel case format.
@@ -319,6 +322,14 @@
   int compareTo(Maturity other) => this.ordinal - other.ordinal;
 }
 
+/// [LintRule]s that implement this interface want to process only some types
+/// of AST nodes, and will register their processors in the registry.
+abstract class NodeLintRule {
+  /// This method is invoked to let the [LintRule] register node processors
+  /// in the given [registry].
+  void registerNodeProcessors(NodeLintRegistry registry);
+}
+
 class PrintingReporter implements Reporter, Logger {
   final Printer _print;
 
diff --git a/pkg/analyzer/lib/src/lint/linter_visitor.dart b/pkg/analyzer/lib/src/lint/linter_visitor.dart
new file mode 100644
index 0000000..141d3d46
--- /dev/null
+++ b/pkg/analyzer/lib/src/lint/linter_visitor.dart
@@ -0,0 +1,1323 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/src/lint/linter.dart';
+import 'package:analyzer/src/services/lint.dart';
+
+/// The type of the function that handles exceptions in lints.
+typedef void LintRuleExceptionHandler(
+    AstNode node, LintRule linter, dynamic exception, StackTrace stackTrace);
+
+/// The AST visitor that runs handlers for nodes from the [registry].
+class LinterVisitor extends RecursiveAstVisitor<void> {
+  final NodeLintRegistry registry;
+  final LintRuleExceptionHandler exceptionHandler;
+
+  LinterVisitor(this.registry, this.exceptionHandler);
+
+  @override
+  void visitAsExpression(AsExpression node) {
+    _runSubscriptions(node, registry._forAsExpression);
+    super.visitAsExpression(node);
+  }
+
+  @override
+  void visitAssertInitializer(AssertInitializer node) {
+    _runSubscriptions(node, registry._forAssertInitializer);
+    super.visitAssertInitializer(node);
+  }
+
+  @override
+  void visitAssertStatement(AssertStatement node) {
+    _runSubscriptions(node, registry._forAssertStatement);
+    super.visitAssertStatement(node);
+  }
+
+  @override
+  void visitAssignmentExpression(AssignmentExpression node) {
+    _runSubscriptions(node, registry._forAssignmentExpression);
+    super.visitAssignmentExpression(node);
+  }
+
+  @override
+  void visitAwaitExpression(AwaitExpression node) {
+    _runSubscriptions(node, registry._forAwaitExpression);
+    super.visitAwaitExpression(node);
+  }
+
+  @override
+  void visitBinaryExpression(BinaryExpression node) {
+    _runSubscriptions(node, registry._forBinaryExpression);
+    super.visitBinaryExpression(node);
+  }
+
+  @override
+  void visitBlock(Block node) {
+    _runSubscriptions(node, registry._forBlock);
+    super.visitBlock(node);
+  }
+
+  @override
+  void visitBlockFunctionBody(BlockFunctionBody node) {
+    _runSubscriptions(node, registry._forBlockFunctionBody);
+    super.visitBlockFunctionBody(node);
+  }
+
+  @override
+  void visitBooleanLiteral(BooleanLiteral node) {
+    _runSubscriptions(node, registry._forBooleanLiteral);
+    super.visitBooleanLiteral(node);
+  }
+
+  @override
+  void visitBreakStatement(BreakStatement node) {
+    _runSubscriptions(node, registry._forBreakStatement);
+    super.visitBreakStatement(node);
+  }
+
+  @override
+  void visitCascadeExpression(CascadeExpression node) {
+    _runSubscriptions(node, registry._forCascadeExpression);
+    super.visitCascadeExpression(node);
+  }
+
+  @override
+  void visitCatchClause(CatchClause node) {
+    _runSubscriptions(node, registry._forCatchClause);
+    super.visitCatchClause(node);
+  }
+
+  @override
+  void visitClassDeclaration(ClassDeclaration node) {
+    _runSubscriptions(node, registry._forClassDeclaration);
+    super.visitClassDeclaration(node);
+  }
+
+  @override
+  void visitClassTypeAlias(ClassTypeAlias node) {
+    _runSubscriptions(node, registry._forClassTypeAlias);
+    super.visitClassTypeAlias(node);
+  }
+
+  @override
+  void visitComment(Comment node) {
+    _runSubscriptions(node, registry._forComment);
+    super.visitComment(node);
+  }
+
+  @override
+  void visitCommentReference(CommentReference node) {
+    _runSubscriptions(node, registry._forCommentReference);
+    super.visitCommentReference(node);
+  }
+
+  @override
+  void visitCompilationUnit(CompilationUnit node) {
+    _runSubscriptions(node, registry._forCompilationUnit);
+    super.visitCompilationUnit(node);
+  }
+
+  @override
+  void visitConditionalExpression(ConditionalExpression node) {
+    _runSubscriptions(node, registry._forConditionalExpression);
+    super.visitConditionalExpression(node);
+  }
+
+  @override
+  void visitConfiguration(Configuration node) {
+    _runSubscriptions(node, registry._forConfiguration);
+    super.visitConfiguration(node);
+  }
+
+  @override
+  void visitConstructorDeclaration(ConstructorDeclaration node) {
+    _runSubscriptions(node, registry._forConstructorDeclaration);
+    super.visitConstructorDeclaration(node);
+  }
+
+  @override
+  void visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
+    _runSubscriptions(node, registry._forConstructorFieldInitializer);
+    super.visitConstructorFieldInitializer(node);
+  }
+
+  @override
+  void visitConstructorName(ConstructorName node) {
+    _runSubscriptions(node, registry._forConstructorName);
+    super.visitConstructorName(node);
+  }
+
+  @override
+  void visitContinueStatement(ContinueStatement node) {
+    _runSubscriptions(node, registry._forContinueStatement);
+    super.visitContinueStatement(node);
+  }
+
+  @override
+  void visitDeclaredIdentifier(DeclaredIdentifier node) {
+    _runSubscriptions(node, registry._forDeclaredIdentifier);
+    super.visitDeclaredIdentifier(node);
+  }
+
+  @override
+  void visitDefaultFormalParameter(DefaultFormalParameter node) {
+    _runSubscriptions(node, registry._forDefaultFormalParameter);
+    super.visitDefaultFormalParameter(node);
+  }
+
+  @override
+  void visitDoStatement(DoStatement node) {
+    _runSubscriptions(node, registry._forDoStatement);
+    super.visitDoStatement(node);
+  }
+
+  @override
+  void visitDottedName(DottedName node) {
+    _runSubscriptions(node, registry._forDottedName);
+    super.visitDottedName(node);
+  }
+
+  @override
+  void visitDoubleLiteral(DoubleLiteral node) {
+    _runSubscriptions(node, registry._forDoubleLiteral);
+    super.visitDoubleLiteral(node);
+  }
+
+  @override
+  void visitEmptyFunctionBody(EmptyFunctionBody node) {
+    _runSubscriptions(node, registry._forEmptyFunctionBody);
+    super.visitEmptyFunctionBody(node);
+  }
+
+  @override
+  void visitEmptyStatement(EmptyStatement node) {
+    _runSubscriptions(node, registry._forEmptyStatement);
+    super.visitEmptyStatement(node);
+  }
+
+  @override
+  void visitEnumConstantDeclaration(EnumConstantDeclaration node) {
+    _runSubscriptions(node, registry._forEnumConstantDeclaration);
+    super.visitEnumConstantDeclaration(node);
+  }
+
+  @override
+  void visitEnumDeclaration(EnumDeclaration node) {
+    _runSubscriptions(node, registry._forEnumDeclaration);
+    super.visitEnumDeclaration(node);
+  }
+
+  @override
+  void visitExportDirective(ExportDirective node) {
+    _runSubscriptions(node, registry._forExportDirective);
+    super.visitExportDirective(node);
+  }
+
+  @override
+  void visitExpressionFunctionBody(ExpressionFunctionBody node) {
+    _runSubscriptions(node, registry._forExpressionFunctionBody);
+    super.visitExpressionFunctionBody(node);
+  }
+
+  @override
+  void visitExpressionStatement(ExpressionStatement node) {
+    _runSubscriptions(node, registry._forExpressionStatement);
+    super.visitExpressionStatement(node);
+  }
+
+  @override
+  void visitExtendsClause(ExtendsClause node) {
+    _runSubscriptions(node, registry._forExtendsClause);
+    super.visitExtendsClause(node);
+  }
+
+  @override
+  void visitFieldDeclaration(FieldDeclaration node) {
+    _runSubscriptions(node, registry._forFieldDeclaration);
+    super.visitFieldDeclaration(node);
+  }
+
+  @override
+  void visitFieldFormalParameter(FieldFormalParameter node) {
+    _runSubscriptions(node, registry._forFieldFormalParameter);
+    super.visitFieldFormalParameter(node);
+  }
+
+  @override
+  void visitForEachStatement(ForEachStatement node) {
+    _runSubscriptions(node, registry._forForEachStatement);
+    super.visitForEachStatement(node);
+  }
+
+  @override
+  void visitFormalParameterList(FormalParameterList node) {
+    _runSubscriptions(node, registry._forFormalParameterList);
+    super.visitFormalParameterList(node);
+  }
+
+  @override
+  void visitForStatement(ForStatement node) {
+    _runSubscriptions(node, registry._forForStatement);
+    super.visitForStatement(node);
+  }
+
+  @override
+  void visitFunctionDeclaration(FunctionDeclaration node) {
+    _runSubscriptions(node, registry._forFunctionDeclaration);
+    super.visitFunctionDeclaration(node);
+  }
+
+  @override
+  void visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
+    _runSubscriptions(node, registry._forFunctionDeclarationStatement);
+    super.visitFunctionDeclarationStatement(node);
+  }
+
+  @override
+  void visitFunctionExpression(FunctionExpression node) {
+    _runSubscriptions(node, registry._forFunctionExpression);
+    super.visitFunctionExpression(node);
+  }
+
+  @override
+  void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
+    _runSubscriptions(node, registry._forFunctionExpressionInvocation);
+    super.visitFunctionExpressionInvocation(node);
+  }
+
+  @override
+  void visitFunctionTypeAlias(FunctionTypeAlias node) {
+    _runSubscriptions(node, registry._forFunctionTypeAlias);
+    super.visitFunctionTypeAlias(node);
+  }
+
+  @override
+  void visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
+    _runSubscriptions(node, registry._forFunctionTypedFormalParameter);
+    super.visitFunctionTypedFormalParameter(node);
+  }
+
+  @override
+  void visitGenericFunctionType(GenericFunctionType node) {
+    _runSubscriptions(node, registry._forGenericFunctionType);
+    super.visitGenericFunctionType(node);
+  }
+
+  @override
+  void visitGenericTypeAlias(GenericTypeAlias node) {
+    _runSubscriptions(node, registry._forGenericTypeAlias);
+    super.visitGenericTypeAlias(node);
+  }
+
+  @override
+  void visitHideCombinator(HideCombinator node) {
+    _runSubscriptions(node, registry._forHideCombinator);
+    super.visitHideCombinator(node);
+  }
+
+  @override
+  void visitIfStatement(IfStatement node) {
+    _runSubscriptions(node, registry._forIfStatement);
+    super.visitIfStatement(node);
+  }
+
+  @override
+  void visitImplementsClause(ImplementsClause node) {
+    _runSubscriptions(node, registry._forImplementsClause);
+    super.visitImplementsClause(node);
+  }
+
+  @override
+  void visitImportDirective(ImportDirective node) {
+    _runSubscriptions(node, registry._forImportDirective);
+    super.visitImportDirective(node);
+  }
+
+  @override
+  void visitIndexExpression(IndexExpression node) {
+    _runSubscriptions(node, registry._forIndexExpression);
+    super.visitIndexExpression(node);
+  }
+
+  @override
+  void visitInstanceCreationExpression(InstanceCreationExpression node) {
+    _runSubscriptions(node, registry._forInstanceCreationExpression);
+    super.visitInstanceCreationExpression(node);
+  }
+
+  @override
+  void visitIntegerLiteral(IntegerLiteral node) {
+    _runSubscriptions(node, registry._forIntegerLiteral);
+    super.visitIntegerLiteral(node);
+  }
+
+  @override
+  void visitInterpolationExpression(InterpolationExpression node) {
+    _runSubscriptions(node, registry._forInterpolationExpression);
+    super.visitInterpolationExpression(node);
+  }
+
+  @override
+  void visitInterpolationString(InterpolationString node) {
+    _runSubscriptions(node, registry._forInterpolationString);
+    super.visitInterpolationString(node);
+  }
+
+  @override
+  void visitIsExpression(IsExpression node) {
+    _runSubscriptions(node, registry._forIsExpression);
+    super.visitIsExpression(node);
+  }
+
+  @override
+  void visitLabel(Label node) {
+    _runSubscriptions(node, registry._forLabel);
+    super.visitLabel(node);
+  }
+
+  @override
+  void visitLabeledStatement(LabeledStatement node) {
+    _runSubscriptions(node, registry._forLabeledStatement);
+    super.visitLabeledStatement(node);
+  }
+
+  @override
+  void visitLibraryDirective(LibraryDirective node) {
+    _runSubscriptions(node, registry._forLibraryDirective);
+    super.visitLibraryDirective(node);
+  }
+
+  @override
+  void visitLibraryIdentifier(LibraryIdentifier node) {
+    _runSubscriptions(node, registry._forLibraryIdentifier);
+    super.visitLibraryIdentifier(node);
+  }
+
+  @override
+  void visitListLiteral(ListLiteral node) {
+    _runSubscriptions(node, registry._forListLiteral);
+    super.visitListLiteral(node);
+  }
+
+  @override
+  void visitMapLiteral(MapLiteral node) {
+    _runSubscriptions(node, registry._forMapLiteral);
+    super.visitMapLiteral(node);
+  }
+
+  @override
+  void visitMapLiteralEntry(MapLiteralEntry node) {
+    _runSubscriptions(node, registry._forMapLiteralEntry);
+    super.visitMapLiteralEntry(node);
+  }
+
+  @override
+  void visitMethodDeclaration(MethodDeclaration node) {
+    _runSubscriptions(node, registry._forMethodDeclaration);
+    super.visitMethodDeclaration(node);
+  }
+
+  @override
+  void visitMethodInvocation(MethodInvocation node) {
+    _runSubscriptions(node, registry._forMethodInvocation);
+    super.visitMethodInvocation(node);
+  }
+
+  @override
+  void visitNamedExpression(NamedExpression node) {
+    _runSubscriptions(node, registry._forNamedExpression);
+    super.visitNamedExpression(node);
+  }
+
+  @override
+  void visitNullLiteral(NullLiteral node) {
+    _runSubscriptions(node, registry._forNullLiteral);
+    super.visitNullLiteral(node);
+  }
+
+  @override
+  void visitParenthesizedExpression(ParenthesizedExpression node) {
+    _runSubscriptions(node, registry._forParenthesizedExpression);
+    super.visitParenthesizedExpression(node);
+  }
+
+  @override
+  void visitPartDirective(PartDirective node) {
+    _runSubscriptions(node, registry._forPartDirective);
+    super.visitPartDirective(node);
+  }
+
+  @override
+  void visitPartOfDirective(PartOfDirective node) {
+    _runSubscriptions(node, registry._forPartOfDirective);
+    super.visitPartOfDirective(node);
+  }
+
+  @override
+  void visitPostfixExpression(PostfixExpression node) {
+    _runSubscriptions(node, registry._forPostfixExpression);
+    super.visitPostfixExpression(node);
+  }
+
+  @override
+  void visitPrefixedIdentifier(PrefixedIdentifier node) {
+    _runSubscriptions(node, registry._forPrefixedIdentifier);
+    super.visitPrefixedIdentifier(node);
+  }
+
+  @override
+  void visitPrefixExpression(PrefixExpression node) {
+    _runSubscriptions(node, registry._forPrefixExpression);
+    super.visitPrefixExpression(node);
+  }
+
+  @override
+  void visitPropertyAccess(PropertyAccess node) {
+    _runSubscriptions(node, registry._forPropertyAccess);
+    super.visitPropertyAccess(node);
+  }
+
+  @override
+  void visitRedirectingConstructorInvocation(
+      RedirectingConstructorInvocation node) {
+    _runSubscriptions(node, registry._forRedirectingConstructorInvocation);
+    super.visitRedirectingConstructorInvocation(node);
+  }
+
+  @override
+  void visitRethrowExpression(RethrowExpression node) {
+    _runSubscriptions(node, registry._forRethrowExpression);
+    super.visitRethrowExpression(node);
+  }
+
+  @override
+  void visitReturnStatement(ReturnStatement node) {
+    _runSubscriptions(node, registry._forReturnStatement);
+    super.visitReturnStatement(node);
+  }
+
+  @override
+  void visitShowCombinator(ShowCombinator node) {
+    _runSubscriptions(node, registry._forShowCombinator);
+    super.visitShowCombinator(node);
+  }
+
+  @override
+  void visitSimpleFormalParameter(SimpleFormalParameter node) {
+    _runSubscriptions(node, registry._forSimpleFormalParameter);
+    super.visitSimpleFormalParameter(node);
+  }
+
+  @override
+  void visitSimpleIdentifier(SimpleIdentifier node) {
+    _runSubscriptions(node, registry._forSimpleIdentifier);
+    super.visitSimpleIdentifier(node);
+  }
+
+  @override
+  void visitSimpleStringLiteral(SimpleStringLiteral node) {
+    _runSubscriptions(node, registry._forSimpleStringLiteral);
+    super.visitSimpleStringLiteral(node);
+  }
+
+  @override
+  void visitStringInterpolation(StringInterpolation node) {
+    _runSubscriptions(node, registry._forStringInterpolation);
+    super.visitStringInterpolation(node);
+  }
+
+  @override
+  void visitSuperConstructorInvocation(SuperConstructorInvocation node) {
+    _runSubscriptions(node, registry._forSuperConstructorInvocation);
+    super.visitSuperConstructorInvocation(node);
+  }
+
+  @override
+  void visitSuperExpression(SuperExpression node) {
+    _runSubscriptions(node, registry._forSuperExpression);
+    super.visitSuperExpression(node);
+  }
+
+  @override
+  void visitSwitchCase(SwitchCase node) {
+    _runSubscriptions(node, registry._forSwitchCase);
+    super.visitSwitchCase(node);
+  }
+
+  @override
+  void visitSwitchDefault(SwitchDefault node) {
+    _runSubscriptions(node, registry._forSwitchDefault);
+    super.visitSwitchDefault(node);
+  }
+
+  @override
+  void visitSwitchStatement(SwitchStatement node) {
+    _runSubscriptions(node, registry._forSwitchStatement);
+    super.visitSwitchStatement(node);
+  }
+
+  @override
+  void visitSymbolLiteral(SymbolLiteral node) {
+    _runSubscriptions(node, registry._forSymbolLiteral);
+    super.visitSymbolLiteral(node);
+  }
+
+  @override
+  void visitThisExpression(ThisExpression node) {
+    _runSubscriptions(node, registry._forThisExpression);
+    super.visitThisExpression(node);
+  }
+
+  @override
+  void visitThrowExpression(ThrowExpression node) {
+    _runSubscriptions(node, registry._forThrowExpression);
+    super.visitThrowExpression(node);
+  }
+
+  @override
+  void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
+    _runSubscriptions(node, registry._forTopLevelVariableDeclaration);
+    super.visitTopLevelVariableDeclaration(node);
+  }
+
+  @override
+  void visitTryStatement(TryStatement node) {
+    _runSubscriptions(node, registry._forTryStatement);
+    super.visitTryStatement(node);
+  }
+
+  @override
+  void visitTypeArgumentList(TypeArgumentList node) {
+    _runSubscriptions(node, registry._forTypeArgumentList);
+    super.visitTypeArgumentList(node);
+  }
+
+  @override
+  void visitTypeName(TypeName node) {
+    _runSubscriptions(node, registry._forTypeName);
+    super.visitTypeName(node);
+  }
+
+  @override
+  void visitTypeParameter(TypeParameter node) {
+    _runSubscriptions(node, registry._forTypeParameter);
+    super.visitTypeParameter(node);
+  }
+
+  @override
+  void visitTypeParameterList(TypeParameterList node) {
+    _runSubscriptions(node, registry._forTypeParameterList);
+    super.visitTypeParameterList(node);
+  }
+
+  @override
+  void visitVariableDeclaration(VariableDeclaration node) {
+    _runSubscriptions(node, registry._forVariableDeclaration);
+    super.visitVariableDeclaration(node);
+  }
+
+  @override
+  void visitVariableDeclarationList(VariableDeclarationList node) {
+    _runSubscriptions(node, registry._forVariableDeclarationList);
+    super.visitVariableDeclarationList(node);
+  }
+
+  @override
+  void visitVariableDeclarationStatement(VariableDeclarationStatement node) {
+    _runSubscriptions(node, registry._forVariableDeclarationStatement);
+    super.visitVariableDeclarationStatement(node);
+  }
+
+  @override
+  void visitWhileStatement(WhileStatement node) {
+    _runSubscriptions(node, registry._forWhileStatement);
+    super.visitWhileStatement(node);
+  }
+
+  @override
+  void visitWithClause(WithClause node) {
+    _runSubscriptions(node, registry._forWithClause);
+    super.visitWithClause(node);
+  }
+
+  @override
+  void visitYieldStatement(YieldStatement node) {
+    _runSubscriptions(node, registry._forYieldStatement);
+    super.visitYieldStatement(node);
+  }
+
+  void _runSubscriptions<T extends AstNode>(
+      T node, List<_Subscription<T>> subscriptions) {
+    for (int i = 0; i < subscriptions.length; i++) {
+      var subscription = subscriptions[i];
+      var timer = subscription.timer;
+      timer?.start();
+      try {
+        node.accept(subscription.visitor);
+      } catch (exception, stackTrace) {
+        exceptionHandler(node, subscription.linter, exception, stackTrace);
+      }
+      timer?.stop();
+    }
+  }
+}
+
+/// The container to register visitors for separate AST node types.
+class NodeLintRegistry {
+  final bool enableTiming;
+  final List<_Subscription<AsExpression>> _forAsExpression = [];
+  final List<_Subscription<AssertInitializer>> _forAssertInitializer = [];
+  final List<_Subscription<AssertStatement>> _forAssertStatement = [];
+  final List<_Subscription<AssignmentExpression>> _forAssignmentExpression = [];
+  final List<_Subscription<AwaitExpression>> _forAwaitExpression = [];
+  final List<_Subscription<BinaryExpression>> _forBinaryExpression = [];
+  final List<_Subscription<Block>> _forBlock = [];
+  final List<_Subscription<BlockFunctionBody>> _forBlockFunctionBody = [];
+  final List<_Subscription<BooleanLiteral>> _forBooleanLiteral = [];
+  final List<_Subscription<BreakStatement>> _forBreakStatement = [];
+  final List<_Subscription<CascadeExpression>> _forCascadeExpression = [];
+  final List<_Subscription<CatchClause>> _forCatchClause = [];
+  final List<_Subscription<ClassDeclaration>> _forClassDeclaration = [];
+  final List<_Subscription<ClassTypeAlias>> _forClassTypeAlias = [];
+  final List<_Subscription<Comment>> _forComment = [];
+  final List<_Subscription<CommentReference>> _forCommentReference = [];
+  final List<_Subscription<CompilationUnit>> _forCompilationUnit = [];
+  final List<_Subscription<ConditionalExpression>> _forConditionalExpression =
+      [];
+  final List<_Subscription<Configuration>> _forConfiguration = [];
+  final List<_Subscription<ConstructorDeclaration>> _forConstructorDeclaration =
+      [];
+  final List<_Subscription<ConstructorFieldInitializer>>
+      _forConstructorFieldInitializer = [];
+  final List<_Subscription<ConstructorName>> _forConstructorName = [];
+  final List<_Subscription<ContinueStatement>> _forContinueStatement = [];
+  final List<_Subscription<DeclaredIdentifier>> _forDeclaredIdentifier = [];
+  final List<_Subscription<DefaultFormalParameter>> _forDefaultFormalParameter =
+      [];
+  final List<_Subscription<DoStatement>> _forDoStatement = [];
+  final List<_Subscription<DottedName>> _forDottedName = [];
+  final List<_Subscription<DoubleLiteral>> _forDoubleLiteral = [];
+  final List<_Subscription<EmptyFunctionBody>> _forEmptyFunctionBody = [];
+  final List<_Subscription<EmptyStatement>> _forEmptyStatement = [];
+  final List<_Subscription<EnumConstantDeclaration>>
+      _forEnumConstantDeclaration = [];
+  final List<_Subscription<EnumDeclaration>> _forEnumDeclaration = [];
+  final List<_Subscription<ExportDirective>> _forExportDirective = [];
+  final List<_Subscription<ExpressionFunctionBody>> _forExpressionFunctionBody =
+      [];
+  final List<_Subscription<ExpressionStatement>> _forExpressionStatement = [];
+  final List<_Subscription<ExtendsClause>> _forExtendsClause = [];
+  final List<_Subscription<FieldDeclaration>> _forFieldDeclaration = [];
+  final List<_Subscription<FieldFormalParameter>> _forFieldFormalParameter = [];
+  final List<_Subscription<ForEachStatement>> _forForEachStatement = [];
+  final List<_Subscription<FormalParameterList>> _forFormalParameterList = [];
+  final List<_Subscription<ForStatement>> _forForStatement = [];
+  final List<_Subscription<FunctionDeclaration>> _forFunctionDeclaration = [];
+  final List<_Subscription<FunctionDeclarationStatement>>
+      _forFunctionDeclarationStatement = [];
+  final List<_Subscription<FunctionExpression>> _forFunctionExpression = [];
+  final List<_Subscription<FunctionExpressionInvocation>>
+      _forFunctionExpressionInvocation = [];
+  final List<_Subscription<FunctionTypeAlias>> _forFunctionTypeAlias = [];
+  final List<_Subscription<FunctionTypedFormalParameter>>
+      _forFunctionTypedFormalParameter = [];
+  final List<_Subscription<GenericFunctionType>> _forGenericFunctionType = [];
+  final List<_Subscription<GenericTypeAlias>> _forGenericTypeAlias = [];
+  final List<_Subscription<HideCombinator>> _forHideCombinator = [];
+  final List<_Subscription<IfStatement>> _forIfStatement = [];
+  final List<_Subscription<ImplementsClause>> _forImplementsClause = [];
+  final List<_Subscription<ImportDirective>> _forImportDirective = [];
+  final List<_Subscription<IndexExpression>> _forIndexExpression = [];
+  final List<_Subscription<InstanceCreationExpression>>
+      _forInstanceCreationExpression = [];
+  final List<_Subscription<IntegerLiteral>> _forIntegerLiteral = [];
+  final List<_Subscription<InterpolationExpression>>
+      _forInterpolationExpression = [];
+  final List<_Subscription<InterpolationString>> _forInterpolationString = [];
+  final List<_Subscription<IsExpression>> _forIsExpression = [];
+  final List<_Subscription<Label>> _forLabel = [];
+  final List<_Subscription<LabeledStatement>> _forLabeledStatement = [];
+  final List<_Subscription<LibraryDirective>> _forLibraryDirective = [];
+  final List<_Subscription<LibraryIdentifier>> _forLibraryIdentifier = [];
+  final List<_Subscription<ListLiteral>> _forListLiteral = [];
+  final List<_Subscription<MapLiteral>> _forMapLiteral = [];
+  final List<_Subscription<MapLiteralEntry>> _forMapLiteralEntry = [];
+  final List<_Subscription<MethodDeclaration>> _forMethodDeclaration = [];
+  final List<_Subscription<MethodInvocation>> _forMethodInvocation = [];
+  final List<_Subscription<NamedExpression>> _forNamedExpression = [];
+  final List<_Subscription<NullLiteral>> _forNullLiteral = [];
+  final List<_Subscription<ParenthesizedExpression>>
+      _forParenthesizedExpression = [];
+  final List<_Subscription<PartDirective>> _forPartDirective = [];
+  final List<_Subscription<PartOfDirective>> _forPartOfDirective = [];
+  final List<_Subscription<PostfixExpression>> _forPostfixExpression = [];
+  final List<_Subscription<PrefixedIdentifier>> _forPrefixedIdentifier = [];
+  final List<_Subscription<PrefixExpression>> _forPrefixExpression = [];
+  final List<_Subscription<PropertyAccess>> _forPropertyAccess = [];
+  final List<_Subscription<RedirectingConstructorInvocation>>
+      _forRedirectingConstructorInvocation = [];
+  final List<_Subscription<RethrowExpression>> _forRethrowExpression = [];
+  final List<_Subscription<ReturnStatement>> _forReturnStatement = [];
+  final List<_Subscription<ShowCombinator>> _forShowCombinator = [];
+  final List<_Subscription<SimpleFormalParameter>> _forSimpleFormalParameter =
+      [];
+  final List<_Subscription<SimpleIdentifier>> _forSimpleIdentifier = [];
+  final List<_Subscription<SimpleStringLiteral>> _forSimpleStringLiteral = [];
+  final List<_Subscription<StringInterpolation>> _forStringInterpolation = [];
+  final List<_Subscription<SuperConstructorInvocation>>
+      _forSuperConstructorInvocation = [];
+  final List<_Subscription<SuperExpression>> _forSuperExpression = [];
+  final List<_Subscription<SwitchCase>> _forSwitchCase = [];
+  final List<_Subscription<SwitchDefault>> _forSwitchDefault = [];
+  final List<_Subscription<SwitchStatement>> _forSwitchStatement = [];
+  final List<_Subscription<SymbolLiteral>> _forSymbolLiteral = [];
+  final List<_Subscription<ThisExpression>> _forThisExpression = [];
+  final List<_Subscription<ThrowExpression>> _forThrowExpression = [];
+  final List<_Subscription<TopLevelVariableDeclaration>>
+      _forTopLevelVariableDeclaration = [];
+  final List<_Subscription<TryStatement>> _forTryStatement = [];
+  final List<_Subscription<TypeArgumentList>> _forTypeArgumentList = [];
+  final List<_Subscription<TypeName>> _forTypeName = [];
+  final List<_Subscription<TypeParameter>> _forTypeParameter = [];
+  final List<_Subscription<TypeParameterList>> _forTypeParameterList = [];
+  final List<_Subscription<VariableDeclaration>> _forVariableDeclaration = [];
+  final List<_Subscription<VariableDeclarationList>>
+      _forVariableDeclarationList = [];
+  final List<_Subscription<VariableDeclarationStatement>>
+      _forVariableDeclarationStatement = [];
+  final List<_Subscription<WhileStatement>> _forWhileStatement = [];
+  final List<_Subscription<WithClause>> _forWithClause = [];
+  final List<_Subscription<YieldStatement>> _forYieldStatement = [];
+
+  NodeLintRegistry(this.enableTiming);
+
+  void addAsExpression(LintRule linter, AstVisitor visitor) {
+    _forAsExpression.add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addAssertInitializer(LintRule linter, AstVisitor visitor) {
+    _forAssertInitializer
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addAssertStatement(LintRule linter, AstVisitor visitor) {
+    _forAssertStatement
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addAssignmentExpression(LintRule linter, AstVisitor visitor) {
+    _forAssignmentExpression
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addAwaitExpression(LintRule linter, AstVisitor visitor) {
+    _forAwaitExpression
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addBinaryExpression(LintRule linter, AstVisitor visitor) {
+    _forBinaryExpression
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addBlock(LintRule linter, AstVisitor visitor) {
+    _forBlock.add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addBlockFunctionBody(LintRule linter, AstVisitor visitor) {
+    _forBlockFunctionBody
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addBooleanLiteral(LintRule linter, AstVisitor visitor) {
+    _forBooleanLiteral
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addBreakStatement(LintRule linter, AstVisitor visitor) {
+    _forBreakStatement
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addCascadeExpression(LintRule linter, AstVisitor visitor) {
+    _forCascadeExpression
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addCatchClause(LintRule linter, AstVisitor visitor) {
+    _forCatchClause.add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addClassDeclaration(LintRule linter, AstVisitor visitor) {
+    _forClassDeclaration
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addClassTypeAlias(LintRule linter, AstVisitor visitor) {
+    _forClassTypeAlias
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addComment(LintRule linter, AstVisitor visitor) {
+    _forComment.add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addCommentReference(LintRule linter, AstVisitor visitor) {
+    _forCommentReference
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addCompilationUnit(LintRule linter, AstVisitor visitor) {
+    _forCompilationUnit
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addConditionalExpression(LintRule linter, AstVisitor visitor) {
+    _forConditionalExpression
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addConfiguration(LintRule linter, AstVisitor visitor) {
+    _forConfiguration
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addConstructorDeclaration(LintRule linter, AstVisitor visitor) {
+    _forConstructorDeclaration
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addConstructorFieldInitializer(LintRule linter, AstVisitor visitor) {
+    _forConstructorFieldInitializer
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addConstructorName(LintRule linter, AstVisitor visitor) {
+    _forConstructorName
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addContinueStatement(LintRule linter, AstVisitor visitor) {
+    _forContinueStatement
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addDeclaredIdentifier(LintRule linter, AstVisitor visitor) {
+    _forDeclaredIdentifier
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addDefaultFormalParameter(LintRule linter, AstVisitor visitor) {
+    _forDefaultFormalParameter
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addDoStatement(LintRule linter, AstVisitor visitor) {
+    _forDoStatement.add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addDottedName(LintRule linter, AstVisitor visitor) {
+    _forDottedName.add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addDoubleLiteral(LintRule linter, AstVisitor visitor) {
+    _forDoubleLiteral
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addEmptyFunctionBody(LintRule linter, AstVisitor visitor) {
+    _forEmptyFunctionBody
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addEmptyStatement(LintRule linter, AstVisitor visitor) {
+    _forEmptyStatement
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addEnumConstantDeclaration(LintRule linter, AstVisitor visitor) {
+    _forEnumConstantDeclaration
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addEnumDeclaration(LintRule linter, AstVisitor visitor) {
+    _forEnumDeclaration
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addExportDirective(LintRule linter, AstVisitor visitor) {
+    _forExportDirective
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addExpressionFunctionBody(LintRule linter, AstVisitor visitor) {
+    _forExpressionFunctionBody
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addExpressionStatement(LintRule linter, AstVisitor visitor) {
+    _forExpressionStatement
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addExtendsClause(LintRule linter, AstVisitor visitor) {
+    _forExtendsClause
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addFieldDeclaration(LintRule linter, AstVisitor visitor) {
+    _forFieldDeclaration
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addFieldFormalParameter(LintRule linter, AstVisitor visitor) {
+    _forFieldFormalParameter
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addForEachStatement(LintRule linter, AstVisitor visitor) {
+    _forForEachStatement
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addFormalParameterList(LintRule linter, AstVisitor visitor) {
+    _forFormalParameterList
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addForStatement(LintRule linter, AstVisitor visitor) {
+    _forForStatement.add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addFunctionDeclaration(LintRule linter, AstVisitor visitor) {
+    _forFunctionDeclaration
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addFunctionDeclarationStatement(LintRule linter, AstVisitor visitor) {
+    _forFunctionDeclarationStatement
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addFunctionExpression(LintRule linter, AstVisitor visitor) {
+    _forFunctionExpression
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addFunctionExpressionInvocation(LintRule linter, AstVisitor visitor) {
+    _forFunctionExpressionInvocation
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addFunctionTypeAlias(LintRule linter, AstVisitor visitor) {
+    _forFunctionTypeAlias
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addFunctionTypedFormalParameter(LintRule linter, AstVisitor visitor) {
+    _forFunctionTypedFormalParameter
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addGenericFunctionType(LintRule linter, AstVisitor visitor) {
+    _forGenericFunctionType
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addGenericTypeAlias(LintRule linter, AstVisitor visitor) {
+    _forGenericTypeAlias
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addHideCombinator(LintRule linter, AstVisitor visitor) {
+    _forHideCombinator
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addIfStatement(LintRule linter, AstVisitor visitor) {
+    _forIfStatement.add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addImplementsClause(LintRule linter, AstVisitor visitor) {
+    _forImplementsClause
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addImportDirective(LintRule linter, AstVisitor visitor) {
+    _forImportDirective
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addIndexExpression(LintRule linter, AstVisitor visitor) {
+    _forIndexExpression
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addInstanceCreationExpression(LintRule linter, AstVisitor visitor) {
+    _forInstanceCreationExpression
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addIntegerLiteral(LintRule linter, AstVisitor visitor) {
+    _forIntegerLiteral
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addInterpolationExpression(LintRule linter, AstVisitor visitor) {
+    _forInterpolationExpression
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addInterpolationString(LintRule linter, AstVisitor visitor) {
+    _forInterpolationString
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addIsExpression(LintRule linter, AstVisitor visitor) {
+    _forIsExpression.add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addLabel(LintRule linter, AstVisitor visitor) {
+    _forLabel.add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addLabeledStatement(LintRule linter, AstVisitor visitor) {
+    _forLabeledStatement
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addLibraryDirective(LintRule linter, AstVisitor visitor) {
+    _forLibraryDirective
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addLibraryIdentifier(LintRule linter, AstVisitor visitor) {
+    _forLibraryIdentifier
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addListLiteral(LintRule linter, AstVisitor visitor) {
+    _forListLiteral.add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addMapLiteral(LintRule linter, AstVisitor visitor) {
+    _forMapLiteral.add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addMapLiteralEntry(LintRule linter, AstVisitor visitor) {
+    _forMapLiteralEntry
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addMethodDeclaration(LintRule linter, AstVisitor visitor) {
+    _forMethodDeclaration
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addMethodInvocation(LintRule linter, AstVisitor visitor) {
+    _forMethodInvocation
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addNamedExpression(LintRule linter, AstVisitor visitor) {
+    _forNamedExpression
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addNullLiteral(LintRule linter, AstVisitor visitor) {
+    _forNullLiteral.add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addParenthesizedExpression(LintRule linter, AstVisitor visitor) {
+    _forParenthesizedExpression
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addPartDirective(LintRule linter, AstVisitor visitor) {
+    _forPartDirective
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addPartOfDirective(LintRule linter, AstVisitor visitor) {
+    _forPartOfDirective
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addPostfixExpression(LintRule linter, AstVisitor visitor) {
+    _forPostfixExpression
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addPrefixedIdentifier(LintRule linter, AstVisitor visitor) {
+    _forPrefixedIdentifier
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addPrefixExpression(LintRule linter, AstVisitor visitor) {
+    _forPrefixExpression
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addPropertyAccess(LintRule linter, AstVisitor visitor) {
+    _forPropertyAccess
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addRedirectingConstructorInvocation(
+      LintRule linter, AstVisitor visitor) {
+    _forRedirectingConstructorInvocation
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addRethrowExpression(LintRule linter, AstVisitor visitor) {
+    _forRethrowExpression
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addReturnStatement(LintRule linter, AstVisitor visitor) {
+    _forReturnStatement
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addShowCombinator(LintRule linter, AstVisitor visitor) {
+    _forShowCombinator
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addSimpleFormalParameter(LintRule linter, AstVisitor visitor) {
+    _forSimpleFormalParameter
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addSimpleIdentifier(LintRule linter, AstVisitor visitor) {
+    _forSimpleIdentifier
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addSimpleStringLiteral(LintRule linter, AstVisitor visitor) {
+    _forSimpleStringLiteral
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addStringInterpolation(LintRule linter, AstVisitor visitor) {
+    _forStringInterpolation
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addSuperConstructorInvocation(LintRule linter, AstVisitor visitor) {
+    _forSuperConstructorInvocation
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addSuperExpression(LintRule linter, AstVisitor visitor) {
+    _forSuperExpression
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addSwitchCase(LintRule linter, AstVisitor visitor) {
+    _forSwitchCase.add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addSwitchDefault(LintRule linter, AstVisitor visitor) {
+    _forSwitchDefault
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addSwitchStatement(LintRule linter, AstVisitor visitor) {
+    _forSwitchStatement
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addSymbolLiteral(LintRule linter, AstVisitor visitor) {
+    _forSymbolLiteral
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addThisExpression(LintRule linter, AstVisitor visitor) {
+    _forThisExpression
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addThrowExpression(LintRule linter, AstVisitor visitor) {
+    _forThrowExpression
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addTopLevelVariableDeclaration(LintRule linter, AstVisitor visitor) {
+    _forTopLevelVariableDeclaration
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addTryStatement(LintRule linter, AstVisitor visitor) {
+    _forTryStatement.add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addTypeArgumentList(LintRule linter, AstVisitor visitor) {
+    _forTypeArgumentList
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addTypeName(LintRule linter, AstVisitor visitor) {
+    _forTypeName.add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addTypeParameter(LintRule linter, AstVisitor visitor) {
+    _forTypeParameter
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addTypeParameterList(LintRule linter, AstVisitor visitor) {
+    _forTypeParameterList
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addVariableDeclaration(LintRule linter, AstVisitor visitor) {
+    _forVariableDeclaration
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addVariableDeclarationList(LintRule linter, AstVisitor visitor) {
+    _forVariableDeclarationList
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addVariableDeclarationStatement(LintRule linter, AstVisitor visitor) {
+    _forVariableDeclarationStatement
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addWhileStatement(LintRule linter, AstVisitor visitor) {
+    _forWhileStatement
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addWithClause(LintRule linter, AstVisitor visitor) {
+    _forWithClause.add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  void addYieldStatement(LintRule linter, AstVisitor visitor) {
+    _forYieldStatement
+        .add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
+  /// Get the timer associated with the given [linter].
+  Stopwatch _getTimer(LintRule linter) {
+    if (enableTiming) {
+      return lintRegistry.getTimer(linter);
+    } else {
+      return null;
+    }
+  }
+}
+
+/// A single subscription for a node type, by the specified [linter].
+class _Subscription<T> {
+  final LintRule linter;
+  final AstVisitor visitor;
+  final Stopwatch timer;
+
+  _Subscription(this.linter, this.visitor, this.timer);
+}
diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart
index fd3b106..d83a9bc 100644
--- a/pkg/analyzer/lib/src/task/dart.dart
+++ b/pkg/analyzer/lib/src/task/dart.dart
@@ -4890,11 +4890,6 @@
   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(
@@ -4921,7 +4916,6 @@
     LibraryElement library = getRequiredInput(LIBRARY_INPUT);
     CompilationUnit unit = getRequiredInput(UNIT_INPUT);
     CompilationUnitElement unitElement = unit.element;
-    TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
     //
     // Resolve TypeName nodes.
     //
@@ -4954,8 +4948,7 @@
       'dependOnAllExportedSources':
           IMPORTED_LIBRARIES.of(unit.library).toMapOf(EXPORT_SOURCE_CLOSURE),
       LIBRARY_INPUT: LIBRARY_ELEMENT4.of(unit.library),
-      UNIT_INPUT: RESOLVED_UNIT3.of(unit),
-      TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
+      UNIT_INPUT: RESOLVED_UNIT3.of(unit)
     };
   }
 
diff --git a/pkg/analyzer/test/generated/compile_time_error_code_kernel_test.dart b/pkg/analyzer/test/generated/compile_time_error_code_kernel_test.dart
index 740f671..9832e8c 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code_kernel_test.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code_kernel_test.dart
@@ -1383,20 +1383,6 @@
 
   @override
   @failingTest
-  test_invalidAnnotation_getter() async {
-    // Expected 1 errors of type CompileTimeErrorCode.INVALID_ANNOTATION, found 0
-    await super.test_invalidAnnotation_getter();
-  }
-
-  @override
-  @failingTest
-  test_invalidAnnotation_importWithPrefix_getter() async {
-    // Bad state: No reference information for V at 27
-    await super.test_invalidAnnotation_importWithPrefix_getter();
-  }
-
-  @override
-  @failingTest
   test_invalidAnnotation_importWithPrefix_notConstantVariable() async {
     // Bad state: No reference information for V at 27
     await super.test_invalidAnnotation_importWithPrefix_notConstantVariable();
@@ -1431,31 +1417,6 @@
 
   @override
   @failingTest
-  test_invalidAnnotation_unresolved_identifier() {
-    return super.test_invalidAnnotation_unresolved_identifier();
-  }
-
-  @override
-  @failingTest
-  test_invalidAnnotation_unresolved_invocation() async {
-    // Bad state: No reference information for Unresolved at 1
-    await super.test_invalidAnnotation_unresolved_invocation();
-  }
-
-  @override
-  @failingTest
-  test_invalidAnnotation_unresolved_prefixedIdentifier() {
-    return super.test_invalidAnnotation_unresolved_prefixedIdentifier();
-  }
-
-  @override
-  @failingTest
-  test_invalidAnnotation_useLibraryScope() {
-    return super.test_invalidAnnotation_useLibraryScope();
-  }
-
-  @override
-  @failingTest
   test_invalidAnnotationFromDeferredLibrary() async {
     // Bad state: No reference information for v at 51
     await super.test_invalidAnnotationFromDeferredLibrary();
@@ -1477,6 +1438,20 @@
 
   @override
   @failingTest
+  test_invalidAnnotationGetter_getter() async {
+    // Expected 1 errors of type CompileTimeErrorCode.INVALID_ANNOTATION, found 0
+    await super.test_invalidAnnotationGetter_getter();
+  }
+
+  @override
+  @failingTest
+  test_invalidAnnotationGetter_importWithPrefix_getter() async {
+    // Bad state: No reference information for V at 27
+    await super.test_invalidAnnotationGetter_importWithPrefix_getter();
+  }
+
+  @override
+  @failingTest
   @FastaProblem('https://github.com/dart-lang/sdk/issues/31001')
   test_invalidConstructorName_notEnclosingClassName_defined() async {
     return super.test_invalidConstructorName_notEnclosingClassName_defined();
@@ -3004,6 +2979,31 @@
 
   @override
   @failingTest
+  test_undefinedAnnotation_unresolved_identifier() {
+    return super.test_undefinedAnnotation_unresolved_identifier();
+  }
+
+  @override
+  @failingTest
+  test_undefinedAnnotation_unresolved_invocation() async {
+    // Bad state: No reference information for Unresolved at 1
+    await super.test_undefinedAnnotation_unresolved_invocation();
+  }
+
+  @override
+  @failingTest
+  test_undefinedAnnotation_unresolved_prefixedIdentifier() {
+    return super.test_undefinedAnnotation_unresolved_prefixedIdentifier();
+  }
+
+  @override
+  @failingTest
+  test_undefinedAnnotation_useLibraryScope() {
+    return super.test_undefinedAnnotation_useLibraryScope();
+  }
+
+  @override
+  @failingTest
   test_undefinedClass_const() async {
     // Bad state: No type information for A at 21
     await super.test_undefinedClass_const();
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 1a09f69..9eac8d1 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code_test.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
@@ -3330,31 +3330,6 @@
     assertErrors(source, [CompileTimeErrorCode.INTEGER_LITERAL_OUT_OF_RANGE]);
   }
 
-  test_invalidAnnotation_getter() async {
-    Source source = addSource(r'''
-get V => 0;
-@V
-main() {
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.INVALID_ANNOTATION]);
-    verify([source]);
-  }
-
-  test_invalidAnnotation_importWithPrefix_getter() async {
-    addNamedSource("/lib.dart", r'''
-library lib;
-get V => 0;''');
-    Source source = addSource(r'''
-import 'lib.dart' as p;
-@p.V
-main() {
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.INVALID_ANNOTATION]);
-    verify([source]);
-  }
-
   test_invalidAnnotation_importWithPrefix_notConstantVariable() async {
     addNamedSource("/lib.dart", r'''
 library lib;
@@ -3418,44 +3393,6 @@
     verify([source]);
   }
 
-  test_invalidAnnotation_unresolved_identifier() async {
-    Source source = addSource(r'''
-@unresolved
-main() {
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.INVALID_ANNOTATION]);
-  }
-
-  test_invalidAnnotation_unresolved_invocation() async {
-    Source source = addSource(r'''
-@Unresolved()
-main() {
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.INVALID_ANNOTATION]);
-  }
-
-  test_invalidAnnotation_unresolved_prefixedIdentifier() async {
-    Source source = addSource(r'''
-import 'dart:math' as p;
-@p.unresolved
-main() {
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.INVALID_ANNOTATION]);
-  }
-
-  test_invalidAnnotation_useLibraryScope() async {
-    Source source = addSource(r'''
-@foo
-class A {
-  static const foo = null;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.INVALID_ANNOTATION]);
-  }
-
   test_invalidAnnotationFromDeferredLibrary() async {
     // See test_invalidAnnotation_notConstantVariable
     await resolveWithErrors(<String>[
@@ -3502,6 +3439,31 @@
     ]);
   }
 
+  test_invalidAnnotationGetter_getter() async {
+    Source source = addSource(r'''
+get V => 0;
+@V
+main() {
+}''');
+    await computeAnalysisResult(source);
+    assertErrors(source, [CompileTimeErrorCode.INVALID_ANNOTATION_GETTER]);
+    verify([source]);
+  }
+
+  test_invalidAnnotationGetter_importWithPrefix_getter() async {
+    addNamedSource("/lib.dart", r'''
+library lib;
+get V => 0;''');
+    Source source = addSource(r'''
+import 'lib.dart' as p;
+@p.V
+main() {
+}''');
+    await computeAnalysisResult(source);
+    assertErrors(source, [CompileTimeErrorCode.INVALID_ANNOTATION_GETTER]);
+    verify([source]);
+  }
+
   test_invalidConstructorName_notEnclosingClassName_defined() async {
     Source source = addSource(r'''
 class A {
@@ -6777,6 +6739,44 @@
     verify([source]);
   }
 
+  test_undefinedAnnotation_unresolved_identifier() async {
+    Source source = addSource(r'''
+@unresolved
+main() {
+}''');
+    await computeAnalysisResult(source);
+    assertErrors(source, [CompileTimeErrorCode.UNDEFINED_ANNOTATION]);
+  }
+
+  test_undefinedAnnotation_unresolved_invocation() async {
+    Source source = addSource(r'''
+@Unresolved()
+main() {
+}''');
+    await computeAnalysisResult(source);
+    assertErrors(source, [CompileTimeErrorCode.UNDEFINED_ANNOTATION]);
+  }
+
+  test_undefinedAnnotation_unresolved_prefixedIdentifier() async {
+    Source source = addSource(r'''
+import 'dart:math' as p;
+@p.unresolved
+main() {
+}''');
+    await computeAnalysisResult(source);
+    assertErrors(source, [CompileTimeErrorCode.UNDEFINED_ANNOTATION]);
+  }
+
+  test_undefinedAnnotation_useLibraryScope() async {
+    Source source = addSource(r'''
+@foo
+class A {
+  static const foo = null;
+}''');
+    await computeAnalysisResult(source);
+    assertErrors(source, [CompileTimeErrorCode.UNDEFINED_ANNOTATION]);
+  }
+
   test_undefinedClass_const() async {
     Source source = addSource(r'''
 f() {
diff --git a/pkg/analyzer/test/generated/hint_code_test.dart b/pkg/analyzer/test/generated/hint_code_test.dart
index 03c52e1..f93161b1 100644
--- a/pkg/analyzer/test/generated/hint_code_test.dart
+++ b/pkg/analyzer/test/generated/hint_code_test.dart
@@ -1096,10 +1096,14 @@
 class A extends Function {}
 ''');
     await computeAnalysisResult(source);
-    assertErrors(source, [
-      HintCode.DEPRECATED_EXTENDS_FUNCTION,
-      StaticWarningCode.FUNCTION_WITHOUT_CALL
-    ]);
+    if (analysisOptions.strongMode) {
+      assertErrors(source, [HintCode.DEPRECATED_EXTENDS_FUNCTION]);
+    } else {
+      assertErrors(source, [
+        HintCode.DEPRECATED_EXTENDS_FUNCTION,
+        StaticWarningCode.FUNCTION_WITHOUT_CALL
+      ]);
+    }
     verify([source]);
   }
 
@@ -1121,10 +1125,14 @@
 class A extends Object with Function {}
 ''');
     await computeAnalysisResult(source);
-    assertErrors(source, [
-      HintCode.DEPRECATED_MIXIN_FUNCTION,
-      StaticWarningCode.FUNCTION_WITHOUT_CALL
-    ]);
+    if (analysisOptions.strongMode) {
+      assertErrors(source, [HintCode.DEPRECATED_MIXIN_FUNCTION]);
+    } else {
+      assertErrors(source, [
+        HintCode.DEPRECATED_MIXIN_FUNCTION,
+        StaticWarningCode.FUNCTION_WITHOUT_CALL
+      ]);
+    }
     verify([source]);
   }
 
diff --git a/pkg/analyzer/test/generated/parser_fasta_test.dart b/pkg/analyzer/test/generated/parser_fasta_test.dart
index b47a19e..3120bb0 100644
--- a/pkg/analyzer/test/generated/parser_fasta_test.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_test.dart
@@ -1059,10 +1059,11 @@
   }
 
   @override
-  Expression parsePrimaryExpression(String code) {
-    createParser(code);
+  Expression parsePrimaryExpression(String code,
+      {int expectedEndOffset, List<ExpectedError> errors}) {
+    createParser(code, expectedEndOffset: expectedEndOffset);
     Expression result = _parserProxy.parsePrimaryExpression();
-    assertNoErrors();
+    assertErrors(codes: null, errors: errors);
     return result;
   }
 
@@ -1378,22 +1379,6 @@
 
   @override
   @failingTest
-  void test_expressionList_multiple_start() {
-    // TODO(brianwilkerson) Wrong errors:
-    // Expected 1 errors of type ParserErrorCode.MISSING_IDENTIFIER, found 0
-    super.test_expressionList_multiple_start();
-  }
-
-  @override
-  @failingTest
-  void test_functionExpression_named() {
-    // TODO(brianwilkerson) Unhandled compile-time error:
-    // A function expression can't have a name.
-    super.test_functionExpression_named();
-  }
-
-  @override
-  @failingTest
   void test_incompleteTypeArguments_field() {
     // TODO(brianwilkerson) reportUnrecoverableErrorWithToken
     super.test_incompleteTypeArguments_field();
@@ -1401,26 +1386,12 @@
 
   @override
   @failingTest
-  void test_isExpression_noType() {
-    // TODO(brianwilkerson) reportUnrecoverableErrorWithToken
-    super.test_isExpression_noType();
-  }
-
-  @override
-  @failingTest
   void test_missingIdentifier_afterAnnotation() {
     // TODO(brianwilkerson) reportUnrecoverableErrorWithToken
     super.test_missingIdentifier_afterAnnotation();
   }
 
   @override
-  @failingTest
-  void test_primaryExpression_argumentDefinitionTest() {
-    // TODO(brianwilkerson) reportUnrecoverableErrorWithToken
-    super.test_primaryExpression_argumentDefinitionTest();
-  }
-
-  @override
   void test_relationalExpression_missing_LHS_RHS() {
     parseExpression("is", codes: [
       ParserErrorCode.EXPECTED_TYPE_NAME,
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index 94c4d91..83855d0 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -218,7 +218,8 @@
 
   Identifier parsePrefixedIdentifier(String code);
 
-  Expression parsePrimaryExpression(String code);
+  Expression parsePrimaryExpression(String code,
+      {int expectedEndOffset, List<ExpectedError> errors});
 
   Expression parseRelationalExpression(String code);
 
@@ -524,6 +525,38 @@
     expect(variable.name, isNotNull);
   }
 
+  void test_parseClassMember_field_nameKeyword() {
+    createParser('var for;');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    listener.assertErrors(usingFastaParser
+        ? [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 3)]
+        : [
+            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 3),
+            expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 4, 3)
+          ]);
+  }
+
+  void test_parseClassMember_field_nameMissing() {
+    createParser('var ;');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    listener.assertErrors(
+        [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 1)]);
+  }
+
+  void test_parseClassMember_field_nameMissing2() {
+    createParser('var "";');
+    ClassMember member = parser.parseClassMember('C');
+    expect(member, isNotNull);
+    listener.assertErrors(usingFastaParser
+        ? [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 2)]
+        : [
+            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 2),
+            expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 4, 2)
+          ]);
+  }
+
   void test_parseClassMember_field_namedOperator() {
     createParser('var operator;');
     ClassMember member = parser.parseClassMember('C');
@@ -3024,8 +3057,7 @@
         errors: usingFastaParser
             ? [
                 expectedError(ParserErrorCode.MISSING_IDENTIFIER, 15, 1),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 15, 1),
-                expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 15, 1),
+                expectedError(ParserErrorCode.EXPECTED_TOKEN, 17, 4),
                 expectedError(ParserErrorCode.MISSING_IDENTIFIER, 22, 1),
                 expectedError(ParserErrorCode.EXPECTED_TOKEN, 22, 1)
               ]
@@ -3946,6 +3978,18 @@
     ]);
   }
 
+  void test_invalidConstructorName_star() {
+    createParser("C.*();");
+    ClassMember member = parser.parseClassMember('C');
+    expectNotNullIfNoErrors(member);
+    listener.assertErrors(usingFastaParser
+        ? [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 2, 1)]
+        : [
+            expectedError(ParserErrorCode.MISSING_IDENTIFIER, 2, 1),
+            expectedError(ParserErrorCode.MISSING_KEYWORD_OPERATOR, 2, 1)
+          ]);
+  }
+
   void test_invalidHexEscape_invalidDigit() {
     StringLiteral literal = parseExpression("'\\x0 a'",
         errors: [expectedError(ParserErrorCode.INVALID_HEX_ESCAPE, 1, 3)]);
@@ -10139,9 +10183,14 @@
   }
 
   @override
-  Expression parsePrimaryExpression(String code) {
+  Expression parsePrimaryExpression(String code,
+      {int expectedEndOffset, List<ExpectedError> errors}) {
     createParser(code);
-    return parser.parsePrimaryExpression();
+    var expression = parser.parsePrimaryExpression();
+    if (errors != null) {
+      listener.assertErrors(errors);
+    }
+    return expression;
   }
 
   @override
@@ -10776,13 +10825,21 @@
   void test_expressionList_multiple_start() {
     List<Expression> result = parseExpressionList('1, 2, 3,');
     expectNotNullIfNoErrors(result);
-    listener.assertErrors(
-        [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 0)]);
-    expect(result, hasLength(4));
-    Expression syntheticExpression = result[3];
-    EngineTestCase.assertInstanceOf((obj) => obj is SimpleIdentifier,
-        SimpleIdentifier, syntheticExpression);
-    expect(syntheticExpression.isSynthetic, isTrue);
+    // The fasta parser does not use parseExpressionList when parsing for loops
+    // and instead parseExpressionList is mapped to parseExpression('[$code]')
+    // which allows and ignores an optional trailing comma.
+    if (usingFastaParser) {
+      listener.assertNoErrors();
+      expect(result, hasLength(3));
+    } else {
+      listener.assertErrors(
+          [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 0)]);
+      expect(result, hasLength(4));
+      Expression syntheticExpression = result[3];
+      EngineTestCase.assertInstanceOf((obj) => obj is SimpleIdentifier,
+          SimpleIdentifier, syntheticExpression);
+      expect(syntheticExpression.isSynthetic, isTrue);
+    }
   }
 
   void test_functionExpression_in_ConstructorFieldInitializer() {
@@ -10806,7 +10863,11 @@
   }
 
   void test_functionExpression_named() {
-    parseExpression("m(f() => 0);", codes: [ParserErrorCode.EXPECTED_TOKEN]);
+    parseExpression("m(f() => 0);", expectedEndOffset: 11, codes: [
+      usingFastaParser
+          ? ParserErrorCode.NAMED_FUNCTION_EXPRESSION
+          : ParserErrorCode.EXPECTED_TOKEN
+    ]);
   }
 
   void test_ifStatement_noElse_statement() {
@@ -11408,11 +11469,18 @@
   void test_isExpression_noType() {
     CompilationUnit unit = parseCompilationUnit(
         "class Bar<T extends Foo> {m(x){if (x is ) return;if (x is !)}}",
-        codes: [
-          ParserErrorCode.EXPECTED_TYPE_NAME,
-          ParserErrorCode.EXPECTED_TYPE_NAME,
-          ParserErrorCode.MISSING_STATEMENT
-        ]);
+        codes: usingFastaParser
+            ? [
+                ParserErrorCode.EXPECTED_TYPE_NAME,
+                ParserErrorCode.EXPECTED_TYPE_NAME,
+                ParserErrorCode.MISSING_IDENTIFIER,
+                ParserErrorCode.EXPECTED_TOKEN,
+              ]
+            : [
+                ParserErrorCode.EXPECTED_TYPE_NAME,
+                ParserErrorCode.EXPECTED_TYPE_NAME,
+                ParserErrorCode.MISSING_STATEMENT
+              ]);
     ClassDeclaration declaration = unit.declarations[0] as ClassDeclaration;
     MethodDeclaration method = declaration.members[0] as MethodDeclaration;
     BlockFunctionBody body = method.body as BlockFunctionBody;
@@ -11424,8 +11492,15 @@
     TypeAnnotation type = expression.type;
     expect(type, isNotNull);
     expect(type is TypeName && type.name.isSynthetic, isTrue);
-    EngineTestCase.assertInstanceOf((obj) => obj is EmptyStatement,
-        EmptyStatement, ifStatement.thenStatement);
+    if (usingFastaParser) {
+      ExpressionStatement thenStatement = ifStatement.thenStatement;
+      expect(thenStatement.semicolon.isSynthetic, isTrue);
+      SimpleIdentifier simpleId = thenStatement.expression;
+      expect(simpleId.isSynthetic, isTrue);
+    } else {
+      EngineTestCase.assertInstanceOf((obj) => obj is EmptyStatement,
+          EmptyStatement, ifStatement.thenStatement);
+    }
   }
 
   void test_keywordInPlaceOfIdentifier() {
@@ -11738,11 +11813,13 @@
   }
 
   void test_primaryExpression_argumentDefinitionTest() {
-    Expression expression = parsePrimaryExpression('?a');
+    SimpleIdentifier expression = parsePrimaryExpression('?a',
+        expectedEndOffset: 0,
+        errors: usingFastaParser
+            ? [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 0, 1)]
+            : [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 0, 1)]);
     expectNotNullIfNoErrors(expression);
-    listener
-        .assertErrors([expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 0, 1)]);
-    expect(expression, new isInstanceOf<SimpleIdentifier>());
+    expect(expression.isSynthetic, usingFastaParser);
   }
 
   void test_propertyAccess_missing_LHS_RHS() {
@@ -13846,6 +13923,23 @@
     expect(creation.argumentList, isNotNull);
   }
 
+  void test_parseInstanceCreation_noKeyword_varInit() {
+    enableOptionalNewAndConst = true;
+    createParser('''
+class C<T, S> {}
+void main() {final c = C<int, int Function(String)>();}
+''');
+    CompilationUnit unit = parser.parseCompilationUnit2();
+    expect(unit, isNotNull);
+    FunctionDeclaration f = unit.declarations[1];
+    BlockFunctionBody body = f.functionExpression.body;
+    VariableDeclarationStatement statement = body.block.statements[0];
+    VariableDeclaration variable = statement.variables.variables[0];
+    MethodInvocation creation = variable.initializer;
+    expect(creation.methodName.name, 'C');
+    expect(creation.typeArguments.toSource(), '<int, int Function(String)>');
+  }
+
   void test_parseLibraryIdentifier_invalid() {
     parseCompilationUnit('library <myLibId>;',
         errors: usingFastaParser
diff --git a/pkg/analyzer/test/generated/static_warning_code_test.dart b/pkg/analyzer/test/generated/static_warning_code_test.dart
index f908337..a78274e 100644
--- a/pkg/analyzer/test/generated/static_warning_code_test.dart
+++ b/pkg/analyzer/test/generated/static_warning_code_test.dart
@@ -1467,7 +1467,11 @@
 class A implements Function {
 }''');
     await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.FUNCTION_WITHOUT_CALL]);
+    if (analysisOptions.strongMode) {
+      assertNoErrors(source);
+    } else {
+      assertErrors(source, [StaticWarningCode.FUNCTION_WITHOUT_CALL]);
+    }
     verify([source]);
   }
 
@@ -1476,7 +1480,11 @@
 class M {}
 class A = Object with M implements Function;''');
     await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.FUNCTION_WITHOUT_CALL]);
+    if (analysisOptions.strongMode) {
+      assertNoErrors(source);
+    } else {
+      assertErrors(source, [StaticWarningCode.FUNCTION_WITHOUT_CALL]);
+    }
     verify([source]);
   }
 
@@ -1487,7 +1495,11 @@
 class B extends A {
 }''');
     await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.FUNCTION_WITHOUT_CALL]);
+    if (analysisOptions.strongMode) {
+      assertNoErrors(source);
+    } else {
+      assertErrors(source, [StaticWarningCode.FUNCTION_WITHOUT_CALL]);
+    }
     verify([source]);
   }
 
@@ -1497,7 +1509,11 @@
 class M {}
 class B = A with M;''');
     await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.FUNCTION_WITHOUT_CALL]);
+    if (analysisOptions.strongMode) {
+      assertNoErrors(source);
+    } else {
+      assertErrors(source, [StaticWarningCode.FUNCTION_WITHOUT_CALL]);
+    }
     verify([source]);
   }
 
@@ -1508,7 +1524,11 @@
 class B implements A {
 }''');
     await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.FUNCTION_WITHOUT_CALL]);
+    if (analysisOptions.strongMode) {
+      assertNoErrors(source);
+    } else {
+      assertErrors(source, [StaticWarningCode.FUNCTION_WITHOUT_CALL]);
+    }
     verify([source]);
   }
 
@@ -1518,7 +1538,11 @@
 class M {}
 class B = Object with M implements A;''');
     await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.FUNCTION_WITHOUT_CALL]);
+    if (analysisOptions.strongMode) {
+      assertNoErrors(source);
+    } else {
+      assertErrors(source, [StaticWarningCode.FUNCTION_WITHOUT_CALL]);
+    }
     verify([source]);
   }
 
@@ -1527,7 +1551,11 @@
 abstract class A implements Function {}
 class B extends Object with A {}''');
     await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.FUNCTION_WITHOUT_CALL]);
+    if (analysisOptions.strongMode) {
+      assertNoErrors(source);
+    } else {
+      assertErrors(source, [StaticWarningCode.FUNCTION_WITHOUT_CALL]);
+    }
     verify([source]);
   }
 
@@ -1536,7 +1564,11 @@
 abstract class A implements Function {}
 class B = Object with A;''');
     await computeAnalysisResult(source);
-    assertErrors(source, [StaticWarningCode.FUNCTION_WITHOUT_CALL]);
+    if (analysisOptions.strongMode) {
+      assertNoErrors(source);
+    } else {
+      assertErrors(source, [StaticWarningCode.FUNCTION_WITHOUT_CALL]);
+    }
     verify([source]);
   }
 
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
index ab5f6b6..99871a4 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
@@ -2261,6 +2261,39 @@
     expect(clazz.name.name, 'A2');
   }
 
+  test_parseFileSync_notAbsolutePath() async {
+    try {
+      driver.parseFileSync('not_absolute.dart');
+      fail('ArgumentError expected.');
+    } on ArgumentError {}
+  }
+
+  test_parseFileSync_notDart() {
+    var p = _p('/test/bin/a.txt');
+    provider.newFile(p, 'class A {}');
+
+    ParseResult parseResult = driver.parseFileSync(p);
+    expect(parseResult, isNotNull);
+    expect(driver.knownFiles, contains(p));
+  }
+
+  test_parseFileSync_shouldRefresh() async {
+    var p = _p('/test/bin/a.dart');
+
+    provider.newFile(p, 'class A {}');
+    driver.addFile(p);
+
+    // Get the result, so force the file reading.
+    await driver.getResult(p);
+
+    // Update the file.
+    provider.newFile(p, 'class A2 {}');
+
+    ParseResult parseResult = driver.parseFileSync(p);
+    var clazz = parseResult.unit.declarations[0] as ClassDeclaration;
+    expect(clazz.name.name, 'A2');
+  }
+
   test_part_getErrors_afterLibrary() async {
     var a = _p('/test/lib/a.dart');
     var b = _p('/test/lib/b.dart');
diff --git a/pkg/analyzer/test/src/dart/analysis/session_test.dart b/pkg/analyzer/test/src/dart/analysis/session_test.dart
index f49208d..8f8a4f4 100644
--- a/pkg/analyzer/test/src/dart/analysis/session_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/session_test.dart
@@ -210,6 +210,11 @@
   Future<ParseResult> parseFile(String path) async {
     return parseResult;
   }
+
+  @override
+  ParseResult parseFileSync(String path) {
+    return parseResult;
+  }
 }
 
 class _SourceMock implements Source {
diff --git a/pkg/analyzer/test/src/summary/expr_builder_test.dart b/pkg/analyzer/test/src/summary/expr_builder_test.dart
index 7382339..0dedca8 100644
--- a/pkg/analyzer/test/src/summary/expr_builder_test.dart
+++ b/pkg/analyzer/test/src/summary/expr_builder_test.dart
@@ -4,6 +4,7 @@
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/summary/expr_builder.dart';
 import 'package:analyzer/src/summary/idl.dart';
 import 'package:analyzer/src/summary/resynthesize.dart';
@@ -446,6 +447,9 @@
   }
 
   void test_pushLocalFunctionReference_nested() {
+    prepareAnalysisContext(new AnalysisOptionsImpl()
+      ..previewDart2 = false
+      ..strongMode = false);
     var expr =
         checkSimpleExpression('(x) => (y) => x + y') as FunctionExpression;
     var outerFunctionElement = expr.element;
@@ -467,6 +471,9 @@
   }
 
   void test_pushLocalFunctionReference_paramReference() {
+    prepareAnalysisContext(new AnalysisOptionsImpl()
+      ..previewDart2 = false
+      ..strongMode = false);
     var expr = checkSimpleExpression('(x, y) => x + y') as FunctionExpression;
     var localFunctionElement = expr.element;
     var xElement = localFunctionElement.parameters[0];
diff --git a/pkg/analyzer/test/src/task/dart_test.dart b/pkg/analyzer/test/src/task/dart_test.dart
index d6e3c01..51d6bb6 100644
--- a/pkg/analyzer/test/src/task/dart_test.dart
+++ b/pkg/analyzer/test/src/task/dart_test.dart
@@ -3757,8 +3757,13 @@
     // validate
     CompilationUnit unit = outputs[RESOLVED_UNIT4];
     ClassDeclaration nodeB = unit.declarations[1];
-    _assertTypeParameterBound(
-        nodeB.typeParameters.typeParameters[0], 'A<dynamic>', 'A');
+    if (context.analysisOptions.strongMode) {
+      _assertTypeParameterBound(
+          nodeB.typeParameters.typeParameters[0], 'A<num>', 'A');
+    } else {
+      _assertTypeParameterBound(
+          nodeB.typeParameters.typeParameters[0], 'A<dynamic>', 'A');
+    }
   }
 
   test_perform_outputs() {
diff --git a/pkg/analyzer/test/src/task/options_test.dart b/pkg/analyzer/test/src/task/options_test.dart
index 186ab04..bd2a25f 100644
--- a/pkg/analyzer/test/src/task/options_test.dart
+++ b/pkg/analyzer/test/src/task/options_test.dart
@@ -52,7 +52,9 @@
       optionsProvider.getOptionsFromString(source);
 
   test_configure_bad_options_contents() {
-    (analysisOptions as AnalysisOptionsImpl).previewDart2 = false;
+    (analysisOptions as AnalysisOptionsImpl)
+      ..previewDart2 = false
+      ..strongMode = false;
     configureContext('''
 analyzer:
   strong-mode:true # misformatted
@@ -156,7 +158,9 @@
   }
 
   test_configure_strong_mode_bad_value() {
-    (analysisOptions as AnalysisOptionsImpl).previewDart2 = false;
+    (analysisOptions as AnalysisOptionsImpl)
+      ..previewDart2 = false
+      ..strongMode = false;
     configureContext('''
 analyzer:
   strong-mode: foo
diff --git a/pkg/analyzer/tool/task_dependency_graph/tasks.dot b/pkg/analyzer/tool/task_dependency_graph/tasks.dot
index a691f61..a812143 100644
--- a/pkg/analyzer/tool/task_dependency_graph/tasks.dot
+++ b/pkg/analyzer/tool/task_dependency_graph/tasks.dot
@@ -339,7 +339,6 @@
   TYPE_PROVIDER -> PartiallyResolveUnitReferencesTask
   TYPE_PROVIDER -> ResolveInstanceFieldsInUnitTask
   TYPE_PROVIDER -> ResolveLibraryTypeNamesTask
-  TYPE_PROVIDER -> ResolveTopLevelUnitTypeBoundsTask
   TYPE_PROVIDER -> ResolveUnitTask
   TYPE_PROVIDER -> ResolveUnitTypeNamesTask
   TYPE_PROVIDER -> ResolveVariableReferencesTask
diff --git a/pkg/analyzer_cli/lib/src/context_cache.dart b/pkg/analyzer_cli/lib/src/context_cache.dart
index 7c82294..9f07d92 100644
--- a/pkg/analyzer_cli/lib/src/context_cache.dart
+++ b/pkg/analyzer_cli/lib/src/context_cache.dart
@@ -95,13 +95,11 @@
     contextOptions.hint = !clOptions.disableHints;
     contextOptions.generateImplicitErrors = clOptions.showPackageWarnings;
     contextOptions.generateSdkErrors = clOptions.showSdkWarnings;
-    if (clOptions.previewDart2 != null) {
-      contextOptions.previewDart2 = clOptions.previewDart2;
-    }
+    contextOptions.previewDart2 = clOptions.previewDart2;
+    contextOptions.strongMode = clOptions.strongMode;
     if (clOptions.useCFE) {
       contextOptions.useFastaParser = true;
     }
-
     return contextOptions;
   }
 
diff --git a/pkg/analyzer_cli/lib/src/options.dart b/pkg/analyzer_cli/lib/src/options.dart
index 5136abf..071b3a4 100644
--- a/pkg/analyzer_cli/lib/src/options.dart
+++ b/pkg/analyzer_cli/lib/src/options.dart
@@ -189,8 +189,7 @@
         machineFormat = args['format'] == 'machine',
         perfReport = args['x-perf-report'],
         useCFE = args['use-cfe'],
-        previewDart2 =
-            args.wasParsed('preview-dart-2') ? args['preview-dart-2'] : null,
+        previewDart2 = args['preview-dart-2'],
         batchMode = args['batch'],
         showPackageWarnings = args['show-package-warnings'] ||
             args['package-warnings'] ||
@@ -515,7 +514,10 @@
           negatable: false,
           hide: hide)
       ..addFlag('preview-dart-2',
-          help: 'Enable the Dart 2.0 preview.', hide: hide);
+          help: 'Enable the Dart 2.0 preview.',
+          defaultsTo: true,
+          hide: hide,
+          negatable: true);
 
     try {
       if (args.contains('--$ignoreUnrecognizedFlagsFlag')) {
diff --git a/pkg/analyzer_cli/test/options_test.dart b/pkg/analyzer_cli/test/options_test.dart
index bdde061..86ff443 100644
--- a/pkg/analyzer_cli/test/options_test.dart
+++ b/pkg/analyzer_cli/test/options_test.dart
@@ -72,10 +72,10 @@
         expect(options.showSdkWarnings, isFalse);
         expect(options.sourceFiles, equals(['foo.dart']));
         expect(options.warningsAreFatal, isFalse);
-        expect(options.strongMode, isFalse);
+        expect(options.strongMode, isTrue);
         expect(options.lintsAreFatal, isFalse);
         expect(options.useCFE, isFalse);
-        expect(options.previewDart2, null);
+        expect(options.previewDart2, isTrue);
       });
 
       test('batch', () {
diff --git a/pkg/analyzer_plugin/lib/src/protocol/protocol_internal.dart b/pkg/analyzer_plugin/lib/src/protocol/protocol_internal.dart
index 5778af8..ba03cb8 100644
--- a/pkg/analyzer_plugin/lib/src/protocol/protocol_internal.dart
+++ b/pkg/analyzer_plugin/lib/src/protocol/protocol_internal.dart
@@ -277,11 +277,9 @@
     if (json is int) {
       return json;
     } else if (json is String) {
-      int value = int.tryParse(json);
-      if (value == null) {
+      return int.parse(json, onError: (String value) {
         throw mismatch(jsonPath, 'int', json);
-      }
-      return value;
+      });
     }
     throw mismatch(jsonPath, 'int', json);
   }
diff --git a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
index e0728a5..9759e18 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
@@ -1288,17 +1288,6 @@
             });
           } else {
             int offset = next.offset;
-            Token comment = next.beginToken.precedingComments;
-            while (comment != null) {
-              int commentOffset = comment.offset;
-              if (commentOffset ==
-                  lineInfo.getOffsetOfLine(
-                      lineInfo.getLocation(commentOffset).lineNumber - 1)) {
-                offset = commentOffset;
-                break;
-              }
-              comment = comment.next;
-            }
             addInsertion(offset, (EditBuilder builder) {
               builder.write("import '");
               builder.write(uri);
diff --git a/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart b/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart
index 8579f0e..018c068 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart
@@ -543,7 +543,10 @@
     // If the current token is synthetic, then check the previous token
     // because it may have been dropped from the parse tree
     Token previous = node.findPrevious(token);
-    if (offset < previous.end) {
+    if (previous == null) {
+      // support dangling expression completion, where previous may be null.
+      return false;
+    } else if (offset < previous.end) {
       return true;
     } else if (offset == previous.end) {
       return token.type.isKeyword || previous.type == TokenType.IDENTIFIER;
diff --git a/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart b/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart
index 15f7284..a7a52c0 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart
@@ -27,15 +27,6 @@
   bool includeConstructorSuggestions = false;
 
   /**
-   * If [includeConstructorSuggestions] is set to true, then this function may
-   * be set to a non-default function to filter out potential suggestions (null)
-   * based on their static [DartType], or change the relative relevance by
-   * returning a higher or lower relevance.
-   */
-  SuggestionsFilter constructorSuggestionsFilter =
-      (DartType _, int relevance) => relevance;
-
-  /**
    * Indicates whether type names should be suggested.
    */
   bool includeTypeNameSuggestions = false;
@@ -210,20 +201,6 @@
       return;
     }
 
-    constructorSuggestionsFilter = (DartType dartType, int relevance) {
-      if (dartType != null) {
-        if (dartType == _requiredType) {
-          return relevance + DART_RELEVANCE_BOOST_TYPE;
-        } else if (dartType.isSubtypeOf(_requiredType)) {
-          return relevance + DART_RELEVANCE_BOOST_SUBTYPE;
-        }
-        if (target.containingNode is InstanceCreationExpression) {
-          return null;
-        }
-      }
-      return relevance;
-    };
-
     returnValueSuggestionsFilter = (DartType dartType, int relevance) {
       if (dartType != null) {
         if (dartType == _requiredType) {
diff --git a/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart b/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
index 4cc4c03..a849278 100644
--- a/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
@@ -240,8 +240,8 @@
 
 import 'foo.dart';
 ''', ['package:aaa/a1.dart'], '''
-import 'package:aaa/a1.dart';
 // comment a2
+import 'package:aaa/a1.dart';
 import 'package:aaa/a2.dart';
 
 import 'foo.dart';
diff --git a/pkg/analyzer_plugin/test/src/utilities/completion/optype_test.dart b/pkg/analyzer_plugin/test/src/utilities/completion/optype_test.dart
index e48e3ea..f89d484 100644
--- a/pkg/analyzer_plugin/test/src/utilities/completion/optype_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/completion/optype_test.dart
@@ -16,15 +16,23 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(OpTypeTest);
+    defineReflectiveTests(OpTypeDart1OnlyTest);
+    defineReflectiveTests(OpTypeDart1Test);
   });
 }
 
-@reflectiveTest
-class OpTypeTest extends AbstractContextTest {
+/// Common test methods to Dart1/Dart2 versions of OpType tests.
+class OpTypeTestCommon extends AbstractContextTest {
   String testpath;
   int completionOffset;
   OpType visitor;
 
+  @override
+  void setUp() {
+    super.setUp();
+    testpath = provider.convertPath('/completionTest.dart');
+  }
+
   void addTestSource(String content) {
     completionOffset = content.indexOf('^');
     expect(completionOffset, isNot(equals(-1)), reason: 'missing ^');
@@ -72,13 +80,26 @@
     expect(visitor.isPrefixed, prefixed, reason: 'prefixed');
     expect(visitor.suggestKind, kind, reason: 'suggestion kind');
   }
+}
+
+/// Execute the tests that work on both.
+@reflectiveTest
+class OpTypeDart1Test extends OpTypeTest {
+  @override
+  bool get enablePreviewDart2 => false;
 
   @override
-  void setUp() {
-    super.setUp();
-    testpath = provider.convertPath('/completionTest.dart');
-  }
+  bool get enableStrongMode => false;
+}
 
+@reflectiveTest
+// TODO: determine if tests here need to be fixed for Dart2.
+class OpTypeDart1OnlyTest extends OpTypeTestCommon {
+  @override
+  bool get enablePreviewDart2 => false;
+
+  @override
+  bool get enableStrongMode => false;
   test_Annotation() async {
     // SimpleIdentifier  Annotation  MethodDeclaration  ClassDeclaration
     addTestSource('class C { @A^ }');
@@ -98,90 +119,6 @@
         typeNames: true);
   }
 
-  test_ArgumentList_constructor_named_resolved_1_0() async {
-    // ArgumentList  InstanceCreationExpression  ExpressionStatement Block
-    addTestSource(
-      'main() { new A.b(^); }'
-          'class A{ A.b({one, two}) {} }',
-    );
-    await assertOpType(namedArgs: true);
-  }
-
-  test_ArgumentList_constructor_named_resolved_1_1() async {
-    // ArgumentList  InstanceCreationExpression  ExpressionStatement  Block
-    addTestSource(
-      'main() { new A.b(o^); }'
-          'class A { A.b({one, two}) {} }',
-    );
-    await assertOpType(namedArgs: true);
-  }
-
-  test_ArgumentList_constructor_resolved_1_0() async {
-    // ArgumentList  InstanceCreationExpression  ExpressionStatement Block
-    addTestSource(
-      'main() { new A(^); }'
-          'class A{ A({one, two}) {} }',
-    );
-    await assertOpType(namedArgs: true);
-  }
-
-  test_ArgumentList_constructor_resolved_1_1() async {
-    // ArgumentList  InstanceCreationExpression  ExpressionStatement  Block
-    addTestSource(
-      'main() { new A(o^); }'
-          'class A { A({one, two}) {} }',
-    );
-    await assertOpType(namedArgs: true);
-  }
-
-  test_ArgumentList_factory_named_resolved_1_0() async {
-    // ArgumentList  InstanceCreationExpression  ExpressionStatement Block
-    addTestSource(
-      'main() { new A.b(^); }'
-          'class A{ factory A.b({one, two}) {} }',
-    );
-    await assertOpType(namedArgs: true);
-  }
-
-  test_ArgumentList_factory_named_resolved_1_1() async {
-    // ArgumentList  InstanceCreationExpression  ExpressionStatement  Block
-    addTestSource(
-      'main() { new A.b(o^); }'
-          'class A { factory A.b({one, two}) {} }',
-    );
-    await assertOpType(namedArgs: true);
-  }
-
-  test_ArgumentList_factory_resolved_1_0() async {
-    // ArgumentList  InstanceCreationExpression  ExpressionStatement Block
-    addTestSource(
-      'main() { new A(^); }'
-          'class A{ factory A({one, two}) {} }',
-    );
-    await assertOpType(namedArgs: true);
-  }
-
-  test_ArgumentList_factory_resolved_1_1() async {
-    // ArgumentList  InstanceCreationExpression  ExpressionStatement  Block
-    addTestSource(
-      'main() { new A(o^); }'
-          'class A { factory A({one, two}) {} }',
-    );
-    await assertOpType(namedArgs: true);
-  }
-
-  test_ArgumentList_method_resolved_1_0() async {
-    // ArgumentList  MethodInvocation  ExpressionStatement  Block
-    addTestSource('main() { foo(^);} foo({one, two}) {}');
-    await assertOpType(namedArgs: true);
-  }
-
-  test_ArgumentList_method_resolved_1_1() async {
-    // ArgumentList  MethodInvocation  ExpressionStatement  Block
-    addTestSource('main() { foo(o^);} foo({one, two}) {}');
-    await assertOpType(namedArgs: true);
-  }
-
   test_ArgumentList_namedParam() async {
     // SimpleIdentifier  NamedExpression  ArgumentList  MethodInvocation
     // ExpressionStatement
@@ -207,18 +144,6 @@
         constructors: previewDart2, returnValue: true, typeNames: true);
   }
 
-  test_ArgumentList_resolved_2_0() async {
-    // ArgumentList  MethodInvocation  ExpressionStatement  Block
-    addTestSource('void main() {int.parse("16", ^)}');
-    await assertOpType(namedArgs: true);
-  }
-
-  test_AsExpression() async {
-    // SimpleIdentifier  TypeName  AsExpression
-    addTestSource('class A {var b; X _c; foo() {var a; (a as ^).foo();}');
-    await assertOpType(typeNames: true);
-  }
-
   test_AsIdentifier() async {
     addTestSource('class A {var asdf; foo() {as^}');
     await assertOpType(
@@ -228,11 +153,6 @@
         voidReturn: true);
   }
 
-  test_AsIdentifier2() async {
-    addTestSource('class A {var asdf; foo() {A as^}');
-    await assertOpType();
-  }
-
   test_Assert() async {
     addTestSource('main() {assert(^)}');
     await assertOpType(
@@ -245,13 +165,6 @@
         constructors: previewDart2, returnValue: true, typeNames: true);
   }
 
-  test_AssignmentExpression_name() async {
-    // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
-    // VariableDeclarationStatement  Block
-    addTestSource('class A {} main() {int a; int ^b = 1;}');
-    await assertOpType(varNames: true);
-  }
-
   test_AssignmentExpression_RHS() async {
     // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
     // VariableDeclarationStatement  Block
@@ -418,34 +331,6 @@
         voidReturn: true);
   }
 
-  test_Block_catch_1a() async {
-    // '}'  Block  BlockFunctionBody  FunctionExpression
-    addTestSource('main() {try {} ^}');
-    // Only return 'on', 'catch', and 'finally' keywords
-    await assertOpType();
-  }
-
-  test_Block_catch_1b() async {
-    // [ExpressionStatement 'c']  Block  BlockFunctionBody
-    addTestSource('main() {try {} c^}');
-    // Only return 'on', 'catch', and 'finally' keywords
-    await assertOpType();
-  }
-
-  test_Block_catch_1c() async {
-    // [EmptyStatement]  Block  BlockFunctionBody  FunctionExpression
-    addTestSource('main() {try {} ^;}');
-    // Only return 'on', 'catch', and 'finally' keywords
-    await assertOpType();
-  }
-
-  test_Block_catch_1d() async {
-    // [VariableDeclarationStatement 'Foo foo']  Block  BlockFunctionBody
-    addTestSource('main() {try {} ^ Foo foo;}');
-    // Only return 'on', 'catch', and 'finally' keywords
-    await assertOpType();
-  }
-
   test_Block_catch_2a() async {
     // '}'  Block  BlockFunctionBody  FunctionExpression
     addTestSource('main() {try {} catch () {} ^}');
@@ -526,9 +411,8 @@
         voidReturn: true);
   }
 
-  test_Block_empty() async {
-    // Block  BlockFunctionBody  MethodDeclaration  ClassDeclaration
-    addTestSource('class A extends E implements I with M {a() {^}}');
+  test_Block_identifier_partial() async {
+    addTestSource('class X {a() {var f; {var x;} D^ var r;} void b() { }}');
     await assertOpType(
         constructors: previewDart2,
         returnValue: true,
@@ -536,33 +420,9 @@
         voidReturn: true);
   }
 
-  test_Block_final() async {
-    addTestSource('main() {final ^}');
-    await assertOpType(typeNames: true);
-  }
-
-  test_Block_final2() async {
-    addTestSource('main() {final S^ v;}');
-    await assertOpType(typeNames: true);
-  }
-
-  test_Block_final3() async {
-    addTestSource('main() {final ^ v;}');
-    await assertOpType(typeNames: true);
-  }
-
-  test_Block_final_final() async {
-    addTestSource('main() {final ^ final S x;}');
-    await assertOpType(typeNames: true);
-  }
-
-  test_Block_final_final2() async {
-    addTestSource('main() {final S^ final S x;}');
-    await assertOpType(typeNames: true);
-  }
-
-  test_Block_identifier_partial() async {
-    addTestSource('class X {a() {var f; {var x;} D^ var r;} void b() { }}');
+  test_Block_empty() async {
+    // Block  BlockFunctionBody  MethodDeclaration  ClassDeclaration
+    addTestSource('class A extends E implements I with M {a() {^}}');
     await assertOpType(
         constructors: previewDart2,
         returnValue: true,
@@ -590,21 +450,6 @@
         voidReturn: true);
   }
 
-  test_Break_after_label() async {
-    addTestSource('main() { foo: while (true) { break foo ^ ; } }');
-    await assertOpType(/* No valid completions */);
-  }
-
-  test_Break_before_label() async {
-    addTestSource('main() { foo: while (true) { break ^ foo; } }');
-    await assertOpType(statementLabel: true);
-  }
-
-  test_Break_no_label() async {
-    addTestSource('main() { foo: while (true) { break ^; } }');
-    await assertOpType(statementLabel: true);
-  }
-
   test_CascadeExpression_selector1() async {
     // PropertyAccess  CascadeExpression  ExpressionStatement  Block
     addTestSource('''
@@ -649,6 +494,740 @@
         voidReturn: true);
   }
 
+  test_CatchClause_typed() async {
+    // Block  CatchClause  TryStatement
+    addTestSource('class A {a() {try{var x;} on E catch (e) {^}}}');
+    await assertOpType(
+        constructors: previewDart2,
+        returnValue: true,
+        typeNames: true,
+        voidReturn: true);
+  }
+
+  test_CatchClause_untyped() async {
+    // Block  CatchClause  TryStatement
+    addTestSource('class A {a() {try{var x;} catch (e, s) {^}}}');
+    await assertOpType(
+        constructors: previewDart2,
+        returnValue: true,
+        typeNames: true,
+        voidReturn: true);
+  }
+
+  test_CommentReference() async {
+    // SimpleIdentifier  CommentReference  Comment  MethodDeclaration
+    addTestSource('class A {/** [^] */ mth() {}');
+    await assertOpType(
+        constructors: previewDart2,
+        returnValue: true,
+        typeNames: true,
+        voidReturn: true,
+        kind: CompletionSuggestionKind.IDENTIFIER);
+  }
+
+  test_ConditionalExpression_elseExpression() async {
+    // SimpleIdentifier  ConditionalExpression  ReturnStatement
+    addTestSource('class C {foo(){var f; {var x;} return a ? T1 : T^}}');
+    await assertOpType(
+        constructors: previewDart2, returnValue: true, typeNames: true);
+  }
+
+  test_ConditionalExpression_elseExpression_empty() async {
+    // SimpleIdentifier  ConditionalExpression  ReturnStatement
+    addTestSource('class C {foo(){var f; {var x;} return a ? T1 : ^}}');
+    await assertOpType(
+        constructors: previewDart2, returnValue: true, typeNames: true);
+  }
+
+  test_ConditionalExpression_partial_thenExpression() async {
+    // SimpleIdentifier  ConditionalExpression  ReturnStatement
+    addTestSource('class C {foo(){var f; {var x;} return a ? T^}}');
+    await assertOpType(
+        constructors: previewDart2, returnValue: true, typeNames: true);
+  }
+
+  test_ConditionalExpression_partial_thenExpression_empty() async {
+    // SimpleIdentifier  ConditionalExpression  ReturnStatement
+    addTestSource('class C {foo(){var f; {var x;} return a ? ^}}');
+    await assertOpType(
+        constructors: previewDart2, returnValue: true, typeNames: true);
+  }
+
+  test_ConditionalExpression_thenExpression() async {
+    // SimpleIdentifier  ConditionalExpression  ReturnStatement
+    addTestSource('class C {foo(){var f; {var x;} return a ? T^ : c}}');
+    await assertOpType(
+        constructors: previewDart2, returnValue: true, typeNames: true);
+  }
+
+  test_DefaultFormalParameter_named_expression() async {
+    // DefaultFormalParameter FormalParameterList MethodDeclaration
+    addTestSource('class A {a(blat: ^) { }}');
+    await assertOpType(
+        constructors: previewDart2, returnValue: true, typeNames: true);
+  }
+
+  test_DoStatement() async {
+    // SimpleIdentifier  DoStatement  Block
+    addTestSource('main() {do{} while(^x);}');
+    await assertOpType(
+        constructors: previewDart2, returnValue: true, typeNames: true);
+  }
+
+  test_ExpressionFunctionBody() async {
+    // SimpleIdentifier  ExpressionFunctionBody  FunctionExpression
+    addTestSource('m(){[1].forEach((x)=>^x);}');
+    await assertOpType(
+        constructors: previewDart2, returnValue: true, typeNames: true);
+  }
+
+  test_ExpressionStatement() async {
+    // ExpressionStatement  Block  BlockFunctionBody
+    addTestSource('n(){f(3);^}');
+    await assertOpType(
+        constructors: previewDart2,
+        returnValue: true,
+        typeNames: true,
+        voidReturn: true);
+  }
+
+  test_ForEachStatement() async {
+    // SimpleIdentifier  ForEachStatement  Block
+    addTestSource('main() {for(z in ^zs) {}}');
+    await assertOpType(
+        constructors: previewDart2, returnValue: true, typeNames: true);
+  }
+
+  test_ForEachStatement_body_typed() async {
+    // Block  ForEachStatement
+    addTestSource('main(args) {for (int foo in bar) {^}}');
+    await assertOpType(
+        constructors: previewDart2,
+        returnValue: true,
+        typeNames: true,
+        voidReturn: true);
+  }
+
+  test_ForEachStatement_body_untyped() async {
+    // Block  ForEachStatement
+    addTestSource('main(args) {for (foo in bar) {^}}');
+    await assertOpType(
+        constructors: previewDart2,
+        returnValue: true,
+        typeNames: true,
+        voidReturn: true);
+  }
+
+  test_ForEachStatement_iterable() async {
+    // SimpleIdentifier  ForEachStatement  Block
+    addTestSource('main(args) {for (int foo in ^) {}}');
+    await assertOpType(
+        constructors: previewDart2, returnValue: true, typeNames: true);
+  }
+
+  test_FormalParameter_partialType() async {
+    // FormalParameterList MethodDeclaration
+    addTestSource('class A {a(b.^ f) { }}');
+    await assertOpType(
+        constructors: previewDart2,
+        returnValue: true,
+        typeNames: true,
+        prefixed: true);
+  }
+
+  test_FormalParameter_partialType2() async {
+    // FormalParameterList MethodDeclaration
+    addTestSource('class A {a(b.z^ f) { }}');
+    await assertOpType(
+        constructors: previewDart2,
+        returnValue: true,
+        typeNames: true,
+        prefixed: true);
+  }
+
+  test_FormalParameter_partialType3() async {
+    // FormalParameterList MethodDeclaration
+    addTestSource('class A {a(b.^) { }}');
+    await assertOpType(
+        constructors: previewDart2,
+        returnValue: true,
+        typeNames: true,
+        prefixed: true);
+  }
+
+  test_ForStatement_condition() async {
+    // SimpleIdentifier  ForStatement
+    addTestSource('main() {for (int index = 0; i^)}');
+    await assertOpType(
+        constructors: previewDart2, returnValue: true, typeNames: true);
+  }
+
+  test_ForStatement_updaters() async {
+    // SimpleIdentifier  ForStatement
+    addTestSource('main() {for (int index = 0; index < 10; i^)}');
+    // TODO (danrubel) may want to exclude methods/functions with void return
+    await assertOpType(
+        constructors: previewDart2,
+        returnValue: true,
+        typeNames: true,
+        voidReturn: true);
+  }
+
+  test_ForStatement_updaters_prefix_expression() async {
+    // SimpleIdentifier  PrefixExpression  ForStatement
+    addTestSource('main() {for (int index = 0; index < 10; ++i^)}');
+    await assertOpType(
+        constructors: previewDart2, returnValue: true, typeNames: true);
+  }
+
+  test_IfStatement() async {
+    // EmptyStatement  IfStatement  Block  BlockFunctionBody
+    addTestSource('main(){var a; if (true) ^}');
+    await assertOpType(
+        constructors: previewDart2,
+        returnValue: true,
+        typeNames: true,
+        voidReturn: true);
+  }
+
+  test_IfStatement_condition() async {
+    // SimpleIdentifier  IfStatement  Block  BlockFunctionBody
+    addTestSource('main(){var a; if (^)}');
+    await assertOpType(
+        constructors: previewDart2, returnValue: true, typeNames: true);
+  }
+
+  test_IfStatement_empty() async {
+    // SimpleIdentifier  PrefixIdentifier  IfStatement
+    addTestSource('class A {foo() {A a; if (^) something}}');
+    await assertOpType(
+        constructors: previewDart2, returnValue: true, typeNames: true);
+  }
+
+  test_IfStatement_invocation() async {
+    // SimpleIdentifier  PrefixIdentifier  IfStatement
+    addTestSource('main() {var a; if (a.^) something}');
+    await assertOpType(
+        constructors: previewDart2,
+        returnValue: true,
+        typeNames: true,
+        prefixed: true);
+  }
+
+  test_IndexExpression() async {
+    addTestSource('class C {foo(){var f; {var x;} f[^]}}');
+    await assertOpType(
+        constructors: previewDart2, returnValue: true, typeNames: true);
+  }
+
+  test_IndexExpression2() async {
+    addTestSource('class C {foo(){var f; {var x;} f[T^]}}');
+    await assertOpType(
+        constructors: previewDart2, returnValue: true, typeNames: true);
+  }
+
+  test_InstanceCreationExpression_keyword() async {
+    // InstanceCreationExpression  ExpressionStatement  Block
+    addTestSource('class C {foo(){var f; {var x;} new^ }}');
+    await assertOpType(
+        constructors: previewDart2,
+        returnValue: true,
+        typeNames: true,
+        voidReturn: true);
+  }
+
+  test_InstanceCreationExpression_keyword2() async {
+    // InstanceCreationExpression  ExpressionStatement  Block
+    addTestSource('class C {foo(){var f; {var x;} new^ C();}}');
+    await assertOpType(
+        constructors: previewDart2,
+        returnValue: true,
+        typeNames: true,
+        voidReturn: true);
+  }
+
+  test_InterpolationExpression() async {
+    // SimpleIdentifier  InterpolationExpression  StringInterpolation
+    addTestSource('main() {String name; print("hello \$^");}');
+    await assertOpType(constructors: previewDart2, returnValue: true);
+  }
+
+  test_InterpolationExpression_block() async {
+    // SimpleIdentifier  InterpolationExpression  StringInterpolation
+    addTestSource('main() {String name; print("hello \${n^}");}');
+    await assertOpType(
+        constructors: previewDart2, returnValue: true, typeNames: true);
+  }
+
+  test_InterpolationExpression_prefix_selector() async {
+    // SimpleIdentifier  PrefixedIdentifier  InterpolationExpression
+    addTestSource('main() {String name; print("hello \${name.^}");}');
+    await assertOpType(
+        constructors: previewDart2,
+        returnValue: true,
+        typeNames: true,
+        prefixed: true);
+  }
+
+  test_InterpolationExpression_prefix_target() async {
+    // SimpleIdentifier  PrefixedIdentifier  InterpolationExpression
+    addTestSource('main() {String name; print("hello \${nam^e.length}");}');
+    await assertOpType(
+        constructors: previewDart2, returnValue: true, typeNames: true);
+  }
+
+  test_IsExpression_target() async {
+    // IfStatement  Block  BlockFunctionBody
+    addTestSource('main(){var a; if (^ is A)}');
+    await assertOpType(
+        constructors: previewDart2, returnValue: true, typeNames: true);
+  }
+
+  test_Literal_list() async {
+    // ']'  ListLiteral  ArgumentList  MethodInvocation
+    addTestSource('main() {var Some; print([^]);}');
+    await assertOpType(
+        constructors: previewDart2, returnValue: true, typeNames: true);
+  }
+
+  test_Literal_list2() async {
+    // SimpleIdentifier ListLiteral  ArgumentList  MethodInvocation
+    addTestSource('main() {var Some; print([S^]);}');
+    await assertOpType(
+        constructors: previewDart2, returnValue: true, typeNames: true);
+  }
+
+  test_MapLiteralEntry() async {
+    // MapLiteralEntry  MapLiteral  VariableDeclaration
+    addTestSource('foo = {^');
+    await assertOpType(
+        constructors: previewDart2, returnValue: true, typeNames: true);
+  }
+
+  test_MapLiteralEntry1() async {
+    // MapLiteralEntry  MapLiteral  VariableDeclaration
+    addTestSource('foo = {T^');
+    await assertOpType(
+        constructors: previewDart2, returnValue: true, typeNames: true);
+  }
+
+  test_MapLiteralEntry2() async {
+    // SimpleIdentifier  MapLiteralEntry  MapLiteral  VariableDeclaration
+    addTestSource('foo = {7:T^};');
+    await assertOpType(
+        constructors: previewDart2, returnValue: true, typeNames: true);
+  }
+
+  test_MethodInvocation_no_semicolon() async {
+    // MethodInvocation  ExpressionStatement  Block
+    addTestSource('''
+      class A implements I {
+        // no semicolon between completion point and next statement
+        set _s2(I x) {x.^ m(null);}
+      }''');
+    await assertOpType(
+        constructors: previewDart2,
+        returnValue: true,
+        typeNames: true,
+        voidReturn: true,
+        prefixed: true);
+  }
+
+  test_PostfixExpression() async {
+    // SimpleIdentifier  PostfixExpression  ForStatement
+    addTestSource('int x = 0; main() {ax+^+;}');
+    await assertOpType(
+        constructors: previewDart2, returnValue: true, typeNames: true);
+  }
+
+  test_PrefixedIdentifier_class_const() async {
+    // SimpleIdentifier PrefixedIdentifier ExpressionStatement Block
+    addTestSource('main() {A.^}');
+    await assertOpType(
+        constructors: previewDart2,
+        returnValue: true,
+        typeNames: true,
+        voidReturn: true,
+        prefixed: true);
+  }
+
+  test_PrefixedIdentifier_class_imported() async {
+    // SimpleIdentifier  PrefixedIdentifier  ExpressionStatement
+    addTestSource('main() {A a; a.^}');
+    await assertOpType(
+        constructors: previewDart2,
+        returnValue: true,
+        typeNames: true,
+        voidReturn: true,
+        prefixed: true);
+  }
+
+  test_PrefixedIdentifier_prefix() async {
+    // SimpleIdentifier  PrefixedIdentifier  ExpressionStatement
+    addTestSource('class X {foo(){A^.bar}}');
+    await assertOpType(
+        constructors: previewDart2,
+        typeNames: true,
+        returnValue: true,
+        voidReturn: true);
+  }
+
+  test_PropertyAccess_expression() async {
+    // SimpleIdentifier  MethodInvocation  PropertyAccess  ExpressionStatement
+    addTestSource('class A {a() {"hello".to^String().length}}');
+    await assertOpType(
+        constructors: previewDart2,
+        returnValue: true,
+        typeNames: true,
+        voidReturn: true,
+        prefixed: true);
+  }
+
+  test_PropertyAccess_selector() async {
+    // SimpleIdentifier  PropertyAccess  ExpressionStatement  Block
+    addTestSource('class A {a() {"hello".length.^}}');
+    await assertOpType(
+        constructors: previewDart2,
+        returnValue: true,
+        typeNames: true,
+        voidReturn: true,
+        prefixed: true);
+  }
+
+  test_ReturnStatement() async {
+    // ReturnStatement  Block
+    addTestSource('f() { var vvv = 42; return ^ }');
+    await assertOpType(
+        constructors: previewDart2, returnValue: true, typeNames: true);
+  }
+
+  test_SwitchCase_between() async {
+    // SwitchCase  SwitchStatement  Block
+    addTestSource('main() {switch(k) {case 1: ^ case 2: return}}');
+    await assertOpType(
+        constructors: previewDart2,
+        returnValue: true,
+        typeNames: true,
+        voidReturn: true);
+  }
+
+  test_SwitchCase_expression1() async {
+    // SimpleIdentifier  SwitchCase  SwitchStatement
+    addTestSource('''m() {switch (x) {case ^D: return;}}''');
+    await assertOpType(
+        constructors: previewDart2, returnValue: true, typeNames: true);
+  }
+
+  test_SwitchCase_expression2() async {
+    // SimpleIdentifier  SwitchCase  SwitchStatement
+    addTestSource('''m() {switch (x) {case ^}}''');
+    await assertOpType(
+        constructors: previewDart2, returnValue: true, typeNames: true);
+  }
+
+  test_SwitchDefault_between() async {
+    // SwitchDefault  SwitchStatement  Block
+    addTestSource('main() {switch(k) {case 1: ^ default: return;}}');
+    await assertOpType(
+        constructors: previewDart2,
+        returnValue: true,
+        typeNames: true,
+        voidReturn: true);
+  }
+
+  test_SwitchStatement_body_end() async {
+    // Token('}')  SwitchStatement  Block
+    addTestSource('main() {switch(k) {case 1:^}}');
+    await assertOpType(
+        constructors: previewDart2,
+        returnValue: true,
+        typeNames: true,
+        voidReturn: true);
+  }
+
+  test_SwitchStatement_body_end2() async {
+    addTestSource('main() {switch(k) {case 1:as^}}');
+    await assertOpType(
+        constructors: previewDart2,
+        returnValue: true,
+        typeNames: true,
+        voidReturn: true);
+  }
+
+  test_SwitchStatement_expression1() async {
+    // SimpleIdentifier  SwitchStatement  Block
+    addTestSource('main() {switch(^k) {case 1:{}}}');
+    await assertOpType(
+        constructors: previewDart2, returnValue: true, typeNames: true);
+  }
+
+  test_SwitchStatement_expression2() async {
+    // SimpleIdentifier  SwitchStatement  Block
+    addTestSource('main() {switch(k^) {case 1:{}}}');
+    await assertOpType(
+        constructors: previewDart2, returnValue: true, typeNames: true);
+  }
+
+  test_SwitchStatement_expression_empty() async {
+    // SimpleIdentifier  SwitchStatement  Block
+    addTestSource('main() {switch(^) {case 1:{}}}');
+    await assertOpType(
+        constructors: previewDart2, returnValue: true, typeNames: true);
+  }
+
+  test_ThisExpression_block() async {
+    // MethodInvocation  ExpressionStatement  Block
+    addTestSource('''
+      class A implements I {
+        // no semicolon between completion point and next statement
+        set s1(I x) {} set _s2(I x) {this.^ m(null);}
+      }''');
+    // TODO(brianwilkerson) We should not be adding constructors here.
+    await assertOpType(
+        constructors: previewDart2,
+        returnValue: true,
+        voidReturn: true,
+        prefixed: true);
+  }
+
+  test_ThisExpression_constructor() async {
+    // SimpleIdentifier  PropertyAccess  ExpressionStatement
+    addTestSource('''
+      class A implements I {
+        A() {this.^}
+      }''');
+    await assertOpType(
+        constructors: previewDart2,
+        returnValue: true,
+        voidReturn: true,
+        prefixed: true);
+  }
+
+  test_ThrowExpression() async {
+    // SimpleIdentifier  ThrowExpression  ExpressionStatement
+    addTestSource('main() {throw ^;}');
+    await assertOpType(
+        constructors: previewDart2, returnValue: true, typeNames: true);
+  }
+
+  test_VariableDeclarationStatement_afterSemicolon() async {
+    // VariableDeclarationStatement  Block  BlockFunctionBody
+    addTestSource('class A {var a; x() {var b;^}}');
+    await assertOpType(
+        constructors: previewDart2,
+        returnValue: true,
+        typeNames: true,
+        voidReturn: true);
+  }
+
+  test_VariableDeclarationStatement_RHS() async {
+    // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
+    // VariableDeclarationStatement
+    addTestSource('class C {bar(){var f; {var x;} var e = ^}}');
+    await assertOpType(
+        constructors: previewDart2, returnValue: true, typeNames: true);
+  }
+
+  test_VariableDeclarationStatement_RHS_missing_semicolon() async {
+    // VariableDeclaration  VariableDeclarationList
+    // VariableDeclarationStatement
+    addTestSource('class C {bar(){var f; {var x;} var e = ^ var g}}');
+    await assertOpType(
+        constructors: previewDart2, returnValue: true, typeNames: true);
+  }
+
+  test_WhileStatement() async {
+    // SimpleIdentifier  WhileStatement  Block
+    addTestSource('mth() { while (b^) {} }}');
+    await assertOpType(
+        constructors: previewDart2, returnValue: true, typeNames: true);
+  }
+
+  test_WithClause() async {
+    // WithClause  ClassDeclaration
+    addTestSource('class x extends Object with ^\n{}');
+    await assertOpType(constructors: previewDart2, typeNames: true);
+  }
+}
+
+@reflectiveTest
+class OpTypeTest extends OpTypeTestCommon {
+  test_ArgumentList_constructor_named_resolved_1_0() async {
+    // ArgumentList  InstanceCreationExpression  ExpressionStatement Block
+    addTestSource(
+      'main() { new A.b(^); }'
+          'class A{ A.b({one, two}) {} }',
+    );
+    await assertOpType(namedArgs: true);
+  }
+
+  test_ArgumentList_constructor_named_resolved_1_1() async {
+    // ArgumentList  InstanceCreationExpression  ExpressionStatement  Block
+    addTestSource(
+      'main() { new A.b(o^); }'
+          'class A { A.b({one, two}) {} }',
+    );
+    await assertOpType(namedArgs: true);
+  }
+
+  test_ArgumentList_constructor_resolved_1_0() async {
+    // ArgumentList  InstanceCreationExpression  ExpressionStatement Block
+    addTestSource(
+      'main() { new A(^); }'
+          'class A{ A({one, two}) {} }',
+    );
+    await assertOpType(namedArgs: true);
+  }
+
+  test_ArgumentList_constructor_resolved_1_1() async {
+    // ArgumentList  InstanceCreationExpression  ExpressionStatement  Block
+    addTestSource(
+      'main() { new A(o^); }'
+          'class A { A({one, two}) {} }',
+    );
+    await assertOpType(namedArgs: true);
+  }
+
+  test_ArgumentList_factory_named_resolved_1_0() async {
+    // ArgumentList  InstanceCreationExpression  ExpressionStatement Block
+    addTestSource(
+      'main() { new A.b(^); }'
+          'class A{ factory A.b({one, two}) {} }',
+    );
+    await assertOpType(namedArgs: true);
+  }
+
+  test_ArgumentList_factory_named_resolved_1_1() async {
+    // ArgumentList  InstanceCreationExpression  ExpressionStatement  Block
+    addTestSource(
+      'main() { new A.b(o^); }'
+          'class A { factory A.b({one, two}) {} }',
+    );
+    await assertOpType(namedArgs: true);
+  }
+
+  test_ArgumentList_factory_resolved_1_0() async {
+    // ArgumentList  InstanceCreationExpression  ExpressionStatement Block
+    addTestSource(
+      'main() { new A(^); }'
+          'class A{ factory A({one, two}) {} }',
+    );
+    await assertOpType(namedArgs: true);
+  }
+
+  test_ArgumentList_factory_resolved_1_1() async {
+    // ArgumentList  InstanceCreationExpression  ExpressionStatement  Block
+    addTestSource(
+      'main() { new A(o^); }'
+          'class A { factory A({one, two}) {} }',
+    );
+    await assertOpType(namedArgs: true);
+  }
+
+  test_ArgumentList_method_resolved_1_0() async {
+    // ArgumentList  MethodInvocation  ExpressionStatement  Block
+    addTestSource('main() { foo(^);} foo({one, two}) {}');
+    await assertOpType(namedArgs: true);
+  }
+
+  test_ArgumentList_method_resolved_1_1() async {
+    // ArgumentList  MethodInvocation  ExpressionStatement  Block
+    addTestSource('main() { foo(o^);} foo({one, two}) {}');
+    await assertOpType(namedArgs: true);
+  }
+
+  test_ArgumentList_resolved_2_0() async {
+    // ArgumentList  MethodInvocation  ExpressionStatement  Block
+    addTestSource('void main() {int.parse("16", ^)}');
+    await assertOpType(namedArgs: true);
+  }
+
+  test_AsExpression() async {
+    // SimpleIdentifier  TypeName  AsExpression
+    addTestSource('class A {var b; X _c; foo() {var a; (a as ^).foo();}');
+    await assertOpType(typeNames: true);
+  }
+
+  test_AsIdentifier2() async {
+    addTestSource('class A {var asdf; foo() {A as^}');
+    await assertOpType();
+  }
+
+  test_AssignmentExpression_name() async {
+    // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
+    // VariableDeclarationStatement  Block
+    addTestSource('class A {} main() {int a; int ^b = 1;}');
+    await assertOpType(varNames: true);
+  }
+
+  test_Block_catch_1a() async {
+    // '}'  Block  BlockFunctionBody  FunctionExpression
+    addTestSource('main() {try {} ^}');
+    // Only return 'on', 'catch', and 'finally' keywords
+    await assertOpType();
+  }
+
+  test_Block_catch_1b() async {
+    // [ExpressionStatement 'c']  Block  BlockFunctionBody
+    addTestSource('main() {try {} c^}');
+    // Only return 'on', 'catch', and 'finally' keywords
+    await assertOpType();
+  }
+
+  test_Block_catch_1c() async {
+    // [EmptyStatement]  Block  BlockFunctionBody  FunctionExpression
+    addTestSource('main() {try {} ^;}');
+    // Only return 'on', 'catch', and 'finally' keywords
+    await assertOpType();
+  }
+
+  test_Block_catch_1d() async {
+    // [VariableDeclarationStatement 'Foo foo']  Block  BlockFunctionBody
+    addTestSource('main() {try {} ^ Foo foo;}');
+    // Only return 'on', 'catch', and 'finally' keywords
+    await assertOpType();
+  }
+
+  test_Block_final() async {
+    addTestSource('main() {final ^}');
+    await assertOpType(typeNames: true);
+  }
+
+  test_Block_final2() async {
+    addTestSource('main() {final S^ v;}');
+    await assertOpType(typeNames: true);
+  }
+
+  test_Block_final3() async {
+    addTestSource('main() {final ^ v;}');
+    await assertOpType(typeNames: true);
+  }
+
+  test_Block_final_final() async {
+    addTestSource('main() {final ^ final S x;}');
+    await assertOpType(typeNames: true);
+  }
+
+  test_Block_final_final2() async {
+    addTestSource('main() {final S^ final S x;}');
+    await assertOpType(typeNames: true);
+  }
+
+  test_Break_after_label() async {
+    addTestSource('main() { foo: while (true) { break foo ^ ; } }');
+    await assertOpType(/* No valid completions */);
+  }
+
+  test_Break_before_label() async {
+    addTestSource('main() { foo: while (true) { break ^ foo; } }');
+    await assertOpType(statementLabel: true);
+  }
+
+  test_Break_no_label() async {
+    addTestSource('main() { foo: while (true) { break ^; } }');
+    await assertOpType(statementLabel: true);
+  }
+
   test_catch_4a1() async {
     addTestSource('main() {try {} ^ on SomeException {}}');
     await assertOpType();
@@ -701,26 +1280,6 @@
     await assertOpType(typeNames: true);
   }
 
-  test_CatchClause_typed() async {
-    // Block  CatchClause  TryStatement
-    addTestSource('class A {a() {try{var x;} on E catch (e) {^}}}');
-    await assertOpType(
-        constructors: previewDart2,
-        returnValue: true,
-        typeNames: true,
-        voidReturn: true);
-  }
-
-  test_CatchClause_untyped() async {
-    // Block  CatchClause  TryStatement
-    addTestSource('class A {a() {try{var x;} catch (e, s) {^}}}');
-    await assertOpType(
-        constructors: previewDart2,
-        returnValue: true,
-        typeNames: true,
-        voidReturn: true);
-  }
-
   test_ClassDeclaration_body() async {
     // ClassDeclaration  CompilationUnit
     addTestSource('@deprecated class A {^}');
@@ -750,52 +1309,6 @@
     await assertOpType();
   }
 
-  test_CommentReference() async {
-    // SimpleIdentifier  CommentReference  Comment  MethodDeclaration
-    addTestSource('class A {/** [^] */ mth() {}');
-    await assertOpType(
-        constructors: previewDart2,
-        returnValue: true,
-        typeNames: true,
-        voidReturn: true,
-        kind: CompletionSuggestionKind.IDENTIFIER);
-  }
-
-  test_ConditionalExpression_elseExpression() async {
-    // SimpleIdentifier  ConditionalExpression  ReturnStatement
-    addTestSource('class C {foo(){var f; {var x;} return a ? T1 : T^}}');
-    await assertOpType(
-        constructors: previewDart2, returnValue: true, typeNames: true);
-  }
-
-  test_ConditionalExpression_elseExpression_empty() async {
-    // SimpleIdentifier  ConditionalExpression  ReturnStatement
-    addTestSource('class C {foo(){var f; {var x;} return a ? T1 : ^}}');
-    await assertOpType(
-        constructors: previewDart2, returnValue: true, typeNames: true);
-  }
-
-  test_ConditionalExpression_partial_thenExpression() async {
-    // SimpleIdentifier  ConditionalExpression  ReturnStatement
-    addTestSource('class C {foo(){var f; {var x;} return a ? T^}}');
-    await assertOpType(
-        constructors: previewDart2, returnValue: true, typeNames: true);
-  }
-
-  test_ConditionalExpression_partial_thenExpression_empty() async {
-    // SimpleIdentifier  ConditionalExpression  ReturnStatement
-    addTestSource('class C {foo(){var f; {var x;} return a ? ^}}');
-    await assertOpType(
-        constructors: previewDart2, returnValue: true, typeNames: true);
-  }
-
-  test_ConditionalExpression_thenExpression() async {
-    // SimpleIdentifier  ConditionalExpression  ReturnStatement
-    addTestSource('class C {foo(){var f; {var x;} return a ? T^ : c}}');
-    await assertOpType(
-        constructors: previewDart2, returnValue: true, typeNames: true);
-  }
-
   test_ConstructorName() async {
     // SimpleIdentifier  PrefixedIdentifier  TypeName  ConstructorName
     // InstanceCreationExpression
@@ -839,42 +1352,11 @@
     await assertOpType(statementLabel: true, caseLabel: true);
   }
 
-  test_DefaultFormalParameter_named_expression() async {
-    // DefaultFormalParameter FormalParameterList MethodDeclaration
-    addTestSource('class A {a(blat: ^) { }}');
-    await assertOpType(
-        constructors: previewDart2, returnValue: true, typeNames: true);
-  }
-
-  test_DoStatement() async {
-    // SimpleIdentifier  DoStatement  Block
-    addTestSource('main() {do{} while(^x);}');
-    await assertOpType(
-        constructors: previewDart2, returnValue: true, typeNames: true);
-  }
-
   test_DoubleLiteral() async {
     addTestSource('main() { print(1.2^); }');
     await assertOpType();
   }
 
-  test_ExpressionFunctionBody() async {
-    // SimpleIdentifier  ExpressionFunctionBody  FunctionExpression
-    addTestSource('m(){[1].forEach((x)=>^x);}');
-    await assertOpType(
-        constructors: previewDart2, returnValue: true, typeNames: true);
-  }
-
-  test_ExpressionStatement() async {
-    // ExpressionStatement  Block  BlockFunctionBody
-    addTestSource('n(){f(3);^}');
-    await assertOpType(
-        constructors: previewDart2,
-        returnValue: true,
-        typeNames: true,
-        voidReturn: true);
-  }
-
   test_ExpressionStatement_name() async {
     // ExpressionStatement  Block  BlockFunctionBody  MethodDeclaration
     addTestSource('class C {a() {C ^}}');
@@ -919,40 +1401,6 @@
     await assertOpType();
   }
 
-  test_ForEachStatement() async {
-    // SimpleIdentifier  ForEachStatement  Block
-    addTestSource('main() {for(z in ^zs) {}}');
-    await assertOpType(
-        constructors: previewDart2, returnValue: true, typeNames: true);
-  }
-
-  test_ForEachStatement_body_typed() async {
-    // Block  ForEachStatement
-    addTestSource('main(args) {for (int foo in bar) {^}}');
-    await assertOpType(
-        constructors: previewDart2,
-        returnValue: true,
-        typeNames: true,
-        voidReturn: true);
-  }
-
-  test_ForEachStatement_body_untyped() async {
-    // Block  ForEachStatement
-    addTestSource('main(args) {for (foo in bar) {^}}');
-    await assertOpType(
-        constructors: previewDart2,
-        returnValue: true,
-        typeNames: true,
-        voidReturn: true);
-  }
-
-  test_ForEachStatement_iterable() async {
-    // SimpleIdentifier  ForEachStatement  Block
-    addTestSource('main(args) {for (int foo in ^) {}}');
-    await assertOpType(
-        constructors: previewDart2, returnValue: true, typeNames: true);
-  }
-
   test_ForEachStatement_loopVariable() async {
     // SimpleIdentifier  ForEachStatement  Block
     addTestSource('main(args) {for (^ in args) {}}');
@@ -983,49 +1431,12 @@
     await assertOpType(typeNames: true);
   }
 
-  test_FormalParameter_partialType() async {
-    // FormalParameterList MethodDeclaration
-    addTestSource('class A {a(b.^ f) { }}');
-    await assertOpType(
-        constructors: previewDart2,
-        returnValue: true,
-        typeNames: true,
-        prefixed: true);
-  }
-
-  test_FormalParameter_partialType2() async {
-    // FormalParameterList MethodDeclaration
-    addTestSource('class A {a(b.z^ f) { }}');
-    await assertOpType(
-        constructors: previewDart2,
-        returnValue: true,
-        typeNames: true,
-        prefixed: true);
-  }
-
-  test_FormalParameter_partialType3() async {
-    // FormalParameterList MethodDeclaration
-    addTestSource('class A {a(b.^) { }}');
-    await assertOpType(
-        constructors: previewDart2,
-        returnValue: true,
-        typeNames: true,
-        prefixed: true);
-  }
-
   test_FormalParameterList() async {
     // FormalParameterList MethodDeclaration
     addTestSource('class A {a(^) { }}');
     await assertOpType(typeNames: true);
   }
 
-  test_ForStatement_condition() async {
-    // SimpleIdentifier  ForStatement
-    addTestSource('main() {for (int index = 0; i^)}');
-    await assertOpType(
-        constructors: previewDart2, returnValue: true, typeNames: true);
-  }
-
   test_ForStatement_initializer() async {
     // SimpleIdentifier  ForStatement
     addTestSource('main() {List a; for (^)}');
@@ -1048,24 +1459,6 @@
     await assertOpType(varNames: true);
   }
 
-  test_ForStatement_updaters() async {
-    // SimpleIdentifier  ForStatement
-    addTestSource('main() {for (int index = 0; index < 10; i^)}');
-    // TODO (danrubel) may want to exclude methods/functions with void return
-    await assertOpType(
-        constructors: previewDart2,
-        returnValue: true,
-        typeNames: true,
-        voidReturn: true);
-  }
-
-  test_ForStatement_updaters_prefix_expression() async {
-    // SimpleIdentifier  PrefixExpression  ForStatement
-    addTestSource('main() {for (int index = 0; index < 10; ++i^)}');
-    await assertOpType(
-        constructors: previewDart2, returnValue: true, typeNames: true);
-  }
-
   test_FunctionDeclaration1() async {
     // SimpleIdentifier  FunctionDeclaration  CompilationUnit
     addTestSource('const ^Fara();');
@@ -1233,40 +1626,6 @@
     await assertOpType(typeNames: true);
   }
 
-  test_IfStatement() async {
-    // EmptyStatement  IfStatement  Block  BlockFunctionBody
-    addTestSource('main(){var a; if (true) ^}');
-    await assertOpType(
-        constructors: previewDart2,
-        returnValue: true,
-        typeNames: true,
-        voidReturn: true);
-  }
-
-  test_IfStatement_condition() async {
-    // SimpleIdentifier  IfStatement  Block  BlockFunctionBody
-    addTestSource('main(){var a; if (^)}');
-    await assertOpType(
-        constructors: previewDart2, returnValue: true, typeNames: true);
-  }
-
-  test_IfStatement_empty() async {
-    // SimpleIdentifier  PrefixIdentifier  IfStatement
-    addTestSource('class A {foo() {A a; if (^) something}}');
-    await assertOpType(
-        constructors: previewDart2, returnValue: true, typeNames: true);
-  }
-
-  test_IfStatement_invocation() async {
-    // SimpleIdentifier  PrefixIdentifier  IfStatement
-    addTestSource('main() {var a; if (a.^) something}');
-    await assertOpType(
-        constructors: previewDart2,
-        returnValue: true,
-        typeNames: true,
-        prefixed: true);
-  }
-
   test_ImplementsClause() async {
     // ImplementsClause  ClassDeclaration
     addTestSource('class x implements ^\n{}');
@@ -1281,44 +1640,12 @@
     await assertOpType();
   }
 
-  test_IndexExpression() async {
-    addTestSource('class C {foo(){var f; {var x;} f[^]}}');
-    await assertOpType(
-        constructors: previewDart2, returnValue: true, typeNames: true);
-  }
-
-  test_IndexExpression2() async {
-    addTestSource('class C {foo(){var f; {var x;} f[T^]}}');
-    await assertOpType(
-        constructors: previewDart2, returnValue: true, typeNames: true);
-  }
-
   test_InstanceCreationExpression() async {
     // SimpleIdentifier  TypeName  ConstructorName  InstanceCreationExpression
     addTestSource('class C {foo(){var f; {var x;} new ^}}');
     await assertOpType(constructors: true);
   }
 
-  test_InstanceCreationExpression_keyword() async {
-    // InstanceCreationExpression  ExpressionStatement  Block
-    addTestSource('class C {foo(){var f; {var x;} new^ }}');
-    await assertOpType(
-        constructors: previewDart2,
-        returnValue: true,
-        typeNames: true,
-        voidReturn: true);
-  }
-
-  test_InstanceCreationExpression_keyword2() async {
-    // InstanceCreationExpression  ExpressionStatement  Block
-    addTestSource('class C {foo(){var f; {var x;} new^ C();}}');
-    await assertOpType(
-        constructors: previewDart2,
-        returnValue: true,
-        typeNames: true,
-        voidReturn: true);
-  }
-
   test_InstanceCreationExpression_trailingStmt() async {
     // SimpleIdentifier  TypeName  ConstructorName  InstanceCreationExpression
     addTestSource('class C {foo(){var f; {var x;} new ^ int x = 7;}}');
@@ -1335,96 +1662,24 @@
     await assertOpType();
   }
 
-  test_InterpolationExpression() async {
-    // SimpleIdentifier  InterpolationExpression  StringInterpolation
-    addTestSource('main() {String name; print("hello \$^");}');
-    await assertOpType(constructors: previewDart2, returnValue: true);
-  }
-
-  test_InterpolationExpression_block() async {
-    // SimpleIdentifier  InterpolationExpression  StringInterpolation
-    addTestSource('main() {String name; print("hello \${n^}");}');
-    await assertOpType(
-        constructors: previewDart2, returnValue: true, typeNames: true);
-  }
-
-  test_InterpolationExpression_prefix_selector() async {
-    // SimpleIdentifier  PrefixedIdentifier  InterpolationExpression
-    addTestSource('main() {String name; print("hello \${name.^}");}');
-    await assertOpType(
-        constructors: previewDart2,
-        returnValue: true,
-        typeNames: true,
-        prefixed: true);
-  }
-
-  test_InterpolationExpression_prefix_target() async {
-    // SimpleIdentifier  PrefixedIdentifier  InterpolationExpression
-    addTestSource('main() {String name; print("hello \${nam^e.length}");}');
-    await assertOpType(
-        constructors: previewDart2, returnValue: true, typeNames: true);
-  }
-
   test_IsExpression() async {
     // SimpleIdentifier  TypeName  IsExpression  IfStatement
     addTestSource('main() {var x; if (x is ^) { }}');
     await assertOpType(typeNames: true);
   }
 
-  test_IsExpression_target() async {
-    // IfStatement  Block  BlockFunctionBody
-    addTestSource('main(){var a; if (^ is A)}');
-    await assertOpType(
-        constructors: previewDart2, returnValue: true, typeNames: true);
-  }
-
   test_IsExpression_type_partial() async {
     // SimpleIdentifier  TypeName  IsExpression  IfStatement
     addTestSource('main(){var a; if (a is Obj^)}');
     await assertOpType(typeNames: true);
   }
 
-  test_Literal_list() async {
-    // ']'  ListLiteral  ArgumentList  MethodInvocation
-    addTestSource('main() {var Some; print([^]);}');
-    await assertOpType(
-        constructors: previewDart2, returnValue: true, typeNames: true);
-  }
-
-  test_Literal_list2() async {
-    // SimpleIdentifier ListLiteral  ArgumentList  MethodInvocation
-    addTestSource('main() {var Some; print([S^]);}');
-    await assertOpType(
-        constructors: previewDart2, returnValue: true, typeNames: true);
-  }
-
   test_Literal_string() async {
     // SimpleStringLiteral  ExpressionStatement  Block
     addTestSource('class A {a() {"hel^lo"}}');
     await assertOpType();
   }
 
-  test_MapLiteralEntry() async {
-    // MapLiteralEntry  MapLiteral  VariableDeclaration
-    addTestSource('foo = {^');
-    await assertOpType(
-        constructors: previewDart2, returnValue: true, typeNames: true);
-  }
-
-  test_MapLiteralEntry1() async {
-    // MapLiteralEntry  MapLiteral  VariableDeclaration
-    addTestSource('foo = {T^');
-    await assertOpType(
-        constructors: previewDart2, returnValue: true, typeNames: true);
-  }
-
-  test_MapLiteralEntry2() async {
-    // SimpleIdentifier  MapLiteralEntry  MapLiteral  VariableDeclaration
-    addTestSource('foo = {7:T^};');
-    await assertOpType(
-        constructors: previewDart2, returnValue: true, typeNames: true);
-  }
-
   test_MethodDeclaration1() async {
     // SimpleIdentifier  MethodDeclaration  ClassDeclaration
     addTestSource('class Bar {const ^Fara();}');
@@ -1584,71 +1839,6 @@
     await assertOpType(typeNames: true);
   }
 
-  test_MethodInvocation_no_semicolon() async {
-    // MethodInvocation  ExpressionStatement  Block
-    addTestSource('''
-      class A implements I {
-        // no semicolon between completion point and next statement
-        set _s2(I x) {x.^ m(null);}
-      }''');
-    await assertOpType(
-        constructors: previewDart2,
-        returnValue: true,
-        typeNames: true,
-        voidReturn: true,
-        prefixed: true);
-  }
-
-  test_PostfixExpression() async {
-    // SimpleIdentifier  PostfixExpression  ForStatement
-    addTestSource('int x = 0; main() {ax+^+;}');
-    await assertOpType(
-        constructors: previewDart2, returnValue: true, typeNames: true);
-  }
-
-  test_PrefixedIdentifier_class_const() async {
-    // SimpleIdentifier PrefixedIdentifier ExpressionStatement Block
-    addTestSource('main() {A.^}');
-    await assertOpType(
-        constructors: previewDart2,
-        returnValue: true,
-        typeNames: true,
-        voidReturn: true,
-        prefixed: true);
-  }
-
-  test_PrefixedIdentifier_class_imported() async {
-    // SimpleIdentifier  PrefixedIdentifier  ExpressionStatement
-    addTestSource('main() {A a; a.^}');
-    await assertOpType(
-        constructors: previewDart2,
-        returnValue: true,
-        typeNames: true,
-        voidReturn: true,
-        prefixed: true);
-  }
-
-  test_PrefixedIdentifier_prefix() async {
-    // SimpleIdentifier  PrefixedIdentifier  ExpressionStatement
-    addTestSource('class X {foo(){A^.bar}}');
-    await assertOpType(
-        constructors: previewDart2,
-        typeNames: true,
-        returnValue: true,
-        voidReturn: true);
-  }
-
-  test_PropertyAccess_expression() async {
-    // SimpleIdentifier  MethodInvocation  PropertyAccess  ExpressionStatement
-    addTestSource('class A {a() {"hello".to^String().length}}');
-    await assertOpType(
-        constructors: previewDart2,
-        returnValue: true,
-        typeNames: true,
-        voidReturn: true,
-        prefixed: true);
-  }
-
   test_PropertyAccess_noTarget() async {
     // SimpleIdentifier  PropertyAccess  ExpressionStatement
     addTestSource('main() {.^}');
@@ -1667,24 +1857,6 @@
     await assertOpType();
   }
 
-  test_PropertyAccess_selector() async {
-    // SimpleIdentifier  PropertyAccess  ExpressionStatement  Block
-    addTestSource('class A {a() {"hello".length.^}}');
-    await assertOpType(
-        constructors: previewDart2,
-        returnValue: true,
-        typeNames: true,
-        voidReturn: true,
-        prefixed: true);
-  }
-
-  test_ReturnStatement() async {
-    // ReturnStatement  Block
-    addTestSource('f() { var vvv = 42; return ^ }');
-    await assertOpType(
-        constructors: previewDart2, returnValue: true, typeNames: true);
-  }
-
   test_SimpleFormalParameter_closure() async {
     // SimpleIdentifier  SimpleFormalParameter  FormalParameterList
     addTestSource('mth() { PNGS.sort((String a, Str^) => a.compareTo(b)); }');
@@ -1745,120 +1917,18 @@
     await assertOpType();
   }
 
-  test_SwitchCase_between() async {
-    // SwitchCase  SwitchStatement  Block
-    addTestSource('main() {switch(k) {case 1: ^ case 2: return}}');
-    await assertOpType(
-        constructors: previewDart2,
-        returnValue: true,
-        typeNames: true,
-        voidReturn: true);
-  }
-
-  test_SwitchCase_expression1() async {
-    // SimpleIdentifier  SwitchCase  SwitchStatement
-    addTestSource('''m() {switch (x) {case ^D: return;}}''');
-    await assertOpType(
-        constructors: previewDart2, returnValue: true, typeNames: true);
-  }
-
-  test_SwitchCase_expression2() async {
-    // SimpleIdentifier  SwitchCase  SwitchStatement
-    addTestSource('''m() {switch (x) {case ^}}''');
-    await assertOpType(
-        constructors: previewDart2, returnValue: true, typeNames: true);
-  }
-
   test_SwitchDefault_before() async {
     // SwitchDefault  SwitchStatement  Block
     addTestSource('main() {switch(k) { ^ default: return;}}');
     await assertOpType();
   }
 
-  test_SwitchDefault_between() async {
-    // SwitchDefault  SwitchStatement  Block
-    addTestSource('main() {switch(k) {case 1: ^ default: return;}}');
-    await assertOpType(
-        constructors: previewDart2,
-        returnValue: true,
-        typeNames: true,
-        voidReturn: true);
-  }
-
   test_SwitchStatement_body_empty() async {
     // Token('}')  SwitchStatement  Block
     addTestSource('main() {switch(k) {^}}');
     await assertOpType();
   }
 
-  test_SwitchStatement_body_end() async {
-    // Token('}')  SwitchStatement  Block
-    addTestSource('main() {switch(k) {case 1:^}}');
-    await assertOpType(
-        constructors: previewDart2,
-        returnValue: true,
-        typeNames: true,
-        voidReturn: true);
-  }
-
-  test_SwitchStatement_body_end2() async {
-    addTestSource('main() {switch(k) {case 1:as^}}');
-    await assertOpType(
-        constructors: previewDart2,
-        returnValue: true,
-        typeNames: true,
-        voidReturn: true);
-  }
-
-  test_SwitchStatement_expression1() async {
-    // SimpleIdentifier  SwitchStatement  Block
-    addTestSource('main() {switch(^k) {case 1:{}}}');
-    await assertOpType(
-        constructors: previewDart2, returnValue: true, typeNames: true);
-  }
-
-  test_SwitchStatement_expression2() async {
-    // SimpleIdentifier  SwitchStatement  Block
-    addTestSource('main() {switch(k^) {case 1:{}}}');
-    await assertOpType(
-        constructors: previewDart2, returnValue: true, typeNames: true);
-  }
-
-  test_SwitchStatement_expression_empty() async {
-    // SimpleIdentifier  SwitchStatement  Block
-    addTestSource('main() {switch(^) {case 1:{}}}');
-    await assertOpType(
-        constructors: previewDart2, returnValue: true, typeNames: true);
-  }
-
-  test_ThisExpression_block() async {
-    // MethodInvocation  ExpressionStatement  Block
-    addTestSource('''
-      class A implements I {
-        // no semicolon between completion point and next statement
-        set s1(I x) {} set _s2(I x) {this.^ m(null);}
-      }''');
-    // TODO(brianwilkerson) We should not be adding constructors here.
-    await assertOpType(
-        constructors: previewDart2,
-        returnValue: true,
-        voidReturn: true,
-        prefixed: true);
-  }
-
-  test_ThisExpression_constructor() async {
-    // SimpleIdentifier  PropertyAccess  ExpressionStatement
-    addTestSource('''
-      class A implements I {
-        A() {this.^}
-      }''');
-    await assertOpType(
-        constructors: previewDart2,
-        returnValue: true,
-        voidReturn: true,
-        prefixed: true);
-  }
-
   test_ThisExpression_constructor_param() async {
     // SimpleIdentifier  FieldFormalParameter  FormalParameterList
     addTestSource('''
@@ -1895,13 +1965,6 @@
     await assertOpType(typeNames: true);
   }
 
-  test_ThrowExpression() async {
-    // SimpleIdentifier  ThrowExpression  ExpressionStatement
-    addTestSource('main() {throw ^;}');
-    await assertOpType(
-        constructors: previewDart2, returnValue: true, typeNames: true);
-  }
-
   test_TopLevelVariableDeclaration_typed_name() async {
     // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
     // TopLevelVariableDeclaration
@@ -1977,43 +2040,4 @@
     addTestSource('main() {final ^}');
     await assertOpType(typeNames: true);
   }
-
-  test_VariableDeclarationStatement_afterSemicolon() async {
-    // VariableDeclarationStatement  Block  BlockFunctionBody
-    addTestSource('class A {var a; x() {var b;^}}');
-    await assertOpType(
-        constructors: previewDart2,
-        returnValue: true,
-        typeNames: true,
-        voidReturn: true);
-  }
-
-  test_VariableDeclarationStatement_RHS() async {
-    // SimpleIdentifier  VariableDeclaration  VariableDeclarationList
-    // VariableDeclarationStatement
-    addTestSource('class C {bar(){var f; {var x;} var e = ^}}');
-    await assertOpType(
-        constructors: previewDart2, returnValue: true, typeNames: true);
-  }
-
-  test_VariableDeclarationStatement_RHS_missing_semicolon() async {
-    // VariableDeclaration  VariableDeclarationList
-    // VariableDeclarationStatement
-    addTestSource('class C {bar(){var f; {var x;} var e = ^ var g}}');
-    await assertOpType(
-        constructors: previewDart2, returnValue: true, typeNames: true);
-  }
-
-  test_WhileStatement() async {
-    // SimpleIdentifier  WhileStatement  Block
-    addTestSource('mth() { while (b^) {} }}');
-    await assertOpType(
-        constructors: previewDart2, returnValue: true, typeNames: true);
-  }
-
-  test_WithClause() async {
-    // WithClause  ClassDeclaration
-    addTestSource('class x extends Object with ^\n{}');
-    await assertOpType(typeNames: true);
-  }
 }
diff --git a/pkg/analyzer_plugin/test/support/abstract_context.dart b/pkg/analyzer_plugin/test/support/abstract_context.dart
index 844b487..d5fc4db 100644
--- a/pkg/analyzer_plugin/test/support/abstract_context.dart
+++ b/pkg/analyzer_plugin/test/support/abstract_context.dart
@@ -62,7 +62,12 @@
   /**
    * Return `true` if strong mode should be enabled for this test.
    */
-  bool get enableStrongMode => false;
+  bool get enableStrongMode => true;
+
+  /**
+   * Return `true` if previewDart2 should be enabled for this test.
+   */
+  bool get enablePreviewDart2 => true;
 
   bool get previewDart2 => driver.analysisOptions.previewDart2;
 
@@ -132,7 +137,8 @@
     PerformanceLog log = new PerformanceLog(_logBuffer);
     AnalysisDriverScheduler scheduler = new AnalysisDriverScheduler(log);
     AnalysisOptionsImpl options = new AnalysisOptionsImpl()
-      ..strongMode = enableStrongMode;
+      ..strongMode = enableStrongMode
+      ..previewDart2 = enablePreviewDart2;
     _driver = new AnalysisDriver(
         scheduler,
         log,
diff --git a/pkg/analyzer_plugin/test/utilities/completion/completion_target_test.dart b/pkg/analyzer_plugin/test/utilities/completion/completion_target_test.dart
new file mode 100644
index 0000000..3894c12
--- /dev/null
+++ b/pkg/analyzer_plugin/test/utilities/completion/completion_target_test.dart
@@ -0,0 +1,57 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/standard_ast_factory.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/ast/token.dart'
+    show SyntheticBeginToken, SyntheticToken;
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
+import 'package:analyzer/src/generated/parser.dart';
+import 'package:analyzer_plugin/src/utilities/completion/completion_target.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(CompletionTargetTest);
+  });
+}
+
+@reflectiveTest
+class CompletionTargetTest {
+  test_danglingExpressionCompletionIsValid() {
+    // Test that users can parse dangling expressions of dart and autocomplete
+    // them without crash/with the correct offset information.
+    final snippet = wrapForCompliance(parseDanglingDart('identifier'));
+    final completionTarget =
+        // ignore: deprecated_member_use
+        new CompletionTarget.forOffset(null, 1, entryPoint: snippet);
+    expect(completionTarget.offset, 1);
+    final replacementRange = completionTarget.computeReplacementRange(1);
+    expect(replacementRange.offset, 0);
+    expect(replacementRange.length, 'identifier'.length);
+  }
+
+  /// Parse a dangling expression (no parent node). The angular plugin, for
+  /// instance, does this.
+  Expression parseDanglingDart(String code) {
+    final reader = new CharSequenceReader(code);
+    final scanner = new Scanner(null, reader, null);
+    return new Parser(null, null).parseExpression(scanner.tokenize());
+  }
+
+  Expression wrapForCompliance(Expression expression) {
+    // TODO(mfairhurst) This should be performed for clients or the need should
+    // be dropped. It's a fairly valid invariant that all autocompletion target
+    // expressions should have parents, and one we can enforce via synthetics.
+    // But clients should not be doing this ideally.
+    return astFactory.parenthesizedExpression(
+        new SyntheticBeginToken(TokenType.OPEN_PAREN, expression.offset)
+          ..next = expression.beginToken,
+        expression,
+        new SyntheticToken(TokenType.CLOSE_PAREN, expression.end));
+  }
+}
diff --git a/pkg/analyzer_plugin/test/utilities/completion/test_all.dart b/pkg/analyzer_plugin/test/utilities/completion/test_all.dart
index 5f06b3a..cdc642d 100644
--- a/pkg/analyzer_plugin/test/utilities/completion/test_all.dart
+++ b/pkg/analyzer_plugin/test/utilities/completion/test_all.dart
@@ -7,10 +7,12 @@
 import 'inherited_reference_contributor_test.dart'
     as inherited_reference_contributor_test;
 import 'type_member_contributor_test.dart' as type_member_contributor_test;
+import 'completion_target_test.dart' as completion_target_test;
 
 main() {
   defineReflectiveSuite(() {
     inherited_reference_contributor_test.main();
     type_member_contributor_test.main();
+    completion_target_test.main();
   }, name: 'subscriptions');
 }
diff --git a/pkg/compiler/lib/src/commandline_options.dart b/pkg/compiler/lib/src/commandline_options.dart
index 199973f..152ac6c 100644
--- a/pkg/compiler/lib/src/commandline_options.dart
+++ b/pkg/compiler/lib/src/commandline_options.dart
@@ -67,6 +67,9 @@
   static const String verbose = '--verbose';
   static const String version = '--version';
 
+  /// Flag for a combination of flags for 'production' mode.
+  static const String benchmarkingProduction = '--benchmarking-production';
+
   static const String conditionalDirectives = '--conditional-directives';
 
   // The syntax-only level of support for generic methods is included in the
@@ -92,11 +95,19 @@
   // https://gist.github.com/eernstg/4353d7b4f669745bed3a5423e04a453c.
   static const String genericMethodSyntax = '--generic-method-syntax';
 
-  // Starts `async` functions synchronously.
+  // Deprecated. This flag is no longer in use for dart2js, but we are keeping
+  // it around for a while longer until all other tools deprecate the same flag.
   //
-  // This is the Dart 2.0 behavior. This flag is only used during the migration.
+  // It was used to start `async` functions synchronously, but now dart2js
+  // switched on this behavior by default.
+  // TODO(sigmund): delete once this is on by default on all of our tools.
   static const String syncAsync = '--sync-async';
 
+  // Starts `async` functions asynchronously.
+  //
+  // This is the old Dart 1.0 behavior. Only used during the migration.
+  static const String noSyncAsync = '--no-sync-async';
+
   // Initializing-formal access is enabled by default and cannot be disabled.
   // For backward compatibility the option is still accepted, but it is ignored.
   static const String initializingFormalAccess = '--initializing-formal-access';
diff --git a/pkg/compiler/lib/src/common_elements.dart b/pkg/compiler/lib/src/common_elements.dart
index 04c300e..3dc07e6 100644
--- a/pkg/compiler/lib/src/common_elements.dart
+++ b/pkg/compiler/lib/src/common_elements.dart
@@ -879,6 +879,11 @@
   ClassEntity get jsInvocationMirrorClass =>
       _jsInvocationMirrorClass ??= _findHelperClass('JSInvocationMirror');
 
+  MemberEntity _invocationTypeArgumentGetter;
+  MemberEntity get invocationTypeArgumentGetter =>
+      _invocationTypeArgumentGetter ??=
+          _findClassMember(jsInvocationMirrorClass, 'typeArguments');
+
   /// Interface used to determine if an object has the JavaScript
   /// indexing behavior. The interface is only visible to specific libraries.
   ClassEntity _jsIndexingBehaviorInterface;
diff --git a/pkg/compiler/lib/src/constants/evaluation.dart b/pkg/compiler/lib/src/constants/evaluation.dart
index 92dca21..b647d48 100644
--- a/pkg/compiler/lib/src/constants/evaluation.dart
+++ b/pkg/compiler/lib/src/constants/evaluation.dart
@@ -42,6 +42,9 @@
   DartType substByContext(
       covariant DartType base, covariant InterfaceType target);
 
+  /// Returns [type] in the context of the [enclosingConstructedType].
+  DartType getTypeInContext(DartType type);
+
   void reportWarning(
       ConstantExpression expression, MessageKind kind, Map arguments);
 
@@ -127,6 +130,47 @@
       reporter.reportWarningMessage(_spannable, kind, arguments);
     }
   }
+
+  @override
+  DartType getTypeInContext(DartType type) {
+    // Running example for comments:
+    //
+    //     class A<T> {
+    //       final T t;
+    //       const A(dynamic t) : this.t = t; // implicitly `t as A.T`
+    //     }
+    //     class B<S> extends A<S> {
+    //       const B(dynamic s) : super(s);
+    //     }
+    //     main() => const B<num>(0);
+    //
+    // We visit `t as A.T` while evaluating `const B<num>(0)`.
+
+    // The `as` type is `A.T`.
+    DartType typeInContext = type;
+
+    // The enclosing type is `B<num>`.
+    DartType enclosingType = enclosingConstructedType;
+    if (enclosingType != null) {
+      ClassEntity contextClass;
+      type.forEachTypeVariable((TypeVariableType type) {
+        if (type.element.typeDeclaration is ClassEntity) {
+          // We find `A` from `A.T`. Since we don't have nested classes, class
+          // based type variables can only come from the same class.
+          contextClass = type.element.typeDeclaration;
+        }
+      });
+      if (contextClass != null) {
+        // The enclosing type `B<num>` as an instance of `A` is `A<num>`.
+        enclosingType = types.asInstanceOf(enclosingType, contextClass);
+      }
+      // `A.T` in the context of the enclosing type `A<num>` is `num`.
+      typeInContext = enclosingType != null
+          ? substByContext(typeInContext, enclosingType)
+          : typeInContext;
+    }
+    return typeInContext;
+  }
 }
 
 /// The normalized arguments passed to a const constructor computed from the
diff --git a/pkg/compiler/lib/src/constants/expressions.dart b/pkg/compiler/lib/src/constants/expressions.dart
index b86d8e7..b590b23 100644
--- a/pkg/compiler/lib/src/constants/expressions.dart
+++ b/pkg/compiler/lib/src/constants/expressions.dart
@@ -11,6 +11,7 @@
 import '../elements/operators.dart';
 import '../elements/types.dart';
 import '../universe/call_structure.dart' show CallStructure;
+import '../util/util.dart';
 import 'constructors.dart';
 import 'evaluation.dart';
 import 'values.dart';
@@ -45,6 +46,7 @@
   POSITIONAL_REFERENCE,
   NAMED_REFERENCE,
   ASSERT,
+  INSTANTIATION,
 }
 
 /// An expression that is a compile-time constant.
@@ -868,30 +870,9 @@
     DartType expressionType =
         expressionValue.getType(environment.commonElements);
 
-    // The `as` type is `A.T`.
-    DartType typeInContext = type;
+    // The `as` type `A.T` in the context of `B<num>` is `num`.
+    DartType typeInContext = environment.getTypeInContext(type);
 
-    // The enclosing type is `B<num>`.
-    DartType enclosingType = environment.enclosingConstructedType;
-    if (enclosingType != null) {
-      ClassEntity contextClass;
-      type.forEachTypeVariable((TypeVariableType type) {
-        if (type.element.typeDeclaration is ClassEntity) {
-          // We find `A` from `A.T`. Since we don't have nested classes, class
-          // based type variables can only come from the same class.
-          contextClass = type.element.typeDeclaration;
-        }
-      });
-      if (contextClass != null) {
-        // The enclosing type `B<num>` as an instance of `A` is `A<num>`.
-        enclosingType =
-            environment.types.asInstanceOf(enclosingType, contextClass);
-      }
-      // `A.T` in the context of the enclosing type `A<num>` is `num`.
-      typeInContext = enclosingType != null
-          ? environment.substByContext(typeInContext, enclosingType)
-          : typeInContext;
-    }
     // Check that the expression type, `int`, is a subtype of the type in
     // context, `num`.
     if (!constantSystem.isSubtype(
@@ -2154,6 +2135,57 @@
   }
 }
 
+class InstantiationConstantExpression extends ConstantExpression {
+  final List<DartType> typeArguments;
+  final ConstantExpression expression;
+
+  InstantiationConstantExpression(this.typeArguments, this.expression);
+
+  ConstantExpressionKind get kind => ConstantExpressionKind.INSTANTIATION;
+
+  @override
+  void _createStructuredText(StringBuffer sb) {
+    sb.write('Instantiation(typeArguments=$typeArguments,expression=');
+    expression._createStructuredText(sb);
+    sb.write(')');
+  }
+
+  @override
+  ConstantValue evaluate(
+      EvaluationEnvironment environment, ConstantSystem constantSystem) {
+    List<DartType> typeArgumentsInContext =
+        typeArguments.map(environment.getTypeInContext).toList();
+    return new InstantiationConstantValue(typeArgumentsInContext,
+        expression.evaluate(environment, constantSystem));
+  }
+
+  @override
+  int _computeHashCode() {
+    return Hashing.objectHash(expression, Hashing.listHash(typeArguments));
+  }
+
+  ConstantExpression apply(NormalizedArguments arguments) {
+    return new InstantiationConstantExpression(
+        typeArguments, expression.apply(arguments));
+  }
+
+  @override
+  bool _equals(InstantiationConstantExpression other) {
+    return equalElements(typeArguments, other.typeArguments) &&
+        expression == other.expression;
+  }
+
+  @override
+  accept(ConstantExpressionVisitor visitor, [context]) {
+    return visitor.visitInstantiation(this, context);
+  }
+
+  @override
+  bool get isPotential {
+    return expression.isPotential;
+  }
+}
+
 abstract class ConstantExpressionVisitor<R, A> {
   const ConstantExpressionVisitor();
 
@@ -2189,6 +2221,7 @@
       StringFromEnvironmentConstantExpression exp, A context);
   R visitDeferred(DeferredConstantExpression exp, A context);
   R visitAssert(AssertConstantExpression exp, A context);
+  R visitInstantiation(InstantiationConstantExpression exp, A context);
 
   R visitPositional(PositionalArgumentReference exp, A context);
   R visitNamed(NamedArgumentReference exp, A context);
@@ -2480,5 +2513,14 @@
     sb.write(')');
   }
 
+  @override
+  void visitInstantiation(InstantiationConstantExpression exp, [_]) {
+    sb.write('<');
+    sb.write(exp.typeArguments.join(', '));
+    sb.write('>(');
+    visit(exp.expression);
+    sb.write(')');
+  }
+
   String toString() => sb.toString();
 }
diff --git a/pkg/compiler/lib/src/constants/values.dart b/pkg/compiler/lib/src/constants/values.dart
index 9fd6a9b..abf5d5a 100644
--- a/pkg/compiler/lib/src/constants/values.dart
+++ b/pkg/compiler/lib/src/constants/values.dart
@@ -9,7 +9,7 @@
 import '../elements/entities.dart';
 import '../elements/types.dart';
 import '../deferred_load.dart' show OutputUnit;
-import '../util/util.dart' show Hashing;
+import '../util/util.dart';
 
 enum ConstantValueKind {
   FUNCTION,
@@ -50,6 +50,8 @@
   R visitDeferredGlobal(
       covariant DeferredGlobalConstantValue constant, covariant A arg);
   R visitNonConstant(covariant NonConstantValue constant, covariant A arg);
+  R visitInstantiation(
+      covariant InstantiationConstantValue constant, covariant A arg);
 }
 
 abstract class ConstantValue {
@@ -131,7 +133,7 @@
 
   List<ConstantValue> getDependencies() => const <ConstantValue>[];
 
-  DartType getType(CommonElements types) => type;
+  FunctionType getType(CommonElements types) => type;
 
   int get hashCode => (17 * element.hashCode) & 0x7fffffff;
 
@@ -775,7 +777,7 @@
         import == other.import;
   }
 
-  get hashCode => (referenced.hashCode * 17 + import.hashCode) & 0x3fffffff;
+  int get hashCode => (referenced.hashCode * 17 + import.hashCode) & 0x3fffffff;
 
   List<ConstantValue> getDependencies() => <ConstantValue>[referenced];
 
@@ -792,6 +794,45 @@
   }
 }
 
+class InstantiationConstantValue extends ConstantValue {
+  final List<DartType> typeArguments;
+  final FunctionConstantValue function;
+
+  InstantiationConstantValue(this.typeArguments, this.function);
+
+  bool operator ==(other) {
+    if (identical(this, other)) return true;
+    return other is InstantiationConstantValue &&
+        function == other.function &&
+        equalElements(typeArguments, other.typeArguments);
+  }
+
+  @override
+  int get hashCode {
+    return Hashing.objectHash(function, Hashing.listHash(typeArguments));
+  }
+
+  List<ConstantValue> getDependencies() => <ConstantValue>[function];
+
+  accept(ConstantValueVisitor visitor, arg) =>
+      visitor.visitInstantiation(this, arg);
+
+  DartType getType(CommonElements types) {
+    FunctionType type = function.getType(types);
+    return type.instantiate(typeArguments);
+  }
+
+  ConstantValueKind get kind => ConstantValueKind.DEFERRED;
+
+  String toDartText() =>
+      '<${typeArguments.join(', ')}>(${function.toDartText()})';
+
+  String toStructuredText() {
+    return 'InstantiationConstant($typeArguments,'
+        '${function.toStructuredText()})';
+  }
+}
+
 /// A reference to a constant in another output unit.
 ///
 /// Used for referring to deferred constants that appear as initializers of
diff --git a/pkg/compiler/lib/src/dart2js.dart b/pkg/compiler/lib/src/dart2js.dart
index b73c362..de73841 100644
--- a/pkg/compiler/lib/src/dart2js.dart
+++ b/pkg/compiler/lib/src/dart2js.dart
@@ -317,7 +317,8 @@
     new OptionHandler(Flags.allowMockCompilation, ignoreOption),
     new OptionHandler(Flags.fastStartup, passThrough),
     new OptionHandler(Flags.genericMethodSyntax, ignoreOption),
-    new OptionHandler(Flags.syncAsync, passThrough),
+    new OptionHandler(Flags.syncAsync, ignoreOption),
+    new OptionHandler(Flags.noSyncAsync, passThrough),
     new OptionHandler(Flags.initializingFormalAccess, ignoreOption),
     new OptionHandler(Flags.minify, passThrough),
     new OptionHandler(Flags.preserveUris, ignoreOption),
@@ -361,6 +362,7 @@
     new OptionHandler(Flags.strongMode, setStrongMode),
     new OptionHandler(Flags.previewDart2, setStrongMode),
     new OptionHandler(Flags.omitImplicitChecks, passThrough),
+    new OptionHandler(Flags.benchmarkingProduction, passThrough),
 
     // TODO(floitsch): remove conditional directives flag.
     // We don't provide the info-message yet, since we haven't publicly
diff --git a/pkg/compiler/lib/src/js_backend/constant_emitter.dart b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
index 064aa93..c218a40 100644
--- a/pkg/compiler/lib/src/js_backend/constant_emitter.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
@@ -333,6 +333,14 @@
     return instantiation;
   }
 
+  @override
+  jsAst.Expression visitInstantiation(InstantiationConstantValue constant,
+      [_]) {
+    // TODO(sigmund, sra): add a runtime representation for constant
+    // instantiations. See issue 32774.
+    return constantReferenceGenerator(constant.function);
+  }
+
   String stripComments(String rawJavaScript) {
     return rawJavaScript.replaceAll(COMMENT_RE, '');
   }
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index 5a6a574c..00393c0 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -1880,6 +1880,11 @@
   }
 
   @override
+  void visitInstantiation(InstantiationConstantValue constant, [_]) {
+    _visit(constant.function);
+  }
+
+  @override
   void visitNull(NullConstantValue constant, [_]) {
     add('null');
   }
@@ -2081,6 +2086,11 @@
   }
 
   @override
+  int visitInstantiation(InstantiationConstantValue constant, [_]) {
+    return _visit(constant.function);
+  }
+
+  @override
   int visitInt(IntConstantValue constant, [_]) {
     return _hashInt(constant.intValue);
   }
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types.dart b/pkg/compiler/lib/src/js_backend/runtime_types.dart
index 9c3dd7b..cb5a5f1 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types.dart
@@ -890,14 +890,19 @@
       if (function is FunctionEntity) {
         Name instanceName;
         bool isCallTarget;
+        bool isNoSuchMethod;
         if (function.isInstanceMember) {
           isCallTarget = worldBuilder.closurizedMembers.contains(function);
           instanceName = function.memberName;
+          isNoSuchMethod = instanceName.text == Identifiers.noSuchMethod_;
         } else {
           isCallTarget = worldBuilder.closurizedStatics.contains(function);
+          isNoSuchMethod = false;
         }
         node = new MethodNode(function, function.parameterStructure,
-            isCallTarget: isCallTarget, instanceName: instanceName);
+            isCallTarget: isCallTarget,
+            instanceName: instanceName,
+            isNoSuchMethod: isNoSuchMethod);
       } else {
         ParameterStructure parameterStructure = new ParameterStructure.fromType(
             elementEnvironment.getLocalFunctionType(function));
@@ -1019,6 +1024,7 @@
       genericInstanceMethods.forEach(processEntity);
       worldBuilder.genericLocalFunctions.forEach(processEntity);
       worldBuilder.closurizedStatics.forEach(processEntity);
+      worldBuilder.userNoSuchMethods.forEach(processEntity);
     });
   }
 
@@ -1294,13 +1300,15 @@
   final ParameterStructure parameterStructure;
   final bool isCallTarget;
   final Name instanceName;
+  final bool isNoSuchMethod;
 
   MethodNode(this.function, this.parameterStructure,
-      {this.isCallTarget, this.instanceName});
+      {this.isCallTarget, this.instanceName, this.isNoSuchMethod: false});
 
   Entity get entity => function;
 
   bool selectorApplies(Selector selector) {
+    if (isNoSuchMethod) return true;
     return (isCallTarget && selector.isClosureCall ||
             instanceName == selector.memberName) &&
         selector.callStructure.signatureApplies(parameterStructure);
@@ -1517,6 +1525,15 @@
     localFunctionsUsingTypeVariableLiterals
         .forEach(potentiallyNeedTypeArguments);
 
+    if (resolutionWorldBuilder.isMemberUsed(
+        closedWorld.commonElements.invocationTypeArgumentGetter)) {
+      // If `Invocation.typeArguments` is live, mark all user-defined
+      // implementations of `noSuchMethod` as needing type arguments.
+      for (MemberEntity member in resolutionWorldBuilder.userNoSuchMethods) {
+        potentiallyNeedTypeArguments(member);
+      }
+    }
+
     Set<Selector> selectorsNeedingTypeArguments = new Set<Selector>();
     typeVariableTests
         .forEachAppliedSelector((Selector selector, Set<Entity> targets) {
diff --git a/pkg/compiler/lib/src/js_emitter/constant_ordering.dart b/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
index a1ee6ab..fcd705d 100644
--- a/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
+++ b/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
@@ -240,6 +240,13 @@
     if (r != 0) return r;
     return a.unit.compareTo(b.unit);
   }
+
+  int visitInstantiation(
+      InstantiationConstantValue a, InstantiationConstantValue b) {
+    int r = compareValues(a.function, b.function);
+    if (r != 0) return r;
+    return compareLists(compareDartTypes, a.typeArguments, b.typeArguments);
+  }
 }
 
 class _KindVisitor implements ConstantValueVisitor<int, Null> {
@@ -259,7 +266,8 @@
   static const int SYNTHETIC = 12;
   static const int DEFERRED = 13;
   static const int DEFERRED_GLOBAL = 14;
-  static const int NONCONSTANT = 13;
+  static const int NONCONSTANT = 15;
+  static const int INSTANTIATION = 16;
 
   static int kind(ConstantValue constant) =>
       constant.accept(const _KindVisitor(), null);
@@ -279,6 +287,7 @@
   int visitSynthetic(SyntheticConstantValue a, _) => SYNTHETIC;
   int visitDeferred(DeferredConstantValue a, _) => DEFERRED;
   int visitDeferredGlobal(DeferredGlobalConstantValue a, _) => DEFERRED_GLOBAL;
+  int visitInstantiation(InstantiationConstantValue a, _) => INSTANTIATION;
 }
 
 /// Visitor for distinguishing types by kind.
diff --git a/pkg/compiler/lib/src/js_model/js_strategy.dart b/pkg/compiler/lib/src/js_model/js_strategy.dart
index 9572c32..11fa8ee 100644
--- a/pkg/compiler/lib/src/js_model/js_strategy.dart
+++ b/pkg/compiler/lib/src/js_model/js_strategy.dart
@@ -699,6 +699,13 @@
     return new DeferredGlobalConstantValue(referenced, constant.unit);
   }
 
+  ConstantValue visitInstantiation(InstantiationConstantValue constant, _) {
+    ConstantValue function = constant.function.accept(this, null);
+    List<DartType> typeArguments =
+        typeConverter.convertTypes(constant.typeArguments);
+    return new InstantiationConstantValue(typeArguments, function);
+  }
+
   List<ConstantValue> _handleValues(List<ConstantValue> values) {
     List<ConstantValue> result;
     for (int i = 0; i < values.length; i++) {
@@ -722,6 +729,8 @@
 
   DartType convert(DartType type) => type.accept(this, null);
 
+  List<DartType> convertTypes(List<DartType> types) => _visitList(types);
+
   DartType visitVoidType(VoidType type, _) => type;
   DartType visitDynamicType(DynamicType type, _) => type;
 
diff --git a/pkg/compiler/lib/src/kernel/element_map_mixins.dart b/pkg/compiler/lib/src/kernel/element_map_mixins.dart
index 8d08535..1a4ca53 100644
--- a/pkg/compiler/lib/src/kernel/element_map_mixins.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_mixins.dart
@@ -699,9 +699,9 @@
 
   @override
   ConstantExpression visitInstantiation(ir.Instantiation node) {
-    // TODO(sigmund, sra): add a constant representation for instantiations.
-    // See issue 32774.
-    return visit(node.expression);
+    return new InstantiationConstantExpression(
+        node.typeArguments.map(elementMap.getDartType).toList(),
+        visit(node.expression));
   }
 
   @override
diff --git a/pkg/compiler/lib/src/options.dart b/pkg/compiler/lib/src/options.dart
index f72edf3..01e4689 100644
--- a/pkg/compiler/lib/src/options.dart
+++ b/pkg/compiler/lib/src/options.dart
@@ -90,6 +90,9 @@
   /// [analyzeOnly].
   bool analyzeSignaturesOnly = false;
 
+  /// Sets a combination of flags for benchmarking 'production' mode.
+  bool benchmarkingProduction = false;
+
   /// ID associated with this sdk build.
   String buildId = _UNDETERMINED_BUILD_ID;
 
@@ -290,6 +293,8 @@
       ..analyzeMain = _hasOption(options, Flags.analyzeMain)
       ..analyzeOnly = _hasOption(options, Flags.analyzeOnly)
       ..analyzeSignaturesOnly = _hasOption(options, Flags.analyzeSignaturesOnly)
+      ..benchmarkingProduction =
+          _hasOption(options, Flags.benchmarkingProduction)
       ..buildId =
           _extractStringOption(options, '--build-id=', _UNDETERMINED_BUILD_ID)
       ..compileForServer = _resolveCompileForServerFromOptions(options)
@@ -343,7 +348,7 @@
       ..useMultiSourceInfo = _hasOption(options, Flags.useMultiSourceInfo)
       ..useNewSourceInfo = _hasOption(options, Flags.useNewSourceInfo)
       ..useStartupEmitter = _hasOption(options, Flags.fastStartup)
-      ..startAsyncSynchronously = _hasOption(options, Flags.syncAsync)
+      ..startAsyncSynchronously = !_hasOption(options, Flags.noSyncAsync)
       ..verbose = _hasOption(options, Flags.verbose);
   }
 
@@ -371,6 +376,15 @@
 
   void deriveOptions() {
     if (analyzeSignaturesOnly || analyzeAll) analyzeOnly = true;
+    if (benchmarkingProduction) {
+      useStartupEmitter = true;
+      trustPrimitives = true;
+      if (strongMode) {
+        omitImplicitChecks = true;
+      } else {
+        trustTypeAnnotations = true;
+      }
+    }
     if (useKernel) generateCodeWithCompileTimeErrors = false;
     if (platformConfigUri == null) {
       platformConfigUri = _resolvePlatformConfig(libraryRoot, null, const []);
diff --git a/pkg/compiler/lib/src/types/constants.dart b/pkg/compiler/lib/src/types/constants.dart
index 0bd4b32..5d2b2af 100644
--- a/pkg/compiler/lib/src/types/constants.dart
+++ b/pkg/compiler/lib/src/types/constants.dart
@@ -84,6 +84,12 @@
   }
 
   @override
+  TypeMask visitInstantiation(
+      InstantiationConstantValue constant, ClosedWorld closedWorld) {
+    return closedWorld.commonMasks.functionType;
+  }
+
+  @override
   TypeMask visitInt(IntConstantValue constant, ClosedWorld closedWorld) {
     if (constant.isUInt31()) return closedWorld.commonMasks.uint31Type;
     if (constant.isUInt32()) return closedWorld.commonMasks.uint32Type;
diff --git a/pkg/compiler/lib/src/universe/codegen_world_builder.dart b/pkg/compiler/lib/src/universe/codegen_world_builder.dart
index d679a67..b6b3485 100644
--- a/pkg/compiler/lib/src/universe/codegen_world_builder.dart
+++ b/pkg/compiler/lib/src/universe/codegen_world_builder.dart
@@ -600,6 +600,24 @@
     _instanceMemberUsage.forEach(processMemberUse);
     return functions;
   }
+
+  @override
+  Iterable<FunctionEntity> get userNoSuchMethods {
+    List<FunctionEntity> functions = <FunctionEntity>[];
+
+    void processMemberUse(MemberEntity member, _MemberUsage memberUsage) {
+      if (member.isInstanceMember &&
+          member is FunctionEntity &&
+          memberUsage.hasUse &&
+          member.name == Identifiers.noSuchMethod_ &&
+          !_world.commonElements.isDefaultNoSuchMethodImplementation(member)) {
+        functions.add(member);
+      }
+    }
+
+    _instanceMemberUsage.forEach(processMemberUse);
+    return functions;
+  }
 }
 
 class ElementCodegenWorldBuilderImpl extends CodegenWorldBuilderImpl {
diff --git a/pkg/compiler/lib/src/universe/resolution_world_builder.dart b/pkg/compiler/lib/src/universe/resolution_world_builder.dart
index fc3502f..2849612 100644
--- a/pkg/compiler/lib/src/universe/resolution_world_builder.dart
+++ b/pkg/compiler/lib/src/universe/resolution_world_builder.dart
@@ -434,6 +434,19 @@
     return functions;
   }
 
+  Iterable<FunctionEntity> get userNoSuchMethods {
+    List<FunctionEntity> functions = <FunctionEntity>[];
+    for (MemberEntity member in processedMembers) {
+      if (member.isInstanceMember &&
+          member.isFunction &&
+          member.name == Identifiers.noSuchMethod_ &&
+          !_commonElements.isDefaultNoSuchMethodImplementation(member)) {
+        functions.add(member);
+      }
+    }
+    return functions;
+  }
+
   Iterable<MemberEntity> get processedMembers => _processedMembers;
 
   ClosedWorld get closedWorldForTesting {
diff --git a/pkg/compiler/lib/src/universe/world_builder.dart b/pkg/compiler/lib/src/universe/world_builder.dart
index 031baf2..9b67772 100644
--- a/pkg/compiler/lib/src/universe/world_builder.dart
+++ b/pkg/compiler/lib/src/universe/world_builder.dart
@@ -293,6 +293,9 @@
   /// Live generic local functions.
   Iterable<Local> get genericLocalFunctions;
 
+  /// Live user-defined 'noSuchMethod' implementations.
+  Iterable<FunctionEntity> get userNoSuchMethods;
+
   /// Type variables used as type literals.
   Iterable<TypeVariableType> get typeVariableTypeLiterals;
 
diff --git a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
index 48eaedb..8fbce54 100644
--- a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
@@ -40,7 +40,6 @@
 import '../compiler/js_utils.dart' as JS;
 import '../compiler/module_builder.dart' show pathToJSIdentifier;
 import '../compiler/shared_compiler.dart';
-import '../compiler/type_utilities.dart';
 import '../js_ast/js_ast.dart' as JS;
 import '../js_ast/js_ast.dart' show js;
 import '../js_ast/source_map_printer.dart' show NodeEnd, NodeSpan, HoverComment;
@@ -56,6 +55,7 @@
 import 'reify_coercions.dart' show CoercionReifier;
 import 'side_effect_analysis.dart'
     show ConstFieldVisitor, isStateless, isPotentiallyMutated;
+import 'type_utilities.dart';
 
 /// The code generator for Dart Dev Compiler.
 ///
@@ -5800,7 +5800,7 @@
 
   @override
   JS.LiteralString visitSimpleStringLiteral(SimpleStringLiteral node) =>
-      js.escapedString(node.value, node.isSingleQuoted ? "'" : '"');
+      js.escapedString(node.value, '"');
 
   @override
   JS.Expression visitAdjacentStrings(AdjacentStrings node) {
@@ -6075,9 +6075,7 @@
     useExtension ??= _isSymbolizedMember(type, name);
     // Rename members that conflict with standard JS members unless we are
     // actually try to access those JS members via interop.
-    var isExternal = element != null &&
-        !(element is ExecutableElement && !element.isExternal);
-    name = JS.memberNameForDartMember(name, isExternal);
+    name = JS.memberNameForDartMember(name, _isExternal(element));
     if (useExtension) {
       return _getExtensionSymbolInternal(name);
     }
diff --git a/pkg/dev_compiler/lib/src/compiler/type_utilities.dart b/pkg/dev_compiler/lib/src/analyzer/type_utilities.dart
similarity index 99%
rename from pkg/dev_compiler/lib/src/compiler/type_utilities.dart
rename to pkg/dev_compiler/lib/src/analyzer/type_utilities.dart
index c33df46..075903f 100644
--- a/pkg/dev_compiler/lib/src/compiler/type_utilities.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/type_utilities.dart
@@ -8,9 +8,9 @@
 import 'package:analyzer/dart/element/type.dart';
 
 import '../analyzer/element_helpers.dart';
+import '../compiler/js_names.dart' as JS;
 import '../js_ast/js_ast.dart' as JS;
 import '../js_ast/js_ast.dart' show js;
-import 'js_names.dart' as JS;
 
 Set<TypeParameterElement> freeTypeParameters(DartType t) {
   var result = new Set<TypeParameterElement>();
diff --git a/pkg/dev_compiler/lib/src/js_ast/printer.dart b/pkg/dev_compiler/lib/src/js_ast/printer.dart
index f2f785c..ea97d34 100644
--- a/pkg/dev_compiler/lib/src/js_ast/printer.dart
+++ b/pkg/dev_compiler/lib/src/js_ast/printer.dart
@@ -1190,7 +1190,8 @@
       spaceOut();
       out("{}");
     } else {
-      blockBody(fun.body, needsSeparation: false, needsNewline: false);
+      spaceOut();
+      blockOut(fun.body, false, false);
     }
     localNamer.leaveScope();
   }
diff --git a/pkg/dev_compiler/lib/src/kernel/command.dart b/pkg/dev_compiler/lib/src/kernel/command.dart
index f19890f..92a045d 100644
--- a/pkg/dev_compiler/lib/src/kernel/command.dart
+++ b/pkg/dev_compiler/lib/src/kernel/command.dart
@@ -213,7 +213,7 @@
       emitMetadata: argResults['emit-metadata'] as bool,
       enableAsserts: argResults['enable-asserts'] as bool);
   var jsModule =
-      compiler.emitProgram(component, result.inputSummaries, summaryUris);
+      compiler.emitModule(component, result.inputSummaries, summaryUris);
 
   var jsCode = jsProgramToCode(jsModule, moduleFormat,
       buildSourceMap: argResults['source-map'] as bool,
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index 7b95975..c39004a 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -255,12 +255,12 @@
 
   Uri get currentLibraryUri => _currentLibrary.importUri;
 
-  JS.Program emitProgram(
-      Component p, List<Component> summaries, List<Uri> summaryUris) {
+  JS.Program emitModule(
+      Component buildUnit, List<Component> summaries, List<Uri> summaryUris) {
     if (_moduleItems.isNotEmpty) {
       throw new StateError('Can only call emitModule once.');
     }
-    _component = p;
+    _component = buildUnit;
 
     for (var i = 0; i < summaries.length; i++) {
       var summary = summaries[i];
@@ -272,7 +272,7 @@
       }
     }
 
-    var libraries = p.libraries.where((l) => !l.isExternal);
+    var libraries = buildUnit.libraries.where((l) => !l.isExternal);
     var ddcRuntime =
         libraries.firstWhere(isSdkInternalRuntime, orElse: () => null);
     if (ddcRuntime != null) {
@@ -291,6 +291,8 @@
     // Initialize our library variables.
     var items = <JS.ModuleItem>[];
     var exports = <JS.NameSpecifier>[];
+    // TODO(jmesserly): this is a performance optimization for V8 to prevent it
+    // from treating our Dart library objects as JS Maps.
     var root = new JS.Identifier('_root');
     items.add(js.statement('const # = Object.create(null)', [root]));
 
@@ -353,7 +355,7 @@
     _copyAndFlattenBlocks(items, _moduleItems);
 
     // Build the module.
-    return new JS.Program(items, name: p.root.name);
+    return new JS.Program(items, name: buildUnit.root.name);
   }
 
   /// Flattens blocks in [items] to a single list.
@@ -454,9 +456,9 @@
       // TODO(jmesserly): we can merge these once we change signatures to be
       // lazily associated at the tear-off point for top-level functions.
       _emitLibraryProcedures(library);
+      _emitTopLevelFields(library.fields);
       library.classes.forEach(_emitClass);
       library.typedefs.forEach(_emitTypedef);
-      _emitTopLevelFields(library.fields);
     } else {
       library.classes.forEach(_emitClass);
       library.typedefs.forEach(_emitTypedef);
@@ -536,6 +538,9 @@
   }
 
   JS.Statement _emitClassDeclaration(Class c) {
+    // Mixins are unrolled in _defineClass.
+    if (c.isSyntheticMixinImplementation) return null;
+
     // If this class is annotated with `@JS`, then there is nothing to emit.
     if (findAnnotation(c, isPublicJSAnnotation) != null) return null;
 
@@ -650,6 +655,7 @@
 
     JS.Expression emitDeferredType(DartType t) {
       if (t is InterfaceType && t.typeArguments.isNotEmpty) {
+        _declareBeforeUse(t.classNode);
         return _emitGenericClassType(t, t.typeArguments.map(emitDeferredType));
       }
       return _emitType(t);
@@ -696,22 +702,19 @@
       return base;
     }
 
-    var mixins = <InterfaceType>[];
-    var mixedInType = c.mixedInType;
-    var superclass = c.superclass;
-    var supertype = c.supertype.asInterfaceType;
-    if (mixedInType != null) {
-      mixins.add(mixedInType.asInterfaceType);
-      for (;
-          superclass.isSyntheticMixinImplementation;
-          superclass = superclass.superclass) {
-        mixins.add(hierarchy
-            .getClassAsInstanceOf(c, superclass.mixedInClass)
-            .asInterfaceType);
-      }
-      if (mixins.length > 1) mixins = mixins.reversed.toList();
-      supertype = hierarchy.getClassAsInstanceOf(c, superclass).asInterfaceType;
-    }
+    // Find the real (user declared) superclass and the list of mixins.
+    // We'll use this to unroll the intermediate classes.
+    //
+    // TODO(jmesserly): consider using Kernel's mixin unrolling.
+    var mixinClasses = <Class>[];
+    var superclass = getSuperclassAndMixins(c, mixinClasses);
+    var supertype = identical(c.superclass, superclass)
+        ? c.supertype.asInterfaceType
+        : hierarchy.getClassAsInstanceOf(c, superclass).asInterfaceType;
+    mixinClasses = mixinClasses.reversed.toList();
+    var mixins = mixinClasses
+        .map((m) => hierarchy.getClassAsInstanceOf(c, m).asInterfaceType)
+        .toList();
 
     var hasUnnamedSuper = _hasUnnamedConstructor(superclass);
 
@@ -1088,7 +1091,9 @@
   /// Emits static fields for a class, and initialize them eagerly if possible,
   /// otherwise define them as lazy properties.
   void _emitStaticFields(Class c, List<JS.Statement> body) {
-    var fields = c.fields.where((f) => f.isStatic).toList();
+    var fields = c.fields
+        .where((f) => f.isStatic && getRedirectingFactories(f) == null)
+        .toList();
     if (c.isEnum) {
       // We know enum fields can be safely emitted as const fields, as long
       // as the `values` field is emitted last.
@@ -1289,7 +1294,9 @@
 
     if (emitMetadata) {
       var constructors = <JS.Property>[];
-      for (var ctor in c.constructors) {
+      var allConstructors = new List<Member>.from(c.constructors)
+        ..addAll(c.procedures.where((p) => p.isFactory));
+      for (var ctor in allConstructors) {
         var memberName = _constructorName(ctor.name.name);
         var type = _emitAnnotatedFunctionType(
             ctor.function.functionType.withoutTypeParameters, ctor);
@@ -1588,13 +1595,13 @@
               }''', [runtimeModule, runtimeModule])));
     }
 
+    Set<Member> redirectingFactories;
     for (var m in c.fields) {
-      if (_extensionTypes.isNativeClass(c)) {
+      if (m.isStatic) {
+        redirectingFactories ??= getRedirectingFactories(m)?.toSet();
+      } else if (_extensionTypes.isNativeClass(c)) {
         jsMethods.addAll(_emitNativeFieldAccessors(m));
-        continue;
-      }
-      if (m.isStatic) continue;
-      if (virtualFields.containsKey(m)) {
+      } else if (virtualFields.containsKey(m)) {
         jsMethods.addAll(_emitVirtualFieldAccessor(m));
       }
     }
@@ -1615,6 +1622,8 @@
         // TODO(jmesserly): is there any other kind of forwarding stub?
         jsMethods.addAll(_emitCovarianceCheckStub(m));
       } else if (m.isFactory) {
+        // Skip redirecting factories (they've already been resolved).
+        if (redirectingFactories?.contains(m) ?? false) continue;
         jsMethods.add(_emitFactoryConstructor(m));
       } else if (m.isAccessor) {
         jsMethods.add(_emitMethodDeclaration(m));
@@ -1718,8 +1727,11 @@
       return [
         new JS.Method(
             name,
-            js.fun('function(x) { return super.# = #._check(x); }',
-                [name, _emitType(substituteType(superMember.setterType))]),
+            js.fun('function(x) { return super.# = #; }', [
+              name,
+              _emitImplicitCast(new JS.Identifier('x'),
+                  substituteType(superMember.setterType))
+            ]),
             isSetter: true),
         new JS.Method(name, js.fun('function() { return super.#; }', [name]),
             isGetter: true)
@@ -1745,8 +1757,8 @@
 
       if (isCovariant(param) &&
           !isCovariant(superMember.function.positionalParameters[i])) {
-        var check = js.call('#._check(#)',
-            [_emitType(superMethodType.positionalParameters[i]), jsParam]);
+        var check =
+            _emitImplicitCast(jsParam, superMethodType.positionalParameters[i]);
         if (i >= function.requiredParameterCount) {
           body.add(js.statement('if (# !== void 0) #;', [jsParam, check]));
         } else {
@@ -1762,12 +1774,11 @@
         var name = _propertyName(param.name);
         var paramType = superMethodType.namedParameters
             .firstWhere((n) => n.name == param.name);
-        body.add(js.statement('if (# in #) #._check(#.#);', [
+        body.add(js.statement('if (# in #) #;', [
           name,
           namedArgumentTemp,
-          _emitType(paramType.type),
-          namedArgumentTemp,
-          name
+          _emitImplicitCast(
+              new JS.PropertyAccess(namedArgumentTemp, name), paramType.type)
         ]));
       }
     }
@@ -1788,10 +1799,11 @@
   JS.Method _emitFactoryConstructor(Procedure node) {
     if (isUnsupportedFactoryConstructor(node)) return null;
 
+    var function = node.function;
     return new JS.Method(
         _constructorName(node.name.name),
-        new JS.Fun(_emitFormalParameters(node.function),
-            _emitFunctionBody(node.function)),
+        new JS.Fun(
+            _emitFormalParameters(function), _emitFunctionBody(function)),
         isStatic: true)
       ..sourceInformation = _nodeEnd(node.fileEndOffset);
   }
@@ -1884,9 +1896,7 @@
       ]);
 
       returnType = _getTypeFromClass(returnType, member.enclosingClass, c);
-      if (!types.isTop(returnType)) {
-        fnBody = js.call('#._check(#)', [_emitType(returnType), fnBody]);
-      }
+      fnBody = _emitImplicitCast(fnBody, returnType);
 
       var fn = new JS.Fun(fnArgs, fnBody.toReturn().toBlock(),
           typeParams: typeParams);
@@ -1943,15 +1953,15 @@
           ? [new JS.Super(), name]
           : [new JS.This(), virtualField];
 
-      String jsCode;
+      JS.Expression value = new JS.Identifier('value');
       if (!field.isFinal && field.isGenericCovariantImpl) {
-        args.add(_emitType(field.type));
-        jsCode = 'function(value) { #[#] = #._check(value); }';
-      } else {
-        jsCode = 'function(value) { #[#] = value; }';
+        value = _emitImplicitCast(value, field.type);
       }
+      args.add(value);
 
-      result.add(new JS.Method(name, js.fun(jsCode, args), isSetter: true)
+      result.add(new JS.Method(
+          name, js.fun('function(value) { #[#] = #; }', args),
+          isSetter: true)
         ..sourceInformation = _nodeStart(field));
     }
 
@@ -1968,7 +1978,7 @@
     // Alternatively, perhaps it could be meta-programmed directly in
     // dart.registerExtensions?
     var jsMethods = <JS.Method>[];
-    if (field.isStatic) return jsMethods;
+    assert(!field.isStatic);
 
     var name = getAnnotationName(field, isJSName) ?? field.name.name;
     // Generate getter
@@ -2110,9 +2120,7 @@
         var init = field.initializer;
         if (init == null ||
             init is BasicLiteral ||
-            init is StaticInvocation && isInlineJS(init.target) ||
-            init is ConstructorInvocation &&
-                isSdkInternalRuntime(init.target.enclosingLibrary)) {
+            init is StaticInvocation && isInlineJS(init.target)) {
           _currentUri = field.fileUri;
           _moduleItems.add(js.statement('# = #;', [
             _emitTopLevelName(field),
@@ -2280,9 +2288,8 @@
     }
 
     useExtension ??= _isSymbolizedMember(type, name);
-    // TODO(vsm): Do not rename members that conflict with standard JS members
-    // if we are actually try to access those JS members via interop.
-    name = JS.memberNameForDartMember(name);
+    name = JS.memberNameForDartMember(
+        name, member is Procedure && member.isExternal);
     if (useExtension) {
       return _getExtensionSymbolInternal(name);
     }
@@ -2977,8 +2984,8 @@
 
     initParameter(VariableDeclaration p, JS.Identifier jsParam) {
       if (isCovariant(p)) {
-        var castType = _emitType(p.type);
-        body.add(js.statement('#._check(#);', [castType, jsParam]));
+        var castExpr = _emitImplicitCast(jsParam, p.type);
+        if (!identical(castExpr, jsParam)) body.add(castExpr.toStatement());
       }
       if (_annotatedNullCheck(p.annotations)) {
         body.add(_nullParameterCheck(jsParam));
@@ -3057,7 +3064,7 @@
   void _emitCovarianceBoundsCheck(
       List<TypeParameter> typeFormals, List<JS.Statement> body) {
     for (var t in typeFormals) {
-      if (t.isGenericCovariantImpl) {
+      if (t.isGenericCovariantImpl && !types.isTop(t.bound)) {
         body.add(runtimeStatement('checkTypeBound(#, #, #)', [
           _emitType(new TypeParameterType(t)),
           _emitType(t.bound),
@@ -3112,9 +3119,7 @@
     if (node == null) return null;
 
     if (node is Not) {
-      // TODO(leafp): consider a peephole opt for identical
-      // and == here.
-      return js.call('!#', _visitTest(node.operand));
+      return visitNot(node);
     }
     if (node is LogicalExpression) {
       JS.Expression shortCircuit(String code) {
@@ -3214,9 +3219,18 @@
   }
 
   @override
-  visitBlock(Block node) =>
-      new JS.Block(node.statements.map(_visitStatement).toList(),
-          isScope: true);
+  visitBlock(Block node) {
+    // If this is the block body of a function, don't mark it as a separate
+    // scope, because the function is the scope. This avoids generating an
+    // unncessary nested block.
+    //
+    // NOTE: we do sometimes need to handle this because Dart and JS rules are
+    // slightly different (in Dart, there is a nested scope), but that's handled
+    // by _emitFunctionBody.
+    var isScope = !identical(node.parent, _currentFunction);
+    return new JS.Block(node.statements.map(_visitStatement).toList(),
+        isScope: isScope);
+  }
 
   @override
   visitEmptyStatement(EmptyStatement node) => new JS.EmptyStatement();
@@ -4218,7 +4232,8 @@
   }
 
   JS.Expression _emitEqualityOperator(
-      Expression left, Member target, Expression right) {
+      Expression left, Member target, Expression right,
+      {bool negated = false}) {
     var leftType = left.getStaticType(types);
 
     // Conceptually `x == y` in Dart is defined as:
@@ -4246,7 +4261,7 @@
     // If we know that the left type uses identity for equality, we can
     // sometimes emit better code, either `===` or `==`.
     if (usesIdentity) {
-      return _emitCoreIdenticalCall([left, right]);
+      return _emitCoreIdenticalCall([left, right], negated: negated);
     }
 
     // If the left side is nullable, we need to use a runtime helper to check
@@ -4254,12 +4269,12 @@
     // a measurable performance effect (possibly the helper is simple enough to
     // be inlined).
     if (isNullable(left)) {
-      return runtimeCall(
-          'equals(#, #)', [_visitExpression(left), _visitExpression(right)]);
+      return js.call(negated ? '!#.equals(#, #)' : '#.equals(#, #)',
+          [runtimeModule, _visitExpression(left), _visitExpression(right)]);
     }
 
     // Otherwise we emit a call to the == method.
-    return js.call('#[#](#)', [
+    return js.call(negated ? '!#[#](#)' : '#[#](#)', [
       _visitExpression(left),
       _emitMemberName('==', type: leftType),
       _visitExpression(right)
@@ -4730,9 +4745,24 @@
 
   @override
   visitNot(Not node) {
+    var operand = node.operand;
+    if (operand is MethodInvocation && operand.name.name == '==') {
+      return _emitEqualityOperator(operand.receiver, operand.interfaceTarget,
+          operand.arguments.positional[0],
+          negated: true);
+    } else if (operand is DirectMethodInvocation && operand.name.name == '==') {
+      return _emitEqualityOperator(
+          operand.receiver, operand.target, operand.arguments.positional[0],
+          negated: true);
+    } else if (operand is StaticInvocation &&
+        operand.target == coreTypes.identicalProcedure) {
+      return _emitCoreIdenticalCall(operand.arguments.positional,
+          negated: true);
+    }
+
     // Logical negation, `!e`, is a boolean conversion context since it is
     // defined as `e ? false : true`.
-    return _visitTest(node);
+    return js.call('!#', _visitTest(operand));
   }
 
   @override
@@ -4863,8 +4893,15 @@
       return jsFrom;
     }
 
-    var code = isTypeError ? '#._check(#)' : '#.as(#)';
-    return js.call(code, [_emitType(to), jsFrom]);
+    return isTypeError
+        ? _emitImplicitCast(jsFrom, to)
+        : js.call('#.as(#)', [_emitType(to), jsFrom]);
+  }
+
+  JS.Expression _emitImplicitCast(JS.Expression expr, DartType type) {
+    return types.isTop(type)
+        ? expr
+        : js.call('#._check(#)', [_emitType(type), expr]);
   }
 
   @override
@@ -5004,6 +5041,10 @@
       JS.Block block = body;
       if (block.statements.length == 1) {
         JS.Statement s = block.statements[0];
+        if (s is JS.Block) {
+          block = s;
+          s = block.statements.length == 1 ? block.statements[0] : null;
+        }
         if (s is JS.Return && s.value != null) body = s.value;
       }
     }
@@ -5108,6 +5149,7 @@
   bool _reifyTearoff(Member member) {
     return member is Procedure &&
         !member.isAccessor &&
+        !member.isFactory &&
         !_isInForeignJS &&
         !usesJSInterop(member) &&
         _reifyFunctionType(member.function);
diff --git a/pkg/dev_compiler/lib/src/kernel/js_typerep.dart b/pkg/dev_compiler/lib/src/kernel/js_typerep.dart
index 0f2a383..8b6500b 100644
--- a/pkg/dev_compiler/lib/src/kernel/js_typerep.dart
+++ b/pkg/dev_compiler/lib/src/kernel/js_typerep.dart
@@ -114,11 +114,12 @@
       if (c == coreTypes.nullClass) return JSType.jsNull;
       if (c == coreTypes.numClass ||
           c == coreTypes.intClass ||
-          c == coreTypes.doubleClass) {
+          c == coreTypes.doubleClass ||
+          c == _jsNumber) {
         return JSType.jsNumber;
       }
-      if (c == coreTypes.boolClass) return JSType.jsBoolean;
-      if (c == coreTypes.stringClass) return JSType.jsString;
+      if (c == coreTypes.boolClass || c == _jsBool) return JSType.jsBoolean;
+      if (c == coreTypes.stringClass || c == _jsString) return JSType.jsString;
       if (c == coreTypes.objectClass) return JSType.jsUnknown;
       if (c == coreTypes.futureOrClass) {
         var argumentRep = typeFor(type.typeArguments[0]);
diff --git a/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart b/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart
index 18fb1a3..d0043bb 100644
--- a/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart
+++ b/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart
@@ -113,9 +113,20 @@
 ///
 /// Given teh node for `@MyAnnotation('FooBar')` this will return `'FooBar'`.
 String getNameFromAnnotation(ConstructorInvocation node) {
-  if (node != null && node.arguments.positional.isNotEmpty) {
-    var first = _followConstFields(node.arguments.positional[0]);
-    if (first is StringLiteral) return first.value;
+  if (node != null) {
+    Expression first;
+    if (node.arguments.named.isNotEmpty) {
+      first = node.arguments.named
+          .firstWhere((n) => n.name == 'name', orElse: () => null)
+          ?.value;
+    }
+    if (node.arguments.positional.isNotEmpty) {
+      first ??= node.arguments.positional[0];
+    }
+    if (first != null) {
+      first = _followConstFields(first);
+      if (first is StringLiteral) return first.value;
+    }
   }
   return null;
 }
@@ -296,3 +307,35 @@
   }
   return false;
 }
+
+/// Returns the redirecting factory constructors for the enclosing class,
+/// if the field [f] is storing that information, otherwise returns `null`.
+Iterable<Member> getRedirectingFactories(Field f) {
+  // TODO(jmesserly): this relies on implementation details in Kernel
+  if (f.name.name == "_redirecting#") {
+    assert(f.isStatic);
+    var list = f.initializer as ListLiteral;
+    return list.expressions.map((e) => (e as StaticGet).target);
+  }
+  return null;
+}
+
+/// Gets the real supertype of [c] and the list of [mixins] in reverse
+/// application order (mixins will appear before ones they override).
+///
+/// This is used to ignore synthetic mixin application classes.
+///
+// TODO(jmesserly): consider replacing this with Kernel's mixin unrolling once
+// we don't have the Analyzer backend to maintain.
+Class getSuperclassAndMixins(Class c, List<Class> mixins) {
+  assert(mixins.isEmpty);
+
+  var mixedInClass = c.mixedInClass;
+  if (mixedInClass != null) mixins.add(mixedInClass);
+
+  var sc = c.superclass;
+  for (; sc.isSyntheticMixinImplementation; sc = sc.superclass) {
+    mixins.add(sc.mixedInClass);
+  }
+  return sc;
+}
diff --git a/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart b/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart
index 0dd31c6..edf71af 100644
--- a/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart
+++ b/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart
@@ -100,19 +100,24 @@
   visitStaticSet(StaticSet node) => isNullable(node.value);
 
   @override
-  visitMethodInvocation(MethodInvocation node) =>
-      _invocationIsNullable(node.interfaceTarget, node.receiver);
+  visitMethodInvocation(MethodInvocation node) => _invocationIsNullable(
+      node.interfaceTarget, node.name.name, node.receiver);
 
   @override
   visitDirectMethodInvocation(DirectMethodInvocation node) =>
-      _invocationIsNullable(node.target, node.receiver);
+      _invocationIsNullable(node.target, node.name.name, node.receiver);
 
   @override
   visitSuperMethodInvocation(SuperMethodInvocation node) =>
-      _invocationIsNullable(node.interfaceTarget);
+      _invocationIsNullable(node.interfaceTarget, node.name.name);
 
-  bool _invocationIsNullable(Member target, [Expression receiver]) {
-    if (target == null) return true;
+  bool _invocationIsNullable(Member target, String name,
+      [Expression receiver]) {
+    // TODO(jmesserly): this is not a valid assumption for user-defined equality
+    // but it is added to match the behavior of the Analyzer backend.
+    // https://github.com/dart-lang/sdk/issues/31854
+    if (name == '==') return false;
+    if (target == null) return true; // dynamic call
     if (target.name.name == 'toString' &&
         receiver != null &&
         receiver.getStaticType(types) == coreTypes.stringClass.rawType) {
@@ -133,11 +138,6 @@
   }
 
   bool _returnValueIsNullable(Member target) {
-    // TODO(jmesserly): this is not a valid assumption for user-defined equality
-    // but it is added to match the behavior of the Analyzer backend.
-    // https://github.com/dart-lang/sdk/issues/31854
-    if (target.name.name == '==') return false;
-
     var targetClass = target.enclosingClass;
     if (targetClass != null) {
       // Convert `int` `double` `num` `String` and `bool` to their corresponding
@@ -168,13 +168,13 @@
       var args = node.arguments.positional;
       var first = args.isNotEmpty ? args.first : null;
       if (first is StringLiteral) {
-        var types = first.value;
-        return types == '' ||
-            types == 'var' ||
-            types.split('|').contains('Null');
+        var typeString = first.value;
+        return typeString == '' ||
+            typeString == 'var' ||
+            typeString.split('|').contains('Null');
       }
     }
-    return _invocationIsNullable(target);
+    return _invocationIsNullable(target, node.name.name);
   }
 
   @override
diff --git a/pkg/dev_compiler/lib/src/kernel/property_model.dart b/pkg/dev_compiler/lib/src/kernel/property_model.dart
index 9f49edb..51cad84 100644
--- a/pkg/dev_compiler/lib/src/kernel/property_model.dart
+++ b/pkg/dev_compiler/lib/src/kernel/property_model.dart
@@ -367,10 +367,12 @@
       visitSuper(c);
     }
 
-    var m = class_.mixedInClass;
-    if (m != null) visitImmediateSuper(m);
-    var s = class_.superclass;
-    if (s != null) visitImmediateSuper(s);
+    if (class_.superclass != null) {
+      var mixins = <Class>[];
+      var superclass = getSuperclassAndMixins(class_, mixins);
+      mixins.forEach(visitImmediateSuper);
+      visitImmediateSuper(superclass);
+    }
   }
 
   /// Searches all concrete instance members declared on this type, skipping
diff --git a/pkg/dev_compiler/test/transformer/hello_app/pubspec.lock b/pkg/dev_compiler/test/transformer/hello_app/pubspec.lock
deleted file mode 100644
index 01b736a..0000000
--- a/pkg/dev_compiler/test/transformer/hello_app/pubspec.lock
+++ /dev/null
@@ -1,226 +0,0 @@
-# Generated by pub
-# See http://pub.dartlang.org/doc/glossary.html#lockfile
-packages:
-  analyzer:
-    description:
-      name: analyzer
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.27.3-alpha.2"
-  args:
-    description:
-      name: args
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.13.3+6"
-  async:
-    description:
-      name: async
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "1.9.0"
-  barback:
-    description:
-      name: barback
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.15.2+7"
-  browser:
-    description:
-      name: browser
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.10.0+2"
-  charcode:
-    description:
-      name: charcode
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "1.1.0"
-  cli_util:
-    description:
-      name: cli_util
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.0.1+2"
-  code_transformers:
-    description:
-      name: code_transformers
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.4.1"
-  collection:
-    description:
-      name: collection
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "1.4.0"
-  crypto:
-    description:
-      name: crypto
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.9.1"
-  csslib:
-    description:
-      name: csslib
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.12.2"
-  dev_compiler:
-    description:
-      path: "../../.."
-      relative: true
-    source: path
-    version: "0.1.22"
-  func:
-    description:
-      name: func
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.1.0"
-  glob:
-    description:
-      name: glob
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "1.1.1"
-  hello_dep:
-    description:
-      path: "../hello_dep"
-      relative: true
-    source: path
-    version: "0.0.1"
-  html:
-    description:
-      name: html
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.12.2+1"
-  http_parser:
-    description:
-      name: http_parser
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "2.2.0"
-  js:
-    description:
-      name: js
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.6.0"
-  logging:
-    description:
-      name: logging
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.11.2"
-  mime:
-    description:
-      name: mime
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.9.3"
-  package_config:
-    description:
-      name: package_config
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.1.3"
-  path:
-    description:
-      name: path
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "1.3.9"
-  plugin:
-    description:
-      name: plugin
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.1.0"
-  pool:
-    description:
-      name: pool
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "1.2.1"
-  pub_semver:
-    description:
-      name: pub_semver
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "1.2.3"
-  shelf:
-    description:
-      name: shelf
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.6.5"
-  shelf_static:
-    description:
-      name: shelf_static
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.2.3+3"
-  source_maps:
-    description:
-      name: source_maps
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.10.1"
-  source_span:
-    description:
-      name: source_span
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "1.2.2"
-  stack_trace:
-    description:
-      name: stack_trace
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "1.6.1"
-  stream_channel:
-    description:
-      name: stream_channel
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "1.3.1"
-  string_scanner:
-    description:
-      name: string_scanner
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.1.4+1"
-  utf:
-    description:
-      name: utf
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.9.0+3"
-  watcher:
-    description:
-      name: watcher
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.9.7"
-  when:
-    description:
-      name: when
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.2.0"
-  which:
-    description:
-      name: which
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.1.3"
-  yaml:
-    description:
-      name: yaml
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "2.1.8"
-sdk: ">=1.14.0 <2.0.0"
diff --git a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/errors.dart b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/errors.dart
index d082f88..4d2f78f 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/errors.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/errors.dart
@@ -36,9 +36,9 @@
   throw new AssertionErrorImpl(message);
 }
 
-throwCyclicInitializationError([String message]) {
+throwCyclicInitializationError([Object field]) {
   if (JS('bool', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
-  throw new CyclicInitializationError(message);
+  throw new CyclicInitializationError(field);
 }
 
 throwNullValueError() {
diff --git a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/types.dart b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/types.dart
index 3215fa5..48b35b0 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/types.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/types.dart
@@ -706,35 +706,22 @@
     return $type.toString();
   }
 
-  // Wrapped types
-  if ($type instanceof $WrappedType) {
-    return "Wrapped(" + $unwrapType($type) + ")";
-  }
-
   // Instance types
   let tag = $type[$_runtimeType];
   if (tag === $Type) {
     let name = $type.name;
-    let args = $getGenericArgs($type);
-    if (!args) return name;
+    let args = ${getGenericArgs(type)};
+    if (args == null) return name;
+
+    if (${getGenericClass(type)} == ${getGenericClass(JSArray)}) name = 'List';
 
     let result = name;
-    let allDynamic = true;
-
     result += '<';
     for (let i = 0; i < args.length; ++i) {
       if (i > 0) result += ', ';
-
-      let argName = $typeName(args[i]);
-      if (argName != 'dynamic') allDynamic = false;
-
-      result += argName;
+      result += $typeName(args[i]);
     }
     result += '>';
-
-    // Don't print the type arguments if they are all dynamic. Show "raw"
-    // types as just the bare type name.
-    if (allDynamic) return name;
     return result;
   }
   if (tag) return "Not a type: " + tag.name;
diff --git a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/utils.dart b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/utils.dart
index 80a84de..d913dfa8 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/utils.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/utils.dart
@@ -69,14 +69,17 @@
   let value = null;
   $desc.get = function() {
     if (init == null) return value;
-
-    // Compute and store the value, guarding against reentry.
     let f = init;
-    init = () => $throwCyclicInitializationError($name);
+    init = $throwCyclicInitializationError;
+    if (f === init) f($name); // throw cycle error
     try {
-      return value = f();
-    } finally {
+      value = f();
       init = null;
+      return value;
+    } catch (e) {
+      init = null;
+      value = null;
+      throw e;
     }
   };
   $desc.configurable = true;
diff --git a/pkg/dev_compiler/tool/input_sdk/private/debugger.dart b/pkg/dev_compiler/tool/input_sdk/private/debugger.dart
index 42128b2..2d9982b 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/debugger.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/debugger.dart
@@ -135,14 +135,10 @@
 }
 
 String getTypeName(type) {
-  var name = dart.typeName(type);
-  // Hack to cleanup names for List<dynamic>
   // TODO(jacobr): it would be nice if there was a way we could distinguish
   // between a List<dynamic> created from Dart and an Array passed in from
   // JavaScript.
-  if (name == 'JSArray<dynamic>' || name == 'JSObject<Array>')
-    return 'List<dynamic>';
-  return name;
+  return dart.typeName(type);
 }
 
 String safePreview(object, config) {
@@ -884,7 +880,6 @@
         ..addAll(sortProperties(instanceMethods));
     }
 
-    var typeName = getTypeName(type);
     var mixin = dart.getMixin(type);
     if (mixin != null) {
       // TODO(jmesserly): this can only be one value.
diff --git a/pkg/dev_compiler/tool/input_sdk/private/interceptors.dart b/pkg/dev_compiler/tool/input_sdk/private/interceptors.dart
index 20aee27..23c00f0 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/interceptors.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/interceptors.dart
@@ -114,8 +114,9 @@
 class JSFunction extends Interceptor {
   toString() {
     // If the function is a Type object, we should just display the type name.
+    //
     // Regular Dart code should typically get wrapped type objects instead of
-    // raw type (aka JS constructor) objects however raw type objects can be
+    // raw type (aka JS constructor) objects, however raw type objects can be
     // exposed to Dart code via JS interop or debugging tools.
     if (dart.isType(this)) return dart.typeName(this);
 
diff --git a/pkg/dev_compiler/tool/kernel_sdk.dart b/pkg/dev_compiler/tool/kernel_sdk.dart
index f8cb4e7..fac6737 100755
--- a/pkg/dev_compiler/tool/kernel_sdk.dart
+++ b/pkg/dev_compiler/tool/kernel_sdk.dart
@@ -47,7 +47,7 @@
   await writeComponentToBinary(component, outputPath);
 
   var jsModule = new ProgramCompiler(component, declaredVariables: {})
-      .emitProgram(component, [], []);
+      .emitModule(component, [], []);
   var moduleFormats = {
     'amd': ModuleFormat.amd,
     'common': ModuleFormat.common,
diff --git a/pkg/front_end/lib/src/fasta/kernel/fasta_accessors.dart b/pkg/front_end/lib/src/fasta/kernel/fasta_accessors.dart
index 79859e9..8e79571 100644
--- a/pkg/front_end/lib/src/fasta/kernel/fasta_accessors.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/fasta_accessors.dart
@@ -434,7 +434,7 @@
 
   Expression buildSimpleRead() {
     if (!isSuper) {
-      return new ShadowThisExpression();
+      return new ShadowThisExpression()..fileOffset = offsetForToken(token);
     } else {
       return helper.buildCompileTimeError(messageSuperAsExpression,
           offsetForToken(token), lengthForToken(token));
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
index 36c7523..b4c9192 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
@@ -413,16 +413,18 @@
       if (isPreIncDec || isPostIncDec) {
         rhsType = inferrer.coreTypes.intClass.rawType;
       } else {
-        // Analyzer uses a null context for the RHS here.
-        // TODO(paulberry): improve on this.
-        rhsType = inferrer.inferExpression(rhs, const UnknownType(), true);
         // It's not necessary to call _storeLetType for [rhs] because the RHS
         // is always passed directly to the combiner; it's never stored in a
         // temporary variable first.
-        assert(identical(combiner.arguments.positional[0], rhs));
+        assert(identical(combiner.arguments.positional.first, rhs));
+        // Analyzer uses a null context for the RHS here.
+        // TODO(paulberry): improve on this.
+        rhsType = inferrer.inferExpression(rhs, const UnknownType(), true);
+        // Do not use rhs after this point because it may be a Shadow node
+        // that has been replaced in the tree with its desugaring.
         var expectedType = getPositionalParameterType(combinerType, 0);
-        inferrer.ensureAssignable(
-            expectedType, rhsType, rhs, combiner.fileOffset);
+        inferrer.ensureAssignable(expectedType, rhsType,
+            combiner.arguments.positional.first, combiner.fileOffset);
       }
       if (isOverloadedArithmeticOperator) {
         combinedType = inferrer.typeSchemaEnvironment
@@ -1910,6 +1912,7 @@
   /// [desugared].
   void _replaceWithDesugared() {
     parent.replaceChild(this, desugared);
+    parent = null;
   }
 
   /// Updates any [Let] nodes in the desugared expression to account for the
diff --git a/pkg/front_end/lib/src/fasta/parser/identifier_context.dart b/pkg/front_end/lib/src/fasta/parser/identifier_context.dart
index b2969e2..26dea92 100644
--- a/pkg/front_end/lib/src/fasta/parser/identifier_context.dart
+++ b/pkg/front_end/lib/src/fasta/parser/identifier_context.dart
@@ -132,8 +132,7 @@
       inDeclaration: true);
 
   /// Identifier is a name being declared by a field declaration.
-  static const fieldDeclaration =
-      const IdentifierContext('fieldDeclaration', inDeclaration: true);
+  static const fieldDeclaration = const FieldDeclarationIdentifierContext();
 
   /// Identifier is the name being declared by a top level function declaration.
   static const topLevelFunctionDeclaration = const IdentifierContext(
@@ -142,8 +141,7 @@
 
   /// Identifier is the start of the name being declared by a method
   /// declaration.
-  static const methodDeclaration =
-      const IdentifierContext('methodDeclaration', inDeclaration: true);
+  static const methodDeclaration = const MethodDeclarationIdentifierContext();
 
   /// Identifier is part of the name being declared by a method declaration,
   /// but it's not the first identifier of the name.
@@ -151,10 +149,8 @@
   /// In valid Dart, this can only happen if the identifier is the name of a
   /// named constructor which is being declared, e.g. `foo` in
   /// `class C { C.foo(); }`.
-  static const methodDeclarationContinuation = const IdentifierContext(
-      'methodDeclarationContinuation',
-      inDeclaration: true,
-      isContinuation: true);
+  static const methodDeclarationContinuation =
+      const MethodDeclarationIdentifierContext.continuation();
 
   /// Identifier appears after the word `operator` in a method declaration.
   ///
diff --git a/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart b/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart
index a5e4efa..97798fb 100644
--- a/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart
+++ b/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart
@@ -31,7 +31,7 @@
       return identifier;
     }
 
-    if (looksLikeStartOfNextDeclaration(identifier) ||
+    if (looksLikeStartOfNextTopLevelDeclaration(identifier) ||
         isOneOfOrEof(
             identifier, const ['<', '{', 'extends', 'with', 'implements'])) {
       identifier = parser.insertSyntheticIdentifier(token, this,
@@ -76,7 +76,7 @@
       }
     }
 
-    if (looksLikeStartOfNextDeclaration(identifier) ||
+    if (looksLikeStartOfNextTopLevelDeclaration(identifier) ||
         isOneOfOrEof(identifier, followingValues)) {
       identifier = parser.insertSyntheticIdentifier(token, this,
           message: fasta.templateExpectedIdentifier.withArguments(identifier));
@@ -141,6 +141,35 @@
   }
 }
 
+class FieldDeclarationIdentifierContext extends IdentifierContext {
+  const FieldDeclarationIdentifierContext()
+      : super('fieldDeclaration', inDeclaration: true);
+
+  @override
+  Token ensureIdentifier(Token token, Parser parser) {
+    Token identifier = token.next;
+    assert(identifier.kind != IDENTIFIER_TOKEN);
+    if (identifier.isIdentifier) {
+      return identifier;
+    }
+    // Recovery
+    if (isOneOfOrEof(identifier, const [';', '=', ',', '}']) ||
+        looksLikeStartOfNextClassMember(identifier)) {
+      return parser.insertSyntheticIdentifier(token, this);
+    } else if (!identifier.isKeywordOrIdentifier) {
+      // When in doubt, consume the token to ensure we make progress
+      // but insert a synthetic identifier to satisfy listeners.
+      return parser.insertSyntheticIdentifier(identifier, this,
+          message: fasta.templateExpectedIdentifier.withArguments(identifier),
+          messageOnToken: identifier);
+    } else {
+      parser.reportRecoverableErrorWithToken(
+          identifier, fasta.templateExpectedIdentifier);
+      return identifier;
+    }
+  }
+}
+
 /// See [IdentifierContext].fieldInitializer
 class FieldInitializerIdentifierContext extends IdentifierContext {
   const FieldInitializerIdentifierContext()
@@ -177,7 +206,7 @@
     if (identifier.isIdentifier) {
       Token next = identifier.next;
       if (isOneOfOrEof(next, const ['.', ';']) ||
-          !looksLikeStartOfNextDeclaration(identifier)) {
+          !looksLikeStartOfNextTopLevelDeclaration(identifier)) {
         return identifier;
       }
       // Although this is a valid library name, the library declaration
@@ -185,7 +214,7 @@
       // In this situation, fall through to insert a synthetic library name.
     }
     if (isOneOfOrEof(identifier, const ['.', ';']) ||
-        looksLikeStartOfNextDeclaration(identifier)) {
+        looksLikeStartOfNextTopLevelDeclaration(identifier)) {
       identifier = parser.insertSyntheticIdentifier(token, this,
           message: fasta.templateExpectedIdentifier.withArguments(identifier));
     } else {
@@ -231,6 +260,43 @@
   }
 }
 
+class MethodDeclarationIdentifierContext extends IdentifierContext {
+  const MethodDeclarationIdentifierContext()
+      : super('methodDeclaration', inDeclaration: true);
+
+  const MethodDeclarationIdentifierContext.continuation()
+      : super('methodDeclarationContinuation',
+            inDeclaration: true, isContinuation: true);
+
+  @override
+  Token ensureIdentifier(Token token, Parser parser) {
+    Token identifier = token.next;
+    assert(identifier.kind != IDENTIFIER_TOKEN);
+    if (identifier.isIdentifier) {
+      return identifier;
+    }
+    // Recovery
+    if (identifier.isUserDefinableOperator && !isContinuation) {
+      return parser.insertSyntheticIdentifier(identifier, this,
+          message: fasta.messageMissingOperatorKeyword,
+          messageOnToken: identifier);
+    } else if (isOneOfOrEof(identifier, const ['.', '(', '{', '=>']) ||
+        looksLikeStartOfNextClassMember(identifier)) {
+      return parser.insertSyntheticIdentifier(token, this);
+    } else if (!identifier.isKeywordOrIdentifier) {
+      // When in doubt, consume the token to ensure we make progress
+      // but insert a synthetic identifier to satisfy listeners.
+      return parser.insertSyntheticIdentifier(identifier, this,
+          message: fasta.templateExpectedIdentifier.withArguments(identifier),
+          messageOnToken: identifier);
+    } else {
+      parser.reportRecoverableErrorWithToken(
+          identifier, fasta.templateExpectedIdentifier);
+      return identifier;
+    }
+  }
+}
+
 /// See [IdentifierContext].typeReference
 class TypeReferenceIdentifierContext extends IdentifierContext {
   const TypeReferenceIdentifierContext()
@@ -315,9 +381,8 @@
   return token.isEof;
 }
 
-bool looksLikeStartOfNextDeclaration(Token token) =>
-    token.isTopLevelKeyword ||
-    isOneOfOrEof(token, const ['const', 'get', 'final', 'set', 'var', 'void']);
+bool looksLikeStartOfNextClassMember(Token token) =>
+    token.isModifier || isOneOfOrEof(token, const ['get', 'set', 'void']);
 
 bool looksLikeStartOfNextStatement(Token token) => isOneOfOrEof(token, const [
       'assert',
@@ -336,6 +401,10 @@
       'while'
     ]);
 
+bool looksLikeStartOfNextTopLevelDeclaration(Token token) =>
+    token.isTopLevelKeyword ||
+    isOneOfOrEof(token, const ['const', 'get', 'final', 'set', 'var', 'void']);
+
 Token skipMetadata(Token token) {
   assert(optional('@', token));
   Token next = token.next;
diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart
index a23beb1..e66820c 100644
--- a/pkg/front_end/lib/src/fasta/parser/parser.dart
+++ b/pkg/front_end/lib/src/fasta/parser/parser.dart
@@ -34,8 +34,6 @@
         EOF_TOKEN,
         EQ_TOKEN,
         FUNCTION_TOKEN,
-        GT_GT_TOKEN,
-        GT_TOKEN,
         HASH_TOKEN,
         HEXADECIMAL_TOKEN,
         IDENTIFIER_TOKEN,
@@ -45,7 +43,6 @@
         OPEN_CURLY_BRACKET_TOKEN,
         OPEN_PAREN_TOKEN,
         OPEN_SQUARE_BRACKET_TOKEN,
-        PERIOD_TOKEN,
         SEMICOLON_TOKEN,
         STRING_INTERPOLATION_IDENTIFIER_TOKEN,
         STRING_INTERPOLATION_TOKEN,
@@ -94,6 +91,8 @@
         isValidTypeReference,
         noType;
 
+import 'type_info_impl.dart' show skipTypeVariables;
+
 import 'util.dart' show optional;
 
 /// An event generating parser of Dart programs. This parser expects all tokens
@@ -1506,76 +1505,14 @@
   /// arguments in generic method invocations can be recognized, and as few as
   /// possible other constructs will pass (e.g., 'a < C, D > 3').
   bool isValidMethodTypeArguments(Token token) {
-    Token Function(Token token) tryParseType;
-
-    /// Returns token after match if [token] matches '<' type (',' type)* '>'
-    /// '(', and otherwise returns null. Does not produce listener events. With
-    /// respect to the final '(', please see the description of
-    /// [isValidMethodTypeArguments].
-    Token tryParseMethodTypeArguments(Token token) {
-      if (!identical(token.kind, LT_TOKEN)) return null;
-      Token endToken = token.endGroup;
-      if (endToken == null ||
-          !identical(endToken.next.kind, OPEN_PAREN_TOKEN)) {
-        return null;
+    // TODO(danrubel): Replace call with a call to computeTypeVar.
+    if (optional('<', token)) {
+      Token endGroup = skipTypeVariables(token);
+      if (endGroup != null && optional('(', endGroup.next)) {
+        return true;
       }
-      token = tryParseType(token.next);
-      while (token != null && identical(token.kind, COMMA_TOKEN)) {
-        token = tryParseType(token.next);
-      }
-      if (token == null || !identical(token.kind, GT_TOKEN)) return null;
-      return token.next;
     }
-
-    /// Returns token after match if [token] matches identifier ('.'
-    /// identifier)?, and otherwise returns null. Does not produce listener
-    /// events.
-    Token tryParseQualified(Token token) {
-      if (!isValidTypeReference(token)) return null;
-      token = token.next;
-      if (!identical(token.kind, PERIOD_TOKEN)) return token;
-      token = token.next;
-      if (!identical(token.kind, IDENTIFIER_TOKEN)) return null;
-      return token.next;
-    }
-
-    /// Returns token after match if [token] matches '<' type (',' type)* '>',
-    /// and otherwise returns null. Does not produce listener events. The final
-    /// '>' may be the first character in a '>>' token, in which case a
-    /// synthetic '>' token is created and returned, representing the second
-    /// '>' in the '>>' token.
-    Token tryParseNestedTypeArguments(Token token) {
-      if (!identical(token.kind, LT_TOKEN)) return null;
-      // If the initial '<' matches the first '>' in a '>>' token, we will have
-      // `token.endGroup == null`, so we cannot rely on `token.endGroup == null`
-      // to imply that the match must fail. Hence no `token.endGroup == null`
-      // test here.
-      token = tryParseType(token.next);
-      while (token != null && identical(token.kind, COMMA_TOKEN)) {
-        token = tryParseType(token.next);
-      }
-      if (token == null) return null;
-      if (identical(token.kind, GT_TOKEN)) return token.next;
-      if (!identical(token.kind, GT_GT_TOKEN)) return null;
-      // [token] is '>>' of which the final '>' that we are parsing is the first
-      // character. In order to keep the parsing process on track we must return
-      // a synthetic '>' corresponding to the second character of that '>>'.
-      Token syntheticToken = new Token(TokenType.GT, token.charOffset + 1);
-      syntheticToken.next = token.next;
-      return syntheticToken;
-    }
-
-    /// Returns token after match if [token] matches typeName typeArguments?,
-    /// and otherwise returns null. Does not produce listener events.
-    tryParseType = (Token token) {
-      token = tryParseQualified(token);
-      if (token == null) return null;
-      Token tokenAfterQualified = token;
-      token = tryParseNestedTypeArguments(token);
-      return token == null ? tokenAfterQualified : token;
-    };
-
-    return tryParseMethodTypeArguments(token) != null;
+    return false;
   }
 
   /// ```
@@ -1981,24 +1918,9 @@
       } else if (next.isKeywordOrIdentifier) {
         reportRecoverableErrorWithToken(next, context.recoveryTemplate);
         token = next;
-      } else if (next.isUserDefinableOperator &&
-          context == IdentifierContext.methodDeclaration) {
-        // If this is a user definable operator, then assume that the user has
-        // forgotten the `operator` keyword.
-        token = rewriteAndRecover(token, fasta.messageMissingOperatorKeyword,
-            new SyntheticKeywordToken(Keyword.OPERATOR, next.offset));
-        return parseOperatorName(token);
       } else {
         reportRecoverableErrorWithToken(next, context.recoveryTemplate);
-        if (context == IdentifierContext.methodDeclaration) {
-          // Since the token is not a keyword or identifier, consume it to
-          // ensure forward progress in parseMethod.
-          token = next.next;
-          // Supply a non-empty method name so that it does not accidentally
-          // match the default constructor.
-          token = insertSyntheticIdentifier(next, context);
-        } else if (context == IdentifierContext.topLevelVariableDeclaration ||
-            context == IdentifierContext.fieldDeclaration) {
+        if (context == IdentifierContext.topLevelVariableDeclaration) {
           // Since the token is not a keyword or identifier, consume it to
           // ensure forward progress in parseField.
           token = next.next;
@@ -2077,8 +1999,6 @@
       followingValues = [';'];
     } else if (context == IdentifierContext.constructorReferenceContinuation) {
       followingValues = ['.', ',', '(', ')', '[', ']', '}', ';'];
-    } else if (context == IdentifierContext.fieldDeclaration) {
-      followingValues = [';', '=', ',', '}'];
     } else if (context == IdentifierContext.enumDeclaration) {
       followingValues = ['{'];
     } else if (context == IdentifierContext.enumValueDeclaration) {
@@ -2097,9 +2017,6 @@
     } else if (context == IdentifierContext.localFunctionDeclaration ||
         context == IdentifierContext.localFunctionDeclarationContinuation) {
       followingValues = ['.', '(', '{', '=>'];
-    } else if (context == IdentifierContext.methodDeclaration ||
-        context == IdentifierContext.methodDeclarationContinuation) {
-      followingValues = ['.', '(', '{', '=>'];
     } else if (context == IdentifierContext.topLevelFunctionDeclaration) {
       followingValues = ['(', '{', '=>'];
     } else if (context == IdentifierContext.topLevelVariableDeclaration) {
@@ -2160,9 +2077,7 @@
     // could create a method to test whether a given token matches one of the
     // patterns.
     List<String> initialKeywords;
-    if (context == IdentifierContext.fieldDeclaration) {
-      initialKeywords = classMemberKeywords();
-    } else if (context == IdentifierContext.enumDeclaration) {
+    if (context == IdentifierContext.enumDeclaration) {
       initialKeywords = topLevelKeywords();
     } else if (context == IdentifierContext.formalParameterDeclaration) {
       initialKeywords = topLevelKeywords()
@@ -2180,10 +2095,6 @@
     } else if (context ==
         IdentifierContext.localFunctionDeclarationContinuation) {
       initialKeywords = statementKeywords();
-    } else if (context == IdentifierContext.methodDeclaration) {
-      initialKeywords = classMemberKeywords();
-    } else if (context == IdentifierContext.methodDeclarationContinuation) {
-      initialKeywords = classMemberKeywords();
     } else if (context == IdentifierContext.topLevelFunctionDeclaration) {
       initialKeywords = topLevelKeywords();
     } else if (context == IdentifierContext.topLevelVariableDeclaration) {
@@ -6209,54 +6120,29 @@
           staticToken, covariantToken, varFinalOrConst, beforeType);
     }
 
-    bool looksLikeMethod = getOrSet != null ||
+    if (getOrSet != null ||
         identical(value, '(') ||
         identical(value, '=>') ||
-        identical(value, '{');
-    if (token == beforeStart && !looksLikeMethod) {
-      // Ensure we make progress.
+        identical(value, '{')) {
+      token = parseMethod(
+          beforeStart,
+          externalToken,
+          staticToken,
+          covariantToken,
+          varFinalOrConst,
+          beforeType,
+          typeInfo,
+          getOrSet,
+          token);
+    } else if (token == beforeStart) {
       // TODO(danrubel): Provide a more specific error message for extra ';'.
       reportRecoverableErrorWithToken(next, fasta.templateExpectedClassMember);
       listener.handleInvalidMember(next);
+      // Ensure we make progress.
       token = next;
     } else {
-      // Looks like a partial declaration.
-      reportRecoverableError(
-          next, fasta.templateExpectedIdentifier.withArguments(next));
-      // Insert a synthetic identifier and continue parsing.
-      if (!next.isIdentifier) {
-        rewriter.insertTokenAfter(
-            token,
-            new SyntheticStringToken(
-                TokenType.IDENTIFIER,
-                '#synthetic_identifier_${next.charOffset}',
-                next.charOffset,
-                0));
-      }
-
-      if (looksLikeMethod) {
-        token = parseMethod(
-            beforeStart,
-            externalToken,
-            staticToken,
-            covariantToken,
-            varFinalOrConst,
-            beforeType,
-            typeInfo,
-            getOrSet,
-            token);
-      } else {
-        token = parseFields(
-            beforeStart,
-            externalToken,
-            staticToken,
-            covariantToken,
-            varFinalOrConst,
-            beforeType,
-            typeInfo,
-            token,
-            false);
-      }
+      token = parseFields(beforeStart, externalToken, staticToken,
+          covariantToken, varFinalOrConst, beforeType, typeInfo, token, false);
     }
 
     listener.endMember();
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
index 47471e5..23a9329 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
@@ -219,7 +219,7 @@
         !_analyzerSubtypeOf(inferrer, inferredType, returnOrYieldContext)) {
       // If the inferred return type isn't a subtype of the context, we use the
       // context.
-      inferredType = returnOrYieldContext;
+      inferredType = greatestClosure(inferrer.coreTypes, returnOrYieldContext);
     }
 
     return _wrapAsyncOrGenerator(inferrer, inferredType);
diff --git a/pkg/front_end/testcases/external_import.dart.direct.expect b/pkg/front_end/testcases/external_import.dart.direct.expect
index 145e77a..b262abf 100644
--- a/pkg/front_end/testcases/external_import.dart.direct.expect
+++ b/pkg/front_end/testcases/external_import.dart.direct.expect
@@ -3,5 +3,6 @@
 @dart._internal::ExternalName::•("file:///usr/local/somewhere")
 library;
 import self as self;
+import "dart:_internal" as _in;
 
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/external_import.dart.direct.transformed.expect b/pkg/front_end/testcases/external_import.dart.direct.transformed.expect
index 145e77a..b262abf 100644
--- a/pkg/front_end/testcases/external_import.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/external_import.dart.direct.transformed.expect
@@ -3,5 +3,6 @@
 @dart._internal::ExternalName::•("file:///usr/local/somewhere")
 library;
 import self as self;
+import "dart:_internal" as _in;
 
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/external_import.dart.outline.expect b/pkg/front_end/testcases/external_import.dart.outline.expect
index d48db80..b446720 100644
--- a/pkg/front_end/testcases/external_import.dart.outline.expect
+++ b/pkg/front_end/testcases/external_import.dart.outline.expect
@@ -3,6 +3,7 @@
 @dart._internal::ExternalName::•("file:///usr/local/somewhere")
 library;
 import self as self;
+import "dart:_internal" as _in;
 
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/external_import.dart.strong.expect b/pkg/front_end/testcases/external_import.dart.strong.expect
index 145e77a..b262abf 100644
--- a/pkg/front_end/testcases/external_import.dart.strong.expect
+++ b/pkg/front_end/testcases/external_import.dart.strong.expect
@@ -3,5 +3,6 @@
 @dart._internal::ExternalName::•("file:///usr/local/somewhere")
 library;
 import self as self;
+import "dart:_internal" as _in;
 
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/external_import.dart.strong.transformed.expect b/pkg/front_end/testcases/external_import.dart.strong.transformed.expect
index 145e77a..b262abf 100644
--- a/pkg/front_end/testcases/external_import.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/external_import.dart.strong.transformed.expect
@@ -3,5 +3,6 @@
 @dart._internal::ExternalName::•("file:///usr/local/somewhere")
 library;
 import self as self;
+import "dart:_internal" as _in;
 
 static method main() → dynamic {}
diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md
index 0cfe661..f87de3d 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -902,11 +902,22 @@
   List<[FieldReference, ConstantReference]> values;
 }
 
-type TearOffConstant extends Constant {
+type PartialInstantiationConstant extends Constant {
   Byte tag = 8;
+  ConstantReference tearOffConstant;
+  List<DartType> typeArguments;
+}
+
+type TearOffConstant extends Constant {
+  Byte tag = 9;
   CanonicalNameReference staticProcedureReference;
 }
 
+type TypeLiteralConstant extends Constant {
+  Byte tag = 10;
+  DartType type;
+}
+
 abstract type Statement extends Node {}
 
 type ExpressionStatement extends Statement {
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index d4983da..4d44b72 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -409,6 +409,7 @@
   accept(TreeVisitor v) => v.visitLibrary(this);
 
   visitChildren(Visitor v) {
+    visitList(annotations, v);
     visitList(dependencies, v);
     visitList(parts, v);
     visitList(typedefs, v);
@@ -418,6 +419,7 @@
   }
 
   transformChildren(Transformer v) {
+    transformList(annotations, v, this);
     transformList(dependencies, v, this);
     transformList(parts, v, this);
     transformList(typedefs, v, this);
@@ -5386,6 +5388,34 @@
   }
 }
 
+class PartialInstantiationConstant extends Constant {
+  final TearOffConstant tearOffConstant;
+  final List<DartType> types;
+
+  PartialInstantiationConstant(this.tearOffConstant, this.types);
+
+  visitChildren(Visitor v) {
+    tearOffConstant.acceptReference(v);
+    visitList(types, v);
+  }
+
+  accept(ConstantVisitor v) => v.visitPartialInstantiationConstant(this);
+  acceptReference(Visitor v) =>
+      v.visitPartialInstantiationConstantReference(this);
+
+  String toString() {
+    return '${runtimeType}(${tearOffConstant.procedure}<${types.join(', ')}>)';
+  }
+
+  int get hashCode => tearOffConstant.hashCode ^ listHashCode(types);
+
+  bool operator ==(Object other) {
+    return other is PartialInstantiationConstant &&
+        other.tearOffConstant == tearOffConstant &&
+        listEquals(other.types, types);
+  }
+}
+
 class TearOffConstant extends Constant {
   final Reference procedureReference;
 
diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart
index 6749c74..bfdf151 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -215,6 +215,14 @@
           fieldValues[fieldRef] = constant;
         }
         return new InstanceConstant(classReference, typeArguments, fieldValues);
+      case ConstantTag.PartialInstantiationConstant:
+        final tearOffConstant = readConstantReference() as TearOffConstant;
+        final int length = readUInt();
+        final List<DartType> types = new List<DartType>(length);
+        for (int i = 0; i < length; i++) {
+          types[i] = readDartType();
+        }
+        return new PartialInstantiationConstant(tearOffConstant, types);
       case ConstantTag.TearOffConstant:
         final Reference reference = readCanonicalNameReference().getReference();
         return new TearOffConstant.byReference(reference);
diff --git a/pkg/kernel/lib/binary/ast_to_binary.dart b/pkg/kernel/lib/binary/ast_to_binary.dart
index 6d4c937..3c8dc01 100644
--- a/pkg/kernel/lib/binary/ast_to_binary.dart
+++ b/pkg/kernel/lib/binary/ast_to_binary.dart
@@ -175,6 +175,14 @@
         writeCanonicalNameReference(fieldRef.canonicalName);
         writeConstantReference(value);
       });
+    } else if (constant is PartialInstantiationConstant) {
+      writeByte(ConstantTag.PartialInstantiationConstant);
+      writeConstantReference(constant.tearOffConstant);
+      final int length = constant.types.length;
+      writeUInt30(length);
+      for (int i = 0; i < length; ++i) {
+        writeDartType(constant.types[i]);
+      }
     } else if (constant is TearOffConstant) {
       writeByte(ConstantTag.TearOffConstant);
       writeCanonicalNameReference(constant.procedure.canonicalName);
@@ -412,7 +420,23 @@
 
       // RList<UInt32> nodeReferences
       if (subsection.nodeToReferenceId != null) {
-        for (var nodeOffset in subsection.offsetsOfReferencedNodes) {
+        final offsets = subsection.offsetsOfReferencedNodes;
+        for (int i = 0; i < offsets.length; ++i) {
+          final nodeOffset = offsets[i];
+          if (nodeOffset < 0) {
+            // Dangling reference.
+            // Find a node which was referenced to report meaningful error.
+            Node referencedNode;
+            subsection.nodeToReferenceId.forEach((node, id) {
+              if (id == i) {
+                referencedNode = node;
+              }
+            });
+            throw 'Unable to write reference to node'
+                ' ${referencedNode.runtimeType} $referencedNode'
+                ' from metadata ${subsection.repository.tag}'
+                ' (node is not written into kernel binary)';
+          }
           writeUInt32(nodeOffset);
         }
         writeUInt32(subsection.offsetsOfReferencedNodes.length);
@@ -1897,6 +1921,19 @@
   }
 
   @override
+  void visitPartialInstantiationConstant(PartialInstantiationConstant node) {
+    throw new UnsupportedError(
+        'serialization of PartialInstantiationConstants ');
+  }
+
+  @override
+  void visitPartialInstantiationConstantReference(
+      PartialInstantiationConstant node) {
+    throw new UnsupportedError(
+        'serialization of PartialInstantiationConstant references');
+  }
+
+  @override
   void visitTearOffConstant(TearOffConstant node) {
     throw new UnsupportedError('serialization of TearOffConstants ');
   }
@@ -2257,6 +2294,6 @@
       : nodeToReferenceId =
             nodeToReferenceId.isNotEmpty ? nodeToReferenceId : null,
         offsetsOfReferencedNodes = nodeToReferenceId.isNotEmpty
-            ? new List<int>.filled(nodeToReferenceId.length, 0)
+            ? new List<int>.filled(nodeToReferenceId.length, -1)
             : null;
 }
diff --git a/pkg/kernel/lib/binary/tag.dart b/pkg/kernel/lib/binary/tag.dart
index e55935e..bc70203 100644
--- a/pkg/kernel/lib/binary/tag.dart
+++ b/pkg/kernel/lib/binary/tag.dart
@@ -147,6 +147,7 @@
   static const int MapConstant = 5;
   static const int ListConstant = 6;
   static const int InstanceConstant = 7;
-  static const int TearOffConstant = 8;
-  static const int TypeLiteralConstant = 9;
+  static const int PartialInstantiationConstant = 8;
+  static const int TearOffConstant = 9;
+  static const int TypeLiteralConstant = 10;
 }
diff --git a/pkg/kernel/lib/clone.dart b/pkg/kernel/lib/clone.dart
index b70521e..c104afe 100644
--- a/pkg/kernel/lib/clone.dart
+++ b/pkg/kernel/lib/clone.dart
@@ -345,7 +345,8 @@
       switchCases[switchCase] = new SwitchCase(
           switchCase.expressions.map(clone).toList(),
           new List<int>.from(switchCase.expressionOffsets),
-          null);
+          null,
+          isDefault: switchCase.isDefault);
     }
     return new SwitchStatement(
         clone(node.expression), node.cases.map(clone).toList());
diff --git a/pkg/kernel/lib/target/targets.dart b/pkg/kernel/lib/target/targets.dart
index c7efa89..ec9a8aa 100644
--- a/pkg/kernel/lib/target/targets.dart
+++ b/pkg/kernel/lib/target/targets.dart
@@ -22,13 +22,11 @@
   final bool syncAsync;
   final List<ProgramRoot> programRoots;
   final Uri kernelRuntime;
-  final bool allowDartInternalImport;
 
   TargetFlags(
       {this.strongMode: false,
       this.treeShake: false,
       this.syncAsync: false,
-      this.allowDartInternalImport: false,
       this.programRoots: const <ProgramRoot>[],
       this.kernelRuntime});
 }
diff --git a/pkg/kernel/lib/target/vm.dart b/pkg/kernel/lib/target/vm.dart
index 7fa5ec3..322d2c5 100644
--- a/pkg/kernel/lib/target/vm.dart
+++ b/pkg/kernel/lib/target/vm.dart
@@ -58,16 +58,6 @@
       ];
 
   @override
-  bool allowPlatformPrivateLibraryAccess(Uri importer, Uri imported) {
-    if (flags.allowDartInternalImport &&
-        (imported.scheme == 'dart') &&
-        (imported.path == '_internal')) {
-      return true;
-    }
-    return super.allowPlatformPrivateLibraryAccess(importer, imported);
-  }
-
-  @override
   void performModularTransformationsOnLibraries(
       CoreTypes coreTypes, ClassHierarchy hierarchy, List<Library> libraries,
       {void logger(String msg)}) {
diff --git a/pkg/kernel/lib/transformations/constants.dart b/pkg/kernel/lib/transformations/constants.dart
index 84ae345..c618d81 100644
--- a/pkg/kernel/lib/transformations/constants.dart
+++ b/pkg/kernel/lib/transformations/constants.dart
@@ -729,6 +729,22 @@
     return canonicalize(backend.buildSymbolConstant(value));
   }
 
+  visitInstantiation(Instantiation node) {
+    final Constant constant = evaluate(node.expression);
+    if (constant is TearOffConstant) {
+      if (node.typeArguments.length ==
+          constant.procedure.function.typeParameters.length) {
+        return canonicalize(
+            new PartialInstantiationConstant(constant, node.typeArguments));
+      }
+      throw new ConstantEvaluationError(
+          'The number of type arguments supplied in the partial instantiation '
+          'does not match the number of type arguments of the $constant.');
+    }
+    throw new ConstantEvaluationError(
+        'Only tear-off constants can be partially instantiated.');
+  }
+
   // Helper methods:
 
   void ensureIsSubtype(Constant constant, DartType type) {
diff --git a/pkg/kernel/lib/visitor.dart b/pkg/kernel/lib/visitor.dart
index fa6337c..cde0c92 100644
--- a/pkg/kernel/lib/visitor.dart
+++ b/pkg/kernel/lib/visitor.dart
@@ -283,6 +283,8 @@
   R visitMapConstant(MapConstant node) => defaultConstant(node);
   R visitListConstant(ListConstant node) => defaultConstant(node);
   R visitInstanceConstant(InstanceConstant node) => defaultConstant(node);
+  R visitPartialInstantiationConstant(PartialInstantiationConstant node) =>
+      defaultConstant(node);
   R visitTearOffConstant(TearOffConstant node) => defaultConstant(node);
   R visitTypeLiteralConstant(TypeLiteralConstant node) => defaultConstant(node);
 }
@@ -334,6 +336,8 @@
   R visitMapConstant(MapConstant node) => defaultConstant(node);
   R visitListConstant(ListConstant node) => defaultConstant(node);
   R visitInstanceConstant(InstanceConstant node) => defaultConstant(node);
+  R visitPartialInstantiationConstant(PartialInstantiationConstant node) =>
+      defaultConstant(node);
   R visitTearOffConstant(TearOffConstant node) => defaultConstant(node);
   R visitTypeLiteralConstant(TypeLiteralConstant node) => defaultConstant(node);
 
@@ -359,6 +363,9 @@
       defaultConstantReference(node);
   R visitInstanceConstantReference(InstanceConstant node) =>
       defaultConstantReference(node);
+  R visitPartialInstantiationConstantReference(
+          PartialInstantiationConstant node) =>
+      defaultConstantReference(node);
   R visitTearOffConstantReference(TearOffConstant node) =>
       defaultConstantReference(node);
   R visitTypeLiteralConstantReference(TypeLiteralConstant node) =>
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 2ae5e58..7b88bf2 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -150,6 +150,25 @@
 analyzer/test/*: Skip # Issue 26813
 analyzer/tool/*: Skip # Issue 26813
 
+# ILLEGAL_ASYNC_RETURN_TYPE warnings appear on some subset of Linux configurations,
+# but do not always fail.
+[ $compiler == dart2analyzer && $system == linux && !$preview_dart_2 && !$strong ]
+analyzer/test/src/dart/ast/ast_test: StaticWarning, Pass
+analyzer/test/src/summary/expr_builder_test: StaticWarning, Pass
+analyzer/test/src/summary/resynthesize_ast_test: StaticWarning, Pass
+analyzer/test/src/summary/resynthesize_kernel_test: StaticWarning, Pass
+front_end/test/incremental_dart2js_load_from_dill_test: StaticWarning, Pass
+front_end/test/incremental_load_from_dill_test: StaticWarning, Pass
+
+# ILLEGAL_ASYNC_RETURN_TYPE warnings
+[ $compiler == dart2analyzer && !$preview_dart_2 && !$strong && ($system == macos || $system == windows) ]
+analyzer/test/src/dart/ast/ast_test: StaticWarning
+analyzer/test/src/summary/expr_builder_test: StaticWarning
+analyzer/test/src/summary/resynthesize_ast_test: StaticWarning
+analyzer/test/src/summary/resynthesize_kernel_test: StaticWarning
+front_end/test/incremental_dart2js_load_from_dill_test: StaticWarning
+front_end/test/incremental_load_from_dill_test: StaticWarning
+
 # Don't analyze tests in strong mode yet
 [ $compiler == dart2analyzer && $strong ]
 *: Skip # Issue 28649
@@ -214,9 +233,6 @@
 analyzer/test/src/summary/resynthesize_ast_test: Pass, Slow
 analyzer/test/src/task/strong/front_end_inference_test: Pass, Slow
 
-[ $runtime == vm && $use_sdk ]
-kernel/test/metadata_test: Skip # Issue 31900
-
 # Timeout. These tests do not run efficiently on our simulator or low-end
 # devices.
 [ $runtime == vm && ($arch == armv5te || $arch == armv6 || $arch == simarm || $arch == simarm64 || $arch == simarmv5te || $arch == simarmv6 || $arch == simdbc64) ]
diff --git a/pkg/vm/bin/kernel_service.dart b/pkg/vm/bin/kernel_service.dart
index e146590..c3b0f6b 100644
--- a/pkg/vm/bin/kernel_service.dart
+++ b/pkg/vm/bin/kernel_service.dart
@@ -49,14 +49,10 @@
 //   1 - Update in-memory file system with in-memory sources (used by tests).
 //   2 - Accept last compilation result.
 //   3 - APP JIT snapshot training run for kernel_service.
-//   4 - Allows for `dart:_internal` to be imported (used by tests).
 const int kCompileTag = 0;
 const int kUpdateSourcesTag = 1;
 const int kAcceptTag = 2;
 const int kTrainTag = 3;
-const int kAllowDartInternalImportTag = 4;
-
-bool allowDartInternalImport = false;
 
 abstract class Compiler {
   final FileSystem fileSystem;
@@ -80,16 +76,13 @@
       print("DFE: platformKernelPath: ${platformKernelPath}");
       print("DFE: strongMode: ${strongMode}");
       print("DFE: syncAsync: ${syncAsync}");
-      print("DFE: allowDartInternalImport: ${allowDartInternalImport}");
     }
 
     options = new CompilerOptions()
       ..strongMode = strongMode
       ..fileSystem = fileSystem
-      ..target = new VmTarget(new TargetFlags(
-          strongMode: strongMode,
-          syncAsync: syncAsync,
-          allowDartInternalImport: allowDartInternalImport))
+      ..target = new VmTarget(
+          new TargetFlags(strongMode: strongMode, syncAsync: syncAsync))
       ..packagesFileUri = packagesUri
       ..sdkSummary = platformKernelPath
       ..verbose = verbose
@@ -101,7 +94,7 @@
           case Severity.internalProblem:
             // TODO(sigmund): support emitting code with errors as long as they
             // are handled in the generated code (issue #30194).
-            printMessage = true;
+            printMessage = false; // errors are printed by VM
             errors.add(message.formatted);
             break;
           case Severity.nit:
@@ -288,15 +281,6 @@
     }
     port.send(new CompilationResult.ok(null).toResponse());
     return;
-  } else if (tag == kAllowDartInternalImportTag) {
-    compiler = lookupIncrementalCompiler(isolateId);
-    assert(
-        lookupIncrementalCompiler(isolateId) == null,
-        "allowDartInternalImport must be set before creating a compiler"
-        " instance.");
-    allowDartInternalImport = true;
-    port.send(new CompilationResult.ok(null).toResponse());
-    return;
   }
 
   // script should only be null for kUpdateSourcesTag.
@@ -332,8 +316,6 @@
     Component component = await compiler.compile(script);
 
     if (compiler.errors.isNotEmpty) {
-      // TODO(sigmund): the compiler prints errors to the console, so we
-      // shouldn't print those messages again here.
       result = new CompilationResult.errors(compiler.errors);
     } else {
       // We serialize the component excluding vm_platform.dill because the VM has
diff --git a/pkg/vm/lib/bytecode/constant_pool.dart b/pkg/vm/lib/bytecode/constant_pool.dart
index 770ff55..25da76d 100644
--- a/pkg/vm/lib/bytecode/constant_pool.dart
+++ b/pkg/vm/lib/bytecode/constant_pool.dart
@@ -17,6 +17,8 @@
   List<ConstantPoolEntry>
 }
 
+type ConstantIndex = UInt;
+
 abstract type ConstantPoolEntry {
   Byte tag;
 }
@@ -57,13 +59,13 @@
 type ConstantICData extends ConstantPoolEntry {
   Byte tag = 7;
   StringReference targetName;
-  UInt argDescConstantIndex;
+  ConstantIndex argDesc;
 }
 
 type ConstantStaticICData extends ConstantPoolEntry {
   Byte tag = 8;
   CanonicalNameReference target;
-  UInt argDescConstantIndex;
+  ConstantIndex argDesc;
 }
 
 type ConstantField extends ConstantPoolEntry {
@@ -104,14 +106,14 @@
 type ConstantList extends ConstantPoolEntry {
   Byte tag = 16;
   NodeReference typeArg;
-  List<UInt> entries;
+  List<ConstantIndex> entries;
 }
 
 type ConstantInstance extends ConstantPoolEntry {
   Byte tag = 17;
   CanonicalNameReference class;
   UInt typeArgumentsConstantIndex;
-  List<Pair<CanonicalNameReference, UInt>> fieldValues;
+  List<Pair<CanonicalNameReference, ConstantIndex>> fieldValues;
 }
 
 type ConstantSymbol extends ConstantPoolEntry {
@@ -119,6 +121,12 @@
   StringReference value;
 }
 
+type ConstantTypeArgumentsForInstanceAllocation extends ConstantPoolEntry {
+  Byte tag = 19;
+  CanonicalNameReference instantiatingClass;
+  ConstantIndex typeArguments;
+}
+
 */
 
 enum ConstantTag {
@@ -141,6 +149,7 @@
   kList,
   kInstance,
   kSymbol,
+  kTypeArgumentsForInstanceAllocation,
 }
 
 abstract class ConstantPoolEntry {
@@ -196,6 +205,9 @@
         return new ConstantInstance.readFromBinary(source);
       case ConstantTag.kSymbol:
         return new ConstantSymbol.readFromBinary(source);
+      case ConstantTag.kTypeArgumentsForInstanceAllocation:
+        return new ConstantTypeArgumentsForInstanceAllocation.readFromBinary(
+            source);
     }
     throw 'Unexpected constant tag $tag';
   }
@@ -798,6 +810,49 @@
       other is ConstantSymbol && this.value == other.value;
 }
 
+class ConstantTypeArgumentsForInstanceAllocation extends ConstantPoolEntry {
+  final Reference _instantiatingClassRef;
+  final int _typeArgumentsConstantIndex;
+
+  Class get instantiatingClass => _instantiatingClassRef.asClass;
+
+  ConstantTypeArgumentsForInstanceAllocation(
+      Class instantiatingClass, int typeArgumentsConstantIndex)
+      : this.byReference(
+            instantiatingClass.reference, typeArgumentsConstantIndex);
+  ConstantTypeArgumentsForInstanceAllocation.byReference(
+      this._instantiatingClassRef, this._typeArgumentsConstantIndex);
+
+  @override
+  ConstantTag get tag => ConstantTag.kTypeArgumentsForInstanceAllocation;
+
+  @override
+  void writeValueToBinary(BinarySink sink) {
+    sink.writeCanonicalNameReference(
+        getCanonicalNameOfClass(instantiatingClass));
+    sink.writeUInt30(_typeArgumentsConstantIndex);
+  }
+
+  ConstantTypeArgumentsForInstanceAllocation.readFromBinary(BinarySource source)
+      : _instantiatingClassRef =
+            source.readCanonicalNameReference().getReference(),
+        _typeArgumentsConstantIndex = source.readUInt();
+
+  @override
+  String toString() =>
+      'TypeArgumentsForInstanceAllocation $instantiatingClass type-args CP#$_typeArgumentsConstantIndex';
+
+  @override
+  int get hashCode =>
+      instantiatingClass.hashCode * 31 + _typeArgumentsConstantIndex;
+
+  @override
+  bool operator ==(other) =>
+      other is ConstantTypeArgumentsForInstanceAllocation &&
+      this.instantiatingClass == other.instantiatingClass &&
+      this._typeArgumentsConstantIndex == other._typeArgumentsConstantIndex;
+}
+
 class ConstantPool {
   final List<ConstantPoolEntry> entries = <ConstantPoolEntry>[];
   final Map<ConstantPoolEntry, int> _canonicalizationCache =
diff --git a/pkg/vm/lib/bytecode/gen_bytecode.dart b/pkg/vm/lib/bytecode/gen_bytecode.dart
index 1fd4ebe..3763ecc 100644
--- a/pkg/vm/lib/bytecode/gen_bytecode.dart
+++ b/pkg/vm/lib/bytecode/gen_bytecode.dart
@@ -10,7 +10,6 @@
 import 'package:kernel/library_index.dart' show LibraryIndex;
 import 'package:kernel/transformations/constants.dart'
     show ConstantEvaluator, ConstantsBackend, EvaluationEnvironment;
-import 'package:kernel/type_algebra.dart' show Substitution;
 import 'package:kernel/type_environment.dart' show TypeEnvironment;
 import 'package:kernel/vm/constants_native_effects.dart'
     show VmConstantsBackend;
@@ -165,7 +164,6 @@
     asm.emitPush(locals.thisVarIndex);
     initializer.accept(this);
 
-    // TODO(alexmarkov): field guards?
     // TODO(alexmarkov): assignability check
 
     final int cpIndex = cp.add(new ConstantFieldOffset(field));
@@ -240,20 +238,28 @@
     return function != null && function.typeParameters.isNotEmpty;
   }
 
-  void _genTypeArguments(List<DartType> typeArgs) {
-    final int typeArgsCPIndex = cp.add(new ConstantTypeArguments(typeArgs));
+  void _genTypeArguments(List<DartType> typeArgs, {Class instantiatingClass}) {
+    int typeArgsCPIndex = cp.add(new ConstantTypeArguments(typeArgs));
+    if (instantiatingClass != null) {
+      typeArgsCPIndex = cp.add(new ConstantTypeArgumentsForInstanceAllocation(
+          instantiatingClass, typeArgsCPIndex));
+    }
     if (typeArgs.isEmpty || !hasTypeParameters(typeArgs)) {
       asm.emitPushConstant(typeArgsCPIndex);
     } else {
       // TODO(alexmarkov): try to reuse instantiator type arguments
-      // TODO(alexmarkov): do not load instantiator type arguments / function type
-      // arguments if they are not needed for these particular [typeArgs].
-      _genPushInstantiatorTypeArguments();
-      _genPushFunctionTypeArguments();
+      _genPushInstantiatorAndFunctionTypeArguments(typeArgs);
       asm.emitInstantiateTypeArgumentsTOS(1, typeArgsCPIndex);
     }
   }
 
+  void _genPushInstantiatorAndFunctionTypeArguments(List<DartType> types) {
+    // TODO(alexmarkov): do not load instantiator type arguments / function type
+    // arguments if they are not needed for these particular [types].
+    _genPushInstantiatorTypeArguments();
+    _genPushFunctionTypeArguments();
+  }
+
   void _genPushInstantiatorTypeArguments() {
     // TODO(alexmarkov): access from closures to up-level type arguments.
     if ((enclosingMember.isInstanceMember || enclosingMember is Constructor) &&
@@ -276,24 +282,6 @@
     }
   }
 
-  List<DartType> _flattenTypeArgumentsForInstantiation(
-      Class instantiatedClass, List<DartType> typeArgs) {
-    assert(typeArgs.length == instantiatedClass.typeParameters.length);
-
-    List<DartType> flatTypeArgs;
-    final supertype = instantiatedClass.supertype;
-    if (supertype == null) {
-      flatTypeArgs = <DartType>[];
-    } else {
-      final substitution =
-          Substitution.fromPairs(instantiatedClass.typeParameters, typeArgs);
-      flatTypeArgs = _flattenTypeArgumentsForInstantiation(supertype.classNode,
-          substitution.substituteSupertype(supertype).typeArguments);
-    }
-    flatTypeArgs.addAll(typeArgs);
-    return flatTypeArgs;
-  }
-
   /// Generates bool condition. Returns `true` if condition is negated.
   bool _genCondition(Node condition) {
     bool negated = false;
@@ -415,10 +403,7 @@
       return;
     }
     if (hasTypeParameters([node.type])) {
-      // TODO(alexmarkov): do not load instantiator type arguments / function
-      // type arguments if they are not needed for this particular type.
-      _genPushInstantiatorTypeArguments();
-      _genPushFunctionTypeArguments();
+      _genPushInstantiatorAndFunctionTypeArguments([node.type]);
     } else {
       _genPushNull(); // Instantiator type arguments.
       _genPushNull(); // Function type arguments.
@@ -480,9 +465,8 @@
     final classIndex = cp.add(new ConstantClass(constructedClass));
 
     if (hasInstantiatorTypeArguments(constructedClass)) {
-      List<DartType> flatTypeArgs = _flattenTypeArgumentsForInstantiation(
-          constructedClass, node.arguments.types);
-      _genTypeArguments(flatTypeArgs);
+      _genTypeArguments(node.arguments.types,
+          instantiatingClass: constructedClass);
       asm.emitPushConstant(cp.add(new ConstantClass(constructedClass)));
       asm.emitAllocateT();
     } else {
@@ -540,10 +524,7 @@
     // TODO(alexmarkov): generate _simpleInstanceOf if possible
 
     if (hasTypeParameters([node.type])) {
-      // TODO(alexmarkov): do not load instantiator type arguments / function type
-      // arguments if they are not needed for this particular type.
-      _genPushInstantiatorTypeArguments();
-      _genPushFunctionTypeArguments();
+      _genPushInstantiatorAndFunctionTypeArguments([node.type]);
     } else {
       _genPushNull(); // Instantiator type arguments.
       _genPushNull(); // Function type arguments.
@@ -873,10 +854,7 @@
     if (!hasTypeParameters([type])) {
       asm.emitPushConstant(typeCPIndex);
     } else {
-      // TODO(alexmarkov): do not load instantiator type arguments / function type
-      // arguments if they are not needed for this particular [type].
-      _genPushInstantiatorTypeArguments();
-      _genPushFunctionTypeArguments();
+      _genPushInstantiatorAndFunctionTypeArguments([type]);
       asm.emitInstantiateType(typeCPIndex);
     }
   }
diff --git a/pkg/vm/testcases/bytecode/instance_creation.dart.expect b/pkg/vm/testcases/bytecode/instance_creation.dart.expect
index e4dca47..b026f3c0 100644
--- a/pkg/vm/testcases/bytecode/instance_creation.dart.expect
+++ b/pkg/vm/testcases/bytecode/instance_creation.dart.expect
@@ -216,39 +216,41 @@
 Bytecode {
   Entry                2
   CheckStack
-  PushConstant         CP#1
+  PushConstant         CP#2
   PushConstant         CP#0
   AllocateT
   StoreLocal           r0
   Push                 r0
-  PushConstant         CP#2
-  PushConstant         CP#4
-  IndirectStaticCall   2, CP#3
-  Drop1
-  Drop1
-  PushConstant         CP#6
+  PushConstant         CP#3
   PushConstant         CP#5
+  IndirectStaticCall   2, CP#4
+  Drop1
+  Drop1
+  PushConstant         CP#8
+  PushConstant         CP#6
   AllocateT
   StoreLocal           r1
   Push                 r1
-  PushConstant         CP#8
-  IndirectStaticCall   1, CP#7
+  PushConstant         CP#10
+  IndirectStaticCall   1, CP#9
   Drop1
   Drop1
-  PushConstant         CP#9
+  PushConstant         CP#11
   ReturnTOS
 }
 ConstantPool {
   [0] = Class #lib::A
-  [1] = TypeArgs [dart.core::int, dart.core::String]
-  [2] = String 'hi'
-  [3] = ArgDesc num-args 2, num-type-args 0, names []
-  [4] = StaticICData target '#lib::A::', arg-desc CP#3
-  [5] = Class #lib::B
-  [6] = TypeArgs [dart.core::List<dart.core::int>, dart.core::String, dart.core::int]
-  [7] = ArgDesc num-args 1, num-type-args 0, names []
-  [8] = StaticICData target '#lib::B::', arg-desc CP#7
-  [9] = Null
+  [1] = TypeArgs []
+  [2] = TypeArgumentsForInstanceAllocation #lib::A type-args CP#1
+  [3] = String 'hi'
+  [4] = ArgDesc num-args 2, num-type-args 0, names []
+  [5] = StaticICData target '#lib::A::', arg-desc CP#4
+  [6] = Class #lib::B
+  [7] = TypeArgs [dart.core::int]
+  [8] = TypeArgumentsForInstanceAllocation #lib::B type-args CP#7
+  [9] = ArgDesc num-args 1, num-type-args 0, names []
+  [10] = StaticICData target '#lib::B::', arg-desc CP#9
+  [11] = Null
 }
 ]static method foo2() → void {
   new self::A::•("hi");
@@ -258,26 +260,27 @@
 Bytecode {
   Entry                1
   CheckStack
-  PushConstant         CP#2
+  PushConstant         CP#3
   Push                 FP[-5]
-  InstantiateTypeArgumentsTOS 1, CP#1
+  InstantiateTypeArgumentsTOS 1, CP#2
   PushConstant         CP#0
   AllocateT
   StoreLocal           r0
   Push                 r0
-  PushConstant         CP#4
-  IndirectStaticCall   1, CP#3
+  PushConstant         CP#5
+  IndirectStaticCall   1, CP#4
   Drop1
   Drop1
-  PushConstant         CP#2
+  PushConstant         CP#3
   ReturnTOS
 }
 ConstantPool {
   [0] = Class #lib::B
-  [1] = TypeArgs [dart.core::List<dart.core::List<#lib::foo3::T>>, dart.core::String, dart.core::List<#lib::foo3::T>]
-  [2] = Null
-  [3] = ArgDesc num-args 1, num-type-args 0, names []
-  [4] = StaticICData target '#lib::B::', arg-desc CP#3
+  [1] = TypeArgs [dart.core::List<#lib::foo3::T>]
+  [2] = TypeArgumentsForInstanceAllocation #lib::B type-args CP#1
+  [3] = Null
+  [4] = ArgDesc num-args 1, num-type-args 0, names []
+  [5] = StaticICData target '#lib::B::', arg-desc CP#4
 }
 ]static method foo3<T extends core::Object>() → void {
   new self::B::•<core::List<self::foo3::T>>();
diff --git a/runtime/BUILD.gn b/runtime/BUILD.gn
index 6fd1c76..585562d 100644
--- a/runtime/BUILD.gn
+++ b/runtime/BUILD.gn
@@ -197,7 +197,7 @@
   if (defined(invoker.extra_deps)) {
     extra_deps += invoker.extra_deps
   }
-  static_library(target_name) {
+  target(dart_component_kind, target_name) {
     configs += [
                  ":dart_arch_config",
                  ":dart_config",
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index 0d475e9..7e9725e 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -10,6 +10,7 @@
 #include <string.h>
 
 #include <cstdarg>
+#include <memory>
 
 #include "bin/builtin.h"
 #include "bin/console.h"
@@ -144,6 +145,8 @@
   V(vm_snapshot_instructions, vm_snapshot_instructions_filename)               \
   V(isolate_snapshot_data, isolate_snapshot_data_filename)                     \
   V(isolate_snapshot_instructions, isolate_snapshot_instructions_filename)     \
+  V(shared_data, shared_data_filename)                                         \
+  V(shared_instructions, shared_instructions_filename)                         \
   V(assembly, assembly_filename)                                               \
   V(script_snapshot, script_snapshot_filename)                                 \
   V(dependencies, dependencies_filename)                                       \
@@ -1217,6 +1220,30 @@
   }
 }
 
+static std::unique_ptr<MappedMemory> MapFile(const char* filename,
+                                             File::MapType type,
+                                             const uint8_t** buffer) {
+  File* file = File::Open(NULL, filename, File::kRead);
+  if (file == NULL) {
+    Log::PrintErr("Failed to open: %s\n", filename);
+    exit(kErrorExitCode);
+  }
+  RefCntReleaseScope<File> rs(file);
+  intptr_t length = file->Length();
+  if (length == 0) {
+    // Can't map an empty file.
+    *buffer = NULL;
+    return NULL;
+  }
+  MappedMemory* mapping = file->Map(type, 0, length);
+  if (mapping == NULL) {
+    Log::PrintErr("Failed to read: %s\n", filename);
+    exit(kErrorExitCode);
+  }
+  *buffer = reinterpret_cast<const uint8_t*>(mapping->address());
+  return std::unique_ptr<MappedMemory>(mapping);
+}
+
 static void CreateAndWritePrecompiledSnapshot(
     Dart_QualifiedFunctionName* standalone_entry_points) {
   ASSERT(IsSnapshottingForPrecompilation());
@@ -1237,6 +1264,19 @@
   } else {
     ASSERT(snapshot_kind == kAppAOTBlobs);
 
+    const uint8_t* shared_data = NULL;
+    const uint8_t* shared_instructions = NULL;
+    std::unique_ptr<MappedMemory> mapped_shared_data;
+    std::unique_ptr<MappedMemory> mapped_shared_instructions;
+    if (shared_data_filename != NULL) {
+      mapped_shared_data =
+          MapFile(shared_data_filename, File::kReadOnly, &shared_data);
+    }
+    if (shared_instructions_filename != NULL) {
+      mapped_shared_instructions = MapFile(
+          shared_instructions_filename, File::kReadOnly, &shared_instructions);
+    }
+
     uint8_t* vm_snapshot_data_buffer = NULL;
     intptr_t vm_snapshot_data_size = 0;
     uint8_t* vm_snapshot_instructions_buffer = NULL;
@@ -1250,7 +1290,7 @@
         &vm_snapshot_instructions_buffer, &vm_snapshot_instructions_size,
         &isolate_snapshot_data_buffer, &isolate_snapshot_data_size,
         &isolate_snapshot_instructions_buffer,
-        &isolate_snapshot_instructions_size);
+        &isolate_snapshot_instructions_size, shared_data, shared_instructions);
     CHECK_RESULT(result);
 
     WriteFile(vm_snapshot_data_filename, vm_snapshot_data_buffer,
@@ -1319,7 +1359,7 @@
       new IsolateData(script_uri, package_root, package_config, NULL);
   Dart_Isolate isolate = NULL;
   isolate = Dart_CreateIsolate(script_uri, main, isolate_snapshot_data,
-                               isolate_snapshot_instructions, flags,
+                               isolate_snapshot_instructions, NULL, NULL, flags,
                                isolate_data, error);
 
   if (isolate == NULL) {
@@ -1355,30 +1395,6 @@
   return isolate;
 }
 
-static MappedMemory* MapFile(const char* filename,
-                             File::MapType type,
-                             const uint8_t** buffer) {
-  File* file = File::Open(NULL, filename, File::kRead);
-  if (file == NULL) {
-    Log::PrintErr("Failed to open: %s\n", filename);
-    exit(kErrorExitCode);
-  }
-  RefCntReleaseScope<File> rs(file);
-  intptr_t length = file->Length();
-  if (length == 0) {
-    // Can't map an empty file.
-    *buffer = NULL;
-    return NULL;
-  }
-  MappedMemory* mapping = file->Map(type, 0, length);
-  if (mapping == NULL) {
-    Log::PrintErr("Failed to read: %s\n", filename);
-    exit(kErrorExitCode);
-  }
-  *buffer = reinterpret_cast<const uint8_t*>(mapping->address());
-  return mapping;
-}
-
 static int GenerateSnapshotFromKernelProgram(void* kernel_program) {
   ASSERT(SnapshotKindAllowedFromKernel());
 
@@ -1538,10 +1554,10 @@
   init_params.entropy_source = DartUtils::EntropySource;
   init_params.start_kernel_isolate = false;
 
-  MappedMemory* mapped_vm_snapshot_data = NULL;
-  MappedMemory* mapped_vm_snapshot_instructions = NULL;
-  MappedMemory* mapped_isolate_snapshot_data = NULL;
-  MappedMemory* mapped_isolate_snapshot_instructions = NULL;
+  std::unique_ptr<MappedMemory> mapped_vm_snapshot_data;
+  std::unique_ptr<MappedMemory> mapped_vm_snapshot_instructions;
+  std::unique_ptr<MappedMemory> mapped_isolate_snapshot_data;
+  std::unique_ptr<MappedMemory> mapped_isolate_snapshot_instructions;
   if (snapshot_kind == kScript) {
     mapped_vm_snapshot_data =
         MapFile(vm_snapshot_data_filename, File::kReadOnly,
@@ -1585,7 +1601,7 @@
                                               commandline_packages_file, NULL);
   Dart_Isolate isolate = Dart_CreateIsolate(NULL, NULL, isolate_snapshot_data,
                                             isolate_snapshot_instructions, NULL,
-                                            isolate_data, &error);
+                                            NULL, NULL, isolate_data, &error);
   if (isolate == NULL) {
     Log::PrintErr("Error: %s\n", error);
     free(error);
@@ -1652,8 +1668,8 @@
 
     Dart_Isolate isolate = NULL;
     isolate = Dart_CreateIsolate(NULL, NULL, isolate_snapshot_data,
-                                 isolate_snapshot_instructions, &flags,
-                                 isolate_data, &error);
+                                 isolate_snapshot_instructions, NULL, NULL,
+                                 &flags, isolate_data, &error);
     if (isolate == NULL) {
       Log::PrintErr("%s\n", error);
       free(error);
@@ -1744,10 +1760,6 @@
     free(error);
   }
   EventHandler::Stop();
-  delete mapped_vm_snapshot_data;
-  delete mapped_vm_snapshot_instructions;
-  delete mapped_isolate_snapshot_data;
-  delete mapped_isolate_snapshot_instructions;
   return 0;
 }
 
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index d8bbc6f..36e3a24 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -87,6 +87,8 @@
 static char* app_script_uri = NULL;
 static const uint8_t* app_isolate_snapshot_data = NULL;
 static const uint8_t* app_isolate_snapshot_instructions = NULL;
+static const uint8_t* app_isolate_shared_data = NULL;
+static const uint8_t* app_isolate_shared_instructions = NULL;
 
 static Dart_Isolate main_isolate = NULL;
 
@@ -373,7 +375,8 @@
         new IsolateData(uri, package_root, packages_config, app_snapshot);
     isolate = Dart_CreateIsolate(
         DART_KERNEL_ISOLATE_NAME, main, isolate_snapshot_data,
-        isolate_snapshot_instructions, flags, isolate_data, error);
+        isolate_snapshot_instructions, app_isolate_shared_data,
+        app_isolate_shared_instructions, flags, isolate_data, error);
   } else {
     void* kernel_service_program = dfe.LoadKernelServiceProgram();
     ASSERT(kernel_service_program != NULL);
@@ -424,9 +427,10 @@
   IsolateData* isolate_data =
       new IsolateData(script_uri, package_root, packages_config, NULL);
 #if defined(DART_PRECOMPILED_RUNTIME)
-  isolate = Dart_CreateIsolate(script_uri, main, isolate_snapshot_data,
-                               isolate_snapshot_instructions, flags,
-                               isolate_data, error);
+  isolate = Dart_CreateIsolate(
+      script_uri, main, isolate_snapshot_data, isolate_snapshot_instructions,
+      app_isolate_shared_data, app_isolate_shared_instructions, flags,
+      isolate_data, error);
 #else
   // Set the flag to load the vmservice library. If not set, the kernel
   // loader might skip loading it. This is flag is not relevant for the
@@ -454,9 +458,10 @@
     }
     skip_library_load = true;
   } else {
-    isolate = Dart_CreateIsolate(script_uri, main, isolate_snapshot_data,
-                                 isolate_snapshot_instructions, flags,
-                                 isolate_data, error);
+    isolate = Dart_CreateIsolate(
+        script_uri, main, isolate_snapshot_data, isolate_snapshot_instructions,
+        app_isolate_shared_data, app_isolate_shared_instructions, flags,
+        isolate_data, error);
   }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
   if (isolate == NULL) {
@@ -583,9 +588,10 @@
   } else {
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
-    isolate = Dart_CreateIsolate(script_uri, main, isolate_snapshot_data,
-                                 isolate_snapshot_instructions, flags,
-                                 isolate_data, error);
+    isolate = Dart_CreateIsolate(
+        script_uri, main, isolate_snapshot_data, isolate_snapshot_instructions,
+        app_isolate_shared_data, app_isolate_shared_instructions, flags,
+        isolate_data, error);
 #if !defined(DART_PRECOMPILED_RUNTIME)
   }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
@@ -714,7 +720,9 @@
 
 static void GenerateAppAOTSnapshot() {
   if (Options::use_blobs()) {
-    Snapshot::GenerateAppAOTAsBlobs(Options::snapshot_filename());
+    Snapshot::GenerateAppAOTAsBlobs(Options::snapshot_filename(),
+                                    app_isolate_shared_data,
+                                    app_isolate_shared_instructions);
   } else {
     Snapshot::GenerateAppAOTAsAssembly(Options::snapshot_filename());
   }
@@ -1076,6 +1084,19 @@
   app_isolate_snapshot_data = _kDartIsolateSnapshotData;
   app_isolate_snapshot_instructions = _kDartIsolateSnapshotInstructions;
 #else
+  AppSnapshot* shared_blobs = NULL;
+  if (Options::shared_blobs_filename() != NULL) {
+    Log::PrintErr("Shared blobs in the standalone VM are for testing only.\n");
+    shared_blobs =
+        Snapshot::TryReadAppSnapshot(Options::shared_blobs_filename());
+    if (shared_blobs == NULL) {
+      Log::PrintErr("Failed to load: %s\n", Options::shared_blobs_filename());
+      Platform::Exit(kErrorExitCode);
+    }
+    const uint8_t* ignored;
+    shared_blobs->SetBuffers(&ignored, &ignored, &app_isolate_shared_data,
+                             &app_isolate_shared_instructions);
+  }
   AppSnapshot* app_snapshot = Snapshot::TryReadAppSnapshot(script_name);
   if (app_snapshot != NULL) {
     vm_run_app_snapshot = true;
@@ -1181,6 +1202,7 @@
 
 #if !defined(DART_LINK_APP_SNAPSHOT)
   delete app_snapshot;
+  delete shared_blobs;
 #endif
   free(app_script_uri);
 
diff --git a/runtime/bin/main_options.h b/runtime/bin/main_options.h
index 80a4579..d4b46d8 100644
--- a/runtime/bin/main_options.h
+++ b/runtime/bin/main_options.h
@@ -21,6 +21,7 @@
   V(package_root, package_root)                                                \
   V(snapshot, snapshot_filename)                                               \
   V(snapshot_depfile, snapshot_deps_filename)                                  \
+  V(shared_blobs, shared_blobs_filename)                                       \
   V(save_obfuscation_map, obfuscation_map_filename)                            \
   V(save_compilation_trace, save_compilation_trace_filename)                   \
   V(load_compilation_trace, load_compilation_trace_filename)                   \
diff --git a/runtime/bin/run_vm_tests.cc b/runtime/bin/run_vm_tests.cc
index 6446440..8293434 100644
--- a/runtime/bin/run_vm_tests.cc
+++ b/runtime/bin/run_vm_tests.cc
@@ -163,7 +163,7 @@
       script_uri, package_root, packages_config, app_snapshot);
   Dart_Isolate isolate = Dart_CreateIsolate(
       DART_KERNEL_ISOLATE_NAME, main, isolate_snapshot_data,
-      isolate_snapshot_instructions, flags, isolate_data, error);
+      isolate_snapshot_instructions, NULL, NULL, flags, isolate_data, error);
   if (isolate == NULL) {
     delete isolate_data;
     return NULL;
diff --git a/runtime/bin/snapshot_utils.cc b/runtime/bin/snapshot_utils.cc
index 999cbe0..dfceb0e 100644
--- a/runtime/bin/snapshot_utils.cc
+++ b/runtime/bin/snapshot_utils.cc
@@ -360,7 +360,9 @@
 #endif
 }
 
-void Snapshot::GenerateAppAOTAsBlobs(const char* snapshot_filename) {
+void Snapshot::GenerateAppAOTAsBlobs(const char* snapshot_filename,
+                                     const uint8_t* shared_data,
+                                     const uint8_t* shared_instructions) {
   uint8_t* vm_data_buffer = NULL;
   intptr_t vm_data_size = 0;
   uint8_t* vm_instructions_buffer = NULL;
@@ -372,7 +374,8 @@
   Dart_Handle result = Dart_CreateAppAOTSnapshotAsBlobs(
       &vm_data_buffer, &vm_data_size, &vm_instructions_buffer,
       &vm_instructions_size, &isolate_data_buffer, &isolate_data_size,
-      &isolate_instructions_buffer, &isolate_instructions_size);
+      &isolate_instructions_buffer, &isolate_instructions_size, shared_data,
+      shared_instructions);
   if (Dart_IsError(result)) {
     ErrorExit(kErrorExitCode, "%s\n", Dart_GetError(result));
   }
diff --git a/runtime/bin/snapshot_utils.h b/runtime/bin/snapshot_utils.h
index 758b386..8b74821 100644
--- a/runtime/bin/snapshot_utils.h
+++ b/runtime/bin/snapshot_utils.h
@@ -30,7 +30,9 @@
  public:
   static void GenerateScript(const char* snapshot_filename);
   static void GenerateAppJIT(const char* snapshot_filename);
-  static void GenerateAppAOTAsBlobs(const char* snapshot_filename);
+  static void GenerateAppAOTAsBlobs(const char* snapshot_filename,
+                                    const uint8_t* shared_data,
+                                    const uint8_t* shared_instructions);
   static void GenerateAppAOTAsAssembly(const char* snapshot_filename);
 
   static AppSnapshot* TryReadAppSnapshot(const char* script_name);
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index 05ac9d1..1e9e8e1 100644
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -850,6 +850,8 @@
                    const char* main,
                    const uint8_t* isolate_snapshot_data,
                    const uint8_t* isolate_snapshot_instructions,
+                   const uint8_t* shared_data,
+                   const uint8_t* shared_instructions,
                    Dart_IsolateFlags* flags,
                    void* callback_data,
                    char** error);
@@ -3307,7 +3309,9 @@
                                  uint8_t** isolate_snapshot_data_buffer,
                                  intptr_t* isolate_snapshot_data_size,
                                  uint8_t** isolate_snapshot_instructions_buffer,
-                                 intptr_t* isolate_snapshot_instructions_size);
+                                 intptr_t* isolate_snapshot_instructions_size,
+                                 const uint8_t* shared_data,
+                                 const uint8_t* shared_instructions);
 
 /**
  * Sorts the class-ids in depth first traversal order of the inheritance
@@ -3380,6 +3384,10 @@
 
 /**
  *  Print a native stack trace. Used for crash handling.
+ *
+ *  If context is NULL, prints the current stack trace. Otherwise, context
+ *  should be a CONTEXT* (Windows) or ucontext_t* (POSIX) from a signal handler
+ *  running on the current thread.
  */
 DART_EXPORT void Dart_DumpNativeStackTrace(void* context);
 
diff --git a/runtime/lib/compact_hash.dart b/runtime/lib/compact_hash.dart
index 82bc532..6f55f41 100644
--- a/runtime/lib/compact_hash.dart
+++ b/runtime/lib/compact_hash.dart
@@ -78,19 +78,14 @@
   static const int _UNUSED_PAIR = 0;
   static const int _DELETED_PAIR = 1;
 
-  // On 32-bit, the top bits are wasted to avoid Mint allocation.
-  // TODO(koda): Reclaim the bits by making the compiler treat hash patterns
-  // as unsigned words.
+  // The top bits are wasted to avoid Mint allocation.
   static int _indexSizeToHashMask(int indexSize) {
     int indexBits = indexSize.bitLength - 2;
-    return internal.is64Bit
-        ? (1 << (32 - indexBits)) - 1
-        : (1 << (30 - indexBits)) - 1;
+    return (1 << (30 - indexBits)) - 1;
   }
 
   static int _hashPattern(int fullHash, int hashMask, int size) {
     final int maskedHash = fullHash & hashMask;
-    // TODO(koda): Consider keeping bit length and use left shift.
     return (maskedHash == 0) ? (size >> 1) : maskedHash * (size >> 1);
   }
 
diff --git a/runtime/lib/integers_patch.dart b/runtime/lib/integers_patch.dart
index d1c13be..15598fe 100644
--- a/runtime/lib/integers_patch.dart
+++ b/runtime/lib/integers_patch.dart
@@ -32,7 +32,7 @@
         return null; // Empty.
       }
     }
-    var smiLimit = is64Bit ? 18 : 9;
+    var smiLimit = 9;
     if ((last - ix) >= smiLimit) {
       return null; // May not fit into a Smi.
     }
@@ -133,7 +133,7 @@
 
   static int _parseRadix(
       String source, int radix, int start, int end, int sign) {
-    int tableIndex = (radix - 2) * 4 + (is64Bit ? 2 : 0);
+    int tableIndex = (radix - 2) * 2;
     int blockSize = _PARSE_LIMITS[tableIndex];
     int length = end - start;
     if (length <= blockSize) {
@@ -159,7 +159,7 @@
     int positiveOverflowLimit = 0;
     int negativeOverflowLimit = 0;
     if (_limitIntsTo64Bits) {
-      tableIndex = tableIndex << 1; // pre-multiply by 2 for simpler indexing
+      tableIndex = tableIndex << 1; // Pre-multiply by 2 for simpler indexing.
       positiveOverflowLimit = _int64OverflowLimits[tableIndex];
       if (positiveOverflowLimit == 0) {
         positiveOverflowLimit =
@@ -175,14 +175,10 @@
         if (result >= positiveOverflowLimit) {
           if ((result > positiveOverflowLimit) ||
               (smi > _int64OverflowLimits[tableIndex + 2])) {
-            // Although the unsigned overflow limits do not depend on the
-            // platform, the multiplier and block size, which are used to
-            // compute it, do.
-            int X = is64Bit ? 1 : 0;
             if (radix == 16 &&
-                !(result >= _int64UnsignedOverflowLimits[X] &&
-                    (result > _int64UnsignedOverflowLimits[X] ||
-                        smi > _int64UnsignedSmiOverflowLimits[X])) &&
+                !(result >= _int64UnsignedOverflowLimit &&
+                    (result > _int64UnsignedOverflowLimit ||
+                        smi > _int64UnsignedSmiOverflowLimit)) &&
                 blockEnd + blockSize > end) {
               return (result * multiplier) + smi;
             }
@@ -227,43 +223,42 @@
 
   // For each radix, 2-36, how many digits are guaranteed to fit in a smi,
   // and magnitude of such a block (radix ** digit-count).
-  // 32-bit limit/multiplier at (radix - 2)*4, 64-bit limit at (radix-2)*4+2
   static const _PARSE_LIMITS = const [
-    30, 1073741824, 62, 4611686018427387904, // radix: 2
-    18, 387420489, 39, 4052555153018976267,
-    15, 1073741824, 30, 1152921504606846976,
-    12, 244140625, 26, 1490116119384765625, //  radix: 5
-    11, 362797056, 23, 789730223053602816,
-    10, 282475249, 22, 3909821048582988049,
-    10, 1073741824, 20, 1152921504606846976,
-    9, 387420489, 19, 1350851717672992089,
-    9, 1000000000, 18, 1000000000000000000, //  radix: 10
-    8, 214358881, 17, 505447028499293771,
-    8, 429981696, 17, 2218611106740436992,
-    8, 815730721, 16, 665416609183179841,
-    7, 105413504, 16, 2177953337809371136,
-    7, 170859375, 15, 437893890380859375, //    radix: 15
-    7, 268435456, 15, 1152921504606846976,
-    7, 410338673, 15, 2862423051509815793,
-    7, 612220032, 14, 374813367582081024,
-    7, 893871739, 14, 799006685782884121,
-    6, 64000000, 14, 1638400000000000000, //    radix: 20
-    6, 85766121, 14, 3243919932521508681,
-    6, 113379904, 13, 282810057883082752,
-    6, 148035889, 13, 504036361936467383,
-    6, 191102976, 13, 876488338465357824,
-    6, 244140625, 13, 1490116119384765625, //   radix: 25
-    6, 308915776, 13, 2481152873203736576,
-    6, 387420489, 13, 4052555153018976267,
-    6, 481890304, 12, 232218265089212416,
-    6, 594823321, 12, 353814783205469041,
-    6, 729000000, 12, 531441000000000000, //    radix: 30
-    6, 887503681, 12, 787662783788549761,
-    6, 1073741824, 12, 1152921504606846976,
-    5, 39135393, 12, 1667889514952984961,
-    5, 45435424, 12, 2386420683693101056,
-    5, 52521875, 12, 3379220508056640625, //    radix: 35
-    5, 60466176, 11, 131621703842267136,
+    30, 1073741824, // radix: 2
+    18, 387420489,
+    15, 1073741824,
+    12, 244140625, //  radix: 5
+    11, 362797056,
+    10, 282475249,
+    10, 1073741824,
+    9, 387420489,
+    9, 1000000000, //  radix: 10
+    8, 214358881,
+    8, 429981696,
+    8, 815730721,
+    7, 105413504,
+    7, 170859375, //    radix: 15
+    7, 268435456,
+    7, 410338673,
+    7, 612220032,
+    7, 893871739,
+    6, 64000000, //    radix: 20
+    6, 85766121,
+    6, 113379904,
+    6, 148035889,
+    6, 191102976,
+    6, 244140625, //   radix: 25
+    6, 308915776,
+    6, 387420489,
+    6, 481890304,
+    6, 594823321,
+    6, 729000000, //    radix: 30
+    6, 887503681,
+    6, 1073741824,
+    5, 39135393,
+    5, 45435424,
+    5, 52521875, //    radix: 35
+    5, 60466176,
   ];
 
   /// Flag indicating if integers are limited by 64 bits
@@ -273,11 +268,8 @@
   static const _maxInt64 = 0x7fffffffffffffff;
   static const _minInt64 = -_maxInt64 - 1;
 
-  static const _int64UnsignedOverflowLimits = const [0xfffffffff, 0xf];
-  static const _int64UnsignedSmiOverflowLimits = const [
-    0xfffffff,
-    0xfffffffffffffff
-  ];
+  static const _int64UnsignedOverflowLimit = 0xfffffffff;
+  static const _int64UnsignedSmiOverflowLimit = 0xfffffff;
 
   /// In the `--limit-ints-to-64-bits` mode calculation of the expression
   ///
diff --git a/runtime/observatory/BUILD.gn b/runtime/observatory/BUILD.gn
index 94f0ce0..77571e2 100644
--- a/runtime/observatory/BUILD.gn
+++ b/runtime/observatory/BUILD.gn
@@ -8,128 +8,71 @@
 import("observatory_sources.gni")
 
 # Construct arguments to the observatory tool for finding pub.
-pub_build_deps = []
-pub_build_args = []
+build_deps = []
+build_args = []
 if (!prebuilt_dart_exe_works) {
-  pub_build_deps += [ "../bin:dart_bootstrap($dart_host_toolchain)" ]
+  build_deps += [ "../bin:dart_bootstrap($dart_host_toolchain)" ]
 
   dart_out_dir = get_label_info("../bin:dart_bootstrap($dart_host_toolchain)",
                                 "root_out_dir")
   dart_bootstrap = rebase_path("$dart_out_dir/dart_bootstrap$executable_suffix")
 
-  pub_build_args = [
+  build_args = [
     "--sdk=True",
     "--dart-executable",
     dart_bootstrap,
   ]
 } else {
-  pub_build_args = [ "--sdk=True" ]
+  build_args = [ "--sdk=True" ]
 }
 
 current_dir = rebase_path(".", "//")
 
-# Helper build rules for packaging the Dart observatory resources.
-copy("copy_observatory") {
+action("build_observatory") {
+  deps = build_deps
+
   sources = rebase_path(observatory_sources, "", ".")
-  outputs = [
-    "$root_gen_dir/observatory_copy/{{source_root_relative_dir}}/{{source_file_part}}",
-  ]
-}
 
-action("write_observatory_pubspec_yaml") {
-  deps = [ ":copy_observatory" ] + pub_build_deps
-
-  inputs = [
-    rebase_path("pubspec.yaml"),
-  ]
+  inputs = sources + [ rebase_path("dart2js.packages") ]
 
   script = "../../tools/observatory_tool.py"
-  args =
-      pub_build_args + [
-        "--silent=True",
-        "--directory",
-        rebase_path("$root_gen_dir/observatory_copy/$current_dir/"),
-        "--command",
-        "rewrite",
-        rebase_path("../observatory/pubspec.yaml"),
-        rebase_path("$root_gen_dir/observatory_copy/$current_dir/pubspec.yaml"),
-        "../../third_party/",
-        rebase_path("../../third_party/"),
-      ]
-
-  outputs = [
-    "$root_gen_dir/observatory_copy/$current_dir/pubspec.yaml",
-  ]
-}
-
-action("copy_observatory_deps") {
-  deps = [ ":write_observatory_pubspec_yaml" ] + pub_build_deps
-
-  inputs = [
-    "$root_gen_dir/observatory_copy/$current_dir/pubspec.yaml",
-  ]
-
-  script = "../../tools/observatory_tool.py"
-  args = pub_build_args + [
-           "--silent=True",
-           "--stamp",
-           rebase_path(
-               "$root_gen_dir/observatory_copy/$current_dir/packages.stamp"),
-           "--directory",
-           rebase_path("$root_gen_dir/observatory_copy/$current_dir/"),
-           "--command",
-           "get",
-         ]
-
-  outputs = [
-    "$root_gen_dir/observatory_copy/$current_dir/packages.stamp",
-  ]
-}
-
-action("pub_build_observatory") {
-  deps = [
-           ":copy_observatory",
-           ":copy_observatory_deps",
-         ] + pub_build_deps
-
-  sources = rebase_path(observatory_sources,
-                        "",
-                        "$root_gen_dir/observatory_copy/$current_dir")
-
-  inputs =
-      sources + [ "$root_gen_dir/observatory_copy/$current_dir/packages.stamp" ]
-
-  script = "../../tools/observatory_tool.py"
-  args = pub_build_args + [
+  args = build_args + [
            "--silent=True",
            "--directory",
-           rebase_path("$root_gen_dir/observatory_copy/$current_dir/"),
+           rebase_path("."),
            "--command",
            "build",
-           rebase_path("$root_out_dir/observatory/build"),
+           rebase_path("web/main.dart"),
+           rebase_path("$root_gen_dir/observatory/web/main.dart.js"),
+           rebase_path("dart2js.packages"),
          ]
 
   outputs = [
-    "$root_out_dir/observatory/build/web/main.dart.js",
+    "$root_gen_dir/observatory/web/main.dart.js",
   ]
 }
 
 action("deploy_observatory") {
-  deps = [ ":pub_build_observatory" ] + pub_build_deps
+  deps = [ ":build_observatory" ] + build_deps
 
   script = "../../tools/observatory_tool.py"
 
   inputs = [
     script,
-    "$root_out_dir/observatory/build/web/main.dart.js",
+    "$root_gen_dir/observatory/web/main.dart.js",
   ]
 
-  args = pub_build_args + [
+  args = build_args + [
            "--silent=True",
            "--directory",
            rebase_path("$root_out_dir/observatory"),
            "--command",
            "deploy",
+           rebase_path("$root_out_dir/observatory/deployed"),
+           rebase_path("web"),
+           rebase_path("lib"),
+           rebase_path("$root_gen_dir/observatory/web/main.dart.js"),
+           rebase_path("../../third_party/observatory_pub_packages/packages"),
          ]
 
   outputs = [
diff --git a/runtime/observatory/dart2js.packages b/runtime/observatory/dart2js.packages
new file mode 100644
index 0000000..b042c03
--- /dev/null
+++ b/runtime/observatory/dart2js.packages
@@ -0,0 +1,24 @@
+# Update if observatory dependencies change
+args:../../third_party/observatory_pub_packages/packages/args/lib
+async:../../third_party/observatory_pub_packages/packages/async/lib
+barback:../../third_party/observatory_pub_packages/packages/barback/lib
+browser:../../third_party/observatory_pub_packages/packages/browser/lib
+charcode:../../third_party/observatory_pub_packages/packages/charcode/lib
+charted:../../third_party/observatory_pub_packages/packages/charted/lib
+collection:../../third_party/observatory_pub_packages/packages/collection/lib
+csslib:../../third_party/observatory_pub_packages/packages/csslib/lib
+html:../../third_party/observatory_pub_packages/packages/html/lib
+intl:../../third_party/observatory_pub_packages/packages/intl/lib
+logging:../../third_party/observatory_pub_packages/packages/logging/lib
+matcher:../../third_party/observatory_pub_packages/packages/matcher/lib
+meta:../../third_party/observatory_pub_packages/packages/meta/lib
+observable:../../third_party/observatory_pub_packages/packages/observable/lib
+path:../../third_party/observatory_pub_packages/packages/path/lib
+pool:../../third_party/observatory_pub_packages/packages/pool/lib
+quiver:../../third_party/observatory_pub_packages/packages/quiver/lib
+source_span:../../third_party/observatory_pub_packages/packages/source_span/lib
+stack_trace:../../third_party/observatory_pub_packages/packages/stack_trace/lib
+unittest:../../third_party/observatory_pub_packages/packages/unittest/lib
+usage:../../third_party/observatory_pub_packages/packages/usage/lib
+utf:../../third_party/observatory_pub_packages/packages/utf/lib
+observatory:lib/
diff --git a/runtime/observatory/pubspec.yaml b/runtime/observatory/pubspec.yaml
deleted file mode 100644
index 4ed0d1f..0000000
--- a/runtime/observatory/pubspec.yaml
+++ /dev/null
@@ -1,60 +0,0 @@
-# Generated file DO NOT EDIT
-name: observatory
-transformers:
-- dart_to_js_script_rewriter
-- $dart2js:
-    suppressWarnings: false
-    commandLineOptions: [--show-package-warnings]
-dependencies:
-  args: ^0.13.2
-  charted: ^0.4.8
-  unittest: < 0.12.0
-  usage: ^1.2.0
-  dart_to_js_script_rewriter: 1.0.3
-dependency_overrides:
-  args:
-    path: ../../third_party/observatory_pub_packages/packages/args
-  async:
-    path: ../../third_party/observatory_pub_packages/packages/async
-  barback:
-    path: ../../third_party/observatory_pub_packages/packages/barback
-  browser:
-    path: ../../third_party/observatory_pub_packages/packages/browser
-  charcode:
-    path: ../../third_party/observatory_pub_packages/packages/charcode
-  charted:
-    path: ../../third_party/observatory_pub_packages/packages/charted
-  collection:
-    path: ../../third_party/observatory_pub_packages/packages/collection
-  csslib:
-    path: ../../third_party/observatory_pub_packages/packages/csslib
-  dart_to_js_script_rewriter:
-    path: ../../third_party/observatory_pub_packages/packages/dart_to_js_script_rewriter
-  html:
-    path: ../../third_party/observatory_pub_packages/packages/html
-  intl:
-    path: ../../third_party/observatory_pub_packages/packages/intl
-  logging:
-    path: ../../third_party/observatory_pub_packages/packages/logging
-  matcher:
-    path: ../../third_party/observatory_pub_packages/packages/matcher
-  meta:
-    path: ../../third_party/observatory_pub_packages/packages/meta
-  observable:
-    path: ../../third_party/observatory_pub_packages/packages/observable
-  path:
-    path: ../../third_party/observatory_pub_packages/packages/path
-  pool:
-    path: ../../third_party/observatory_pub_packages/packages/pool
-  quiver:
-    path: ../../third_party/observatory_pub_packages/packages/quiver
-  source_span:
-    path: ../../third_party/observatory_pub_packages/packages/source_span
-  stack_trace:
-    path: ../../third_party/observatory_pub_packages/packages/stack_trace
-  unittest:
-    path: ../../third_party/observatory_pub_packages/packages/unittest
-  usage:
-    path: ../../third_party/observatory_pub_packages/packages/usage
-  utf:
-    path: ../../third_party/observatory_pub_packages/packages/utf
diff --git a/runtime/observatory/tests/observatory_ui/mocks/repositories/flag.dart b/runtime/observatory/tests/observatory_ui/mocks/repositories/flag.dart
index c6755e6..578c034 100644
--- a/runtime/observatory/tests/observatory_ui/mocks/repositories/flag.dart
+++ b/runtime/observatory/tests/observatory_ui/mocks/repositories/flag.dart
@@ -9,6 +9,7 @@
   bool isListInvoked = false;
 
   Future<Iterable<M.Flag>> list() async {
+    await null;
     isListInvoked = true;
     return _list;
   }
diff --git a/runtime/platform/assert.cc b/runtime/platform/assert.cc
index 7929b27..fb7cc88 100644
--- a/runtime/platform/assert.cc
+++ b/runtime/platform/assert.cc
@@ -4,9 +4,9 @@
 
 #include "platform/assert.h"
 
+#include "include/dart_api.h"
 #include "platform/globals.h"
 #include "vm/os.h"
-#include "vm/profiler.h"
 
 namespace dart {
 
@@ -38,7 +38,7 @@
   // until the program is exiting before producing a non-zero exit
   // code through abort.
   if (kind_ == ASSERT) {
-    NOT_IN_PRODUCT(Profiler::DumpStackTrace());
+    NOT_IN_PRODUCT(Dart_DumpNativeStackTrace(NULL));
     OS::Abort();
   }
   failed_ = true;
diff --git a/runtime/platform/globals.h b/runtime/platform/globals.h
index ef225bc..10e307c 100644
--- a/runtime/platform/globals.h
+++ b/runtime/platform/globals.h
@@ -245,6 +245,13 @@
 #error Architecture was not detected as supported by Dart.
 #endif
 
+#if defined(TARGET_ARCH_ARM64) || defined(TARGET_ARCH_X64)
+// On 64 bit architectures the optimizing compilers should prefer unboxed int64
+// and unboxed uint32 values, which have direct support in the instruction set.
+// We avoid the unboxed signed int32 type.
+#define AVOID_UNBOXED_INT32 1
+#endif
+
 // DART_FORCE_INLINE strongly hints to the compiler that a function should
 // be inlined. Your function is not guaranteed to be inlined but this is
 // stronger than just using "inline".
diff --git a/runtime/platform/utils.h b/runtime/platform/utils.h
index 2917008..c717cbc 100644
--- a/runtime/platform/utils.h
+++ b/runtime/platform/utils.h
@@ -317,7 +317,7 @@
   static uword NBitMask(uint32_t n) {
     ASSERT(n <= kBitsPerWord);
     if (n == kBitsPerWord) {
-#if defined(TARGET_ARCH_X64)
+#if defined(ARCH_IS_64_BIT)
       return 0xffffffffffffffffll;
 #else
       return 0xffffffff;
diff --git a/runtime/runtime_args.gni b/runtime/runtime_args.gni
index 13751eb..e88807e 100644
--- a/runtime/runtime_args.gni
+++ b/runtime/runtime_args.gni
@@ -69,4 +69,12 @@
   # revision. The short git hash can be omitted by setting
   # dart_version_git_info=false
   dart_custom_version_for_pub = ""
+
+  # Controls whether the VM is built as a static library or a shared library.
+  if (is_fuchsia) {
+    # Allow for deduping the VM between standalone, flutter_runner and dart_runner.
+    dart_component_kind = "shared_library"
+  } else {
+    dart_component_kind = "static_library"
+  }
 }
diff --git a/runtime/tests/vm/dart/error_messages_in_null_checks_test.dart b/runtime/tests/vm/dart/error_messages_in_null_checks_test.dart
new file mode 100644
index 0000000..b40c5a9
--- /dev/null
+++ b/runtime/tests/vm/dart/error_messages_in_null_checks_test.dart
@@ -0,0 +1,98 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// This test verifies that NoSuchMethodError thrown from null checks
+// corresponding to devirtualized calls in AOT mode have detailed messages
+// (dartbug.com/32863).
+
+import "package:expect/expect.dart";
+
+class A {
+  void foo() {
+    Expect.fail('A.foo should not be reachable');
+  }
+
+  dynamic get bar {
+    Expect.fail('A.bar should not be reachable');
+  }
+
+  set bazz(int x) {
+    Expect.fail('A.bazz should not be reachable');
+  }
+}
+
+A myNull;
+double doubleNull;
+int intNull;
+
+main(List<String> args) {
+  // Make sure value of `myNull` is not a compile-time null and
+  // devirtualization happens.
+  if (args.length > 42) {
+    myNull = new A();
+    doubleNull = 3.14;
+    intNull = 2;
+  }
+
+  Expect.throws(
+      () => myNull.foo(),
+      (e) =>
+          e is NoSuchMethodError &&
+          e.toString().startsWith(
+              'NoSuchMethodError: The method \'foo\' was called on null.'));
+
+  Expect.throws(
+      () => myNull.foo,
+      (e) =>
+          e is NoSuchMethodError &&
+          e.toString().startsWith(
+              'NoSuchMethodError: The getter \'foo\' was called on null.'));
+
+  Expect.throws(
+      () => myNull.bar,
+      (e) =>
+          e is NoSuchMethodError &&
+          e.toString().startsWith(
+              'NoSuchMethodError: The getter \'bar\' was called on null.'));
+
+  Expect.throws(
+      () => myNull.bar(),
+      (e) =>
+          e is NoSuchMethodError &&
+          e.toString().startsWith(
+              'NoSuchMethodError: The method \'bar\' was called on null.'));
+
+  Expect.throws(() {
+    myNull.bazz = 3;
+  },
+      (e) =>
+          e is NoSuchMethodError &&
+          e.toString().startsWith(
+              'NoSuchMethodError: The setter \'bazz=\' was called on null.'));
+
+  Expect.throws(
+      () => doubleNull + 2.17,
+      (e) =>
+          e is NoSuchMethodError &&
+          e.toString().startsWith(
+              'NoSuchMethodError: The method \'+\' was called on null.'));
+
+  Expect.throws(
+      () => 9.81 - doubleNull,
+      (e) =>
+          e is NoSuchMethodError &&
+          // If '-' is specialized.
+          (e.toString().startsWith(
+                  'NoSuchMethodError: The method \'-\' was called on null.') ||
+              // If '-' is not specialized, it calls toDouble() internally.
+              e.toString().startsWith(
+                  'NoSuchMethodError: The method \'toDouble\' was called on null.')));
+
+  Expect.throws(
+      () => intNull * 7,
+      (e) =>
+          e is NoSuchMethodError &&
+          e.toString().startsWith(
+              'NoSuchMethodError: The method \'*\' was called on null.'));
+}
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 07ba355..26c3491 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -9,12 +9,12 @@
 cc/Fail0: Fail # These tests are expected to crash on all platforms.
 cc/Fail1: Fail # These tests are expected to crash on all platforms.
 cc/Fail2: Fail # These tests are expected to crash on all platforms.
-cc/IsolateReload_PendingConstructorCall_AbstractToConcrete: SkipSlow # Issue 28198
-cc/IsolateReload_PendingConstructorCall_ConcreteToAbstract: SkipSlow # Issue 28198
-cc/IsolateReload_PendingStaticCall_DefinedToNSM: SkipSlow # Issue 28198
-cc/IsolateReload_PendingStaticCall_NSMToDefined: SkipSlow # Issue 28198
-cc/IsolateReload_PendingUnqualifiedCall_InstanceToStatic: SkipSlow # Issue 28198
-cc/IsolateReload_PendingUnqualifiedCall_StaticToInstance: SkipSlow # Issue 28198
+cc/IsolateReload_PendingConstructorCall_AbstractToConcrete: Fail # Issue 32981
+cc/IsolateReload_PendingConstructorCall_ConcreteToAbstract: Fail # Issue 32981
+cc/IsolateReload_PendingStaticCall_DefinedToNSM: Fail # Issue 32981
+cc/IsolateReload_PendingStaticCall_NSMToDefined: Fail # Issue 32981
+cc/IsolateReload_PendingUnqualifiedCall_InstanceToStatic: Fail # Issue 32981
+cc/IsolateReload_PendingUnqualifiedCall_StaticToInstance: Fail # Issue 32981
 cc/IsolateReload_RunNewFieldInitializersWithGenerics: Fail # Issue 32299
 cc/Profiler_InliningIntervalBoundry: Skip # Differences in ia32, debug, release
 cc/SNPrint_BadArgs: Crash, Fail # These tests are expected to crash on all platforms.
@@ -34,6 +34,7 @@
 [ $compiler == dart2js ]
 dart/byte_array_optimized_test: Skip # compilers not aware of byte arrays
 dart/byte_array_test: Skip # compilers not aware of byte arrays
+dart/error_messages_in_null_checks_test: SkipByDesign # Dart2js throws NullError exceptions with different messages.
 dart/inline_stack_frame_test: Skip # Issue 7953, Methods can be missing in dart2js stack traces due to inlining. Also when minifying they can be renamed, which is issue 7953.
 dart/optimized_stacktrace_line_and_column_test: RuntimeError # The source positions do not match with dart2js.
 dart/optimized_stacktrace_line_test: RuntimeError # The source positions do not match with dart2js.
diff --git a/runtime/vm/class_table.cc b/runtime/vm/class_table.cc
index 3ac1c40..447ea45 100644
--- a/runtime/vm/class_table.cc
+++ b/runtime/vm/class_table.cc
@@ -21,27 +21,27 @@
     : top_(kNumPredefinedCids),
       capacity_(0),
       table_(NULL),
-      old_tables_(new MallocGrowableArray<RawClass**>()) {
+      old_tables_(new MallocGrowableArray<ClassAndSize*>()) {
   NOT_IN_PRODUCT(class_heap_stats_table_ = NULL);
   NOT_IN_PRODUCT(predefined_class_heap_stats_table_ = NULL);
   if (Dart::vm_isolate() == NULL) {
     capacity_ = initial_capacity_;
-    table_ = reinterpret_cast<RawClass**>(
-        calloc(capacity_, sizeof(RawClass*)));  // NOLINT
+    table_ = reinterpret_cast<ClassAndSize*>(
+        calloc(capacity_, sizeof(ClassAndSize)));  // NOLINT
   } else {
     // Duplicate the class table from the VM isolate.
     ClassTable* vm_class_table = Dart::vm_isolate()->class_table();
     capacity_ = vm_class_table->capacity_;
-    table_ = reinterpret_cast<RawClass**>(
-        calloc(capacity_, sizeof(RawClass*)));  // NOLINT
+    table_ = reinterpret_cast<ClassAndSize*>(
+        calloc(capacity_, sizeof(ClassAndSize)));  // NOLINT
     for (intptr_t i = kObjectCid; i < kInstanceCid; i++) {
-      table_[i] = vm_class_table->At(i);
+      table_[i] = vm_class_table->PairAt(i);
     }
-    table_[kTypeArgumentsCid] = vm_class_table->At(kTypeArgumentsCid);
-    table_[kFreeListElement] = vm_class_table->At(kFreeListElement);
-    table_[kForwardingCorpse] = vm_class_table->At(kForwardingCorpse);
-    table_[kDynamicCid] = vm_class_table->At(kDynamicCid);
-    table_[kVoidCid] = vm_class_table->At(kVoidCid);
+    table_[kTypeArgumentsCid] = vm_class_table->PairAt(kTypeArgumentsCid);
+    table_[kFreeListElement] = vm_class_table->PairAt(kFreeListElement);
+    table_[kForwardingCorpse] = vm_class_table->PairAt(kForwardingCorpse);
+    table_[kDynamicCid] = vm_class_table->PairAt(kDynamicCid);
+    table_[kVoidCid] = vm_class_table->PairAt(kVoidCid);
 
 #ifndef PRODUCT
     class_heap_stats_table_ = reinterpret_cast<ClassHeapStats*>(
@@ -83,7 +83,7 @@
   }
 }
 
-void ClassTable::AddOldTable(RawClass** old_table) {
+void ClassTable::AddOldTable(ClassAndSize* old_table) {
   ASSERT(Thread::Current()->IsMutatorThread());
   old_tables_->Add(old_table);
 }
@@ -112,9 +112,9 @@
   if (index != kIllegalCid) {
     ASSERT(index > 0);
     ASSERT(index < kNumPredefinedCids);
-    ASSERT(table_[index] == 0);
+    ASSERT(table_[index].class_ == NULL);
     ASSERT(index < capacity_);
-    table_[index] = cls.raw();
+    table_[index] = ClassAndSize(cls.raw(), Class::instance_size(cls.raw()));
     // Add the vtable for this predefined class into the static vtable registry
     // if it has not been setup yet.
     cpp_vtable cls_vtable = cls.handle_vtable();
@@ -128,16 +128,16 @@
       // Grow the capacity of the class table.
       // TODO(koda): Add ClassTable::Grow to share code.
       intptr_t new_capacity = capacity_ + capacity_increment_;
-      RawClass** new_table = reinterpret_cast<RawClass**>(
-          malloc(new_capacity * sizeof(RawClass*)));  // NOLINT
-      memmove(new_table, table_, capacity_ * sizeof(RawClass*));
+      ClassAndSize* new_table = reinterpret_cast<ClassAndSize*>(
+          malloc(new_capacity * sizeof(ClassAndSize)));  // NOLINT
+      memmove(new_table, table_, capacity_ * sizeof(ClassAndSize));
 #ifndef PRODUCT
       ClassHeapStats* new_stats_table = reinterpret_cast<ClassHeapStats*>(
           realloc(class_heap_stats_table_,
                   new_capacity * sizeof(ClassHeapStats)));  // NOLINT
 #endif
       for (intptr_t i = capacity_; i < new_capacity; i++) {
-        new_table[i] = NULL;
+        new_table[i] = ClassAndSize(NULL, 0);
         NOT_IN_PRODUCT(new_stats_table[i].Initialize());
       }
       capacity_ = new_capacity;
@@ -151,7 +151,7 @@
              top_);
     }
     cls.set_id(top_);
-    table_[top_] = cls.raw();
+    table_[top_] = ClassAndSize(cls.raw());
     top_++;  // Increment next index.
   }
 }
@@ -165,16 +165,16 @@
       FATAL1("Fatal error in ClassTable::Register: invalid index %" Pd "\n",
              index);
     }
-    RawClass** new_table = reinterpret_cast<RawClass**>(
-        malloc(new_capacity * sizeof(RawClass*)));  // NOLINT
-    memmove(new_table, table_, capacity_ * sizeof(RawClass*));
+    ClassAndSize* new_table = reinterpret_cast<ClassAndSize*>(
+        malloc(new_capacity * sizeof(ClassAndSize)));  // NOLINT
+    memmove(new_table, table_, capacity_ * sizeof(ClassAndSize));
 #ifndef PRODUCT
     ClassHeapStats* new_stats_table = reinterpret_cast<ClassHeapStats*>(
         realloc(class_heap_stats_table_,
                 new_capacity * sizeof(ClassHeapStats)));  // NOLINT
 #endif
     for (intptr_t i = capacity_; i < new_capacity; i++) {
-      new_table[i] = NULL;
+      new_table[i] = ClassAndSize(NULL);
       NOT_IN_PRODUCT(new_stats_table[i].Initialize());
     }
     capacity_ = new_capacity;
@@ -184,7 +184,7 @@
     ASSERT(capacity_increment_ >= 1);
   }
 
-  ASSERT(table_[index] == 0);
+  ASSERT(table_[index].class_ == NULL);
   if (index >= top_) {
     top_ = index + 1;
   }
@@ -192,14 +192,14 @@
 
 #if defined(DEBUG)
 void ClassTable::Unregister(intptr_t index) {
-  table_[index] = 0;
+  table_[index] = ClassAndSize(NULL);
 }
 #endif
 
 void ClassTable::Remap(intptr_t* old_to_new_cid) {
   ASSERT(Thread::Current()->IsAtSafepoint());
   intptr_t num_cids = NumCids();
-  RawClass** cls_by_old_cid = new RawClass*[num_cids];
+  ClassAndSize* cls_by_old_cid = new ClassAndSize[num_cids];
   for (intptr_t i = 0; i < num_cids; i++) {
     cls_by_old_cid[i] = table_[i];
   }
@@ -211,7 +211,16 @@
 
 void ClassTable::VisitObjectPointers(ObjectPointerVisitor* visitor) {
   ASSERT(visitor != NULL);
-  visitor->VisitPointers(reinterpret_cast<RawObject**>(&table_[0]), top_);
+  for (intptr_t i = 0; i < top_; i++) {
+    visitor->VisitPointer(reinterpret_cast<RawObject**>(&(table_[i].class_)));
+  }
+}
+
+void ClassTable::CopySizesFromClassObjects() {
+  ASSERT(kIllegalCid == 0);
+  for (intptr_t i = 1; i < top_; i++) {
+    SetAt(i, At(i));
+  }
 }
 
 void ClassTable::Validate() {
@@ -248,6 +257,19 @@
   }
 }
 
+void ClassTable::SetAt(intptr_t index, RawClass* raw_cls) {
+  ASSERT(index < capacity_);
+  if (raw_cls == NULL) {
+    table_[index] = ClassAndSize(raw_cls, 0);
+  } else {
+    table_[index] = ClassAndSize(raw_cls, Class::instance_size(raw_cls));
+  }
+}
+
+ClassAndSize::ClassAndSize(RawClass* clazz) : class_(clazz) {
+  size_ = clazz == NULL ? 0 : Class::instance_size(clazz);
+}
+
 #ifndef PRODUCT
 void ClassTable::PrintToJSONObject(JSONObject* object) {
   if (!FLAG_support_service) {
diff --git a/runtime/vm/class_table.h b/runtime/vm/class_table.h
index 7eae60b..560e686 100644
--- a/runtime/vm/class_table.h
+++ b/runtime/vm/class_table.h
@@ -14,6 +14,7 @@
 
 class Class;
 class ClassStats;
+class ClassTable;
 class JSONArray;
 class JSONObject;
 class JSONStream;
@@ -22,6 +23,29 @@
 class ObjectPointerVisitor;
 class RawClass;
 
+class ClassAndSize {
+ public:
+  ClassAndSize() : class_(NULL), size_(0) {}
+  explicit ClassAndSize(RawClass* clazz);
+  ClassAndSize(RawClass* clazz, intptr_t size) : class_(clazz), size_(size) {}
+  RawClass* get_raw_class() const { return class_; }
+  intptr_t size() const { return size_; }
+
+ private:
+  RawClass* class_;
+  intptr_t size_;
+
+  friend class ClassTable;
+};
+
+#if defined(ARCH_IS_32_BIT)
+const int kSizeOfClassPairLog2 = 3;
+#else
+const int kSizeOfClassPairLog2 = 4;
+#endif
+
+COMPILE_ASSERT((1 << kSizeOfClassPairLog2) == sizeof(ClassAndSize));
+
 #ifndef PRODUCT
 template <typename T>
 class AllocStats {
@@ -165,10 +189,20 @@
   // Thread-safe.
   RawClass* At(intptr_t index) const {
     ASSERT(IsValidIndex(index));
+    return table_[index].class_;
+  }
+
+  intptr_t SizeAt(intptr_t index) const {
+    ASSERT(IsValidIndex(index));
+    return table_[index].size_;
+  }
+
+  ClassAndSize PairAt(intptr_t index) const {
+    ASSERT(IsValidIndex(index));
     return table_[index];
   }
 
-  void SetAt(intptr_t index, RawClass* raw_cls) { table_[index] = raw_cls; }
+  void SetAt(intptr_t index, RawClass* raw_cls);
 
   bool IsValidIndex(intptr_t index) const {
     return (index > 0) && (index < top_);
@@ -176,7 +210,7 @@
 
   bool HasValidClassAt(intptr_t index) const {
     ASSERT(IsValidIndex(index));
-    return table_[index] != NULL;
+    return table_[index].class_ != NULL;
   }
 
   intptr_t NumCids() const { return top_; }
@@ -199,6 +233,11 @@
 
   void VisitObjectPointers(ObjectPointerVisitor* visitor);
 
+  // If a snapshot reader has populated the class table then the
+  // sizes in the class table are not correct. Iterates through the
+  // table, updating the sizes.
+  void CopySizesFromClassObjects();
+
   void Validate();
 
   void Print();
@@ -245,7 +284,7 @@
   void PrintToJSONObject(JSONObject* object);
 #endif  // !PRODUCT
 
-  void AddOldTable(RawClass** old_table);
+  void AddOldTable(ClassAndSize* old_table);
   // Deallocates table copies. Do not call during concurrent access to table.
   void FreeOldTables();
 
@@ -267,8 +306,8 @@
   intptr_t capacity_;
 
   // Copy-on-write is used for table_, with old copies stored in old_tables_.
-  RawClass** table_;
-  MallocGrowableArray<RawClass**>* old_tables_;
+  ClassAndSize* table_;
+  MallocGrowableArray<ClassAndSize*>* old_tables_;
 
 #ifndef PRODUCT
   ClassHeapStats* class_heap_stats_table_;
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index 6243d52..650db2a 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -1699,18 +1699,12 @@
         }
       }
 
-      RawInstructions* instr = code->ptr()->instructions_;
-      int32_t text_offset = s->GetTextOffset(instr, code);
-      s->Write<int32_t>(text_offset);
+      s->WriteInstructions(code->ptr()->instructions_, code);
       if (s->kind() == Snapshot::kFullJIT) {
         // TODO(rmacnak): Fix references to disabled code before serializing.
-        if (code->ptr()->active_instructions_ != code->ptr()->instructions_) {
-          // For now, we write the FixCallersTarget or equivalent stub. This
-          // will cause a fixup if this code is called.
-          instr = code->ptr()->active_instructions_;
-          text_offset = s->GetTextOffset(instr, code);
-        }
-        s->Write<int32_t>(text_offset);
+        // For now, we may write the FixCallersTarget or equivalent stub. This
+        // will cause a fixup if this code is called.
+        s->WriteInstructions(code->ptr()->active_instructions_, code);
       }
 
       s->WriteRef(code->ptr()->object_pool_);
@@ -1771,8 +1765,7 @@
       Deserializer::InitializeHeader(code, kCodeCid, Code::InstanceSize(0),
                                      is_vm_object);
 
-      int32_t text_offset = d->Read<int32_t>();
-      RawInstructions* instr = d->GetInstructionsAt(text_offset);
+      RawInstructions* instr = d->ReadInstructions();
 
       code->ptr()->entry_point_ = Instructions::UncheckedEntryPoint(instr);
       code->ptr()->checked_entry_point_ =
@@ -1782,8 +1775,7 @@
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
       if (d->kind() == Snapshot::kFullJIT) {
-        int32_t text_offset = d->Read<int32_t>();
-        RawInstructions* instr = d->GetInstructionsAt(text_offset);
+        RawInstructions* instr = d->ReadInstructions();
         code->ptr()->active_instructions_ = instr;
         code->ptr()->entry_point_ = Instructions::UncheckedEntryPoint(instr);
         code->ptr()->checked_entry_point_ =
@@ -1993,8 +1985,6 @@
   virtual ~RODataSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
-    objects_.Add(object);
-
     // A string's hash must already be computed when we write it because it
     // will be loaded into read-only memory. Extra bytes due to allocation
     // rounding need to be deterministically set for reliable deduplication in
@@ -2004,11 +1994,30 @@
     } else {
       Object::FinalizeReadOnlyObject(object);
     }
+
+    uint32_t ignored;
+    if (s->GetSharedDataOffset(object, &ignored)) {
+      shared_objects_.Add(object);
+    } else {
+      objects_.Add(object);
+    }
   }
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(cid_);
-    intptr_t count = objects_.length();
+    intptr_t count = shared_objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      RawObject* object = shared_objects_[i];
+      uint32_t offset;
+      if (!s->GetSharedDataOffset(object, &offset)) {
+        UNREACHABLE();
+      }
+      s->WriteUnsigned(offset);
+      s->AssignRef(object);
+    }
+
+    count = objects_.length();
     s->WriteUnsigned(count);
     uint32_t running_offset = 0;
     for (intptr_t i = 0; i < count; i++) {
@@ -2029,6 +2038,7 @@
  private:
   const intptr_t cid_;
   GrowableArray<RawObject*> objects_;
+  GrowableArray<RawObject*> shared_objects_;
 };
 #endif  // !DART_PRECOMPILED_RUNTIME
 
@@ -2039,6 +2049,12 @@
 
   void ReadAlloc(Deserializer* d) {
     intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      uint32_t offset = d->ReadUnsigned();
+      d->AssignRef(d->GetSharedObjectAt(offset));
+    }
+
+    count = d->ReadUnsigned();
     uint32_t running_offset = 0;
     for (intptr_t i = 0; i < count; i++) {
       running_offset += d->ReadUnsigned() << kObjectAlignmentLog2;
@@ -3054,8 +3070,7 @@
       if (s->kind() == Snapshot::kFullAOT) {
         RawInstructions* instr = type_testing_stubs_.LookupByAddresss(
             type->ptr()->type_test_stub_entry_point_);
-        const int32_t text_offset = s->GetTextOffset(instr, Code::null());
-        s->Write<int32_t>(text_offset);
+        s->WriteInstructions(instr, Code::null());
       }
     }
     count = objects_.length();
@@ -3071,8 +3086,7 @@
       if (s->kind() == Snapshot::kFullAOT) {
         RawInstructions* instr = type_testing_stubs_.LookupByAddresss(
             type->ptr()->type_test_stub_entry_point_);
-        const int32_t text_offset = s->GetTextOffset(instr, Code::null());
-        s->Write<int32_t>(text_offset);
+        s->WriteInstructions(instr, Code::null());
       }
     }
 
@@ -3081,11 +3095,11 @@
     if (s->kind() == Snapshot::kFullAOT && is_vm_isolate) {
       RawInstructions* dynamic_instr = type_testing_stubs_.LookupByAddresss(
           Type::dynamic_type().type_test_stub_entry_point());
-      s->Write<int32_t>(s->GetTextOffset(dynamic_instr, Code::null()));
+      s->WriteInstructions(dynamic_instr, Code::null());
 
       RawInstructions* void_instr = type_testing_stubs_.LookupByAddresss(
           Type::void_type().type_test_stub_entry_point());
-      s->Write<int32_t>(s->GetTextOffset(void_instr, Code::null()));
+      s->WriteInstructions(void_instr, Code::null());
     }
   }
 
@@ -3135,8 +3149,7 @@
       type->ptr()->token_pos_ = d->ReadTokenPosition();
       type->ptr()->type_state_ = d->Read<int8_t>();
       if (d->kind() == Snapshot::kFullAOT) {
-        const int32_t text_offset = d->Read<int32_t>();
-        instr_ = d->GetInstructionsAt(text_offset);
+        instr_ = d->ReadInstructions();
         type_ = type;
         type_.SetTypeTestingStub(instr_);
       }
@@ -3154,8 +3167,7 @@
       type->ptr()->token_pos_ = d->ReadTokenPosition();
       type->ptr()->type_state_ = d->Read<int8_t>();
       if (d->kind() == Snapshot::kFullAOT) {
-        const int32_t text_offset = d->Read<int32_t>();
-        instr_ = d->GetInstructionsAt(text_offset);
+        instr_ = d->ReadInstructions();
         type_ = type;
         type_.SetTypeTestingStub(instr_);
       }
@@ -3164,9 +3176,9 @@
     // The dynamic/void objects are not serialized, so we manually send
     // the type testing stub for it.
     if (d->kind() == Snapshot::kFullAOT && is_vm_isolate) {
-      instr_ = d->GetInstructionsAt(d->Read<int32_t>());
+      instr_ = d->ReadInstructions();
       Type::dynamic_type().SetTypeTestingStub(instr_);
-      instr_ = d->GetInstructionsAt(d->Read<int32_t>());
+      instr_ = d->ReadInstructions();
       Type::void_type().SetTypeTestingStub(instr_);
     }
   }
@@ -3234,8 +3246,7 @@
       if (s->kind() == Snapshot::kFullAOT) {
         RawInstructions* instr = type_testing_stubs_.LookupByAddresss(
             type->ptr()->type_test_stub_entry_point_);
-        const int32_t text_offset = s->GetTextOffset(instr, Code::null());
-        s->Write<int32_t>(text_offset);
+        s->WriteInstructions(instr, Code::null());
       }
     }
   }
@@ -3275,8 +3286,7 @@
         *p = d->ReadRef();
       }
       if (d->kind() == Snapshot::kFullAOT) {
-        const int32_t text_offset = d->Read<int32_t>();
-        instr_ = d->GetInstructionsAt(text_offset);
+        instr_ = d->ReadInstructions();
         type_ = type;
         type_.SetTypeTestingStub(instr_);
       }
@@ -3334,8 +3344,7 @@
       if (s->kind() == Snapshot::kFullAOT) {
         RawInstructions* instr = type_testing_stubs_.LookupByAddresss(
             type->ptr()->type_test_stub_entry_point_);
-        const int32_t text_offset = s->GetTextOffset(instr, Code::null());
-        s->Write<int32_t>(text_offset);
+        s->WriteInstructions(instr, Code::null());
       }
     }
   }
@@ -3380,8 +3389,7 @@
       type->ptr()->index_ = d->Read<int16_t>();
       type->ptr()->type_state_ = d->Read<int8_t>();
       if (d->kind() == Snapshot::kFullAOT) {
-        const int32_t text_offset = d->Read<int32_t>();
-        instr_ = d->GetInstructionsAt(text_offset);
+        instr_ = d->ReadInstructions();
         type_ = type;
         type_.SetTypeTestingStub(instr_);
       }
@@ -4819,14 +4827,19 @@
 #endif  // !DART_PRECOMPILED_RUNTIME
 }
 
-int32_t Serializer::GetTextOffset(RawInstructions* instr, RawCode* code) const {
+void Serializer::WriteInstructions(RawInstructions* instr, RawCode* code) {
   intptr_t offset = heap_->GetObjectId(instr);
   if (offset == 0) {
     offset = image_writer_->GetTextOffsetFor(instr, code);
     ASSERT(offset != 0);
     heap_->SetObjectId(instr, offset);
   }
-  return offset;
+  Write<int32_t>(offset);
+}
+
+bool Serializer::GetSharedDataOffset(RawObject* object,
+                                     uint32_t* offset) const {
+  return image_writer_->GetSharedDataOffsetFor(object, offset);
 }
 
 uint32_t Serializer::GetDataOffset(RawObject* object) const {
@@ -5100,8 +5113,7 @@
 }
 
 intptr_t Serializer::WriteVMSnapshot(const Array& symbols,
-                                     ZoneGrowableArray<Object*>* seed_objects,
-                                     ZoneGrowableArray<Code*>* seed_code) {
+                                     ZoneGrowableArray<Object*>* seeds) {
   NoSafepointScope no_safepoint;
 
   AddVMIsolateBaseObjects();
@@ -5113,15 +5125,9 @@
       Push(StubCode::EntryAt(i)->code());
     }
   }
-  if (seed_objects != NULL) {
-    for (intptr_t i = 0; i < seed_objects->length(); i++) {
-      Push((*seed_objects)[i]->raw());
-    }
-  }
-  if (seed_code != NULL) {
-    for (intptr_t i = 0; i < seed_code->length(); i++) {
-      Code* code = (*seed_code)[i];
-      GetTextOffset(code->instructions(), code->raw());
+  if (seeds != NULL) {
+    for (intptr_t i = 0; i < seeds->length(); i++) {
+      Push((*seeds)[i]->raw());
     }
   }
 
@@ -5147,27 +5153,6 @@
   return next_ref_index_ - 1;
 }
 
-// Collects Instructions from the VM isolate and adds them to object id table
-// with offsets that will refer to the VM snapshot, causing them to be shared
-// across isolates.
-class SeedInstructionsVisitor : public ObjectVisitor {
- public:
-  SeedInstructionsVisitor(uword text_base, Heap* heap)
-      : text_base_(text_base), heap_(heap) {}
-
-  void VisitObject(RawObject* obj) {
-    if (obj->IsInstructions()) {
-      uword addr = RawObject::ToAddr(obj);
-      uint32_t offset = addr - text_base_;
-      heap_->SetObjectId(obj, -offset);
-    }
-  }
-
- private:
-  uword text_base_;
-  Heap* heap_;
-};
-
 void Serializer::WriteIsolateSnapshot(intptr_t num_base_objects,
                                       ObjectStore* object_store) {
   NoSafepointScope no_safepoint;
@@ -5178,12 +5163,6 @@
     for (intptr_t i = 1; i < base_objects.Length(); i++) {
       AddBaseObject(base_objects.At(i));
     }
-    const uint8_t* text_base = Dart::vm_snapshot_instructions();
-    if (text_base != NULL) {
-      SeedInstructionsVisitor visitor(reinterpret_cast<uword>(text_base),
-                                      heap_);
-      Dart::vm_isolate()->heap()->VisitObjectsImagePages(&visitor);
-    }
   } else {
     // Base objects carried over from WriteVMIsolateSnapshot.
     num_base_objects_ += num_base_objects;
@@ -5215,8 +5194,10 @@
                            Snapshot::Kind kind,
                            const uint8_t* buffer,
                            intptr_t size,
+                           const uint8_t* data_buffer,
                            const uint8_t* instructions_buffer,
-                           const uint8_t* data_buffer)
+                           const uint8_t* shared_data_buffer,
+                           const uint8_t* shared_instructions_buffer)
     : StackResource(thread),
       heap_(thread->isolate()->heap()),
       zone_(thread->zone()),
@@ -5229,7 +5210,9 @@
   if (Snapshot::IncludesCode(kind)) {
     ASSERT(instructions_buffer != NULL);
     ASSERT(data_buffer != NULL);
-    image_reader_ = new (zone_) ImageReader(instructions_buffer, data_buffer);
+    image_reader_ =
+        new (zone_) ImageReader(data_buffer, instructions_buffer,
+                                shared_data_buffer, shared_instructions_buffer);
   }
 }
 
@@ -5431,7 +5414,8 @@
   return ApiError::null();
 }
 
-RawInstructions* Deserializer::GetInstructionsAt(int32_t offset) const {
+RawInstructions* Deserializer::ReadInstructions() {
+  int32_t offset = Read<int32_t>();
   return image_reader_->GetInstructionsAt(offset);
 }
 
@@ -5439,6 +5423,10 @@
   return image_reader_->GetObjectAt(offset);
 }
 
+RawObject* Deserializer::GetSharedObjectAt(uint32_t offset) const {
+  return image_reader_->GetSharedObjectAt(offset);
+}
+
 void Deserializer::Prepare() {
   num_base_objects_ = ReadUnsigned();
   num_objects_ = ReadUnsigned();
@@ -5622,6 +5610,8 @@
     refs_ = NULL;
   }
 
+  thread()->isolate()->class_table()->CopySizesFromClassObjects();
+
 #if defined(DEBUG)
   Isolate* isolate = thread()->isolate();
   isolate->ValidateClassTable();
@@ -5644,8 +5634,7 @@
   SeedVMIsolateVisitor(Zone* zone, bool include_code)
       : zone_(zone),
         include_code_(include_code),
-        objects_(new (zone) ZoneGrowableArray<Object*>(4 * KB)),
-        codes_(new (zone) ZoneGrowableArray<Code*>(4 * KB)),
+        seeds_(new (zone) ZoneGrowableArray<Object*>(4 * KB)),
         script_(Script::Handle(zone)),
         code_(Code::Handle(zone)),
         stack_maps_(Array::Handle(zone)),
@@ -5659,7 +5648,7 @@
     }
 
     library_ = cls.library();
-    objects_->Add(&Object::Handle(zone_, library_.kernel_data()));
+    AddSeed(library_.kernel_data());
 
     if (!include_code_) return;
 
@@ -5684,45 +5673,40 @@
   void Visit(const Script& script) {
     kernel_program_info_ = script_.kernel_program_info();
     if (!kernel_program_info_.IsNull()) {
-      objects_->Add(
-          &Object::Handle(zone_, kernel_program_info_.string_offsets()));
-      objects_->Add(&Object::Handle(zone_, kernel_program_info_.string_data()));
-      objects_->Add(
-          &Object::Handle(zone_, kernel_program_info_.canonical_names()));
-      objects_->Add(
-          &Object::Handle(zone_, kernel_program_info_.metadata_payloads()));
-      objects_->Add(
-          &Object::Handle(zone_, kernel_program_info_.metadata_mappings()));
-      objects_->Add(&Object::Handle(zone_, kernel_program_info_.constants()));
+      AddSeed(kernel_program_info_.string_offsets());
+      AddSeed(kernel_program_info_.string_data());
+      AddSeed(kernel_program_info_.canonical_names());
+      AddSeed(kernel_program_info_.metadata_payloads());
+      AddSeed(kernel_program_info_.metadata_mappings());
+      AddSeed(kernel_program_info_.constants());
     } else {
-      objects_->Add(&Object::Handle(zone_, script_.tokens()));
+      AddSeed(script_.tokens());
     }
   }
 
-  ZoneGrowableArray<Object*>* objects() { return objects_; }
-  ZoneGrowableArray<Code*>* codes() { return codes_; }
+  ZoneGrowableArray<Object*>* seeds() { return seeds_; }
 
  private:
   void Visit(const Code& code) {
     ASSERT(include_code_);
     if (code.IsNull()) return;
 
-    codes_->Add(&Code::Handle(zone_, code.raw()));
-    objects_->Add(&Object::Handle(zone_, code.pc_descriptors()));
-    objects_->Add(&Object::Handle(zone_, code.code_source_map()));
+    AddSeed(code.pc_descriptors());
+    AddSeed(code.code_source_map());
 
     stack_maps_ = code_.stackmaps();
     if (!stack_maps_.IsNull()) {
       for (intptr_t i = 0; i < stack_maps_.Length(); i++) {
-        objects_->Add(&Object::Handle(zone_, stack_maps_.At(i)));
+        AddSeed(stack_maps_.At(i));
       }
     }
   }
 
+  void AddSeed(RawObject* seed) { seeds_->Add(&Object::Handle(zone_, seed)); }
+
   Zone* zone_;
   bool include_code_;
-  ZoneGrowableArray<Object*>* objects_;
-  ZoneGrowableArray<Code*>* codes_;
+  ZoneGrowableArray<Object*>* seeds_;
   Script& script_;
   Code& code_;
   Array& stack_maps_;
@@ -5745,8 +5729,7 @@
       isolate_snapshot_size_(0),
       vm_image_writer_(vm_image_writer),
       isolate_image_writer_(isolate_image_writer),
-      seed_objects_(NULL),
-      seed_code_(NULL),
+      seeds_(NULL),
       saved_symbol_table_(Array::Handle(zone())),
       new_vm_symbol_table_(Array::Handle(zone())),
       clustered_vm_size_(0),
@@ -5777,8 +5760,7 @@
                                  Snapshot::IncludesCode(kind));
     ProgramVisitor::VisitClasses(&visitor);
     ProgramVisitor::VisitFunctions(&visitor);
-    seed_objects_ = visitor.objects();
-    seed_code_ = visitor.codes();
+    seeds_ = visitor.seeds();
 
     // Tuck away the current symbol table.
     saved_symbol_table_ = object_store->symbol_table();
@@ -5819,9 +5801,9 @@
   // VM snapshot roots are:
   // - the symbol table
   // - all the token streams
-  // - the stub code (precompiled snapshots only)
-  intptr_t num_objects = serializer.WriteVMSnapshot(new_vm_symbol_table_,
-                                                    seed_objects_, seed_code_);
+  // - the stub code (App-AOT, App-JIT or Core-JIT)
+  intptr_t num_objects =
+      serializer.WriteVMSnapshot(new_vm_symbol_table_, seeds_);
   serializer.FillHeader(serializer.kind());
   clustered_vm_size_ = serializer.bytes_written();
 
@@ -5893,30 +5875,30 @@
   }
 }
 
-static const uint8_t* DataBuffer(const Snapshot* snapshot) {
-  if (Snapshot::IncludesCode(snapshot->kind())) {
-    uword offset =
-        Utils::RoundUp(snapshot->length(), OS::kMaxPreferredCodeAlignment);
-    return snapshot->Addr() + offset;
-  }
-  return NULL;
-}
-
 FullSnapshotReader::FullSnapshotReader(const Snapshot* snapshot,
                                        const uint8_t* instructions_buffer,
+                                       const uint8_t* shared_data,
+                                       const uint8_t* shared_instructions,
                                        Thread* thread)
     : kind_(snapshot->kind()),
       thread_(thread),
       buffer_(snapshot->content()),
       size_(snapshot->length()),
-      instructions_buffer_(instructions_buffer),
-      data_buffer_(DataBuffer(snapshot)) {
+      data_image_(snapshot->DataImage()),
+      instructions_image_(instructions_buffer) {
   thread->isolate()->set_compilation_allowed(kind_ != Snapshot::kFullAOT);
+
+  if (shared_data == NULL) {
+    shared_data_image_ = NULL;
+  } else {
+    shared_data_image_ = Snapshot::SetupFromBuffer(shared_data)->DataImage();
+  }
+  shared_instructions_image_ = shared_instructions;
 }
 
 RawApiError* FullSnapshotReader::ReadVMSnapshot() {
-  Deserializer deserializer(thread_, kind_, buffer_, size_,
-                            instructions_buffer_, data_buffer_);
+  Deserializer deserializer(thread_, kind_, buffer_, size_, data_image_,
+                            instructions_image_, NULL, NULL);
 
   RawApiError* error = deserializer.VerifyVersionAndFeatures(/*isolate=*/NULL);
   if (error != ApiError::null()) {
@@ -5924,13 +5906,12 @@
   }
 
   if (Snapshot::IncludesCode(kind_)) {
-    ASSERT(instructions_buffer_ != NULL);
-    thread_->isolate()->SetupImagePage(instructions_buffer_,
-                                       /* is_executable */ true);
-    ASSERT(data_buffer_ != NULL);
-    thread_->isolate()->SetupImagePage(data_buffer_,
+    ASSERT(data_image_ != NULL);
+    thread_->isolate()->SetupImagePage(data_image_,
                                        /* is_executable */ false);
-    Dart::set_vm_snapshot_instructions(instructions_buffer_);
+    ASSERT(instructions_image_ != NULL);
+    thread_->isolate()->SetupImagePage(instructions_image_,
+                                       /* is_executable */ true);
   }
 
   deserializer.ReadVMSnapshot();
@@ -5939,8 +5920,9 @@
 }
 
 RawApiError* FullSnapshotReader::ReadIsolateSnapshot() {
-  Deserializer deserializer(thread_, kind_, buffer_, size_,
-                            instructions_buffer_, data_buffer_);
+  Deserializer deserializer(thread_, kind_, buffer_, size_, data_image_,
+                            instructions_image_, shared_data_image_,
+                            shared_instructions_image_);
 
   RawApiError* error =
       deserializer.VerifyVersionAndFeatures(thread_->isolate());
@@ -5949,12 +5931,20 @@
   }
 
   if (Snapshot::IncludesCode(kind_)) {
-    ASSERT(instructions_buffer_ != NULL);
-    thread_->isolate()->SetupImagePage(instructions_buffer_,
-                                       /* is_executable */ true);
-    ASSERT(data_buffer_ != NULL);
-    thread_->isolate()->SetupImagePage(data_buffer_,
+    ASSERT(data_image_ != NULL);
+    thread_->isolate()->SetupImagePage(data_image_,
                                        /* is_executable */ false);
+    ASSERT(instructions_image_ != NULL);
+    thread_->isolate()->SetupImagePage(instructions_image_,
+                                       /* is_executable */ true);
+    if (shared_data_image_ != NULL) {
+      thread_->isolate()->SetupImagePage(shared_data_image_,
+                                         /* is_executable */ false);
+    }
+    if (shared_instructions_image_ != NULL) {
+      thread_->isolate()->SetupImagePage(shared_instructions_image_,
+                                         /* is_executable */ true);
+    }
   }
 
   deserializer.ReadIsolateSnapshot(thread_->isolate()->object_store());
diff --git a/runtime/vm/clustered_snapshot.h b/runtime/vm/clustered_snapshot.h
index c9e4970..1e2da8c 100644
--- a/runtime/vm/clustered_snapshot.h
+++ b/runtime/vm/clustered_snapshot.h
@@ -136,8 +136,7 @@
   ~Serializer();
 
   intptr_t WriteVMSnapshot(const Array& symbols,
-                           ZoneGrowableArray<Object*>* seed_objects,
-                           ZoneGrowableArray<Code*>* seed_code);
+                           ZoneGrowableArray<Object*>* seeds);
   void WriteIsolateSnapshot(intptr_t num_base_objects,
                             ObjectStore* object_store);
 
@@ -254,7 +253,8 @@
     Write<int32_t>(cid);
   }
 
-  int32_t GetTextOffset(RawInstructions* instr, RawCode* code) const;
+  void WriteInstructions(RawInstructions* instr, RawCode* code);
+  bool GetSharedDataOffset(RawObject* object, uint32_t* offset) const;
   uint32_t GetDataOffset(RawObject* object) const;
   intptr_t GetDataSize() const;
   intptr_t GetTextSize() const;
@@ -293,8 +293,10 @@
                Snapshot::Kind kind,
                const uint8_t* buffer,
                intptr_t size,
+               const uint8_t* data_buffer,
                const uint8_t* instructions_buffer,
-               const uint8_t* data_buffer);
+               const uint8_t* shared_data_buffer,
+               const uint8_t* shared_instructions_buffer);
   ~Deserializer();
 
   void ReadIsolateSnapshot(ObjectStore* object_store);
@@ -350,8 +352,9 @@
     return Read<int32_t>();
   }
 
-  RawInstructions* GetInstructionsAt(int32_t offset) const;
+  RawInstructions* ReadInstructions();
   RawObject* GetObjectAt(uint32_t offset) const;
+  RawObject* GetSharedObjectAt(uint32_t offset) const;
 
   RawApiError* VerifyVersionAndFeatures(Isolate* isolate);
 
@@ -423,8 +426,7 @@
   ForwardList* forward_list_;
   ImageWriter* vm_image_writer_;
   ImageWriter* isolate_image_writer_;
-  ZoneGrowableArray<Object*>* seed_objects_;
-  ZoneGrowableArray<Code*>* seed_code_;
+  ZoneGrowableArray<Object*>* seeds_;
   Array& saved_symbol_table_;
   Array& new_vm_symbol_table_;
 
@@ -441,6 +443,8 @@
  public:
   FullSnapshotReader(const Snapshot* snapshot,
                      const uint8_t* instructions_buffer,
+                     const uint8_t* shared_data,
+                     const uint8_t* shared_instructions,
                      Thread* thread);
   ~FullSnapshotReader() {}
 
@@ -452,8 +456,10 @@
   Thread* thread_;
   const uint8_t* buffer_;
   intptr_t size_;
-  const uint8_t* instructions_buffer_;
-  const uint8_t* data_buffer_;
+  const uint8_t* data_image_;
+  const uint8_t* instructions_image_;
+  const uint8_t* shared_data_image_;
+  const uint8_t* shared_instructions_image_;
 
   DISALLOW_COPY_AND_ASSIGN(FullSnapshotReader);
 };
diff --git a/runtime/vm/code_descriptors.cc b/runtime/vm/code_descriptors.cc
index 1682003..206c249 100644
--- a/runtime/vm/code_descriptors.cc
+++ b/runtime/vm/code_descriptors.cc
@@ -24,13 +24,15 @@
 
     PcDescriptors::EncodeInteger(&encoded_data_, merged_kind_try);
     PcDescriptors::EncodeInteger(&encoded_data_, pc_offset - prev_pc_offset);
-    PcDescriptors::EncodeInteger(&encoded_data_, deopt_id - prev_deopt_id);
-    PcDescriptors::EncodeInteger(&encoded_data_,
-                                 token_pos.value() - prev_token_pos);
-
     prev_pc_offset = pc_offset;
-    prev_deopt_id = deopt_id;
-    prev_token_pos = token_pos.value();
+
+    if (!FLAG_precompiled_mode) {
+      PcDescriptors::EncodeInteger(&encoded_data_, deopt_id - prev_deopt_id);
+      PcDescriptors::EncodeInteger(&encoded_data_,
+                                   token_pos.value() - prev_token_pos);
+      prev_deopt_id = deopt_id;
+      prev_token_pos = token_pos.value();
+    }
   }
 }
 
@@ -366,6 +368,15 @@
   }
 }
 
+void CodeSourceMapBuilder::NoteNullCheck(int32_t pc_offset,
+                                         TokenPosition pos,
+                                         intptr_t name_index) {
+  BufferChangePosition(pos);
+  BufferAdvancePC(pc_offset - buffered_pc_offset_);
+  FlushBuffer();
+  WriteNullCheck(name_index);
+}
+
 intptr_t CodeSourceMapBuilder::GetFunctionId(intptr_t inline_id) {
   const Function& function = *inline_id_to_function_[inline_id];
   for (intptr_t i = 0; i < inlined_functions_.Length(); i++) {
@@ -459,6 +470,10 @@
         token_positions->RemoveLast();
         break;
       }
+      case CodeSourceMapBuilder::kNullCheck: {
+        stream.Read<int32_t>();
+        break;
+      }
       default:
         UNREACHABLE();
     }
@@ -516,6 +531,10 @@
         function_stack.RemoveLast();
         break;
       }
+      case CodeSourceMapBuilder::kNullCheck: {
+        stream.Read<int32_t>();
+        break;
+      }
       default:
         UNREACHABLE();
     }
@@ -563,6 +582,10 @@
         function_stack.RemoveLast();
         break;
       }
+      case CodeSourceMapBuilder::kNullCheck: {
+        stream.Read<int32_t>();
+        break;
+      }
       default:
         UNREACHABLE();
     }
@@ -617,6 +640,13 @@
         token_positions.RemoveLast();
         break;
       }
+      case CodeSourceMapBuilder::kNullCheck: {
+        const intptr_t name_index = stream.Read<int32_t>();
+        THR_Print("%" Px "-%" Px ": null check PP#%" Pd "\n",
+                  start + current_pc_offset, start + current_pc_offset,
+                  name_index);
+        break;
+      }
       default:
         UNREACHABLE();
     }
@@ -624,4 +654,46 @@
   THR_Print("}\n");
 }
 
+intptr_t CodeSourceMapReader::GetNullCheckNameIndexAt(int32_t pc_offset) {
+  NoSafepointScope no_safepoint;
+  ReadStream stream(map_.Data(), map_.Length());
+
+  int32_t current_pc_offset = 0;
+
+  while (stream.PendingBytes() > 0) {
+    uint8_t opcode = stream.Read<uint8_t>();
+    switch (opcode) {
+      case CodeSourceMapBuilder::kChangePosition: {
+        stream.Read<int32_t>();
+        break;
+      }
+      case CodeSourceMapBuilder::kAdvancePC: {
+        int32_t delta = stream.Read<int32_t>();
+        current_pc_offset += delta;
+        RELEASE_ASSERT(current_pc_offset <= pc_offset);
+        break;
+      }
+      case CodeSourceMapBuilder::kPushFunction: {
+        stream.Read<int32_t>();
+        break;
+      }
+      case CodeSourceMapBuilder::kPopFunction: {
+        break;
+      }
+      case CodeSourceMapBuilder::kNullCheck: {
+        const int32_t name_index = stream.Read<int32_t>();
+        if (current_pc_offset == pc_offset) {
+          return name_index;
+        }
+        break;
+      }
+      default:
+        UNREACHABLE();
+    }
+  }
+
+  UNREACHABLE();
+  return -1;
+}
+
 }  // namespace dart
diff --git a/runtime/vm/code_descriptors.h b/runtime/vm/code_descriptors.h
index c31b4a1..6c0daab 100644
--- a/runtime/vm/code_descriptors.h
+++ b/runtime/vm/code_descriptors.h
@@ -222,6 +222,7 @@
   static const uint8_t kAdvancePC = 1;
   static const uint8_t kPushFunction = 2;
   static const uint8_t kPopFunction = 3;
+  static const uint8_t kNullCheck = 4;
 
   void StartInliningInterval(int32_t pc_offset, intptr_t inline_id);
   void BeginCodeSourceRange(int32_t pc_offset);
@@ -229,6 +230,7 @@
   void NoteDescriptor(RawPcDescriptors::Kind kind,
                       int32_t pc_offset,
                       TokenPosition pos);
+  void NoteNullCheck(int32_t pc_offset, TokenPosition pos, intptr_t name_index);
 
   RawArray* InliningIdToFunction();
   RawCodeSourceMap* Finalize();
@@ -265,6 +267,10 @@
     written_inline_id_stack_.RemoveLast();
     written_token_pos_stack_.RemoveLast();
   }
+  void WriteNullCheck(int32_t name_index) {
+    stream_.Write<uint8_t>(kNullCheck);
+    stream_.Write<int32_t>(name_index);
+  }
 
   void FlushBuffer();
   void FlushBufferStack();
@@ -314,6 +320,8 @@
   void DumpInlineIntervals(uword start);
   void DumpSourcePositions(uword start);
 
+  intptr_t GetNullCheckNameIndexAt(int32_t pc_offset);
+
  private:
   const CodeSourceMap& map_;
   const Array& functions_;
diff --git a/runtime/vm/compiler/aot/aot_call_specializer.cc b/runtime/vm/compiler/aot/aot_call_specializer.cc
index caedbd7..4fea9a6 100644
--- a/runtime/vm/compiler/aot/aot_call_specializer.cc
+++ b/runtime/vm/compiler/aot/aot_call_specializer.cc
@@ -289,7 +289,12 @@
   ASSERT((cid == kDoubleCid) ||
          (FLAG_limit_ints_to_64_bits && (cid == kMintCid)));
 
-  AddCheckNull(input, call->deopt_id(), call->env(), call);
+  const String& function_name =
+      (call->IsInstanceCall()
+           ? call->AsInstanceCall()->function_name()
+           : String::ZoneHandle(Z, call->AsStaticCall()->function().name()));
+
+  AddCheckNull(input, function_name, call->deopt_id(), call->env(), call);
 
   input = input->CopyWithType(Z);
 
diff --git a/runtime/vm/compiler/assembler/assembler_arm.cc b/runtime/vm/compiler/assembler/assembler_arm.cc
index 2d7bfca..86e7876 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm.cc
@@ -1745,7 +1745,7 @@
   const intptr_t offset =
       Isolate::class_table_offset() + ClassTable::table_offset();
   LoadFromOffset(kWord, result, result, offset);
-  ldr(result, Address(result, class_id, LSL, 2));
+  ldr(result, Address(result, class_id, LSL, kSizeOfClassPairLog2));
 }
 
 void Assembler::LoadClass(Register result, Register object, Register scratch) {
diff --git a/runtime/vm/compiler/assembler/assembler_arm.h b/runtime/vm/compiler/assembler/assembler_arm.h
index ab6f811..9b81f54 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.h
+++ b/runtime/vm/compiler/assembler/assembler_arm.h
@@ -141,6 +141,11 @@
                 static_cast<uint32_t>(rm);
   }
 
+  static bool CanHold(uint32_t immediate) {
+    Operand dummy;
+    return CanHold(immediate, &dummy);
+  }
+
   static bool CanHold(uint32_t immediate, Operand* o) {
     // Avoid the more expensive test for frequent small immediate values.
     if (immediate < (1 << kImmed8Bits)) {
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.cc b/runtime/vm/compiler/assembler/assembler_arm64.cc
index e28333f..255c85b 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm64.cc
@@ -660,24 +660,43 @@
   blr(TMP);
 }
 
-void Assembler::AddImmediate(Register dest, Register rn, int64_t imm) {
+void Assembler::AddImmediate(Register dest,
+                             Register rn,
+                             int64_t imm,
+                             OperandSize sz) {
   Operand op;
   if (imm == 0) {
     if (dest != rn) {
-      mov(dest, rn);
+      if (sz == kWord) {
+        uxtw(dest, rn);
+      } else {
+        mov(dest, rn);
+      }
     }
     return;
   }
   if (Operand::CanHold(imm, kXRegSizeInBits, &op) == Operand::Immediate) {
-    add(dest, rn, op);
+    if (sz == kDoubleWord) {
+      add(dest, rn, op);
+    } else {
+      addw(dest, rn, op);
+    }
   } else if (Operand::CanHold(-imm, kXRegSizeInBits, &op) ==
              Operand::Immediate) {
-    sub(dest, rn, op);
+    if (sz == kDoubleWord) {
+      sub(dest, rn, op);
+    } else {
+      subw(dest, rn, op);
+    }
   } else {
     // TODO(zra): Try adding top 12 bits, then bottom 12 bits.
     ASSERT(rn != TMP2);
     LoadImmediate(TMP2, imm);
-    add(dest, rn, Operand(TMP2));
+    if (sz == kDoubleWord) {
+      add(dest, rn, Operand(TMP2));
+    } else {
+      addw(dest, rn, Operand(TMP2));
+    }
   }
 }
 
@@ -1030,6 +1049,8 @@
   const intptr_t offset =
       Isolate::class_table_offset() + ClassTable::table_offset();
   LoadFromOffset(result, result, offset);
+  ASSERT(kSizeOfClassPairLog2 == 4);
+  add(class_id, class_id, Operand(class_id));
   ldr(result, Address(result, class_id, UXTX, Address::Scaled));
 }
 
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.h b/runtime/vm/compiler/assembler/assembler_arm64.h
index 373f848..437c246 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.h
+++ b/runtime/vm/compiler/assembler/assembler_arm64.h
@@ -390,6 +390,17 @@
   // undefined.
   static bool IsImmLogical(uint64_t value, uint8_t width, Operand* imm_op);
 
+  static bool IsImmLogical(int64_t imm) {
+    Operand operand;
+    return IsImmLogical(imm, kXRegSizeInBits, &operand);
+  }
+
+  static bool IsImmArithmethic(int64_t imm) {
+    Operand operand;
+    CanHold(imm, kXRegSizeInBits, &operand);
+    return operand.type_ == Immediate;
+  }
+
   // An immediate imm can be an operand to add/sub when the return value is
   // Immediate, or a logical operation over sz bits when the return value is
   // BitfieldImm. If the return value is Unknown, then the immediate can't be
@@ -1069,12 +1080,18 @@
     const Register crn = ConcreteRegister(rn);
     EmitFPIntCvtOp(SCVTFD, static_cast<Register>(vd), crn, kWord);
   }
-  void fcvtzds(Register rd, VRegister vn) {
+  void fcvtzdsx(Register rd, VRegister vn) {
     ASSERT(rd != R31);
     ASSERT(rd != CSP);
     const Register crd = ConcreteRegister(rd);
     EmitFPIntCvtOp(FCVTZDS, crd, static_cast<Register>(vn));
   }
+  void fcvtzdsw(Register rd, VRegister vn) {
+    ASSERT(rd != R31);
+    ASSERT(rd != CSP);
+    const Register crd = ConcreteRegister(rd);
+    EmitFPIntCvtOp(FCVTZDS, crd, static_cast<Register>(vn), kWord);
+  }
   void fmovdd(VRegister vd, VRegister vn) { EmitFPOneSourceOp(FMOVDD, vd, vn); }
   void fabsd(VRegister vd, VRegister vn) { EmitFPOneSourceOp(FABSD, vd, vn); }
   void fnegd(VRegister vd, VRegister vn) { EmitFPOneSourceOp(FNEGD, vd, vn); }
@@ -1365,9 +1382,17 @@
     LslImmediate(dst, src, kSmiTagSize);
   }
 
-  void BranchIfNotSmi(Register reg, Label* label) { tbnz(label, reg, kSmiTag); }
+  void BranchIfNotSmi(Register reg, Label* label) {
+    ASSERT(kSmiTagMask == 1);
+    ASSERT(kSmiTag == 0);
+    tbnz(label, reg, 0);
+  }
 
-  void BranchIfSmi(Register reg, Label* label) { tbz(label, reg, kSmiTag); }
+  void BranchIfSmi(Register reg, Label* label) {
+    ASSERT(kSmiTagMask == 1);
+    ASSERT(kSmiTag == 0);
+    tbz(label, reg, 0);
+  }
 
   void Branch(const StubEntry& stub_entry,
               Register pp,
@@ -1393,7 +1418,10 @@
   // the object pool when possible. Unless you are sure that the untagged object
   // pool pointer is in another register, or that it is not available at all,
   // PP should be passed for pp.
-  void AddImmediate(Register dest, Register rn, int64_t imm);
+  void AddImmediate(Register dest,
+                    Register rn,
+                    int64_t imm,
+                    OperandSize sz = kDoubleWord);
   void AddImmediateSetFlags(Register dest,
                             Register rn,
                             int64_t imm,
@@ -1451,6 +1479,11 @@
     kValueCanBeSmi,
   };
 
+  enum CanBeHeapPointer {
+    kValueIsNotHeapPointer,
+    kValueCanBeHeapPointer,
+  };
+
   // Storing into an object.
   void StoreIntoObject(Register object,
                        const Address& dest,
@@ -1500,6 +1533,7 @@
   void CompareObject(Register reg, const Object& object);
 
   void LoadClassId(Register result, Register object);
+  // Overwrites class_id register.
   void LoadClassById(Register result, Register class_id);
   void LoadClass(Register result, Register object);
   void CompareClassId(Register object,
@@ -1591,6 +1625,43 @@
                       Register tmp,
                       OperandSize sz);
 
+  void AssertSmiInRange(
+      Register object,
+      CanBeHeapPointer can_be_heap_pointer = kValueIsNotHeapPointer) {
+#if defined(DEBUG)
+    Label ok;
+    if (can_be_heap_pointer == kValueCanBeHeapPointer) {
+      BranchIfNotSmi(object, &ok);
+    }
+    cmp(object, Operand(object, SXTW, 0));
+    b(&ok, EQ);
+    Stop("Smi out of range");
+
+    Bind(&ok);
+#endif
+  }
+
+  void AssertValidUint32(Register r) {
+#if defined(DEBUG)
+    Label ok;
+    cmp(ZR, Operand(r, LSR, 32));
+    b(&ok, EQ);
+    Stop("uint32 should be zero extended");
+    Bind(&ok);
+#endif
+  }
+
+  void AssertValidSignExtendedInt32(Register r) {
+#if defined(DEBUGFOO)
+    Label ok;
+    AsrImmediate(TMP, r, 63);  // 0 or -1.
+    cmp(TMP, Operand(r, ASR, 31));
+    b(&ok, EQ);
+    Stop("int32 should be sign extended");
+    Bind(&ok);
+#endif
+  }
+
  private:
   AssemblerBuffer buffer_;  // Contains position independent code.
   ObjectPoolWrapper object_pool_wrapper_;
diff --git a/runtime/vm/compiler/assembler/assembler_arm64_test.cc b/runtime/vm/compiler/assembler/assembler_arm64_test.cc
index a41fad24..523688b 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64_test.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm64_test.cc
@@ -2576,17 +2576,73 @@
   EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
-ASSEMBLER_TEST_GENERATE(Fcvtzds, assembler) {
+ASSEMBLER_TEST_GENERATE(Fcvtzdsx, assembler) {
   __ LoadDImmediate(V0, 42.0);
-  __ fcvtzds(R0, V0);
+  __ fcvtzdsx(R0, V0);
   __ ret();
 }
 
-ASSEMBLER_TEST_RUN(Fcvtzds, test) {
+ASSEMBLER_TEST_RUN(Fcvtzdsx, test) {
   typedef int64_t (*Int64Return)() DART_UNUSED;
   EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
+ASSEMBLER_TEST_GENERATE(Fcvtzdsw, assembler) {
+  __ LoadDImmediate(V0, 42.0);
+  __ fcvtzdsw(R0, V0);
+  __ ret();
+}
+
+ASSEMBLER_TEST_RUN(Fcvtzdsw, test) {
+  typedef int64_t (*Int64Return)() DART_UNUSED;
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
+}
+
+ASSEMBLER_TEST_GENERATE(Fcvtzdsx_overflow, assembler) {
+  __ LoadDImmediate(V0, 1e20);
+  __ fcvtzdsx(R0, V0);
+  __ ret();
+}
+
+ASSEMBLER_TEST_RUN(Fcvtzdsx_overflow, test) {
+  typedef int64_t (*Int64Return)() DART_UNUSED;
+  EXPECT_EQ(kMaxInt64, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
+}
+
+ASSEMBLER_TEST_GENERATE(Fcvtzdsx_overflow_negative, assembler) {
+  __ LoadDImmediate(V0, -1e20);
+  __ fcvtzdsx(R0, V0);
+  __ ret();
+}
+
+ASSEMBLER_TEST_RUN(Fcvtzdsx_overflow_negative, test) {
+  typedef int64_t (*Int64Return)() DART_UNUSED;
+  EXPECT_EQ(kMinInt64, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
+}
+
+ASSEMBLER_TEST_GENERATE(Fcvtzdsw_overflow, assembler) {
+  __ LoadDImmediate(V0, 1e10);
+  __ fcvtzdsw(R0, V0);
+  __ ret();
+}
+
+ASSEMBLER_TEST_RUN(Fcvtzdsw_overflow, test) {
+  typedef int64_t (*Int64Return)() DART_UNUSED;
+  EXPECT_EQ(kMaxInt32, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
+}
+
+ASSEMBLER_TEST_GENERATE(Fcvtzdsw_overflow_negative, assembler) {
+  __ LoadDImmediate(V0, -1e10);
+  __ fcvtzdsw(R0, V0);
+  __ sxtw(R0, R0);
+  __ ret();
+}
+
+ASSEMBLER_TEST_RUN(Fcvtzdsw_overflow_negative, test) {
+  typedef int64_t (*Int64Return)() DART_UNUSED;
+  EXPECT_EQ(kMinInt32, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
+}
+
 ASSEMBLER_TEST_GENERATE(Scvtfdx, assembler) {
   __ LoadImmediate(R0, 42);
   __ scvtfdx(V0, R0);
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.cc b/runtime/vm/compiler/assembler/assembler_ia32.cc
index 035c00b..0ba938b 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.cc
+++ b/runtime/vm/compiler/assembler/assembler_ia32.cc
@@ -2425,7 +2425,8 @@
   const intptr_t offset =
       Isolate::class_table_offset() + ClassTable::table_offset();
   movl(result, Address(result, offset));
-  movl(result, Address(result, class_id, TIMES_4, 0));
+  ASSERT(kSizeOfClassPairLog2 == 3);
+  movl(result, Address(result, class_id, TIMES_8, 0));
 }
 
 void Assembler::LoadClass(Register result, Register object, Register scratch) {
diff --git a/runtime/vm/compiler/assembler/assembler_x64.cc b/runtime/vm/compiler/assembler/assembler_x64.cc
index 72bbf42..e08f526 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64.cc
@@ -1887,6 +1887,10 @@
   const intptr_t offset =
       Isolate::class_table_offset() + ClassTable::table_offset();
   movq(result, Address(result, offset));
+  ASSERT(kSizeOfClassPairLog2 == 4);
+  // TIMES_16 is not a real scale factor on x64, so we double the class id
+  // and use TIMES_8.
+  addq(class_id, class_id);
   movq(result, Address(result, class_id, TIMES_8, 0));
 }
 
diff --git a/runtime/vm/compiler/assembler/assembler_x64.h b/runtime/vm/compiler/assembler/assembler_x64.h
index 5b85011..70c492a 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.h
+++ b/runtime/vm/compiler/assembler/assembler_x64.h
@@ -521,7 +521,10 @@
     return CompareImmediate(reg, Immediate(immediate));
   }
 
-  void testl(Register reg, const Immediate& imm) { testq(reg, imm); }
+  void testl(Register reg, const Immediate& imm) {
+    Immediate imm2(imm.value() & 0xffffffffll);
+    testq(reg, imm2);
+  }
   void testb(const Address& address, const Immediate& imm);
 
   void testq(Register reg, const Immediate& imm);
@@ -710,6 +713,11 @@
     kValueCanBeSmi,
   };
 
+  enum CanBeHeapPointer {
+    kValueIsNotHeapPointer,
+    kValueCanBeHeapPointer,
+  };
+
   // Destroys value.
   void StoreIntoObject(Register object,      // Object we are storing into.
                        const Address& dest,  // Where we are storing into.
@@ -766,6 +774,7 @@
   // Loading and comparing classes of objects.
   void LoadClassId(Register result, Register object);
 
+  // Overwrites class_id register.
   void LoadClassById(Register result, Register class_id);
 
   void LoadClass(Register result, Register object);
@@ -939,6 +948,26 @@
                                            Register array,
                                            Register index);
 
+  void AssertSmiInRange(
+      Register object,
+      CanBeHeapPointer can_be_heap_pointer = kValueIsNotHeapPointer) {
+#if defined(DEBUG)
+    Register tmp = object == TMP ? TMP2 : TMP;
+    Label ok;
+    if (can_be_heap_pointer == kValueCanBeHeapPointer) {
+      testl(object, Immediate(kSmiTagMask));
+      ASSERT(kSmiTag == 0);
+      j(ZERO, &ok);
+    }
+    movsxd(tmp, object);
+    cmpq(tmp, object);
+    j(EQUAL, &ok);
+    Stop("Smi out of range");
+
+    Bind(&ok);
+#endif
+  }
+
   static Address VMTagAddress() {
     return Address(THR, Thread::vm_tag_offset());
   }
@@ -948,6 +977,24 @@
   static bool IsSafe(const Object& object) { return true; }
   static bool IsSafeSmi(const Object& object) { return object.IsSmi(); }
 
+  void AssertValidUint32(Register r) {
+    Label ok;
+    movl(TMP, r);
+    cmpq(TMP, r);
+    j(EQUAL, &ok);
+    Stop("uint32 should be zero extended");
+    Bind(&ok);
+  }
+
+  void AssertValidSignExtendedInt32(Register r) {
+    Label ok;
+    movsxd(TMP, r);
+    cmpq(TMP, r);
+    j(EQUAL, &ok);
+    Stop("int32 should be sign extended");
+    Bind(&ok);
+  }
+
  private:
   AssemblerBuffer buffer_;
 
diff --git a/runtime/vm/compiler/backend/flow_graph.cc b/runtime/vm/compiler/backend/flow_graph.cc
index 499bfc7..df9fc5b 100644
--- a/runtime/vm/compiler/backend/flow_graph.cc
+++ b/runtime/vm/compiler/backend/flow_graph.cc
@@ -1643,10 +1643,14 @@
     }
 
     if (should_unbox) {
+#if defined(AVOID_UNBOXED_INT32)
+      unboxed = kUnboxedInt64;
+#else
       unboxed =
           RangeUtils::Fits(phi->range(), RangeBoundary::kRangeBoundaryInt32)
               ? kUnboxedInt32
               : kUnboxedInt64;
+#endif
     }
   }
 
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index e7b1a69..199e17c 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -589,13 +589,14 @@
 
 void FlowGraphCompiler::GenerateDeferredCode() {
   for (intptr_t i = 0; i < slow_path_code_.length(); i++) {
+    SlowPathCode* const slow_path = slow_path_code_[i];
     const CombinedCodeStatistics::EntryCounter stats_tag =
         CombinedCodeStatistics::SlowPathCounterFor(
-            slow_path_code_[i]->instruction()->tag());
+            slow_path->instruction()->tag());
     SpecialStatsBegin(stats_tag);
     BeginCodeSourceRange();
-    slow_path_code_[i]->GenerateCode(this);
-    EndCodeSourceRange(TokenPosition::kDeferredSlowPath);
+    slow_path->GenerateCode(this);
+    EndCodeSourceRange(slow_path->instruction()->token_pos());
     SpecialStatsEnd(stats_tag);
   }
   for (intptr_t i = 0; i < deopt_infos_.length(); i++) {
@@ -641,6 +642,13 @@
                 CurrentTryIndex());
 }
 
+void FlowGraphCompiler::AddNullCheck(intptr_t pc_offset,
+                                     TokenPosition token_pos,
+                                     intptr_t null_check_name_idx) {
+  code_source_map_builder_->NoteNullCheck(pc_offset, token_pos,
+                                          null_check_name_idx);
+}
+
 void FlowGraphCompiler::AddStaticCallTarget(const Function& func) {
   ASSERT(func.IsZoneHandle());
   static_calls_target_table_.Add(
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.h b/runtime/vm/compiler/backend/flow_graph_compiler.h
index f61ef7b..b4123f2 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.h
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.h
@@ -572,6 +572,10 @@
                      TokenPosition token_pos,
                      intptr_t try_index);
 
+  void AddNullCheck(intptr_t pc_offset,
+                    TokenPosition token_pos,
+                    intptr_t null_check_name_idx);
+
   void RecordSafepoint(LocationSummary* locs,
                        intptr_t slow_path_argument_count = 0);
 
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 4f2db6a..772b0e8 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -776,9 +776,7 @@
 
 const Object& Value::BoundConstant() const {
   ASSERT(BindsToConstant());
-  ConstantInstr* constant = definition()->AsConstant();
-  ASSERT(constant != NULL);
-  return constant->value();
+  return definition()->AsConstant()->value();
 }
 
 GraphEntryInstr::GraphEntryInstr(const ParsedFunction& parsed_function,
@@ -1585,10 +1583,10 @@
   return Utils::IsPowerOfTwo(Utils::Abs(int_value));
 }
 
-static intptr_t RepresentationBits(Representation r) {
+static intptr_t SignificantRepresentationBits(Representation r) {
   switch (r) {
     case kTagged:
-      return kBitsPerWord - 1;
+      return 31;
     case kUnboxedInt32:
     case kUnboxedUint32:
       return 32;
@@ -1602,7 +1600,7 @@
 
 static int64_t RepresentationMask(Representation r) {
   return static_cast<int64_t>(static_cast<uint64_t>(-1) >>
-                              (64 - RepresentationBits(r)));
+                              (64 - SignificantRepresentationBits(r)));
 }
 
 static bool ToIntegerConstant(Value* value, int64_t* result) {
@@ -1869,9 +1867,9 @@
 
     case Token::kBIT_NOT:
       if (value.IsSmi()) {
-        result = Integer::New(~Smi::Cast(value).Value());
+        result = Integer::New(~Smi::Cast(value).Value(), Heap::kOld);
       } else if (value.IsMint()) {
-        result = Integer::New(~Mint::Cast(value).value());
+        result = Integer::New(~Mint::Cast(value).value(), Heap::kOld);
       }
       break;
 
@@ -2106,7 +2104,7 @@
     case Token::kBIT_AND:
       if (rhs == 0) {
         return right()->definition();
-      } else if (rhs == range_mask) {
+      } else if ((rhs & range_mask) == range_mask) {
         return left()->definition();
       }
       break;
@@ -2163,7 +2161,8 @@
       break;
 
     case Token::kSHL: {
-      const intptr_t kMaxShift = RepresentationBits(representation()) - 1;
+      const intptr_t kMaxShift =
+          SignificantRepresentationBits(representation()) - 1;
       if (rhs == 0) {
         return left()->definition();
       } else if ((rhs < 0) || (rhs >= kMaxShift)) {
@@ -2494,9 +2493,11 @@
     Definition* replacement = this;
 
     switch (conv->from()) {
+#if !defined(AVOID_UNBOXED_INT32)
       case kUnboxedInt32:
         replacement = new BoxInt32Instr(conv->value()->CopyWithType());
         break;
+#endif
       case kUnboxedUint32:
         replacement = new BoxUint32Instr(conv->value()->CopyWithType());
         break;
@@ -2674,6 +2675,35 @@
     return replacement;
   }
 
+  if (value()->BindsToConstant()) {
+    const Object& input = value()->BoundConstant();
+    int64_t constant;
+    if (input.IsSmi()) {
+      constant = Smi::Cast(input).Value();
+    } else if (input.IsMint()) {
+      constant = Mint::Cast(input).value();
+    } else {
+      return this;
+    }
+    Definition* replacement = NULL;
+    if (to() == kUnboxedUint32) {
+      const Object& cast = Integer::Handle(
+          flow_graph->zone(),
+          Integer::New(static_cast<uint32_t>(constant), Heap::kOld));
+      replacement = new UnboxedConstantInstr(cast, kUnboxedUint32);
+    } else if (to() == kUnboxedInt32) {
+      const Object& cast = Integer::Handle(
+          flow_graph->zone(),
+          Integer::New(static_cast<int32_t>(constant), Heap::kOld));
+      replacement = new UnboxedConstantInstr(cast, kUnboxedUint32);
+    } else if (to() == kUnboxedInt64) {
+      replacement = new UnboxedConstantInstr(input, kUnboxedInt64);
+    }
+    if (replacement != NULL) {
+      flow_graph->InsertBefore(this, replacement, env(), FlowGraph::kValue);
+      return replacement;
+    }
+  }
   return this;
 }
 
@@ -3019,8 +3049,10 @@
 
 BoxInstr* BoxInstr::Create(Representation from, Value* value) {
   switch (from) {
+#if !defined(AVOID_UNBOXED_INT32)
     case kUnboxedInt32:
       return new BoxInt32Instr(value);
+#endif
 
     case kUnboxedUint32:
       return new BoxUint32Instr(value);
@@ -3045,10 +3077,11 @@
                                intptr_t deopt_id,
                                SpeculativeMode speculative_mode) {
   switch (to) {
+#if !defined(AVOID_UNBOXED_INT32)
     case kUnboxedInt32:
       return new UnboxInt32Instr(UnboxInt32Instr::kNoTruncation, value,
                                  deopt_id, speculative_mode);
-
+#endif
     case kUnboxedUint32:
       return new UnboxUint32Instr(value, deopt_id, speculative_mode);
 
@@ -3970,6 +4003,8 @@
 
   virtual const char* name() = 0;
 
+  virtual void AddMetadataForRuntimeCall(FlowGraphCompiler* compiler) {}
+
   virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
     if (Assembler::EmittingComments()) {
       __ Comment("slow path %s operation", name());
@@ -3985,6 +4020,7 @@
     compiler->AddDescriptor(
         RawPcDescriptors::kOther, compiler->assembler()->CodeSize(),
         instruction()->deopt_id(), instruction()->token_pos(), try_index_);
+    AddMetadataForRuntimeCall(compiler);
     compiler->RecordSafepoint(locs, num_args_);
     Environment* env = compiler->SlowPathEnvironmentFor(instruction());
     compiler->EmitCatchEntryState(env, try_index_);
@@ -4038,7 +4074,6 @@
 
 class NullErrorSlowPath : public ThrowErrorSlowPathCode {
  public:
-  // TODO(dartbug.com/30480): Pass arguments for NoSuchMethodError.
   static const intptr_t kNumberOfArguments = 0;
 
   NullErrorSlowPath(CheckNullInstr* instruction, intptr_t try_index)
@@ -4047,7 +4082,15 @@
                                kNumberOfArguments,
                                try_index) {}
 
-  virtual const char* name() { return "check null"; }
+  const char* name() override { return "check null"; }
+
+  void AddMetadataForRuntimeCall(FlowGraphCompiler* compiler) override {
+    const String& function_name = instruction()->AsCheckNull()->function_name();
+    const intptr_t name_index =
+        compiler->assembler()->object_pool_wrapper().FindObject(function_name);
+    compiler->AddNullCheck(compiler->assembler()->CodeSize(),
+                           instruction()->token_pos(), name_index);
+  }
 };
 
 void CheckNullInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
@@ -4750,7 +4793,7 @@
 // Make representaion from type name used by SIMD_OP_LIST.
 #define REP(T) (kUnboxed##T)
 static const Representation kUnboxedBool = kTagged;
-static const Representation kUnboxedInt8 = kUnboxedInt32;
+static const Representation kUnboxedInt8 = kUnboxedUint32;
 
 #define ENCODE_INPUTS_0()
 #define ENCODE_INPUTS_1(In0) REP(In0)
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index 829a16e..6fd8fdd 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -2012,7 +2012,12 @@
 
   virtual Representation representation() const { return representation_; }
 
-  virtual void set_representation(Representation r) { representation_ = r; }
+  virtual void set_representation(Representation r) {
+#if defined(AVOID_UNBOXED_INT32)
+    ASSERT(r != kUnboxedInt32);
+#endif
+    representation_ = r;
+  }
 
   virtual intptr_t Hashcode() const {
     UNREACHABLE();
@@ -2799,13 +2804,14 @@
 
   virtual TokenPosition token_pos() const { return token_pos_; }
 
-  bool IsUnboxedSignedIntegerConstant() const {
-    return representation() == kUnboxedInt32 ||
+  bool IsUnboxedIntegerConstant() const {
+    return representation() == kUnboxedUint32 ||
+           representation() == kUnboxedInt32 ||
            representation() == kUnboxedInt64;
   }
 
-  int64_t GetUnboxedSignedIntegerConstantValue() const {
-    ASSERT(IsUnboxedSignedIntegerConstant());
+  int64_t GetUnboxedIntegerConstantValue() const {
+    ASSERT(IsUnboxedIntegerConstant());
     return value_.IsSmi() ? Smi::Cast(value_).Value()
                           : Mint::Cast(value_).value();
   }
@@ -5428,7 +5434,11 @@
                             truncation_mode,
                             value,
                             deopt_id,
-                            speculative_mode) {}
+                            speculative_mode) {
+#if defined(AVOID_UNBOXED_INT32)
+    UNREACHABLE();
+#endif
+  }
 
   virtual bool ComputeCanDeoptimize() const;
 
@@ -6820,13 +6830,20 @@
 // execution proceeds to the next instruction.
 class CheckNullInstr : public TemplateInstruction<1, Throws, NoCSE> {
  public:
-  CheckNullInstr(Value* value, intptr_t deopt_id, TokenPosition token_pos)
-      : TemplateInstruction(deopt_id), token_pos_(token_pos) {
+  CheckNullInstr(Value* value,
+                 const String& function_name,
+                 intptr_t deopt_id,
+                 TokenPosition token_pos)
+      : TemplateInstruction(deopt_id),
+        token_pos_(token_pos),
+        function_name_(function_name) {
+    ASSERT(function_name.IsNotTemporaryScopedHandle());
     SetInputAt(0, value);
   }
 
   Value* value() const { return inputs_[0]; }
   virtual TokenPosition token_pos() const { return token_pos_; }
+  const String& function_name() const { return function_name_; }
 
   DECLARE_INSTRUCTION(CheckNull)
 
@@ -6842,6 +6859,7 @@
 
  private:
   const TokenPosition token_pos_;
+  const String& function_name_;
 
   DISALLOW_COPY_AND_ASSIGN(CheckNullInstr);
 };
@@ -6956,10 +6974,15 @@
         to_representation_(to),
         is_truncating_(to == kUnboxedUint32) {
     ASSERT(from != to);
+#if !defined(AVOID_UNBOXED_INT32)
     ASSERT((from == kUnboxedInt64) || (from == kUnboxedUint32) ||
            (from == kUnboxedInt32));
     ASSERT((to == kUnboxedInt64) || (to == kUnboxedUint32) ||
            (to == kUnboxedInt32));
+#else
+    ASSERT((from == kUnboxedInt64) || (from == kUnboxedUint32));
+    ASSERT((to == kUnboxedInt64) || (to == kUnboxedUint32));
+#endif
     SetInputAt(0, value);
   }
 
@@ -7067,6 +7090,12 @@
 #define SIMD_CONVERSION(M, FromType, ToType)                                   \
   M(1, _, FromType##To##ToType, (FromType), ToType)
 
+#if defined(AVOID_UNBOXED_INT32)
+#define Int32x4Arg Uint32
+#else
+#define Int32x4Arg Int32
+#endif
+
 // List of all recognized SIMD operations.
 // Note: except for operations that map to operators (Add, Mul, Sub, Div,
 // BitXor, BitOr) all other operations must match names used by
@@ -7092,7 +7121,8 @@
   M(2, _, Float32x4LessThan, (Float32x4, Float32x4), Int32x4)                  \
   M(2, _, Float32x4LessThanOrEqual, (Float32x4, Float32x4), Int32x4)           \
   M(2, _, Float32x4NotEqual, (Float32x4, Float32x4), Int32x4)                  \
-  M(4, _, Int32x4Constructor, (Int32, Int32, Int32, Int32), Int32x4)           \
+  M(4, _, Int32x4Constructor,                                                  \
+    (Int32x4Arg, Int32x4Arg, Int32x4Arg, Int32x4Arg), Int32x4)                 \
   M(4, _, Int32x4BoolConstructor, (Bool, Bool, Bool, Bool), Int32x4)           \
   M(4, _, Float32x4Constructor, (Double, Double, Double, Double), Float32x4)   \
   M(2, _, Float64x2Constructor, (Double, Double), Float64x2)                   \
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index 9b5729c..6e310bf 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -328,7 +328,8 @@
                                        const Location& destination,
                                        Register tmp) {
   if (destination.IsRegister()) {
-    if (representation() == kUnboxedInt32) {
+    if (representation() == kUnboxedInt32 ||
+        representation() == kUnboxedUint32) {
       __ LoadImmediate(destination.reg(), Smi::Cast(value_).Value());
     } else {
       ASSERT(representation() == kTagged);
@@ -5985,34 +5986,45 @@
   LocationSummary* summary = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
   summary->set_in(0, Location::RequiresRegister());
-  summary->set_in(1, Location::RequiresRegister());
   summary->set_out(0, Location::RequiresRegister());
+  ConstantInstr* right_constant = right()->definition()->AsConstant();
+  if (right_constant != NULL && op_kind() != Token::kMUL &&
+      right_constant->value().IsSmi() &&
+      Operand::CanHold(Smi::Cast(right_constant->value()).Value())) {
+    summary->set_in(1, Location::Constant(right_constant));
+  } else {
+    summary->set_in(1, Location::RequiresRegister());
+  }
   return summary;
 }
 
 void BinaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   Register left = locs()->in(0).reg();
-  Register right = locs()->in(1).reg();
   Register out = locs()->out(0).reg();
   ASSERT(out != left);
+  Location r = locs()->in(1);
+  if (op_kind() == Token::kMUL) {
+    __ mul(out, left, r.reg());
+    return;
+  }
+  const Operand right = r.IsRegister()
+                            ? Operand(r.reg())
+                            : Operand(Smi::Cast(r.constant()).Value());
   switch (op_kind()) {
     case Token::kBIT_AND:
-      __ and_(out, left, Operand(right));
+      __ and_(out, left, right);
       break;
     case Token::kBIT_OR:
-      __ orr(out, left, Operand(right));
+      __ orr(out, left, right);
       break;
     case Token::kBIT_XOR:
-      __ eor(out, left, Operand(right));
+      __ eor(out, left, right);
       break;
     case Token::kADD:
-      __ add(out, left, Operand(right));
+      __ add(out, left, right);
       break;
     case Token::kSUB:
-      __ sub(out, left, Operand(right));
-      break;
-    case Token::kMUL:
-      __ mul(out, left, right);
+      __ sub(out, left, right);
       break;
     default:
       UNREACHABLE();
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index 9c0a698..abafd9d 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -324,8 +324,9 @@
 void ConstantInstr::EmitMoveToLocation(FlowGraphCompiler* compiler,
                                        const Location& destination,
                                        Register tmp) {
+  ASSERT(representation() != kUnboxedInt32);
   if (destination.IsRegister()) {
-    if (representation() == kUnboxedInt32 ||
+    if (representation() == kUnboxedUint32 ||
         representation() == kUnboxedInt64) {
       const int64_t value = value_.IsSmi() ? Smi::Cast(value_).Value()
                                            : Mint::Cast(value_).value();
@@ -353,11 +354,7 @@
     ASSERT(destination.IsStackSlot());
     ASSERT(tmp != kNoRegister);
     const intptr_t dest_offset = destination.ToStackSlotOffset();
-    if (value_.IsSmi() && representation() == kUnboxedInt32) {
-      __ LoadImmediate(tmp, static_cast<int32_t>(Smi::Cast(value_).Value()));
-    } else {
-      __ LoadObject(tmp, value_);
-    }
+    __ LoadObject(tmp, value_);
     __ StoreToOffset(tmp, destination.base_reg(), dest_offset);
   }
 }
@@ -365,7 +362,7 @@
 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone,
                                                            bool opt) const {
   const intptr_t kNumInputs = 0;
-  const intptr_t kNumTemps = IsUnboxedSignedIntegerConstant() ? 0 : 1;
+  const intptr_t kNumTemps = IsUnboxedIntegerConstant() ? 0 : 1;
   LocationSummary* locs = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
   switch (representation()) {
@@ -373,7 +370,7 @@
       locs->set_out(0, Location::RequiresFpuRegister());
       locs->set_temp(0, Location::RequiresRegister());
       break;
-    case kUnboxedInt32:
+    case kUnboxedUint32:  // We don't used signed int32 on ARM64.
     case kUnboxedInt64:
       locs->set_out(0, Location::RequiresRegister());
       break;
@@ -387,7 +384,7 @@
 void UnboxedConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   if (!locs()->out(0).IsInvalid()) {
     const Register scratch =
-        IsUnboxedSignedIntegerConstant() ? kNoRegister : locs()->temp(0).reg();
+        IsUnboxedIntegerConstant() ? kNoRegister : locs()->temp(0).reg();
     EmitMoveToLocation(compiler, locs()->out(0), scratch);
   }
 }
@@ -593,9 +590,9 @@
       right_constant = right.constant_instruction();
     }
 
-    if (right_constant->IsUnboxedSignedIntegerConstant()) {
-      __ CompareImmediate(
-          left.reg(), right_constant->GetUnboxedSignedIntegerConstantValue());
+    if (right_constant->IsUnboxedIntegerConstant()) {
+      __ CompareImmediate(left.reg(),
+                          right_constant->GetUnboxedIntegerConstantValue());
     } else {
       ASSERT(right_constant->representation() == kTagged);
       __ CompareObject(left.reg(), right.constant());
@@ -997,9 +994,13 @@
     case kTwoByteStringCid:
     case kExternalOneByteStringCid:
     case kExternalTwoByteStringCid:
+      return CompileType::FromCid(kSmiCid);
+
     case kTypedDataInt32ArrayCid:
     case kTypedDataUint32ArrayCid:
-      return CompileType::FromCid(kSmiCid);
+      // TODO(erikcorry): Perhaps this can return a faster type.  See
+      // https://github.com/dart-lang/sdk/issues/32582
+      return CompileType::Int();
 
     default:
       UNIMPLEMENTED();
@@ -1024,11 +1025,10 @@
     case kExternalTwoByteStringCid:
       return kTagged;
     case kTypedDataInt32ArrayCid:
-      return kUnboxedInt32;
-    case kTypedDataUint32ArrayCid:
-      return kUnboxedUint32;
     case kTypedDataInt64ArrayCid:
       return kUnboxedInt64;
+    case kTypedDataUint32ArrayCid:
+      return kUnboxedUint32;
     case kTypedDataFloat32ArrayCid:
     case kTypedDataFloat64ArrayCid:
       return kUnboxedDouble;
@@ -1154,24 +1154,35 @@
     return;
   }
 
-  if ((representation() == kUnboxedInt32) ||
-      (representation() == kUnboxedUint32)) {
+  if (representation() == kUnboxedUint32) {
+    ASSERT(class_id() == kTypedDataUint32ArrayCid);
     const Register result = locs()->out(0).reg();
+    if (aligned()) {
+      __ ldr(result, element_address, kUnsignedWord);
+    } else {
+      __ LoadUnaligned(result, address, TMP, kUnsignedWord);
+    }
+    __ AssertValidUint32(result);
+    return;
+  }
+
+  if (representation() == kUnboxedInt64) {
+    Register result = locs()->out(0).reg();
     switch (class_id()) {
       case kTypedDataInt32ArrayCid:
-        ASSERT(representation() == kUnboxedInt32);
+        ASSERT(representation() == kUnboxedInt64);
         if (aligned()) {
           __ ldr(result, element_address, kWord);
         } else {
           __ LoadUnaligned(result, address, TMP, kWord);
         }
+        __ AssertValidSignExtendedInt32(result);
         break;
-      case kTypedDataUint32ArrayCid:
-        ASSERT(representation() == kUnboxedUint32);
+      case kTypedDataInt64ArrayCid:
         if (aligned()) {
-          __ ldr(result, element_address, kUnsignedWord);
+          __ ldr(result, element_address, kDoubleWord);
         } else {
-          __ LoadUnaligned(result, address, TMP, kUnsignedWord);
+          __ LoadUnaligned(result, address, TMP, kDoubleWord);
         }
         break;
       default:
@@ -1180,17 +1191,6 @@
     return;
   }
 
-  if (representation() == kUnboxedInt64) {
-    ASSERT(class_id() == kTypedDataInt64ArrayCid);
-    Register result = locs()->out(0).reg();
-    if (aligned()) {
-      __ ldr(result, element_address, kDoubleWord);
-    } else {
-      __ LoadUnaligned(result, address, TMP, kDoubleWord);
-    }
-    return;
-  }
-
   ASSERT(representation() == kTagged);
   const Register result = locs()->out(0).reg();
   switch (class_id()) {
@@ -1273,7 +1273,6 @@
         default:
           UNREACHABLE();
       }
-      __ SmiTag(result);
       break;
     case kTwoByteStringCid:
     case kExternalTwoByteStringCid:
@@ -1287,12 +1286,15 @@
         default:
           UNREACHABLE();
       }
-      __ SmiTag(result);
       break;
     default:
       UNREACHABLE();
       break;
   }
+  if (representation_ == kTagged) {
+    ASSERT(can_pack_into_smi());
+    __ SmiTag(result);
+  }
 }
 
 Representation StoreIndexedInstr::RequiredInputRepresentation(
@@ -1313,7 +1315,6 @@
     case kTypedDataUint16ArrayCid:
       return kTagged;
     case kTypedDataInt32ArrayCid:
-      return kUnboxedInt32;
     case kTypedDataUint32ArrayCid:
       return kUnboxedUint32;
     case kTypedDataInt64ArrayCid:
@@ -2770,18 +2771,27 @@
   if (locs.in(1).IsConstant()) {
     const Object& constant = locs.in(1).constant();
     ASSERT(constant.IsSmi());
-    // Immediate shift operation takes 6 bits for the count.
-    const intptr_t kCountLimit = 0x3F;
+    // Immediate shift operation takes 5 bits for the count.
+    const intptr_t kCountLimit = 0x1F;
+    // These should be around the same size.
+    COMPILE_ASSERT(kCountLimit + 1 == kSmiBits + 2);
     const intptr_t value = Smi::Cast(constant).Value();
     ASSERT((0 < value) && (value < kCountLimit));
     if (shift_left->can_overflow()) {
       // Check for overflow (preserve left).
-      __ LslImmediate(TMP, left, value);
-      __ cmp(left, Operand(TMP, ASR, value));
+      __ LslImmediate(TMP, left, value, kWord);
+      __ cmpw(left, Operand(TMP, ASR, value));
       __ b(deopt, NE);  // Overflow.
     }
-    // Shift for result now we know there is no overflow.
+    // Shift for result now we know there is no overflow.  This writes the full
+    // 64 bits of the output register, but unless we are in truncating mode the
+    // top bits will just be sign extension bits.
     __ LslImmediate(result, left, value);
+    if (shift_left->is_truncating()) {
+      // This preserves the invariant that Smis only use the low 32 bits of the
+      // register, the high bits being sign extension bits.
+      __ sxtw(result, result);
+    }
     return;
   }
 
@@ -2789,28 +2799,33 @@
   const Register right = locs.in(1).reg();
   Range* right_range = shift_left->right_range();
   if (shift_left->left()->BindsToConstant() && shift_left->can_overflow()) {
-    // TODO(srdjan): Implement code below for is_truncating().
     // If left is constant, we know the maximal allowed size for right.
     const Object& obj = shift_left->left()->BoundConstant();
-    if (obj.IsSmi()) {
-      const intptr_t left_int = Smi::Cast(obj).Value();
-      if (left_int == 0) {
-        __ CompareRegisters(right, ZR);
-        __ b(deopt, MI);
-        __ mov(result, ZR);
-        return;
-      }
-      const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int);
-      const bool right_needs_check =
-          !RangeUtils::IsWithin(right_range, 0, max_right - 1);
-      if (right_needs_check) {
-        __ CompareImmediate(right,
-                            reinterpret_cast<int64_t>(Smi::New(max_right)));
-        __ b(deopt, CS);
-      }
-      __ SmiUntag(TMP, right);
-      __ lslv(result, left, TMP);
+    // Even though we have a non-Smi constant on the left, we might still emit
+    // a Smi op here.  In that case the Smi check above will have deopted, so
+    // we can't reach this point. Emit a breakpoint to be sure.
+    if (!obj.IsSmi()) {
+      __ Breakpoint();
+      return;
     }
+    const intptr_t left_int = Smi::Cast(obj).Value();
+    if (left_int == 0) {
+      __ CompareRegisters(right, ZR);
+      __ b(deopt, MI);
+      __ mov(result, ZR);
+      return;
+    }
+    const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int);
+    const bool right_needs_check =
+        !RangeUtils::IsWithin(right_range, 0, max_right - 1);
+    if (right_needs_check) {
+      __ CompareImmediate(right,
+                          reinterpret_cast<int64_t>(Smi::New(max_right)));
+      __ b(deopt, CS);
+    }
+    __ SmiUntag(TMP, right);
+    __ lslv(result, left, TMP);
+    ASSERT(!shift_left->is_truncating());
     return;
   }
 
@@ -2834,7 +2849,11 @@
       __ SmiUntag(TMP, right);
       __ lslv(result, left, TMP);
     }
+    if (shift_left->is_truncating()) {
+      __ sxtw(result, result);
+    }
   } else {
+    // If we can overflow.
     if (right_needs_check) {
       ASSERT(shift_left->CanDeoptimize());
       __ CompareImmediate(right,
@@ -2842,15 +2861,16 @@
       __ b(deopt, CS);
     }
     // Left is not a constant.
-    // Check if count too large for handling it inlined.
+    // Check if count is too large for handling it inlined.
     __ SmiUntag(TMP, right);
     // Overflow test (preserve left, right, and TMP);
     const Register temp = locs.temp(0).reg();
-    __ lslv(temp, left, TMP);
-    __ asrv(TMP2, temp, TMP);
-    __ CompareRegisters(left, TMP2);
+    __ lslvw(temp, left, TMP);
+    __ asrvw(TMP2, temp, TMP);
+    __ cmpw(left, Operand(TMP2));
     __ b(deopt, NE);  // Overflow.
-    // Shift for result now we know there is no overflow.
+    // Shift for result now we know there is no overflow.  This is a 64 bit
+    // operation, so no sign extension is needed.
     __ lslv(result, left, TMP);
   }
 }
@@ -2931,18 +2951,20 @@
 
   switch (op_kind()) {
     case Token::kADD:
-      __ adds(result, left, Operand(right));
+      __ addsw(result, left, Operand(right));
       __ b(slow_path->entry_label(), VS);
+      __ sxtw(result, result);
       break;
     case Token::kSUB:
-      __ subs(result, left, Operand(right));
+      __ subsw(result, left, Operand(right));
       __ b(slow_path->entry_label(), VS);
+      __ sxtw(result, result);
       break;
     case Token::kMUL:
       __ SmiUntag(TMP, left);
-      __ mul(result, TMP, right);
-      __ smulh(TMP, TMP, right);
-      // TMP: result bits 64..127.
+      __ smull(result, TMP, right);
+      __ AsrImmediate(TMP, result, 31);
+      // TMP: result bits 31-63
       __ cmp(TMP, Operand(result, ASR, 63));
       __ b(slow_path->entry_label(), NE);
       break;
@@ -2967,8 +2989,8 @@
 
       __ SmiUntag(TMP, right);
       __ lslv(result, left, TMP);
-      __ asrv(TMP2, result, TMP);
-      __ CompareRegisters(left, TMP2);
+      __ asrvw(TMP2, result, TMP);
+      __ cmp(left, Operand(TMP2, SXTW, 0));
       __ b(slow_path->entry_label(), NE);  // Overflow.
       break;
     case Token::kSHR:
@@ -2978,6 +3000,8 @@
                           reinterpret_cast<int64_t>(Smi::New(Smi::kBits)));
       __ b(slow_path->entry_label(), CS);
 
+      __ AssertSmiInRange(left);
+      __ AssertSmiInRange(right);
       __ SmiUntag(result, right);
       __ SmiUntag(TMP, left);
       __ asrv(result, TMP, result);
@@ -2987,6 +3011,7 @@
       UNIMPLEMENTED();
   }
   __ Bind(slow_path->exit_label());
+  __ AssertSmiInRange(result, Assembler::kValueCanBeHeapPointer);
 }
 
 class CheckedSmiComparisonSlowPath
@@ -3177,20 +3202,28 @@
       case Token::kADD: {
         if (deopt == NULL) {
           __ AddImmediate(result, left, imm);
+          if (is_truncating()) {
+            __ sxtw(result, result);
+          }
         } else {
-          __ AddImmediateSetFlags(result, left, imm);
+          __ AddImmediateSetFlags(result, left, imm, kWord);
           __ b(deopt, VS);
+          __ sxtw(result, result);
         }
         break;
       }
       case Token::kSUB: {
         if (deopt == NULL) {
           __ AddImmediate(result, left, -imm);
+          if (is_truncating()) {
+            __ sxtw(result, result);
+          }
         } else {
           // Negating imm and using AddImmediateSetFlags would not detect the
-          // overflow when imm == kMinInt64.
-          __ SubImmediateSetFlags(result, left, imm);
+          // overflow when imm == kMinInt32.
+          __ SubImmediateSetFlags(result, left, imm, kWord);
           __ b(deopt, VS);
+          __ sxtw(result, result);
         }
         break;
       }
@@ -3198,12 +3231,14 @@
         // Keep left value tagged and untag right value.
         const intptr_t value = Smi::Cast(constant).Value();
         __ LoadImmediate(TMP, value);
-        __ mul(result, left, TMP);
+        __ smull(result, left, TMP);
         if (deopt != NULL) {
-          __ smulh(TMP, left, TMP);
-          // TMP: result bits 64..127.
+          __ AsrImmediate(TMP, result, 31);
+          // TMP: result bits 31..63.
           __ cmp(TMP, Operand(result, ASR, 63));
           __ b(deopt, NE);
+        } else if (is_truncating()) {
+          __ sxtw(result, result);
         }
         break;
       }
@@ -3214,9 +3249,10 @@
         const intptr_t shift_count =
             Utils::ShiftForPowerOfTwo(Utils::Abs(value)) + kSmiTagSize;
         ASSERT(kSmiTagSize == 1);
-        __ AsrImmediate(TMP, left, 63);
+        __ AsrImmediate(TMP, left, 31);  // All 1s or all 0s.
         ASSERT(shift_count > 1);  // 1, -1 case handled above.
         const Register temp = TMP2;
+        // Adjust so that we round to 0 instead of round down.
         __ add(temp, left, Operand(TMP, LSR, 64 - shift_count));
         ASSERT(shift_count > 0);
         __ AsrImmediate(result, temp, shift_count);
@@ -3251,6 +3287,7 @@
         UNREACHABLE();
         break;
     }
+    __ AssertSmiInRange(result);
     return;
   }
 
@@ -3259,18 +3296,26 @@
     case Token::kADD: {
       if (deopt == NULL) {
         __ add(result, left, Operand(right));
+        if (is_truncating()) {
+          __ sxtw(result, result);
+        }
       } else {
-        __ adds(result, left, Operand(right));
+        __ addsw(result, left, Operand(right));
         __ b(deopt, VS);
+        __ sxtw(result, result);
       }
       break;
     }
     case Token::kSUB: {
       if (deopt == NULL) {
         __ sub(result, left, Operand(right));
+        if (is_truncating()) {
+          __ sxtw(result, result);
+        }
       } else {
-        __ subs(result, left, Operand(right));
+        __ subsw(result, left, Operand(right));
         __ b(deopt, VS);
+        __ sxtw(result, result);
       }
       break;
     }
@@ -3278,10 +3323,13 @@
       __ SmiUntag(TMP, left);
       if (deopt == NULL) {
         __ mul(result, TMP, right);
+        if (is_truncating()) {
+          __ sxtw(result, result);
+        }
       } else {
-        __ mul(result, TMP, right);
-        __ smulh(TMP, TMP, right);
-        // TMP: result bits 64..127.
+        __ smull(result, TMP, right);
+        __ AsrImmediate(TMP, result, 31);
+        // TMP: result bits 31..63.
         __ cmp(TMP, Operand(result, ASR, 63));
         __ b(deopt, NE);
       }
@@ -3316,7 +3364,7 @@
 
       // Check the corner case of dividing the 'MIN_SMI' with -1, in which
       // case we cannot tag the result.
-      __ CompareImmediate(result, 0x4000000000000000LL);
+      __ CompareImmediate(result, 0x40000000LL);
       __ b(deopt, EQ);
       __ SmiTag(result);
       break;
@@ -3361,8 +3409,10 @@
         __ b(deopt, LT);
       }
       __ SmiUntag(TMP, right);
-      // sarl operation masks the count to 6 bits.
-      const intptr_t kCountLimit = 0x3F;
+      // The asrv operation masks the count to 6 bits, but any shift between 31
+      // and 63 gives the same result because 32 bit Smis are stored sign
+      // extended in the registers.
+      const intptr_t kCountLimit = 0x1F;
       if (!RangeUtils::OnlyLessThanOrEqualTo(right_range(), kCountLimit)) {
         __ LoadImmediate(TMP2, kCountLimit);
         __ CompareRegisters(TMP, TMP2);
@@ -3391,6 +3441,7 @@
       UNREACHABLE();
       break;
   }
+  __ AssertSmiInRange(result);
 }
 
 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Zone* zone,
@@ -3540,13 +3591,19 @@
 
 LocationSummary* BoxInteger32Instr::MakeLocationSummary(Zone* zone,
                                                         bool opt) const {
-  ASSERT((from_representation() == kUnboxedInt32) ||
-         (from_representation() == kUnboxedUint32));
+  ASSERT(from_representation() == kUnboxedUint32);
   const intptr_t kNumInputs = 1;
-  const intptr_t kNumTemps = 0;
+  const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1;
   LocationSummary* summary = new (zone)
-      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+      LocationSummary(zone, kNumInputs, kNumTemps,
+                      ValueFitsSmi() ? LocationSummary::kNoCall
+                                     : LocationSummary::kCallOnSlowPath);
+  // Get two distinct registers for input and output, plus a temp
+  // register for testing for overflow and allocating a Mint.
   summary->set_in(0, Location::RequiresRegister());
+  if (!ValueFitsSmi()) {
+    summary->set_temp(0, Location::RequiresRegister());
+  }
   summary->set_out(0, Location::RequiresRegister());
   return summary;
 }
@@ -3555,16 +3612,51 @@
   Register value = locs()->in(0).reg();
   Register out = locs()->out(0).reg();
   ASSERT(value != out);
+  Label done;
 
-  ASSERT(kSmiTagSize == 1);
-  // TODO(vegorov) implement and use UBFM/SBFM for this.
-  __ LslImmediate(out, value, 32);
   if (from_representation() == kUnboxedInt32) {
-    __ AsrImmediate(out, out, 32 - kSmiTagSize);
+    ASSERT(kSmiTag == 0);
+    // Signed Bitfield Insert in Zero instruction extracts the 31 significant
+    // bits from a Smi.
+    __ sbfiz(out, value, kSmiTagSize, 32 - kSmiTagSize);
+    if (ValueFitsSmi()) {
+      return;
+    }
+    Register temp = locs()->temp(0).reg();
+    __ cmp(out, Operand(value, LSL, 1));
+    __ b(&done, EQ);  // Jump if the sbfiz instruction didn't lose info.
+    BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), out,
+                                    temp);
+    __ sxtw(temp, value);
   } else {
     ASSERT(from_representation() == kUnboxedUint32);
-    __ LsrImmediate(out, out, 32 - kSmiTagSize);
+    ASSERT(kSmiTag == 0);
+    // A 32 bit positive Smi has one tag bit and one unused sign bit,
+    // leaving only 30 bits for the payload.
+    __ ubfiz(out, value, kSmiTagSize, kSmiBits);
+    if (ValueFitsSmi()) {
+      return;
+    }
+    Register temp = locs()->temp(0).reg();
+    __ TestImmediate(value, 0xc0000000);
+    __ b(&done, EQ);  // Jump if both bits are zero.
+    BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), out,
+                                    temp);
+    __ ubfiz(temp, value, 0, 32);  // Zero extend word.
   }
+
+  __ StoreToOffset(locs()->temp(0).reg(), out,
+                   Mint::value_offset() - kHeapObjectTag);
+
+#if defined(DEBUG)
+  Label skip_smi_test;
+  __ b(&skip_smi_test);
+  __ Bind(&done);
+  __ AssertSmiInRange(out, Assembler::kValueCanBeHeapPointer);
+  __ Bind(&skip_smi_test);
+#else
+  __ Bind(&done);
+#endif
 }
 
 LocationSummary* BoxInt64Instr::MakeLocationSummary(Zone* zone,
@@ -3592,7 +3684,8 @@
   }
 
   ASSERT(kSmiTag == 0);
-  __ LslImmediate(out, in, kSmiTagSize);
+  __ LslImmediate(out, in, kSmiTagSize, kWord);
+  __ sxtw(out, out);
   Label done;
   __ cmp(in, Operand(out, ASR, kSmiTagSize));
   __ b(&done, EQ);
@@ -3617,44 +3710,37 @@
 }
 
 void UnboxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  // We don't use unboxed signed int32 on 64 bit platforms, so this is an
+  // unboxing to 32 bit unsigned integer, zero extended.
+  ASSERT(representation() == kUnboxedUint32);
+  ASSERT(is_truncating());
   const intptr_t value_cid = value()->Type()->ToCid();
   const Register out = locs()->out(0).reg();
   const Register value = locs()->in(0).reg();
-  Label* deopt = CanDeoptimize() ? compiler->AddDeoptStub(
-                                       GetDeoptId(), ICData::kDeoptUnboxInteger)
-                                 : NULL;
 
   if (value_cid == kSmiCid) {
-    __ SmiUntag(out, value);
+    ASSERT(kSmiTagSize == 1);
+    // Unsigned bitfield extract, untags the Smi, truncating to 32 bit unsigned.
+    __ ubfx(out, value, 1, 32);
   } else if (value_cid == kMintCid) {
-    __ LoadFieldFromOffset(out, value, Mint::value_offset());
-  } else if (!CanDeoptimize()) {
-    // Type information is not conclusive, but range analysis found
-    // the value to be in int64 range. Therefore it must be a smi
-    // or mint value.
-    ASSERT(is_truncating());
-    Label done;
-    __ SmiUntag(out, value);
-    __ BranchIfSmi(value, &done);
-    __ LoadFieldFromOffset(out, value, Mint::value_offset());
-    __ Bind(&done);
+    __ LoadFieldFromOffset(out, value, Mint::value_offset(), kUnsignedWord);
   } else {
+    // Type information is not conclusive.
     Label done;
-    __ SmiUntag(out, value);
+    ASSERT(kSmiTagSize == 1);
+    // Unsigned bitfield extract, untags the Smi, truncating to 32 bit unsigned.
+    __ ubfx(out, value, 1, 32);
     __ BranchIfSmi(value, &done);
-    __ CompareClassId(value, kMintCid);
-    __ b(deopt, NE);
-    __ LoadFieldFromOffset(out, value, Mint::value_offset());
+    if (CanDeoptimize()) {
+      Label* deopt =
+          compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptUnboxInteger);
+      __ CompareClassId(value, kMintCid);
+      __ b(deopt, NE);
+    }
+    __ LoadFieldFromOffset(out, value, Mint::value_offset(), kUnsignedWord);
     __ Bind(&done);
   }
-
-  // TODO(vegorov): as it is implemented right now truncating unboxing would
-  // leave "garbage" in the higher word.
-  if (!is_truncating() && (deopt != NULL)) {
-    ASSERT(representation() == kUnboxedInt32);
-    __ cmp(out, Operand(out, SXTW, 0));
-    __ b(deopt, NE);
-  }
+  __ AssertValidUint32(out);
 }
 
 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Zone* zone,
@@ -4333,8 +4419,9 @@
   switch (op_kind()) {
     case Token::kNEGATE: {
       Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp);
-      __ subs(result, ZR, Operand(value));
+      __ subsw(result, ZR, Operand(value));
       __ b(deopt, VS);
+      __ sxtw(result, result);
       break;
     }
     case Token::kBIT_NOT:
@@ -4345,6 +4432,7 @@
     default:
       UNREACHABLE();
   }
+  __ AssertSmiInRange(result);
 }
 
 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone,
@@ -4396,7 +4484,7 @@
   const Register value = locs()->in(0).reg();
   const VRegister result = locs()->out(0).fpu_reg();
   __ SmiUntag(TMP, value);
-  __ scvtfdx(result, TMP);
+  __ scvtfdw(result, TMP);
 }
 
 LocationSummary* Int64ToDoubleInstr::MakeLocationSummary(Zone* zone,
@@ -4440,12 +4528,13 @@
   __ fcmpd(VTMP, VTMP);
   __ b(&do_call, VS);
 
-  __ fcvtzds(result, VTMP);
+  __ fcvtzdsx(result, VTMP);
   // Overflow is signaled with minint.
 
   // Check for overflow and that it fits into Smi.
-  __ CompareImmediate(result, 0xC000000000000000);
-  __ b(&do_call, MI);
+  __ AsrImmediate(TMP, result, 30);
+  __ cmp(TMP, Operand(result, ASR, 63));
+  __ b(&do_call, NE);
   __ SmiTag(result);
   __ b(&done);
   __ Bind(&do_call);
@@ -4462,6 +4551,7 @@
                                args_info, locs(), ICData::Handle(),
                                ICData::kStatic);
   __ Bind(&done);
+  __ AssertSmiInRange(result, Assembler::kValueCanBeHeapPointer);
 }
 
 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(Zone* zone,
@@ -4485,11 +4575,13 @@
   __ fcmpd(value, value);
   __ b(deopt, VS);
 
-  __ fcvtzds(result, value);
+  __ fcvtzdsx(result, value);
   // Check for overflow and that it fits into Smi.
-  __ CompareImmediate(result, 0xC000000000000000);
-  __ b(deopt, MI);
+  __ AsrImmediate(TMP, result, 30);
+  __ cmp(TMP, Operand(result, ASR, 63));
+  __ b(deopt, NE);
   __ SmiTag(result);
+  __ AssertSmiInRange(result);
 }
 
 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(Zone* zone,
@@ -4758,7 +4850,7 @@
 
   // Check the corner case of dividing the 'MIN_SMI' with -1, in which
   // case we cannot tag the result.
-  __ CompareImmediate(result_div, 0x4000000000000000);
+  __ CompareImmediate(result_div, 0x40000000);
   __ b(deopt, EQ);
   // result_mod <- left - right * result_div.
   __ msub(result_mod, TMP, result_div, result_mod);
@@ -5007,8 +5099,7 @@
     Register r = TMP;
     if (right.IsConstant()) {
       ConstantInstr* constant_instr = right.constant_instruction();
-      const int64_t value =
-          constant_instr->GetUnboxedSignedIntegerConstantValue();
+      const int64_t value = constant_instr->GetUnboxedIntegerConstantValue();
       __ LoadImmediate(r, value);
     } else {
       r = right.reg();
@@ -5025,8 +5116,7 @@
 
   if (right.IsConstant()) {
     ConstantInstr* constant_instr = right.constant_instruction();
-    const int64_t value =
-        constant_instr->GetUnboxedSignedIntegerConstantValue();
+    const int64_t value = constant_instr->GetUnboxedIntegerConstantValue();
     switch (op_kind()) {
       case Token::kADD:
         if (CanDeoptimize()) {
@@ -5206,37 +5296,82 @@
   LocationSummary* summary = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
   summary->set_in(0, Location::RequiresRegister());
-  summary->set_in(1, Location::RequiresRegister());
   summary->set_out(0, Location::RequiresRegister());
+  ConstantInstr* right_constant = right()->definition()->AsConstant();
+  if (right_constant != NULL &&
+      (right_constant->value().IsSmi() || right_constant->value().IsMint())) {
+    int64_t imm = right_constant->GetUnboxedIntegerConstantValue();
+    bool is_arithmetic = op_kind() == Token::kADD || op_kind() == Token::kSUB;
+    bool is_logical = op_kind() == Token::kBIT_AND ||
+                      op_kind() == Token::kBIT_OR ||
+                      op_kind() == Token::kBIT_XOR;
+    if ((is_logical && Operand::IsImmLogical(imm)) ||
+        (is_arithmetic && Operand::IsImmArithmethic(imm))) {
+      summary->set_in(1, Location::Constant(right_constant));
+      return summary;
+    }
+  }
+  summary->set_in(1, Location::RequiresRegister());
   return summary;
 }
 
 void BinaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ConstantInstr* right_constant = right()->definition()->AsConstant();
   Register left = locs()->in(0).reg();
-  Register right = locs()->in(1).reg();
-  Operand r = Operand(right);
+  Location right = locs()->in(1);
   Register out = locs()->out(0).reg();
-  switch (op_kind()) {
-    case Token::kBIT_AND:
-      __ and_(out, left, r);
-      break;
-    case Token::kBIT_OR:
-      __ orr(out, left, r);
-      break;
-    case Token::kBIT_XOR:
-      __ eor(out, left, r);
-      break;
-    case Token::kADD:
-      __ addw(out, left, r);
-      break;
-    case Token::kSUB:
-      __ subw(out, left, r);
-      break;
-    case Token::kMUL:
-      __ mulw(out, left, right);
-      break;
-    default:
-      UNREACHABLE();
+  int64_t imm = 0;
+  if (right_constant != NULL) {
+    const Object& constant = right_constant->value();
+    if (constant.IsSmi()) {
+      imm = Smi::Cast(constant).AsInt64Value();
+    } else {
+      imm = Mint::Cast(constant).value();
+    }
+  }
+  if (right.IsRegister()) {
+    switch (op_kind()) {
+      case Token::kBIT_AND:
+        __ and_(out, left, Operand(right.reg()));
+        break;
+      case Token::kBIT_OR:
+        __ orr(out, left, Operand(right.reg()));
+        break;
+      case Token::kBIT_XOR:
+        __ eor(out, left, Operand(right.reg()));
+        break;
+      case Token::kADD:
+        __ addw(out, left, Operand(right.reg()));
+        break;
+      case Token::kSUB:
+        __ subw(out, left, Operand(right.reg()));
+        break;
+      case Token::kMUL:
+        __ mulw(out, left, right.reg());
+        break;
+      default:
+        UNREACHABLE();
+    }
+  } else {
+    switch (op_kind()) {
+      case Token::kBIT_AND:
+        __ andi(out, left, Immediate(imm));
+        break;
+      case Token::kBIT_OR:
+        __ orri(out, left, Immediate(imm));
+        break;
+      case Token::kBIT_XOR:
+        __ eori(out, left, Immediate(imm));
+        break;
+      case Token::kADD:
+        __ AddImmediate(out, left, imm, kWord);
+        break;
+      case Token::kSUB:
+        __ AddImmediate(out, left, -imm, kWord);
+        break;
+      default:
+        UNREACHABLE();
+    }
   }
 }
 
@@ -5287,6 +5422,10 @@
   Register shifter = locs()->in(1).reg();
 
   // TODO(johnmccutchan): Use range information to avoid these checks.
+  // Assert this is a legitimate Smi in debug mode, but does not assert
+  // anything about the range relative to the bit width.
+  __ AssertSmiInRange(shifter);
+
   __ SmiUntag(TMP, shifter);
   __ CompareImmediate(TMP, 0);
   // If shift value is < 0, deoptimize.
@@ -5306,7 +5445,7 @@
 
   __ CompareImmediate(TMP, kShifterLimit);
   // If shift value is > 31, return zero.
-  __ csel(out, out, ZR, GT);
+  __ csel(out, ZR, out, GT);
 }
 
 LocationSummary* UnaryUint32OpInstr::MakeLocationSummary(Zone* zone,
@@ -5337,19 +5476,14 @@
   LocationSummary* summary = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
   if (from() == kUnboxedInt64) {
-    ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32));
-  } else if (to() == kUnboxedInt64) {
-    ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32));
+    ASSERT(to() == kUnboxedUint32);  // No unboxed int32 on ARM64.
   } else {
-    ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32));
-    ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32));
+    ASSERT(to() == kUnboxedInt64);
+    ASSERT(from() == kUnboxedUint32);  // No unboxed int32 on ARM64.
   }
+  ASSERT(!CanDeoptimize());
   summary->set_in(0, Location::RequiresRegister());
-  if (CanDeoptimize()) {
-    summary->set_out(0, Location::RequiresRegister());
-  } else {
-    summary->set_out(0, Location::SameAsFirstInput());
-  }
+  summary->set_out(0, Location::SameAsFirstInput());
   return summary;
 }
 
@@ -5357,52 +5491,16 @@
   ASSERT(from() != to());  // We don't convert from a representation to itself.
   const Register value = locs()->in(0).reg();
   const Register out = locs()->out(0).reg();
-  Label* deopt = !CanDeoptimize() ? NULL
-                                  : compiler->AddDeoptStub(
-                                        deopt_id(), ICData::kDeoptUnboxInteger);
-  if (from() == kUnboxedInt32 && to() == kUnboxedUint32) {
-    if (CanDeoptimize()) {
-      __ tbnz(deopt, value,
-              31);  // If sign bit is set it won't fit in a uint32.
-    }
-    if (out != value) {
-      __ mov(out, value);  // For positive values the bits are the same.
-    }
-  } else if (from() == kUnboxedUint32 && to() == kUnboxedInt32) {
-    if (CanDeoptimize()) {
-      __ tbnz(deopt, value,
-              31);  // If high bit is set it won't fit in an int32.
-    }
-    if (out != value) {
-      __ mov(out, value);  // For 31 bit values the bits are the same.
-    }
-  } else if (from() == kUnboxedInt64) {
-    if (to() == kUnboxedInt32) {
-      if (is_truncating() || out != value) {
-        __ sxtw(out, value);  // Signed extension 64->32.
-      }
-    } else {
-      ASSERT(to() == kUnboxedUint32);
-      if (is_truncating() || out != value) {
-        __ uxtw(out, value);  // Unsigned extension 64->32.
-      }
-    }
-    if (CanDeoptimize()) {
-      ASSERT(to() == kUnboxedInt32);
-      __ cmp(out, Operand(value));
-      __ b(deopt, NE);  // Value cannot be held in Int32, deopt.
-    }
-  } else if (to() == kUnboxedInt64) {
-    if (from() == kUnboxedUint32) {
-      if (out != value) {
-        __ mov(out, value);
-      }
-    } else {
-      ASSERT(from() == kUnboxedInt32);
-      __ sxtw(out, value);  // Signed extension 32->64.
-    }
+  ASSERT(!CanDeoptimize());
+  if (from() == kUnboxedInt64) {
+    ASSERT(to() == kUnboxedUint32);
+    __ uxtw(out, value);  // Zero the top bits.
   } else {
-    UNREACHABLE();
+    ASSERT(from() == kUnboxedUint32);
+    ASSERT(to() == kUnboxedInt64);
+    if (out != value) {
+      __ mov(out, value);  // Bits are the same.
+    }
   }
 }
 
diff --git a/runtime/vm/compiler/backend/il_ia32.cc b/runtime/vm/compiler/backend/il_ia32.cc
index c92b517..4505c0f 100644
--- a/runtime/vm/compiler/backend/il_ia32.cc
+++ b/runtime/vm/compiler/backend/il_ia32.cc
@@ -187,7 +187,8 @@
   if (destination.IsRegister()) {
     if (value_.IsSmi() && Smi::Cast(value_).Value() == 0) {
       __ xorl(destination.reg(), destination.reg());
-    } else if (value_.IsSmi() && (representation() == kUnboxedInt32)) {
+    } else if (value_.IsSmi() && (representation() == kUnboxedInt32 ||
+                                  representation() == kUnboxedUint32)) {
       __ movl(destination.reg(), Immediate(Smi::Cast(value_).Value()));
     } else {
       ASSERT(representation() == kTagged);
@@ -3236,6 +3237,16 @@
                                                           bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = (op_kind() == Token::kMUL) ? 1 : 0;
+  ConstantInstr* right_constant = right()->definition()->AsConstant();
+  if (right_constant != NULL && right_constant->value().IsSmi() &&
+      op_kind() != Token::kMUL) {
+    LocationSummary* summary = new (zone)
+        LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+    summary->set_in(0, Location::RequiresRegister());
+    summary->set_in(1, Location::Constant(right_constant));
+    summary->set_out(0, Location::SameAsFirstInput());
+    return summary;
+  }
   LocationSummary* summary = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
   if (op_kind() == Token::kMUL) {
@@ -3251,25 +3262,33 @@
 
 void BinaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   Register left = locs()->in(0).reg();
-  Register right = locs()->in(1).reg();
   Register out = locs()->out(0).reg();
   ASSERT(out == left);
-  switch (op_kind()) {
-    case Token::kBIT_AND:
-    case Token::kBIT_OR:
-    case Token::kBIT_XOR:
-    case Token::kADD:
-    case Token::kSUB:
-      EmitIntegerArithmetic(compiler, op_kind(), left, right, NULL);
-      return;
+  if (locs()->in(1).IsRegister()) {
+    Register right = locs()->in(1).reg();
+    switch (op_kind()) {
+      case Token::kBIT_AND:
+      case Token::kBIT_OR:
+      case Token::kBIT_XOR:
+      case Token::kADD:
+      case Token::kSUB:
+        EmitIntegerArithmetic(compiler, op_kind(), left, right, NULL);
+        return;
 
-    case Token::kMUL:
-      __ mull(right);  // Result in EDX:EAX.
-      ASSERT(out == EAX);
-      ASSERT(locs()->temp(0).reg() == EDX);
-      break;
-    default:
-      UNREACHABLE();
+      case Token::kMUL:
+        __ mull(right);  // Result in EDX:EAX.
+        ASSERT(out == EAX);
+        ASSERT(locs()->temp(0).reg() == EDX);
+        break;
+      default:
+        UNREACHABLE();
+    }
+  } else {
+    ASSERT(locs()->in(1).IsConstant());
+    ConstantInstr* right_constant = right()->definition()->AsConstant();
+    const Object& constant = right_constant->value();
+    int64_t imm = Smi::Cast(constant).AsInt64Value();
+    EmitIntegerArithmetic(compiler, op_kind(), left, Immediate(imm), NULL);
   }
 }
 
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index b44d650..a564b48 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -287,7 +287,7 @@
                                        const Location& destination,
                                        Register tmp) {
   if (destination.IsRegister()) {
-    if (representation() == kUnboxedInt32 ||
+    if (representation() == kUnboxedUint32 ||
         representation() == kUnboxedInt64) {
       const int64_t value = value_.IsSmi() ? Smi::Cast(value_).Value()
                                            : Mint::Cast(value_).value();
@@ -320,19 +320,14 @@
     __ movsd(destination.ToStackSlotAddress(), XMM0);
   } else {
     ASSERT(destination.IsStackSlot());
-    if (value_.IsSmi() && representation() == kUnboxedInt32) {
-      __ movl(destination.ToStackSlotAddress(),
-              Immediate(Smi::Cast(value_).Value()));
-    } else {
-      __ StoreObject(destination.ToStackSlotAddress(), value_);
-    }
+    __ StoreObject(destination.ToStackSlotAddress(), value_);
   }
 }
 
 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone,
                                                            bool opt) const {
   const intptr_t kNumInputs = 0;
-  const intptr_t kNumTemps = IsUnboxedSignedIntegerConstant() ? 0 : 1;
+  const intptr_t kNumTemps = IsUnboxedIntegerConstant() ? 0 : 1;
   LocationSummary* locs = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
   switch (representation()) {
@@ -340,7 +335,7 @@
       locs->set_out(0, Location::RequiresFpuRegister());
       locs->set_temp(0, Location::RequiresRegister());
       break;
-    case kUnboxedInt32:
+    case kUnboxedUint32:
     case kUnboxedInt64:
       locs->set_out(0, Location::RequiresRegister());
       break;
@@ -355,7 +350,7 @@
   // The register allocator drops constant definitions that have no uses.
   if (!locs()->out(0).IsInvalid()) {
     const Register scratch =
-        IsUnboxedSignedIntegerConstant() ? kNoRegister : locs()->temp(0).reg();
+        IsUnboxedIntegerConstant() ? kNoRegister : locs()->temp(0).reg();
     EmitMoveToLocation(compiler, locs()->out(0), scratch);
   }
 }
@@ -609,9 +604,9 @@
       constant = right.constant_instruction();
     }
 
-    if (constant->IsUnboxedSignedIntegerConstant()) {
+    if (constant->IsUnboxedIntegerConstant()) {
       __ cmpq(left.reg(),
-              Immediate(constant->GetUnboxedSignedIntegerConstantValue()));
+              Immediate(constant->GetUnboxedIntegerConstantValue()));
     } else {
       ASSERT(constant->representation() == kTagged);
       __ CompareObject(left.reg(), right.constant());
@@ -1074,11 +1069,13 @@
     case kTwoByteStringCid:
     case kExternalOneByteStringCid:
     case kExternalTwoByteStringCid:
-    case kTypedDataInt32ArrayCid:
-    case kTypedDataUint32ArrayCid:
       return CompileType::FromCid(kSmiCid);
 
+    case kTypedDataInt32ArrayCid:
+    case kTypedDataUint32ArrayCid:
     case kTypedDataInt64ArrayCid:
+      // TODO(erikcorry): Perhaps this can return a faster type.  See
+      // https://github.com/dart-lang/sdk/issues/32582
       return CompileType::Int();
 
     default:
@@ -1103,10 +1100,9 @@
     case kExternalOneByteStringCid:
     case kExternalTwoByteStringCid:
       return kTagged;
-    case kTypedDataInt32ArrayCid:
-      return kUnboxedInt32;
     case kTypedDataUint32ArrayCid:
       return kUnboxedUint32;
+    case kTypedDataInt32ArrayCid:
     case kTypedDataInt64ArrayCid:
       return kUnboxedInt64;
     case kTypedDataFloat32ArrayCid:
@@ -1191,20 +1187,31 @@
     return;
   }
 
-  if ((representation() == kUnboxedUint32) ||
-      (representation() == kUnboxedInt32)) {
+  if ((representation() == kUnboxedUint32)) {
+    ASSERT(class_id() == kTypedDataUint32ArrayCid);
+    if ((index_scale() == 1) && index.IsRegister()) {
+      __ SmiUntag(index.reg());
+    }
+    Register result = locs()->out(0).reg();
+    __ movl(result, element_address);
+    return;
+  }
+
+  if (representation() == kUnboxedInt64) {
     if ((index_scale() == 1) && index.IsRegister()) {
       __ SmiUntag(index.reg());
     }
     Register result = locs()->out(0).reg();
     switch (class_id()) {
       case kTypedDataInt32ArrayCid:
-        ASSERT(representation() == kUnboxedInt32);
-        __ movsxd(result, element_address);
-        break;
-      case kTypedDataUint32ArrayCid:
-        ASSERT(representation() == kUnboxedUint32);
+        ASSERT(representation() == kUnboxedInt64);
         __ movl(result, element_address);
+        __ movsxd(result, result);
+        __ AssertValidSignExtendedInt32(result);
+        break;
+      case kTypedDataInt64ArrayCid:
+        ASSERT(representation() == kUnboxedInt64);
+        __ movq(result, element_address);
         break;
       default:
         UNREACHABLE();
@@ -1212,16 +1219,6 @@
     return;
   }
 
-  if (representation() == kUnboxedInt64) {
-    ASSERT(class_id() == kTypedDataInt64ArrayCid);
-    if ((index_scale() == 1) && index.IsRegister()) {
-      __ SmiUntag(index.reg());
-    }
-    Register result = locs()->out(0).reg();
-    __ movq(result, element_address);
-    return;
-  }
-
   ASSERT(representation() == kTagged);
 
   if ((index_scale() == 1) && index.IsRegister()) {
@@ -1261,16 +1258,24 @@
 
 LocationSummary* LoadCodeUnitsInstr::MakeLocationSummary(Zone* zone,
                                                          bool opt) const {
+  const bool might_box = (representation() == kTagged) && !can_pack_into_smi();
   const intptr_t kNumInputs = 2;
-  const intptr_t kNumTemps = 0;
-  LocationSummary* summary = new (zone)
-      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  const intptr_t kNumTemps = might_box ? 2 : 0;
+  LocationSummary* summary = new (zone) LocationSummary(
+      zone, kNumInputs, kNumTemps,
+      might_box ? LocationSummary::kCallOnSlowPath : LocationSummary::kNoCall);
   summary->set_in(0, Location::RequiresRegister());
   // The smi index is either untagged (element size == 1), or it is left smi
   // tagged (for all element sizes > 1).
   summary->set_in(1, index_scale() == 1 ? Location::WritableRegister()
                                         : Location::RequiresRegister());
   summary->set_out(0, Location::RequiresRegister());
+
+  if (might_box) {
+    summary->set_temp(0, Location::RequiresRegister());
+    summary->set_temp(1, Location::RequiresRegister());
+  }
+
   return summary;
 }
 
@@ -1302,7 +1307,6 @@
         default:
           UNREACHABLE();
       }
-      __ SmiTag(result);
       break;
     case kTwoByteStringCid:
     case kExternalTwoByteStringCid:
@@ -1316,12 +1320,34 @@
         default:
           UNREACHABLE();
       }
-      __ SmiTag(result);
       break;
     default:
       UNREACHABLE();
       break;
   }
+  if (representation_ == kTagged) {
+    if (can_pack_into_smi()) {
+      __ SmiTag(result);
+    } else {
+      // If the value cannot fit in a smi then allocate a mint box for it.
+      Register temp = locs()->temp(0).reg();
+      Register temp2 = locs()->temp(1).reg();
+      // Temp register needs to be manually preserved on allocation slow-path.
+      locs()->live_registers()->Add(locs()->temp(0), kUnboxedInt32);
+
+      ASSERT(temp != result);
+      __ MoveRegister(temp, result);
+      __ SmiTag(result);
+
+      Label done;
+      __ TestImmediate(temp, Immediate(0xc0000000ll));
+      __ j(ZERO, &done);
+      BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(),
+                                      result, temp2);
+      __ movq(FieldAddress(result, Mint::value_offset()), temp);
+      __ Bind(&done);
+    }
+  }
 }
 
 Representation StoreIndexedInstr::RequiredInputRepresentation(
@@ -1340,10 +1366,9 @@
     case kTypedDataInt16ArrayCid:
     case kTypedDataUint16ArrayCid:
       return kTagged;
-    case kTypedDataInt32ArrayCid:
-      return kUnboxedInt32;
     case kTypedDataUint32ArrayCid:
       return kUnboxedUint32;
+    case kTypedDataInt32ArrayCid:
     case kTypedDataInt64ArrayCid:
       return kUnboxedInt64;
     case kTypedDataFloat32ArrayCid:
@@ -2711,27 +2736,32 @@
   if (locs.in(1).IsConstant()) {
     const Object& constant = locs.in(1).constant();
     ASSERT(constant.IsSmi());
-    // shlq operation masks the count to 6 bits.
-    const intptr_t kCountLimit = 0x3F;
+    // shll operation masks the count to 5 bits.
+    const intptr_t kCountLimit = 0x1F;
     const intptr_t value = Smi::Cast(constant).Value();
     ASSERT((0 < value) && (value < kCountLimit));
     if (shift_left->can_overflow()) {
       if (value == 1) {
         // Use overflow flag.
-        __ shlq(left, Immediate(1));
+        __ shll(left, Immediate(1));
         __ j(OVERFLOW, deopt);
+        __ movsxd(left, left);
         return;
       }
       // Check for overflow.
       Register temp = locs.temp(0).reg();
       __ movq(temp, left);
-      __ shlq(left, Immediate(value));
-      __ sarq(left, Immediate(value));
+      __ shll(left, Immediate(value));
+      __ sarl(left, Immediate(value));
+      __ movsxd(left, left);
       __ cmpq(left, temp);
       __ j(NOT_EQUAL, deopt);  // Overflow.
     }
     // Shift for result now we know there is no overflow.
     __ shlq(left, Immediate(value));
+    if (shift_left->is_truncating()) {
+      __ movsxd(left, left);
+    }
     return;
   }
 
@@ -2742,23 +2772,32 @@
     // TODO(srdjan): Implement code below for is_truncating().
     // If left is constant, we know the maximal allowed size for right.
     const Object& obj = shift_left->left()->BoundConstant();
-    if (obj.IsSmi()) {
-      const intptr_t left_int = Smi::Cast(obj).Value();
-      if (left_int == 0) {
-        __ CompareImmediate(right, Immediate(0));
-        __ j(NEGATIVE, deopt);
-        return;
-      }
-      const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int);
-      const bool right_needs_check =
-          !RangeUtils::IsWithin(right_range, 0, max_right - 1);
-      if (right_needs_check) {
-        __ CompareImmediate(
-            right, Immediate(reinterpret_cast<int64_t>(Smi::New(max_right))));
-        __ j(ABOVE_EQUAL, deopt);
-      }
-      __ SmiUntag(right);
-      __ shlq(left, right);
+    // Even though we have a non-Smi constant on the left, we might still emit
+    // a Smi op here.  In that case the Smi check above will have deopted, so
+    // we can't reach this point. Emit a breakpoint to be sure.
+    if (!obj.IsSmi()) {
+      __ int3();
+      return;
+    }
+    const intptr_t left_int = Smi::Cast(obj).Value();
+    if (left_int == 0) {
+      __ CompareImmediate(right, Immediate(0));
+      __ j(NEGATIVE, deopt);
+      return;
+    }
+    const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int);
+    const bool right_needs_check =
+        !RangeUtils::IsWithin(right_range, 0, max_right - 1);
+    if (right_needs_check) {
+      __ CompareImmediate(
+          right, Immediate(reinterpret_cast<int64_t>(Smi::New(max_right))));
+      __ j(ABOVE_EQUAL, deopt);
+    }
+    __ AssertSmiInRange(right);
+    __ SmiUntag(right);
+    __ shlq(left, right);
+    if (shift_left->is_truncating()) {
+      __ movsxd(left, left);
     }
     return;
   }
@@ -2782,13 +2821,18 @@
       __ xorq(left, left);
       __ jmp(&done, Assembler::kNearJump);
       __ Bind(&is_not_zero);
+      __ AssertSmiInRange(right);
       __ SmiUntag(right);
       __ shlq(left, right);
       __ Bind(&done);
     } else {
+      __ AssertSmiInRange(right);
       __ SmiUntag(right);
       __ shlq(left, right);
     }
+    if (shift_left->is_truncating()) {
+      __ movsxd(left, left);
+    }
   } else {
     if (right_needs_check) {
       ASSERT(shift_left->CanDeoptimize());
@@ -2798,16 +2842,18 @@
     }
     // Left is not a constant.
     Register temp = locs.temp(0).reg();
-    // Check if count too large for handling it inlined.
-    __ movq(temp, left);
+    // Check if count is too large for handling it inlined.
+    __ movl(temp, left);
+    __ AssertSmiInRange(right);
     __ SmiUntag(right);
     // Overflow test (preserve temp and right);
-    __ shlq(left, right);
-    __ sarq(left, right);
-    __ cmpq(left, temp);
+    __ shll(temp, right);
+    __ sarl(temp, right);
+    __ cmpl(temp, left);
     __ j(NOT_EQUAL, deopt);  // Overflow.
     // Shift for result now we know there is no overflow.
     __ shlq(left, right);
+    ASSERT(!shift_left->is_truncating());
   }
 }
 
@@ -2907,19 +2953,23 @@
   switch (op_kind()) {
     case Token::kADD:
       __ movq(result, left);
-      __ addq(result, right);
+      __ addl(result, right);
       __ j(OVERFLOW, slow_path->entry_label());
+      __ movsxd(result, result);
       break;
     case Token::kSUB:
       __ movq(result, left);
-      __ subq(result, right);
+      __ subl(result, right);
       __ j(OVERFLOW, slow_path->entry_label());
+      __ movsxd(result, result);
       break;
     case Token::kMUL:
       __ movq(result, left);
+      __ AssertSmiInRange(result);
       __ SmiUntag(result);
-      __ imulq(result, right);
+      __ imull(result, right);
       __ j(OVERFLOW, slow_path->entry_label());
+      __ movsxd(result, result);
       break;
     case Token::kBIT_OR:
       ASSERT(left == result);
@@ -2940,13 +2990,15 @@
       __ j(ABOVE_EQUAL, slow_path->entry_label());
 
       __ movq(RCX, right);
+      __ AssertSmiInRange(RCX);
       __ SmiUntag(RCX);
       __ movq(result, left);
-      __ shlq(result, RCX);
+      __ shll(result, RCX);
       __ movq(TMP, result);
-      __ sarq(TMP, RCX);
-      __ cmpq(TMP, left);
+      __ sarl(TMP, RCX);
+      __ cmpl(TMP, left);
       __ j(NOT_EQUAL, slow_path->entry_label());
+      __ movsxd(result, result);
       break;
     case Token::kSHR: {
       Label shift_count_ok;
@@ -2955,6 +3007,8 @@
       __ cmpq(right, Immediate(Smi::RawValue(Smi::kBits)));
       __ j(ABOVE_EQUAL, slow_path->entry_label());
 
+      __ AssertSmiInRange(left);
+      __ AssertSmiInRange(right);
       __ movq(RCX, right);
       __ SmiUntag(RCX);
       __ movq(result, left);
@@ -3103,6 +3157,16 @@
          Immediate(reinterpret_cast<int64_t>(constant.raw())).is_int32();
 }
 
+static bool CanBeUint32Immediate(const Object& constant) {
+  if (constant.IsSmi()) {
+    return Immediate(Smi::Cast(constant).Value()).is_uint32();
+  }
+  if (constant.IsMint()) {
+    return Immediate(Mint::Cast(constant).value()).is_uint32();
+  }
+  return false;
+}
+
 static bool IsSmiValue(const Object& constant, intptr_t value) {
   return constant.IsSmi() && (Smi::Cast(constant).Value() == value);
 }
@@ -3212,20 +3276,41 @@
     const int64_t imm = reinterpret_cast<int64_t>(constant.raw());
     switch (op_kind()) {
       case Token::kADD: {
-        __ AddImmediate(left, Immediate(imm));
-        if (deopt != NULL) __ j(OVERFLOW, deopt);
+        if (deopt != NULL) {
+          __ AddImmediate(left, Immediate(imm), Assembler::k32Bit);
+          __ j(OVERFLOW, deopt);
+        } else {
+          __ AddImmediate(left, Immediate(imm), Assembler::k64Bit);
+        }
+        if (deopt != NULL || is_truncating()) {
+          __ movsxd(left, left);
+        }
         break;
       }
       case Token::kSUB: {
-        __ SubImmediate(left, Immediate(imm));
-        if (deopt != NULL) __ j(OVERFLOW, deopt);
+        if (deopt != NULL) {
+          __ SubImmediate(left, Immediate(imm), Assembler::k32Bit);
+          __ j(OVERFLOW, deopt);
+        } else {
+          __ SubImmediate(left, Immediate(imm), Assembler::k64Bit);
+        }
+        if (deopt != NULL || is_truncating()) {
+          __ movsxd(left, left);
+        }
         break;
       }
       case Token::kMUL: {
         // Keep left value tagged and untag right value.
         const intptr_t value = Smi::Cast(constant).Value();
-        __ MulImmediate(left, Immediate(value));
-        if (deopt != NULL) __ j(OVERFLOW, deopt);
+        if (deopt != NULL) {
+          __ MulImmediate(left, Immediate(value), Assembler::k32Bit);
+          __ j(OVERFLOW, deopt);
+        } else {
+          __ MulImmediate(left, Immediate(value), Assembler::k64Bit);
+        }
+        if (deopt != NULL || is_truncating()) {
+          __ movsxd(left, left);
+        }
         break;
       }
       case Token::kTRUNCDIV: {
@@ -3237,7 +3322,9 @@
         ASSERT(kSmiTagSize == 1);
         Register temp = locs()->temp(0).reg();
         __ movq(temp, left);
-        __ sarq(temp, Immediate(63));
+        // Since Smis are sign extended this is enough shift to put all-1s or
+        // all-0s in the temp register.
+        __ sarq(temp, Immediate(31));
         ASSERT(shift_count > 1);  // 1, -1 case handled above.
         __ shrq(temp, Immediate(64 - shift_count));
         __ addq(left, temp);
@@ -3266,8 +3353,10 @@
       }
 
       case Token::kSHR: {
-        // sarq operation masks the count to 6 bits.
-        const intptr_t kCountLimit = 0x3F;
+        // The sarq operation masks the count to 6 bits, but any shift between
+        // 31 and 63 gives the same result because 32 bit Smis are stored sign
+        // extended in the registers.
+        const intptr_t kCountLimit = 0x1F;
         const intptr_t value = Smi::Cast(constant).Value();
         __ sarq(left,
                 Immediate(Utils::Minimum(value + kSmiTagSize, kCountLimit)));
@@ -3279,6 +3368,7 @@
         UNREACHABLE();
         break;
     }
+    __ AssertSmiInRange(left);
     return;
   }  // locs()->in(1).IsConstant().
 
@@ -3286,19 +3376,40 @@
     const Address& right = locs()->in(1).ToStackSlotAddress();
     switch (op_kind()) {
       case Token::kADD: {
-        __ addq(left, right);
-        if (deopt != NULL) __ j(OVERFLOW, deopt);
+        if (deopt != NULL) {
+          __ addl(left, right);
+          __ j(OVERFLOW, deopt);
+        } else {
+          __ addq(left, right);
+        }
+        if (deopt != NULL || is_truncating()) {
+          __ movsxd(left, left);
+        }
         break;
       }
       case Token::kSUB: {
-        __ subq(left, right);
-        if (deopt != NULL) __ j(OVERFLOW, deopt);
+        if (deopt != NULL) {
+          __ subl(left, right);
+          __ j(OVERFLOW, deopt);
+        } else {
+          __ subq(left, right);
+        }
+        if (deopt != NULL || is_truncating()) {
+          __ movsxd(left, left);
+        }
         break;
       }
       case Token::kMUL: {
         __ SmiUntag(left);
-        __ imulq(left, right);
-        if (deopt != NULL) __ j(OVERFLOW, deopt);
+        if (deopt != NULL) {
+          __ imull(left, right);
+          __ j(OVERFLOW, deopt);
+        } else {
+          __ imulq(left, right);
+        }
+        if (deopt != NULL || is_truncating()) {
+          __ movsxd(left, left);
+        }
         break;
       }
       case Token::kBIT_AND: {
@@ -3327,19 +3438,40 @@
   Register right = locs()->in(1).reg();
   switch (op_kind()) {
     case Token::kADD: {
-      __ addq(left, right);
-      if (deopt != NULL) __ j(OVERFLOW, deopt);
+      if (deopt != NULL) {
+        __ addl(left, right);
+        __ j(OVERFLOW, deopt);
+      } else {
+        __ addq(left, right);
+      }
+      if (deopt != NULL || is_truncating()) {
+        __ movsxd(left, left);
+      }
       break;
     }
     case Token::kSUB: {
-      __ subq(left, right);
-      if (deopt != NULL) __ j(OVERFLOW, deopt);
+      if (deopt != NULL) {
+        __ subl(left, right);
+        __ j(OVERFLOW, deopt);
+      } else {
+        __ subq(left, right);
+      }
+      if (deopt != NULL || is_truncating()) {
+        __ movsxd(left, left);
+      }
       break;
     }
     case Token::kMUL: {
       __ SmiUntag(left);
-      __ imulq(left, right);
-      if (deopt != NULL) __ j(OVERFLOW, deopt);
+      if (deopt != NULL) {
+        __ imull(left, right);
+        __ j(OVERFLOW, deopt);
+      } else {
+        __ imulq(left, right);
+      }
+      if (deopt != NULL || is_truncating()) {
+        __ movsxd(left, left);
+      }
       break;
     }
     case Token::kBIT_AND: {
@@ -3358,8 +3490,6 @@
       break;
     }
     case Token::kTRUNCDIV: {
-      Label not_32bit, done;
-
       Register temp = locs()->temp(0).reg();
       ASSERT(left == RAX);
       ASSERT((right != RDX) && (right != RAX));
@@ -3370,43 +3500,20 @@
         __ testq(right, right);
         __ j(ZERO, deopt);
       }
-      // Check if both operands fit into 32bits as idiv with 64bit operands
-      // requires twice as many cycles and has much higher latency.
-      // We are checking this before untagging them to avoid corner case
-      // dividing INT_MAX by -1 that raises exception because quotient is
-      // too large for 32bit register.
-      __ movsxd(temp, left);
-      __ cmpq(temp, left);
-      __ j(NOT_EQUAL, &not_32bit);
-      __ movsxd(temp, right);
-      __ cmpq(temp, right);
-      __ j(NOT_EQUAL, &not_32bit);
-
       // Both operands are 31bit smis. Divide using 32bit idiv.
       __ SmiUntag(left);
       __ SmiUntag(right);
       __ cdq();
       __ idivl(right);
-      __ movsxd(result, result);
-      __ jmp(&done);
-
-      // Divide using 64bit idiv.
-      __ Bind(&not_32bit);
-      __ SmiUntag(left);
-      __ SmiUntag(right);
-      __ cqo();         // Sign extend RAX -> RDX:RAX.
-      __ idivq(right);  //  RAX: quotient, RDX: remainder.
       // Check the corner case of dividing the 'MIN_SMI' with -1, in which
       // case we cannot tag the result.
-      __ CompareImmediate(result, Immediate(0x4000000000000000));
+      __ cmpl(result, Immediate(0x40000000));
       __ j(EQUAL, deopt);
-      __ Bind(&done);
+      __ movsxd(result, result);
       __ SmiTag(result);
       break;
     }
     case Token::kMOD: {
-      Label not_32bit, div_done;
-
       Register temp = locs()->temp(0).reg();
       ASSERT(left == RDX);
       ASSERT((right != RDX) && (right != RAX));
@@ -3417,17 +3524,6 @@
         __ testq(right, right);
         __ j(ZERO, deopt);
       }
-      // Check if both operands fit into 32bits as idiv with 64bit operands
-      // requires twice as many cycles and has much higher latency.
-      // We are checking this before untagging them to avoid corner case
-      // dividing INT_MAX by -1 that raises exception because quotient is
-      // too large for 32bit register.
-      __ movsxd(temp, left);
-      __ cmpq(temp, left);
-      __ j(NOT_EQUAL, &not_32bit);
-      __ movsxd(temp, right);
-      __ cmpq(temp, right);
-      __ j(NOT_EQUAL, &not_32bit);
       // Both operands are 31bit smis. Divide using 32bit idiv.
       __ SmiUntag(left);
       __ SmiUntag(right);
@@ -3435,16 +3531,7 @@
       __ cdq();
       __ idivl(right);
       __ movsxd(result, result);
-      __ jmp(&div_done);
 
-      // Divide using 64bit idiv.
-      __ Bind(&not_32bit);
-      __ SmiUntag(left);
-      __ SmiUntag(right);
-      __ movq(RAX, RDX);
-      __ cqo();         // Sign extend RAX -> RDX:RAX.
-      __ idivq(right);  //  RAX: quotient, RDX: remainder.
-      __ Bind(&div_done);
       //  res = left % right;
       //  if (res < 0) {
       //    if (right < 0) {
@@ -3482,7 +3569,10 @@
         __ j(LESS, deopt);
       }
       __ SmiUntag(right);
-      // sarq operation masks the count to 6 bits.
+      // The sarq operation masks the count to 6 bits, but any shift between 31
+      // and 63 gives the same result because 32 bit Smis are stored sign
+      // extended in the registers.  We check for 63 in order to take the branch
+      // more predictably.
       const intptr_t kCountLimit = 0x3F;
       if (!RangeUtils::OnlyLessThanOrEqualTo(right_range(), kCountLimit)) {
         __ CompareImmediate(right, Immediate(kCountLimit));
@@ -3681,7 +3771,12 @@
   LocationSummary* summary = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
   summary->set_in(0, Location::RequiresRegister());
-  summary->set_out(0, Location::SameAsFirstInput());
+  const intptr_t value_cid = value()->Type()->ToCid();
+  if (value_cid == kSmiCid || value_cid == kMintCid) {
+    summary->set_out(0, Location::SameAsFirstInput());
+  } else {
+    summary->set_out(0, Location::RequiresRegister());
+  }
   if (kNumTemps > 0) {
     summary->set_temp(0, Location::RequiresRegister());
   }
@@ -3689,75 +3784,88 @@
 }
 
 void UnboxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  // We don't use unboxed signed int32 on 64 bit platforms, so this is an
+  // unboxing to 32 bit unsigned integer, zero extended.
+  ASSERT(representation() == kUnboxedUint32);
+  ASSERT(is_truncating());
   const intptr_t value_cid = value()->Type()->ToCid();
   const Register value = locs()->in(0).reg();
-  Label* deopt = CanDeoptimize() ? compiler->AddDeoptStub(
-                                       GetDeoptId(), ICData::kDeoptUnboxInteger)
-                                 : NULL;
-  ASSERT(value == locs()->out(0).reg());
+  const Register out = locs()->out(0).reg();
+  Label done_and_no_need_to_check_range;
 
   if (value_cid == kSmiCid) {
-    __ SmiUntag(value);
+    ASSERT(value == out);
+    __ AssertSmiInRange(value);
+    // A 32 bit Smi (31 bits plus tag) can just be made into a uint32 with a 32
+    // bit sar operation.
+    __ sarl(value, Immediate(kSmiTagShift));
   } else if (value_cid == kMintCid) {
-    __ movq(value, FieldAddress(value, Mint::value_offset()));
-  } else if (!CanDeoptimize()) {
-    // Type information is not conclusive, but range analysis found
-    // the value to be in int64 range. Therefore it must be a smi
-    // or mint value.
-    ASSERT(is_truncating());
-    Label done;
-    __ SmiUntag(value);
-    __ j(NOT_CARRY, &done, Assembler::kNearJump);
-    __ movq(value, Address(value, TIMES_2, Mint::value_offset()));
-    __ Bind(&done);
-    return;
+    ASSERT(value == out);
+    __ movl(value, FieldAddress(value, Mint::value_offset()));
   } else {
     Label done;
-    // Optimistically untag value.
-    __ SmiUntagOrCheckClass(value, kMintCid, &done);
-    __ j(NOT_EQUAL, deopt);
-    // Undo untagging by multiplying value with 2.
-    __ movq(value, Address(value, TIMES_2, Mint::value_offset()));
+    ASSERT(out != value);
+    __ movl(out, value);
+    __ sarl(out, Immediate(kSmiTagShift));  // See sarl comment above.
+    ASSERT(kSmiTag == 0);
+    __ j(NOT_CARRY, &done, Assembler::kNearJump);
+    if (CanDeoptimize()) {
+      Label* deopt =
+          compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptUnboxInteger);
+      __ LoadClassId(TMP, value);
+      __ cmpl(TMP, Immediate(kMintCid));
+      __ j(NOT_EQUAL, deopt);
+    }
+    __ movl(out, FieldAddress(value, Mint::value_offset()));
     __ Bind(&done);
   }
-
-  // TODO(vegorov): as it is implemented right now truncating unboxing would
-  // leave "garbage" in the higher word.
-  if (!is_truncating() && (deopt != NULL)) {
-    ASSERT(representation() == kUnboxedInt32);
-    Register temp = locs()->temp(0).reg();
-    __ movsxd(temp, value);
-    __ cmpq(temp, value);
-    __ j(NOT_EQUAL, deopt);
-  }
+  __ AssertValidUint32(locs()->out(0).reg());
 }
 
 LocationSummary* BoxInteger32Instr::MakeLocationSummary(Zone* zone,
                                                         bool opt) const {
-  ASSERT((from_representation() == kUnboxedInt32) ||
-         (from_representation() == kUnboxedUint32));
+  ASSERT(from_representation() == kUnboxedUint32);
   const intptr_t kNumInputs = 1;
-  const intptr_t kNumTemps = 0;
+  const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1;
   LocationSummary* summary = new (zone)
-      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
-  summary->set_in(0, Location::RequiresRegister());
-  summary->set_out(0, Location::RequiresRegister());
+      LocationSummary(zone, kNumInputs, kNumTemps,
+                      ValueFitsSmi() ? LocationSummary::kNoCall
+                                     : LocationSummary::kCallOnSlowPath);
+  const bool needs_writable_input =
+      ValueFitsSmi() || (from_representation() == kUnboxedUint32);
+  summary->set_in(0, needs_writable_input ? Location::RequiresRegister()
+                                          : Location::WritableRegister());
+  if (!ValueFitsSmi()) {
+    summary->set_temp(0, Location::RequiresRegister());
+  }
+  summary->set_out(0, ValueFitsSmi() ? Location::SameAsFirstInput()
+                                     : Location::RequiresRegister());
   return summary;
 }
 
 void BoxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
   const Register value = locs()->in(0).reg();
   const Register out = locs()->out(0).reg();
-  ASSERT(value != out);
 
-  ASSERT(kSmiTagSize == 1);
-  if (from_representation() == kUnboxedInt32) {
-    __ movsxd(out, value);
-  } else {
-    ASSERT(from_representation() == kUnboxedUint32);
-    __ movl(out, value);
+  // Unsigned unboxed 32 bit to sign extended 31 bit Smi.
+  __ leaq(out, Address(value, value, TIMES_1, 0));
+
+  if (!ValueFitsSmi()) {
+    Label done;
+    ASSERT(value != out);
+    __ TestImmediate(value, Immediate(0xc0000000ll));
+    __ j(ZERO, &done);
+
+    // Allocate a mint.
+    // Value input is a writable register and we have to inform the compiler of
+    // the type so it can be preserved untagged on the slow path
+    locs()->live_registers()->Add(locs()->in(0), kUnboxedInt32);
+    BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), out,
+                                    locs()->temp(0).reg());
+    __ AssertValidUint32(value);
+    __ movq(FieldAddress(out, Mint::value_offset()), value);
+    __ Bind(&done);
   }
-  __ SmiTag(out);
 }
 
 LocationSummary* BoxInt64Instr::MakeLocationSummary(Zone* zone,
@@ -3779,15 +3887,20 @@
 void BoxInt64Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
   const Register out = locs()->out(0).reg();
   const Register value = locs()->in(0).reg();
-  __ MoveRegister(out, value);
-  __ SmiTag(out);
+  __ leaq(out, Address(value, value, TIMES_1, 0));
   if (!ValueFitsSmi()) {
     const Register temp = locs()->temp(0).reg();
     Label done;
-    __ j(NO_OVERFLOW, &done);
+    __ movq(temp, value);
+    __ sarq(temp, Immediate(30));
+    __ addq(temp, Immediate(1));
+    __ cmpq(temp, Immediate(2));
+    __ j(BELOW, &done);
+
     BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), out,
                                     temp);
     __ movq(FieldAddress(out, Mint::value_offset()), value);
+
     __ Bind(&done);
   }
 }
@@ -4349,8 +4462,9 @@
   switch (op_kind()) {
     case Token::kNEGATE: {
       Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp);
+      __ cmpq(value, Immediate(-0x80000000ll));
+      __ j(EQUAL, deopt);
       __ negq(value);
-      __ j(OVERFLOW, deopt);
       break;
     }
     case Token::kBIT_NOT:
@@ -4499,6 +4613,7 @@
 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   Register value = locs()->in(0).reg();
   FpuRegister result = locs()->out(0).fpu_reg();
+  __ AssertSmiInRange(value);
   __ SmiUntag(value);
   __ cvtsi2sdq(result, value);
 }
@@ -4528,14 +4643,15 @@
   ASSERT(result != value_obj);
   ASSERT(result != temp);
   __ movsd(value_double, FieldAddress(value_obj, Double::value_offset()));
-  __ cvttsd2siq(result, value_double);
+  __ cvttsd2sil(result, value_double);
   // Overflow is signalled with minint.
   Label do_call, done;
   // Check for overflow and that it fits into Smi.
-  __ movq(temp, result);
-  __ shlq(temp, Immediate(1));
+  __ movl(temp, result);
+  __ shll(temp, Immediate(1));
   __ j(OVERFLOW, &do_call, Assembler::kNearJump);
-  __ SmiTag(result);
+  ASSERT(kSmiTagShift == 1 && kSmiTag == 0);
+  __ movsxd(result, temp);
   __ jmp(&done);
   __ Bind(&do_call);
   __ pushq(value_obj);
@@ -4571,14 +4687,15 @@
   XmmRegister value = locs()->in(0).fpu_reg();
   Register temp = locs()->temp(0).reg();
 
-  __ cvttsd2siq(result, value);
+  __ cvttsd2sil(result, value);
   // Overflow is signalled with minint.
   Label do_call, done;
   // Check for overflow and that it fits into Smi.
-  __ movq(temp, result);
-  __ shlq(temp, Immediate(1));
+  __ movl(temp, result);
+  __ shll(temp, Immediate(1));
   __ j(OVERFLOW, deopt);
-  __ SmiTag(result);
+  ASSERT(kSmiTagShift == 1 && kSmiTag == 0);
+  __ movsxd(result, temp);
 }
 
 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(Zone* zone,
@@ -4877,6 +4994,7 @@
   // Both inputs must be writable because they will be untagged.
   summary->set_in(0, Location::RegisterLocation(RAX));
   summary->set_in(1, Location::WritableRegister());
+  // Output is a pair of registers.
   summary->set_out(0, Location::Pair(Location::RegisterLocation(RAX),
                                      Location::RegisterLocation(RDX)));
   return summary;
@@ -4891,50 +5009,26 @@
   PairLocation* pair = locs()->out(0).AsPairLocation();
   Register result1 = pair->At(0).reg();
   Register result2 = pair->At(1).reg();
-  Label not_32bit, done;
-  Register temp = RDX;
-  ASSERT(left == RAX);
-  ASSERT((right != RDX) && (right != RAX));
-  ASSERT(result1 == RAX);
-  ASSERT(result2 == RDX);
   if (RangeUtils::CanBeZero(divisor_range())) {
     // Handle divide by zero in runtime.
     __ testq(right, right);
     __ j(ZERO, deopt);
   }
-  // Check if both operands fit into 32bits as idiv with 64bit operands
-  // requires twice as many cycles and has much higher latency.
-  // We are checking this before untagging them to avoid corner case
-  // dividing INT_MAX by -1 that raises exception because quotient is
-  // too large for 32bit register.
-  __ movsxd(temp, left);
-  __ cmpq(temp, left);
-  __ j(NOT_EQUAL, &not_32bit);
-  __ movsxd(temp, right);
-  __ cmpq(temp, right);
-  __ j(NOT_EQUAL, &not_32bit);
-
+  ASSERT(left == RAX);
+  ASSERT((right != RDX) && (right != RAX));
+  ASSERT(result1 == RAX);
+  ASSERT(result2 == RDX);
   // Both operands are 31bit smis. Divide using 32bit idiv.
   __ SmiUntag(left);
   __ SmiUntag(right);
   __ cdq();
   __ idivl(right);
-  __ movsxd(RAX, RAX);
-  __ movsxd(RDX, RDX);
-  __ jmp(&done);
-
-  // Divide using 64bit idiv.
-  __ Bind(&not_32bit);
-  __ SmiUntag(left);
-  __ SmiUntag(right);
-  __ cqo();         // Sign extend RAX -> RDX:RAX.
-  __ idivq(right);  //  RAX: quotient, RDX: remainder.
   // Check the corner case of dividing the 'MIN_SMI' with -1, in which
   // case we cannot tag the result.
-  __ CompareImmediate(RAX, Immediate(0x4000000000000000));
+  __ cmpl(RAX, Immediate(0x40000000));
   __ j(EQUAL, deopt);
-  __ Bind(&done);
-
+  __ movsxd(RAX, RAX);
+  __ movsxd(RDX, RDX);
   // Modulo correction (RDX).
   //  res = left % right;
   //  if (res < 0) {
@@ -4944,16 +5038,16 @@
   //      res = res + right;
   //    }
   //  }
-  Label all_done;
+  Label done;
   __ cmpq(RDX, Immediate(0));
-  __ j(GREATER_EQUAL, &all_done, Assembler::kNearJump);
+  __ j(GREATER_EQUAL, &done, Assembler::kNearJump);
   // Result is negative, adjust it.
   if ((divisor_range() == NULL) || divisor_range()->Overlaps(-1, 1)) {
     Label subtract;
     __ cmpq(right, Immediate(0));
     __ j(LESS, &subtract, Assembler::kNearJump);
     __ addq(RDX, right);
-    __ jmp(&all_done, Assembler::kNearJump);
+    __ jmp(&done, Assembler::kNearJump);
     __ Bind(&subtract);
     __ subq(RDX, right);
   } else if (divisor_range()->IsPositive()) {
@@ -4963,7 +5057,7 @@
     // Right is negative.
     __ subq(RDX, right);
   }
-  __ Bind(&all_done);
+  __ Bind(&done);
 
   __ SmiTag(RAX);
   __ SmiTag(RDX);
@@ -5221,8 +5315,7 @@
 
   if (right.IsConstant()) {
     ConstantInstr* constant_instr = right.constant_instruction();
-    const int64_t value =
-        constant_instr->GetUnboxedSignedIntegerConstantValue();
+    const int64_t value = constant_instr->GetUnboxedIntegerConstantValue();
     EmitInt64Arithmetic(compiler, op_kind(), left.reg(), Immediate(value),
                         deopt);
   } else {
@@ -5305,6 +5398,7 @@
     // Code for a variable shift amount.
     // Deoptimize if shift count is > 63 or negative.
     // Sarq and shlq instructions mask the count to 6 bits.
+    __ AssertSmiInRange(RCX);
     __ SmiUntag(RCX);
     if (!IsShiftCountInRange()) {
       __ cmpq(RCX, Immediate(kMintShiftCountLimit));
@@ -5337,21 +5431,31 @@
 }
 
 CompileType BinaryUint32OpInstr::ComputeType() const {
-  return CompileType::FromCid(kSmiCid);
+  return CompileType::Int();
 }
 
 CompileType ShiftUint32OpInstr::ComputeType() const {
-  return CompileType::FromCid(kSmiCid);
+  return CompileType::Int();
 }
 
 CompileType UnaryUint32OpInstr::ComputeType() const {
-  return CompileType::FromCid(kSmiCid);
+  return CompileType::Int();
 }
 
 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Zone* zone,
                                                           bool opt) const {
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
+  ConstantInstr* right_constant = right()->definition()->AsConstant();
+  if (right_constant != NULL && op_kind() != Token::kMUL &&
+      CanBeUint32Immediate(right_constant->value())) {
+    LocationSummary* summary = new (zone)
+        LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+    summary->set_in(0, Location::RequiresRegister());
+    summary->set_in(1, Location::Constant(right_constant));
+    summary->set_out(0, Location::SameAsFirstInput());
+    return summary;
+  }
   LocationSummary* summary = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
   summary->set_in(0, Location::RequiresRegister());
@@ -5365,6 +5469,7 @@
                                   Token::Kind op_kind,
                                   Register left,
                                   const OperandType& right) {
+  __ AssertValidUint32(left);
   switch (op_kind) {
     case Token::kADD:
       __ addl(left, right);
@@ -5387,24 +5492,21 @@
     default:
       UNREACHABLE();
   }
+  __ AssertValidUint32(left);
 }
 
 void BinaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   Register left = locs()->in(0).reg();
-  Register right = locs()->in(1).reg();
   Register out = locs()->out(0).reg();
   ASSERT(out == left);
-  switch (op_kind()) {
-    case Token::kBIT_AND:
-    case Token::kBIT_OR:
-    case Token::kBIT_XOR:
-    case Token::kADD:
-    case Token::kSUB:
-    case Token::kMUL:
-      EmitIntegerArithmetic(compiler, op_kind(), left, right);
-      return;
-    default:
-      UNREACHABLE();
+  if (locs()->in(1).IsRegister()) {
+    Register right = locs()->in(1).reg();
+    EmitIntegerArithmetic(compiler, op_kind(), left, right);
+  } else {
+    ASSERT(locs()->in(1).IsConstant());
+    ConstantInstr* right_constant = right()->definition()->AsConstant();
+    int32_t imm = right_constant->GetUnboxedIntegerConstantValue();
+    EmitIntegerArithmetic(compiler, op_kind(), left, Immediate(imm));
   }
 }
 
@@ -5460,6 +5562,7 @@
   Label zero;
 
   // TODO(johnmccutchan): Use range information to avoid these checks.
+  __ AssertSmiInRange(shifter);
   __ SmiUntag(shifter);
   __ cmpq(shifter, Immediate(0));
   // If shift value is < 0, deoptimize.
@@ -5484,13 +5587,14 @@
 
   __ Bind(&zero);
   // Shift was greater than 31 bits, just return zero.
-  __ xorq(left, left);
+  __ xorl(left, left);
 
   // Exit path.
   __ Bind(&done);
 }
 
 DEFINE_BACKEND(UnaryUint32Op, (SameAsFirstInput, Register value)) {
+  __ AssertValidUint32(value);
   __ notl(value);
 }
 
@@ -5525,8 +5629,8 @@
     const Register out = locs()->out(0).reg();
     // Representations are bitwise equivalent but we want to normalize
     // upperbits for safety reasons.
-    // TODO(vegorov) if we ensure that we never use upperbits we could
-    // avoid this.
+    // TODO(vegorov) if we ensure that we never leave garbage in the upper bits
+    // we could avoid this.
     __ movl(out, value);
   } else if (from() == kUnboxedUint32 && to() == kUnboxedInt32) {
     // Representations are bitwise equivalent.
diff --git a/runtime/vm/compiler/backend/inliner.cc b/runtime/vm/compiler/backend/inliner.cc
index e137fad..5db455b 100644
--- a/runtime/vm/compiler/backend/inliner.cc
+++ b/runtime/vm/compiler/backend/inliner.cc
@@ -2478,13 +2478,16 @@
         DoubleToFloatInstr(new (Z) Value(stored_value), call->deopt_id());
     cursor =
         flow_graph->AppendTo(cursor, stored_value, NULL, FlowGraph::kValue);
+#if !defined(AVOID_UNBOXED_INT32)
   } else if (array_cid == kTypedDataInt32ArrayCid) {
     stored_value =
         new (Z) UnboxInt32Instr(UnboxInt32Instr::kTruncate,
                                 new (Z) Value(stored_value), call->deopt_id());
     cursor = flow_graph->AppendTo(cursor, stored_value, call->env(),
                                   FlowGraph::kValue);
-  } else if (array_cid == kTypedDataUint32ArrayCid) {
+#endif
+  } else if (array_cid == kTypedDataUint32ArrayCid ||
+             array_cid == kTypedDataInt32ArrayCid) {
     stored_value =
         new (Z) UnboxUint32Instr(new (Z) Value(stored_value), call->deopt_id());
     ASSERT(stored_value->AsUnboxInteger()->is_truncating());
@@ -2786,13 +2789,16 @@
         DoubleToFloatInstr(new (Z) Value(stored_value), call->deopt_id());
     cursor =
         flow_graph->AppendTo(cursor, stored_value, NULL, FlowGraph::kValue);
+#if !defined(AVOID_UNBOXED_INT32)
   } else if (view_cid == kTypedDataInt32ArrayCid) {
     stored_value =
         new (Z) UnboxInt32Instr(UnboxInt32Instr::kTruncate,
                                 new (Z) Value(stored_value), call->deopt_id());
     cursor = flow_graph->AppendTo(cursor, stored_value, call->env(),
                                   FlowGraph::kValue);
-  } else if (view_cid == kTypedDataUint32ArrayCid) {
+#endif
+  } else if (view_cid == kTypedDataInt32ArrayCid ||  // Again, outside ifdef.
+             view_cid == kTypedDataUint32ArrayCid) {
     stored_value =
         new (Z) UnboxUint32Instr(new (Z) Value(stored_value), call->deopt_id());
     ASSERT(stored_value->AsUnboxInteger()->is_truncating());
diff --git a/runtime/vm/compiler/backend/range_analysis_test.cc b/runtime/vm/compiler/backend/range_analysis_test.cc
index 081c7e8..175b42b 100644
--- a/runtime/vm/compiler/backend/range_analysis_test.cc
+++ b/runtime/vm/compiler/backend/range_analysis_test.cc
@@ -66,17 +66,10 @@
                 RangeBoundary::PositiveInfinity());
   TEST_RANGE_OP(Range::Shl, -1, 1, 63, 63, RangeBoundary(kMinInt64),
                 RangeBoundary::PositiveInfinity());
-  if (kBitsPerWord == 64) {
-    TEST_RANGE_OP_SMI(Range::Shl, -1, 1, 62, 62, RangeBoundary(kSmiMin),
-                      RangeBoundary(kSmiMax));
-    TEST_RANGE_OP_SMI(Range::Shl, -1, 1, 30, 30, RangeBoundary(-(1 << 30)),
-                      RangeBoundary(1 << 30));
-  } else {
-    TEST_RANGE_OP_SMI(Range::Shl, -1, 1, 30, 30, RangeBoundary(kSmiMin),
-                      RangeBoundary(kSmiMax));
-    TEST_RANGE_OP_SMI(Range::Shl, -1, 1, 62, 62, RangeBoundary(kSmiMin),
-                      RangeBoundary(kSmiMax));
-  }
+  TEST_RANGE_OP_SMI(Range::Shl, -1, 1, 30, 30, RangeBoundary(kSmiMin),
+                    RangeBoundary(kSmiMax));
+  TEST_RANGE_OP_SMI(Range::Shl, -1, 1, 62, 62, RangeBoundary(kSmiMin),
+                    RangeBoundary(kSmiMax));
   TEST_RANGE_OP(Range::Shl, 0, 100, 0, 64, RangeBoundary(0),
                 RangeBoundary::PositiveInfinity());
   TEST_RANGE_OP(Range::Shl, -100, 0, 0, 64, RangeBoundary::NegativeInfinity(),
diff --git a/runtime/vm/compiler/call_specializer.cc b/runtime/vm/compiler/call_specializer.cc
index 30e0407..870884e 100644
--- a/runtime/vm/compiler/call_specializer.cc
+++ b/runtime/vm/compiler/call_specializer.cc
@@ -349,13 +349,15 @@
 }
 
 void CallSpecializer::AddCheckNull(Value* to_check,
+                                   const String& function_name,
                                    intptr_t deopt_id,
                                    Environment* deopt_environment,
                                    Instruction* insert_before) {
   ASSERT(I->strong() && FLAG_use_strong_mode_types);
   if (to_check->Type()->is_nullable()) {
-    CheckNullInstr* check_null = new (Z) CheckNullInstr(
-        to_check->CopyWithType(Z), deopt_id, insert_before->token_pos());
+    CheckNullInstr* check_null =
+        new (Z) CheckNullInstr(to_check->CopyWithType(Z), function_name,
+                               deopt_id, insert_before->token_pos());
     if (FLAG_trace_strong_mode_types) {
       THR_Print("[Strong mode] Inserted %s\n", check_null->ToCString());
     }
@@ -1558,10 +1560,10 @@
 }
 
 void CallSpecializer::VisitLoadCodeUnits(LoadCodeUnitsInstr* instr) {
-// TODO(zerny): Use kUnboxedUint32 once it is fully supported/optimized.
-#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM)
+  // Note that on ARM64 the result can always be packed into a Smi, so this
+  // is never triggered.
+  // TODO(zerny): Use kUnboxedUint32 once it is fully supported/optimized.
   if (!instr->can_pack_into_smi()) instr->set_representation(kUnboxedInt64);
-#endif
 }
 
 static bool CidTestResultsContains(const ZoneGrowableArray<intptr_t>& results,
diff --git a/runtime/vm/compiler/call_specializer.h b/runtime/vm/compiler/call_specializer.h
index d74784e..04bf617 100644
--- a/runtime/vm/compiler/call_specializer.h
+++ b/runtime/vm/compiler/call_specializer.h
@@ -93,6 +93,7 @@
 
   // Insert a null check if needed.
   void AddCheckNull(Value* to_check,
+                    const String& function_name,
                     intptr_t deopt_id,
                     Environment* deopt_environment,
                     Instruction* insert_before);
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 4b86b49..82d89d1 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -6985,8 +6985,9 @@
 }
 
 Fragment StreamingFlowGraphBuilder::CheckNull(TokenPosition position,
-                                              LocalVariable* receiver) {
-  return flow_graph_builder_->CheckNull(position, receiver);
+                                              LocalVariable* receiver,
+                                              const String& function_name) {
+  return flow_graph_builder_->CheckNull(position, receiver, function_name);
 }
 
 Fragment StreamingFlowGraphBuilder::StaticCall(TokenPosition position,
@@ -7427,7 +7428,7 @@
   }
 
   if (direct_call.check_receiver_for_null_) {
-    instructions += CheckNull(TokenPosition::kNoSource, receiver);
+    instructions += CheckNull(position, receiver, getter_name);
   }
 
   if (!direct_call.target_.IsNull()) {
@@ -7489,7 +7490,7 @@
   }
 
   if (direct_call.check_receiver_for_null_) {
-    instructions += CheckNull(position, receiver);
+    instructions += CheckNull(position, receiver, setter_name);
   }
 
   if (!direct_call.target_.IsNull()) {
@@ -8045,7 +8046,7 @@
   }
 
   if (direct_call.check_receiver_for_null_) {
-    instructions += CheckNull(position, receiver_temp);
+    instructions += CheckNull(position, receiver_temp, name);
   }
 
   if (!direct_call.target_.IsNull()) {
@@ -10884,6 +10885,35 @@
         temp_instance_ = H.Canonicalize(temp_instance_);
         break;
       }
+      case kPartialInstantiationConstant: {
+        const intptr_t entry_index = builder_.ReadUInt();
+        temp_object_ = constants.At(entry_index);
+
+        const intptr_t number_of_type_arguments = builder_.ReadUInt();
+        if (temp_class_.NumTypeArguments() > 0) {
+          temp_type_arguments_ =
+              TypeArguments::New(number_of_type_arguments, Heap::kOld);
+          for (intptr_t j = 0; j < number_of_type_arguments; ++j) {
+            temp_type_arguments_.SetTypeAt(j, type_translator_.BuildType());
+          }
+        } else {
+          ASSERT(number_of_type_arguments == 0);
+          temp_type_arguments_ = TypeArguments::null();
+        }
+
+        // Make a copy of the old closure, with the delayed type arguments
+        // set to [temp_type_arguments_].
+        temp_closure_ = Closure::RawCast(temp_object_.raw());
+        temp_function_ = temp_closure_.function();
+        temp_type_arguments2_ = temp_closure_.instantiator_type_arguments();
+        temp_type_arguments3_ = temp_closure_.function_type_arguments();
+        temp_context_ = temp_closure_.context();
+        temp_closure_ = Closure::New(
+            temp_type_arguments2_, Object::null_type_arguments(),
+            temp_type_arguments_, temp_function_, temp_context_, Heap::kOld);
+        temp_instance_ = H.Canonicalize(temp_closure_);
+        break;
+      }
       case kTearOffConstant: {
         const NameIndex index = builder_.ReadCanonicalNameReference();
         NameIndex lib_index = index;
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
index 337c045d6..b4c4b83 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
@@ -1357,7 +1357,9 @@
   Fragment Constant(const Object& value);
   Fragment IntConstant(int64_t value);
   Fragment LoadStaticField();
-  Fragment CheckNull(TokenPosition position, LocalVariable* receiver);
+  Fragment CheckNull(TokenPosition position,
+                     LocalVariable* receiver,
+                     const String& function_name);
   Fragment StaticCall(TokenPosition position,
                       const Function& target,
                       intptr_t argument_count,
@@ -1680,12 +1682,16 @@
         zone_(zone),
         temp_type_(AbstractType::Handle(zone)),
         temp_type_arguments_(TypeArguments::Handle(zone)),
+        temp_type_arguments2_(TypeArguments::Handle(zone)),
+        temp_type_arguments3_(TypeArguments::Handle(zone)),
         temp_object_(Object::Handle(zone)),
         temp_array_(Array::Handle(zone)),
         temp_instance_(Instance::Handle(zone)),
         temp_field_(Field::Handle(zone)),
         temp_class_(Class::Handle(zone)),
         temp_function_(Function::Handle(zone)),
+        temp_closure_(Closure::Handle(zone)),
+        temp_context_(Context::Handle(zone)),
         temp_integer_(Integer::Handle(zone)) {}
 
   // Reads the constant table from the binary.
@@ -1707,12 +1713,16 @@
   Zone* zone_;
   AbstractType& temp_type_;
   TypeArguments& temp_type_arguments_;
+  TypeArguments& temp_type_arguments2_;
+  TypeArguments& temp_type_arguments3_;
   Object& temp_object_;
   Array& temp_array_;
   Instance& temp_instance_;
   Field& temp_field_;
   Class& temp_class_;
   Function& temp_function_;
+  Closure& temp_closure_;
+  Context& temp_context_;
   Integer& temp_integer_;
 };
 
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index 5d91b40..93ce810 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -1565,11 +1565,12 @@
 }
 
 Fragment FlowGraphBuilder::CheckNull(TokenPosition position,
-                                     LocalVariable* receiver) {
+                                     LocalVariable* receiver,
+                                     const String& function_name) {
   Fragment instructions = LoadLocal(receiver);
 
   CheckNullInstr* check_null =
-      new (Z) CheckNullInstr(Pop(), GetNextDeoptId(), position);
+      new (Z) CheckNullInstr(Pop(), function_name, GetNextDeoptId(), position);
 
   instructions <<= check_null;
 
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.h b/runtime/vm/compiler/frontend/kernel_to_il.h
index abdf092..1aa740d 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.h
+++ b/runtime/vm/compiler/frontend/kernel_to_il.h
@@ -763,7 +763,9 @@
   Fragment LoadStaticField();
   Fragment NativeCall(const String* name, const Function* function);
   Fragment Return(TokenPosition position);
-  Fragment CheckNull(TokenPosition position, LocalVariable* receiver);
+  Fragment CheckNull(TokenPosition position,
+                     LocalVariable* receiver,
+                     const String& function_name);
   void SetResultTypeForStaticCall(StaticCallInstr* call,
                                   const Function& target,
                                   intptr_t argument_count,
diff --git a/runtime/vm/compiler/intrinsifier.cc b/runtime/vm/compiler/intrinsifier.cc
index 654d33c..8ea16bb 100644
--- a/runtime/vm/compiler/intrinsifier.cc
+++ b/runtime/vm/compiler/intrinsifier.cc
@@ -373,6 +373,9 @@
   }
 
   Definition* AddUnboxInstr(Representation rep, Value* value, bool is_checked) {
+#if defined(AVOID_UNBOXED_INT32)
+    ASSERT(rep != kUnboxedInt32);
+#endif
     Definition* unboxed_value =
         AddDefinition(UnboxInstr::Create(rep, value, Thread::kNoDeoptId));
     if (is_checked) {
@@ -455,7 +458,11 @@
     case kTypedDataInt32ArrayCid:
     case kExternalTypedDataInt32ArrayCid:
       result = builder.AddDefinition(
+#if defined(AVOID_UNBOXED_INT32)
+          BoxInstr::Create(kUnboxedInt64, new Value(result)));
+#else
           BoxInstr::Create(kUnboxedInt32, new Value(result)));
+#endif
       break;
     case kTypedDataUint32ArrayCid:
     case kExternalTypedDataUint32ArrayCid:
diff --git a/runtime/vm/compiler/intrinsifier_arm.cc b/runtime/vm/compiler/intrinsifier_arm.cc
index 1fa171f..9b0c63b 100644
--- a/runtime/vm/compiler/intrinsifier_arm.cc
+++ b/runtime/vm/compiler/intrinsifier_arm.cc
@@ -1647,7 +1647,7 @@
   __ Ret();
 
   __ Bind(&use_canonical_type);
-  __ LoadClassById(R2, R1);
+  __ LoadClassById(R2, R1);  // Overwrites R1.
   __ ldrh(R3, FieldAddress(R2, Class::num_type_arguments_offset()));
   __ CompareImmediate(R3, 0);
   __ b(&fall_through, NE);
diff --git a/runtime/vm/compiler/intrinsifier_arm64.cc b/runtime/vm/compiler/intrinsifier_arm64.cc
index 4da90f0..2102c93 100644
--- a/runtime/vm/compiler/intrinsifier_arm64.cc
+++ b/runtime/vm/compiler/intrinsifier_arm64.cc
@@ -265,8 +265,9 @@
 void Intrinsifier::Integer_addFromInteger(Assembler* assembler) {
   Label fall_through;
   TestBothArgumentsSmis(assembler, &fall_through);  // Checks two smis.
-  __ adds(R0, R0, Operand(R1));                     // Adds.
+  __ addsw(R0, R0, Operand(R1));                    // Adds.
   __ b(&fall_through, VS);                          // Fall-through on overflow.
+  __ sxtw(R0, R0);  // Sign extend - flags not affected.
   __ ret();
   __ Bind(&fall_through);
 }
@@ -278,8 +279,9 @@
 void Intrinsifier::Integer_subFromInteger(Assembler* assembler) {
   Label fall_through;
   TestBothArgumentsSmis(assembler, &fall_through);
-  __ subs(R0, R0, Operand(R1));  // Subtract.
-  __ b(&fall_through, VS);       // Fall-through on overflow.
+  __ subsw(R0, R0, Operand(R1));  // Subtract.
+  __ b(&fall_through, VS);        // Fall-through on overflow.
+  __ sxtw(R0, R0);                // Sign extend - flags not affected.
   __ ret();
   __ Bind(&fall_through);
 }
@@ -287,8 +289,9 @@
 void Intrinsifier::Integer_sub(Assembler* assembler) {
   Label fall_through;
   TestBothArgumentsSmis(assembler, &fall_through);
-  __ subs(R0, R1, Operand(R0));  // Subtract.
-  __ b(&fall_through, VS);       // Fall-through on overflow.
+  __ subsw(R0, R1, Operand(R0));  // Subtract.
+  __ b(&fall_through, VS);        // Fall-through on overflow.
+  __ sxtw(R0, R0);                // Sign extend - flags not affected.
   __ ret();
   __ Bind(&fall_through);
 }
@@ -299,9 +302,9 @@
   TestBothArgumentsSmis(assembler, &fall_through);  // checks two smis
   __ SmiUntag(R0);  // Untags R6. We only want result shifted by one.
 
-  __ mul(TMP, R0, R1);
-  __ smulh(TMP2, R0, R1);
-  // TMP: result bits 64..127.
+  __ smull(TMP, R0, R1);
+  __ AsrImmediate(TMP2, TMP, 31);
+  // TMP: result bits 31..63.
   __ cmp(TMP2, Operand(TMP, ASR, 63));
   __ b(&fall_through, NE);
   __ mov(R0, TMP);
@@ -417,7 +420,7 @@
 
   // Check the corner case of dividing the 'MIN_SMI' with -1, in which case we
   // cannot tag the result.
-  __ CompareImmediate(R0, 0x4000000000000000);
+  __ CompareImmediate(R0, 0x40000000);
   __ b(&fall_through, EQ);
   __ SmiTag(R0);  // Not equal. Okay to tag and return.
   __ ret();       // Return.
@@ -428,8 +431,9 @@
   Label fall_through;
   __ ldr(R0, Address(SP, +0 * kWordSize));  // Grab first argument.
   __ BranchIfNotSmi(R0, &fall_through);
-  __ negs(R0, R0);
+  __ negsw(R0, R0);
   __ b(&fall_through, VS);
+  __ sxtw(R0, R0);  // Sign extend - flags not affected.
   __ ret();
   __ Bind(&fall_through);
 }
@@ -488,9 +492,9 @@
   // Check if count too large for handling it inlined.
   __ SmiUntag(TMP, right);  // SmiUntag right into TMP.
   // Overflow test (preserve left, right, and TMP);
-  __ lslv(temp, left, TMP);
-  __ asrv(TMP2, temp, TMP);
-  __ CompareRegisters(left, TMP2);
+  __ lslvw(temp, left, TMP);
+  __ asrvw(TMP2, temp, TMP);
+  __ cmpw(left, Operand(TMP2));
   __ b(&fall_through, NE);  // Overflow.
   // Shift for result now we know there is no overflow.
   __ lslv(result, left, TMP);
@@ -563,6 +567,7 @@
 
   __ CompareClassId(R0, kDoubleCid);
   __ b(&fall_through, EQ);
+  __ AssertSmiInRange(R1);
   __ LoadObject(R0, Bool::False());  // Smi == Mint -> false.
   __ ret();
 
@@ -573,6 +578,7 @@
   __ b(&fall_through, NE);
   // Receiver is Mint, return false if right is Smi.
   __ BranchIfNotSmi(R0, &fall_through);
+  __ AssertSmiInRange(R0);
   __ LoadObject(R0, Bool::False());
   __ ret();
   // TODO(srdjan): Implement Mint == Mint comparison.
@@ -1495,11 +1501,12 @@
   __ fcmpd(V0, V0);
   __ b(&fall_through, VS);
 
-  __ fcvtzds(R0, V0);
+  __ fcvtzdsx(R0, V0);
   // Overflow is signaled with minint.
   // Check for overflow and that it fits into Smi.
-  __ CompareImmediate(R0, 0xC000000000000000);
-  __ b(&fall_through, MI);
+  __ AsrImmediate(TMP, R0, 30);
+  __ cmp(TMP, Operand(R0, ASR, 63));
+  __ b(&fall_through, NE);
   __ SmiTag(R0);
   __ ret();
   __ Bind(&fall_through);
@@ -1516,10 +1523,10 @@
   __ fcmpd(V0, V0);
   __ b(&double_hash, VS);
 
-  // Convert double value to signed 64-bit int in R0 and back to a
+  // Convert double value to signed 32-bit int in R0 and back to a
   // double value in V1.
-  __ fcvtzds(R0, V0);
-  __ scvtfdx(V1, R0);
+  __ fcvtzdsw(R0, V0);
+  __ scvtfdw(V1, R0);
 
   // Tag the int as a Smi, making sure that it fits; this checks for
   // overflow in the conversion from double to int. Conversion
@@ -1527,8 +1534,9 @@
   // INT64_MAX or INT64_MIN (saturation).
   Label fall_through;
   ASSERT(kSmiTag == 0 && kSmiTagShift == 1);
-  __ adds(R0, R0, Operand(R0));
+  __ addsw(R0, R0, Operand(R0));
   __ b(&fall_through, VS);
+  __ sxtw(R0, R0);  // Sign extend - flags not affected.
 
   // Compare the two double values. If they are equal, we return the
   // Smi tagged result immediately as the hash code.
@@ -1702,7 +1710,7 @@
   __ ret();
 
   __ Bind(&use_canonical_type);
-  __ LoadClassById(R2, R1);
+  __ LoadClassById(R2, R1);  // Overwrites R1.
   __ ldr(R3, FieldAddress(R2, Class::num_type_arguments_offset()), kHalfword);
   __ CompareImmediate(R3, 0);
   __ b(&fall_through, NE);
@@ -1736,7 +1744,7 @@
   // Objects have the same class and neither is a closure.
   // Check if there are no type arguments. In this case we can return true.
   // Otherwise fall through into the runtime to handle comparison.
-  __ LoadClassById(R3, R1);
+  __ LoadClassById(R3, R1);  // Overwrites R1.
   __ ldr(R3, FieldAddress(R3, Class::num_type_arguments_offset()), kHalfword);
   __ CompareImmediate(R3, 0);
   __ b(&fall_through, NE);
diff --git a/runtime/vm/compiler/intrinsifier_x64.cc b/runtime/vm/compiler/intrinsifier_x64.cc
index 1e2574c..c8ddf76 100644
--- a/runtime/vm/compiler/intrinsifier_x64.cc
+++ b/runtime/vm/compiler/intrinsifier_x64.cc
@@ -269,8 +269,10 @@
   Label fall_through;
   TestBothArgumentsSmis(assembler, &fall_through);
   // RAX contains right argument.
-  __ addq(RAX, Address(RSP, +2 * kWordSize));
+  __ AssertSmiInRange(RAX);
+  __ addl(RAX, Address(RSP, +2 * kWordSize));
   __ j(OVERFLOW, &fall_through, Assembler::kNearJump);
+  __ movsxd(RAX, RAX);
   // Result is in RAX.
   __ ret();
   __ Bind(&fall_through);
@@ -284,8 +286,10 @@
   Label fall_through;
   TestBothArgumentsSmis(assembler, &fall_through);
   // RAX contains right argument, which is the actual minuend of subtraction.
-  __ subq(RAX, Address(RSP, +2 * kWordSize));
+  __ AssertSmiInRange(RAX);
+  __ subl(RAX, Address(RSP, +2 * kWordSize));
   __ j(OVERFLOW, &fall_through, Assembler::kNearJump);
+  __ movsxd(RAX, RAX);
   // Result is in RAX.
   __ ret();
   __ Bind(&fall_through);
@@ -295,10 +299,13 @@
   Label fall_through;
   TestBothArgumentsSmis(assembler, &fall_through);
   // RAX contains right argument, which is the actual subtrahend of subtraction.
+  __ AssertSmiInRange(RAX);
   __ movq(RCX, RAX);
   __ movq(RAX, Address(RSP, +2 * kWordSize));
-  __ subq(RAX, RCX);
+  __ AssertSmiInRange(RAX);
+  __ subl(RAX, RCX);
   __ j(OVERFLOW, &fall_through, Assembler::kNearJump);
+  __ movsxd(RAX, RAX);
   // Result is in RAX.
   __ ret();
   __ Bind(&fall_through);
@@ -308,10 +315,12 @@
   Label fall_through;
   TestBothArgumentsSmis(assembler, &fall_through);
   // RAX is the right argument.
+  __ AssertSmiInRange(RAX);
   ASSERT(kSmiTag == 0);  // Adjust code below if not the case.
   __ SmiUntag(RAX);
-  __ imulq(RAX, Address(RSP, +2 * kWordSize));
+  __ imull(RAX, Address(RSP, +2 * kWordSize));
   __ j(OVERFLOW, &fall_through, Assembler::kNearJump);
+  __ movsxd(RAX, RAX);
   // Result is in RAX.
   __ ret();
   __ Bind(&fall_through);
@@ -333,7 +342,9 @@
 //   RAX: Untagged fallthrough result (remainder to be adjusted), or
 //   RAX: Tagged return result (remainder).
 static void EmitRemainderOperation(Assembler* assembler) {
-  Label return_zero, try_modulo, not_32bit, done;
+  Label return_zero, try_modulo, not_32bit;
+  __ AssertSmiInRange(RAX);
+  __ AssertSmiInRange(RCX);
   // Check for quick zero results.
   __ cmpq(RAX, Immediate(0));
   __ j(EQUAL, &return_zero, Assembler::kNearJump);
@@ -355,33 +366,12 @@
 
   __ Bind(&try_modulo);
 
-  // Check if both operands fit into 32bits as idiv with 64bit operands
-  // requires twice as many cycles and has much higher latency. We are checking
-  // this before untagging them to avoid corner case dividing INT_MAX by -1 that
-  // raises exception because quotient is too large for 32bit register.
-  __ movsxd(RBX, RAX);
-  __ cmpq(RBX, RAX);
-  __ j(NOT_EQUAL, &not_32bit, Assembler::kNearJump);
-  __ movsxd(RBX, RCX);
-  __ cmpq(RBX, RCX);
-  __ j(NOT_EQUAL, &not_32bit, Assembler::kNearJump);
-
   // Both operands are 31bit smis. Divide using 32bit idiv.
   __ SmiUntag(RAX);
   __ SmiUntag(RCX);
   __ cdq();
   __ idivl(RCX);
   __ movsxd(RAX, RDX);
-  __ jmp(&done, Assembler::kNearJump);
-
-  // Divide using 64bit idiv.
-  __ Bind(&not_32bit);
-  __ SmiUntag(RAX);
-  __ SmiUntag(RCX);
-  __ cqo();
-  __ idivq(RCX);
-  __ movq(RAX, RDX);
-  __ Bind(&done);
 }
 
 // Implementation:
@@ -396,7 +386,9 @@
 void Intrinsifier::Integer_moduloFromInteger(Assembler* assembler) {
   Label fall_through, negative_result;
   TestBothArgumentsSmis(assembler, &fall_through);
+  __ AssertSmiInRange(RAX);
   __ movq(RCX, Address(RSP, +2 * kWordSize));
+  __ AssertSmiInRange(RCX);
   // RAX: Tagged left (dividend).
   // RCX: Tagged right (divisor).
   __ cmpq(RCX, Immediate(0));
@@ -430,21 +422,17 @@
   Label fall_through, not_32bit;
   TestBothArgumentsSmis(assembler, &fall_through);
   // RAX: right argument (divisor)
+  __ AssertSmiInRange(RAX);
   __ cmpq(RAX, Immediate(0));
   __ j(EQUAL, &fall_through, Assembler::kNearJump);
   __ movq(RCX, RAX);
   __ movq(RAX, Address(RSP, +2 * kWordSize));  // Left argument (dividend).
+  __ AssertSmiInRange(RAX);
 
-  // Check if both operands fit into 32bits as idiv with 64bit operands
-  // requires twice as many cycles and has much higher latency. We are checking
-  // this before untagging them to avoid corner case dividing INT_MAX by -1 that
-  // raises exception because quotient is too large for 32bit register.
-  __ movsxd(RBX, RAX);
-  __ cmpq(RBX, RAX);
-  __ j(NOT_EQUAL, &not_32bit);
-  __ movsxd(RBX, RCX);
-  __ cmpq(RBX, RCX);
-  __ j(NOT_EQUAL, &not_32bit);
+  // Check the corner case of dividing the 'MIN_SMI' with -1, in which case we
+  // cannot tag the result.
+  __ cmpq(RAX, Immediate(-0x80000000ll));
+  __ j(EQUAL, &fall_through);
 
   // Both operands are 31bit smis. Divide using 32bit idiv.
   __ SmiUntag(RAX);
@@ -454,21 +442,6 @@
   __ movsxd(RAX, RAX);
   __ SmiTag(RAX);  // Result is guaranteed to fit into a smi.
   __ ret();
-
-  // Divide using 64bit idiv.
-  __ Bind(&not_32bit);
-  __ SmiUntag(RAX);
-  __ SmiUntag(RCX);
-  __ pushq(RDX);  // Preserve RDX in case of 'fall_through'.
-  __ cqo();
-  __ idivq(RCX);
-  __ popq(RDX);
-  // Check the corner case of dividing the 'MIN_SMI' with -1, in which case we
-  // cannot tag the result.
-  __ cmpq(RAX, Immediate(0x4000000000000000));
-  __ j(EQUAL, &fall_through);
-  __ SmiTag(RAX);
-  __ ret();
   __ Bind(&fall_through);
 }
 
@@ -477,8 +450,10 @@
   __ movq(RAX, Address(RSP, +1 * kWordSize));
   __ testq(RAX, Immediate(kSmiTagMask));
   __ j(NOT_ZERO, &fall_through, Assembler::kNearJump);  // Non-smi value.
+  __ AssertSmiInRange(RAX);
+  __ cmpq(RAX, Immediate(-0x80000000ll));
+  __ j(EQUAL, &fall_through, Assembler::kNearJump);
   __ negq(RAX);
-  __ j(OVERFLOW, &fall_through, Assembler::kNearJump);
   // Result is in RAX.
   __ ret();
   __ Bind(&fall_through);
@@ -487,6 +462,7 @@
 void Intrinsifier::Integer_bitAndFromInteger(Assembler* assembler) {
   Label fall_through;
   TestBothArgumentsSmis(assembler, &fall_through);
+  __ AssertSmiInRange(RAX);
   // RAX is the right argument.
   __ andq(RAX, Address(RSP, +2 * kWordSize));
   // Result is in RAX.
@@ -502,6 +478,7 @@
   Label fall_through;
   TestBothArgumentsSmis(assembler, &fall_through);
   // RAX is the right argument.
+  __ AssertSmiInRange(RAX);
   __ orq(RAX, Address(RSP, +2 * kWordSize));
   // Result is in RAX.
   __ ret();
@@ -517,6 +494,7 @@
   TestBothArgumentsSmis(assembler, &fall_through);
   // RAX is the right argument.
   __ xorq(RAX, Address(RSP, +2 * kWordSize));
+  __ AssertSmiInRange(RAX);
   // Result is in RAX.
   __ ret();
   __ Bind(&fall_through);
@@ -532,28 +510,32 @@
   Label fall_through, overflow;
   TestBothArgumentsSmis(assembler, &fall_through);
   // Shift value is in RAX. Compare with tagged Smi.
+  __ AssertSmiInRange(RAX);
   __ cmpq(RAX, Immediate(Smi::RawValue(Smi::kBits)));
   __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump);
 
   __ SmiUntag(RAX);
   __ movq(RCX, RAX);                           // Shift amount must be in RCX.
   __ movq(RAX, Address(RSP, +2 * kWordSize));  // Value.
+  __ AssertSmiInRange(RAX);
 
   // Overflow test - all the shifted-out bits must be same as the sign bit.
   __ movq(RDI, RAX);
-  __ shlq(RAX, RCX);
-  __ sarq(RAX, RCX);
+  __ shll(RAX, RCX);
+  __ sarl(RAX, RCX);
+  __ movsxd(RAX, RAX);
   __ cmpq(RAX, RDI);
   __ j(NOT_EQUAL, &overflow, Assembler::kNearJump);
 
-  __ shlq(RAX, RCX);  // Shift for result now we know there is no overflow.
+  __ shlq(RDI, RCX);  // Shift for result now we know there is no overflow.
+  __ movq(RAX, RDI);
 
   // RAX is a correctly tagged Smi.
   __ ret();
 
   __ Bind(&overflow);
-  // Mint is rarely used on x64 (only for integers requiring 64 bit instead of
-  // 63 bits as represented by Smi).
+  // Mint is used on x64 for integers requiring 64 bit instead of 31 bits as
+  // represented by Smi.
   __ Bind(&fall_through);
 }
 
@@ -561,6 +543,7 @@
   Label fall_through, true_label;
   TestBothArgumentsSmis(assembler, &fall_through);
   // RAX contains the right argument.
+  __ AssertSmiInRange(RAX);
   __ cmpq(Address(RSP, +2 * kWordSize), RAX);
   __ j(true_condition, &true_label, Assembler::kNearJump);
   __ LoadObject(RAX, Bool::False());
@@ -606,6 +589,9 @@
   __ orq(RAX, RCX);
   __ testq(RAX, Immediate(kSmiTagMask));
   __ j(NOT_ZERO, &check_for_mint, Assembler::kNearJump);
+  // Or-ing them together should still leave them both as compressible smis.
+  __ AssertSmiInRange(RAX);
+  __ AssertSmiInRange(RCX);
   // Both arguments are smi, '===' is good enough.
   __ LoadObject(RAX, Bool::False());
   __ ret();
@@ -623,9 +609,21 @@
   // Left (receiver) is Smi, return false if right is not Double.
   // Note that an instance of Mint or Bigint never contains a value that can be
   // represented by Smi.
+  __ AssertSmiInRange(RAX);
   __ movq(RAX, Address(RSP, +kArgumentOffset * kWordSize));
   __ CompareClassId(RAX, kDoubleCid);
   __ j(EQUAL, &fall_through);
+#if defined(DEBUG)
+  Label ok;
+  __ CompareClassId(RAX, kMintCid);
+  __ j(NOT_EQUAL, &ok);
+  __ movq(RAX, FieldAddress(RAX, Mint::value_offset()));
+  __ sarq(RCX, Immediate(1));
+  __ cmpq(RAX, RCX);
+  __ j(NOT_EQUAL, &ok);
+  __ Stop("Smi wrapped in a Mint");
+  __ Bind(&ok);
+#endif
   __ LoadObject(RAX, Bool::False());
   __ ret();
 
@@ -637,6 +635,7 @@
   __ movq(RAX, Address(RSP, +kArgumentOffset * kWordSize));
   __ testq(RAX, Immediate(kSmiTagMask));
   __ j(NOT_ZERO, &fall_through);
+  __ AssertSmiInRange(RAX);
   // Smi == Mint -> false.
   __ LoadObject(RAX, Bool::False());
   __ ret();
@@ -666,6 +665,7 @@
   __ Bind(&shift_count_ok);
   __ movq(RCX, RAX);                           // Shift amount must be in RCX.
   __ movq(RAX, Address(RSP, +2 * kWordSize));  // Value.
+  __ AssertSmiInRange(RAX);
   __ SmiUntag(RAX);                            // Value.
   __ sarq(RAX, RCX);
   __ SmiTag(RAX);
@@ -676,6 +676,7 @@
 // Argument is Smi (receiver).
 void Intrinsifier::Smi_bitNegate(Assembler* assembler) {
   __ movq(RAX, Address(RSP, +1 * kWordSize));  // Index.
+  __ AssertSmiInRange(RAX);
   __ notq(RAX);
   __ andq(RAX, Immediate(~kSmiTagMask));  // Remove inverted smi-tag.
   __ ret();
@@ -684,6 +685,7 @@
 void Intrinsifier::Smi_bitLength(Assembler* assembler) {
   ASSERT(kSmiTagShift == 1);
   __ movq(RAX, Address(RSP, +1 * kWordSize));  // Index.
+  __ AssertSmiInRange(RAX);
   // XOR with sign bit to complement bits if value is negative.
   __ movq(RCX, RAX);
   __ sarq(RCX, Immediate(63));  // All 0 or all 1.
@@ -709,6 +711,7 @@
   __ subq(R8, Immediate(2));  // x_used > 0, Smi. R8 = x_used - 1, round up.
   __ sarq(R8, Immediate(2));  // R8 + 1 = number of digit pairs to read.
   __ movq(RCX, Address(RSP, 2 * kWordSize));  // n is Smi
+  __ AssertSmiInRange(RCX);
   __ SmiUntag(RCX);
   __ movq(RBX, Address(RSP, 1 * kWordSize));  // r_digits
   __ movq(RSI, RCX);
@@ -744,6 +747,7 @@
 
   __ movq(RDI, Address(RSP, 4 * kWordSize));  // x_digits
   __ movq(RCX, Address(RSP, 2 * kWordSize));  // n is Smi
+  __ AssertSmiInRange(RCX);
   __ SmiUntag(RCX);
   __ movq(RBX, Address(RSP, 1 * kWordSize));  // r_digits
   __ movq(RDX, RCX);
@@ -1231,6 +1235,7 @@
   __ LoadObject(RAX, Bool::True());
   __ ret();
   __ Bind(&is_smi);
+  __ AssertSmiInRange(RAX);
   __ SmiUntag(RAX);
   __ cvtsi2sdq(XMM1, RAX);
   __ jmp(&double_op);
@@ -1291,6 +1296,7 @@
   __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0);
   __ ret();
   __ Bind(&is_smi);
+  __ AssertSmiInRange(RAX);
   __ SmiUntag(RAX);
   __ cvtsi2sdq(XMM1, RAX);
   __ jmp(&double_op);
@@ -1320,6 +1326,7 @@
   __ testq(RAX, Immediate(kSmiTagMask));
   __ j(NOT_ZERO, &fall_through);
   // Is Smi.
+  __ AssertSmiInRange(RAX);
   __ SmiUntag(RAX);
   __ cvtsi2sdq(XMM1, RAX);
   __ movq(RAX, Address(RSP, +2 * kWordSize));
@@ -1342,6 +1349,7 @@
   __ testq(RAX, Immediate(kSmiTagMask));
   __ j(NOT_ZERO, &fall_through);
   // Is Smi.
+  __ AssertSmiInRange(RAX);
   __ SmiUntag(RAX);
   __ cvtsi2sdq(XMM0, RAX);
   const Class& double_class =
@@ -1412,14 +1420,15 @@
 void Intrinsifier::DoubleToInteger(Assembler* assembler) {
   __ movq(RAX, Address(RSP, +1 * kWordSize));
   __ movsd(XMM0, FieldAddress(RAX, Double::value_offset()));
-  __ cvttsd2siq(RAX, XMM0);
+  __ cvttsd2sil(RAX, XMM0);
   // Overflow is signalled with minint.
   Label fall_through;
   // Check for overflow and that it fits into Smi.
   __ movq(RCX, RAX);
-  __ shlq(RCX, Immediate(1));
+  __ shll(RCX, Immediate(1));
   __ j(OVERFLOW, &fall_through, Assembler::kNearJump);
-  __ SmiTag(RAX);
+  ASSERT(kSmiTagShift == 1 && kSmiTag == 0);
+  __ movsxd(RAX, RCX);
   __ ret();
   __ Bind(&fall_through);
 }
@@ -1431,16 +1440,17 @@
   // back to a double in XMM1.
   __ movq(RCX, Address(RSP, +1 * kWordSize));
   __ movsd(XMM0, FieldAddress(RCX, Double::value_offset()));
-  __ cvttsd2siq(RAX, XMM0);
-  __ cvtsi2sdq(XMM1, RAX);
+  __ cvttsd2sil(RAX, XMM0);
+  __ cvtsi2sdl(XMM1, RAX);
 
   // Tag the int as a Smi, making sure that it fits; this checks for
   // overflow and NaN in the conversion from double to int. Conversion
-  // overflow from cvttsd2si is signalled with an INT64_MIN value.
+  // overflow from cvttsd2sil is signalled with an INT32_MIN value.
   Label fall_through;
   ASSERT(kSmiTag == 0 && kSmiTagShift == 1);
-  __ addq(RAX, RAX);
+  __ addl(RAX, RAX);
   __ j(OVERFLOW, &fall_through, Assembler::kNearJump);
+  __ movsxd(RAX, RAX);
 
   // Compare the two double values. If they are equal, we return the
   // Smi tagged result immediately as the hash code.
@@ -1478,6 +1488,7 @@
   __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0);
   __ ret();
   __ Bind(&is_smi);
+  __ AssertSmiInRange(RAX);
   __ SmiUntag(RAX);
   __ cvtsi2sdq(XMM1, RAX);
   __ jmp(&double_op);
diff --git a/runtime/vm/constants_arm.h b/runtime/vm/constants_arm.h
index 9fc7a63..8be187e 100644
--- a/runtime/vm/constants_arm.h
+++ b/runtime/vm/constants_arm.h
@@ -40,8 +40,8 @@
 // Stack alignment: 4 bytes always, 8 bytes at public interfaces
 
 // Linux (Debian armhf) and Android also differ in whether floating point
-// arguments are passed in registers. Linux uses hardfp and Android uses
-// softfp. See TargetCPUFeatures::hardfp_supported().
+// arguments are passed in floating point registers. Linux uses hardfp and
+// Android uses softfp. See TargetCPUFeatures::hardfp_supported().
 
 // iOS ABI
 // See "iOS ABI Function Call Guide"
@@ -56,7 +56,7 @@
 // R15:   Program counter
 // Stack alignment: 4 bytes always, 4 bytes at public interfaces
 
-// iOS passes floating point arguments in registers (hardfp)
+// iOS passes floating point arguments in integer registers (softfp)
 
 enum Register {
   R0 = 0,
diff --git a/runtime/vm/constants_arm64.h b/runtime/vm/constants_arm64.h
index 95b3f87..cbf0db4 100644
--- a/runtime/vm/constants_arm64.h
+++ b/runtime/vm/constants_arm64.h
@@ -708,14 +708,14 @@
 
 enum Extend {
   kNoExtend = -1,
-  UXTB = 0,
-  UXTH = 1,
-  UXTW = 2,
-  UXTX = 3,
-  SXTB = 4,
-  SXTH = 5,
-  SXTW = 6,
-  SXTX = 7,
+  UXTB = 0,  // Zero extend byte.
+  UXTH = 1,  // Zero extend halfword (16 bits).
+  UXTW = 2,  // Zero extend word (32 bits).
+  UXTX = 3,  // Zero extend doubleword (64 bits).
+  SXTB = 4,  // Sign extend byte.
+  SXTH = 5,  // Sign extend halfword (16 bits).
+  SXTW = 6,  // Sign extend word (32 bits).
+  SXTX = 7,  // Sign extend doubleword (64 bits).
   kMaxExtend = 8,
 };
 
diff --git a/runtime/vm/cpu_arm.cc b/runtime/vm/cpu_arm.cc
index 4988b21..052f5ed 100644
--- a/runtime/vm/cpu_arm.cc
+++ b/runtime/vm/cpu_arm.cc
@@ -82,7 +82,8 @@
 #endif
 
 #if defined(USING_SIMULATOR)
-#if defined(TARGET_ARCH_ARM_5TE) || defined(TARGET_OS_ANDROID)
+#if defined(TARGET_ARCH_ARM_5TE) || defined(TARGET_OS_ANDROID) \
+    || defined(TARGET_OS_IOS)
 DEFINE_FLAG(bool, sim_use_hardfp, false, "Use the hardfp ABI.");
 #else
 DEFINE_FLAG(bool, sim_use_hardfp, true, "Use the hardfp ABI.");
@@ -150,7 +151,7 @@
   vfp_supported_ = FLAG_use_vfp;
   integer_division_supported_ = FLAG_use_integer_division;
   neon_supported_ = FLAG_use_neon;
-  hardfp_supported_ = true;
+  hardfp_supported_ = false;
 #if defined(DEBUG)
   initialized_ = true;
 #endif
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index fb393bd..4efa972 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -50,7 +50,6 @@
 DebugInfo* Dart::pprof_symbol_generator_ = NULL;
 ReadOnlyHandles* Dart::predefined_handles_ = NULL;
 Snapshot::Kind Dart::vm_snapshot_kind_ = Snapshot::kInvalid;
-const uint8_t* Dart::vm_snapshot_instructions_ = NULL;
 Dart_ThreadExitCallback Dart::thread_exit_callback_ = NULL;
 Dart_FileOpenCallback Dart::file_open_callback_ = NULL;
 Dart_FileReadCallback Dart::file_read_callback_ = NULL;
@@ -229,7 +228,7 @@
       } else {
         return strdup("Invalid vm isolate snapshot seen");
       }
-      FullSnapshotReader reader(snapshot, instructions_snapshot, T);
+      FullSnapshotReader reader(snapshot, instructions_snapshot, NULL, NULL, T);
       const Error& error = Error::Handle(reader.ReadVMSnapshot());
       if (!error.IsNull()) {
         // Must copy before leaving the zone.
@@ -503,6 +502,8 @@
 
 RawError* Dart::InitializeIsolate(const uint8_t* snapshot_data,
                                   const uint8_t* snapshot_instructions,
+                                  const uint8_t* shared_data,
+                                  const uint8_t* shared_instructions,
                                   intptr_t snapshot_length,
                                   kernel::Program* kernel_program,
                                   void* data) {
@@ -547,7 +548,8 @@
     if (FLAG_trace_isolates) {
       OS::Print("Size of isolate snapshot = %" Pd "\n", snapshot->length());
     }
-    FullSnapshotReader reader(snapshot, snapshot_instructions, T);
+    FullSnapshotReader reader(snapshot, snapshot_instructions, shared_data,
+                              shared_instructions, T);
     const Error& error = Error::Handle(reader.ReadIsolateSnapshot());
     if (!error.IsNull()) {
       return error.raw();
diff --git a/runtime/vm/dart.h b/runtime/vm/dart.h
index 5c8177c..ce8b5e0 100644
--- a/runtime/vm/dart.h
+++ b/runtime/vm/dart.h
@@ -48,6 +48,8 @@
   // from_kernel.  Otherwise, initialize from sources.
   static RawError* InitializeIsolate(const uint8_t* snapshot_data,
                                      const uint8_t* snapshot_instructions,
+                                     const uint8_t* shared_data,
+                                     const uint8_t* shared_instructions,
                                      intptr_t snapshot_length,
                                      kernel::Program* kernel_program,
                                      void* data);
@@ -78,12 +80,6 @@
                                     bool is_vm_snapshot,
                                     Snapshot::Kind kind);
   static Snapshot::Kind vm_snapshot_kind() { return vm_snapshot_kind_; }
-  static const uint8_t* vm_snapshot_instructions() {
-    return vm_snapshot_instructions_;
-  }
-  static void set_vm_snapshot_instructions(const uint8_t* buffer) {
-    vm_snapshot_instructions_ = buffer;
-  }
 
   static Dart_ThreadExitCallback thread_exit_callback() {
     return thread_exit_callback_;
@@ -131,7 +127,6 @@
   static DebugInfo* pprof_symbol_generator_;
   static ReadOnlyHandles* predefined_handles_;
   static Snapshot::Kind vm_snapshot_kind_;
-  static const uint8_t* vm_snapshot_instructions_;
   static Dart_ThreadExitCallback thread_exit_callback_;
   static Dart_FileOpenCallback file_open_callback_;
   static Dart_FileReadCallback file_read_callback_;
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 43db729..8ae8279 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -1090,6 +1090,8 @@
                                   const char* main,
                                   const uint8_t* snapshot_data,
                                   const uint8_t* snapshot_instructions,
+                                  const uint8_t* shared_data,
+                                  const uint8_t* shared_instructions,
                                   intptr_t snapshot_length,
                                   kernel::Program* kernel_program,
                                   Dart_IsolateFlags* flags,
@@ -1122,8 +1124,9 @@
     Dart_EnterScope();
     const Error& error_obj =
         Error::Handle(Z, Dart::InitializeIsolate(
-                             snapshot_data, snapshot_instructions,
-                             snapshot_length, kernel_program, callback_data));
+                             snapshot_data, snapshot_instructions, shared_data,
+                             shared_instructions, snapshot_length,
+                             kernel_program, callback_data));
     if (error_obj.IsNull()) {
 #if defined(DART_NO_SNAPSHOT) && !defined(PRODUCT)
       if (FLAG_check_function_fingerprints && kernel_program == NULL) {
@@ -1162,12 +1165,15 @@
                    const char* main,
                    const uint8_t* snapshot_data,
                    const uint8_t* snapshot_instructions,
+                   const uint8_t* shared_data,
+                   const uint8_t* shared_instructions,
                    Dart_IsolateFlags* flags,
                    void* callback_data,
                    char** error) {
   API_TIMELINE_DURATION(Thread::Current());
   return CreateIsolate(script_uri, main, snapshot_data, snapshot_instructions,
-                       -1, NULL, flags, callback_data, error);
+                       shared_data, shared_instructions, -1, NULL, flags,
+                       callback_data, error);
 }
 
 DART_EXPORT Dart_Isolate Dart_CreateIsolateFromKernel(const char* script_uri,
@@ -1184,7 +1190,7 @@
     flags = &api_flags;
   }
   flags->use_dart_frontend = true;
-  return CreateIsolate(script_uri, main, NULL, NULL, -1,
+  return CreateIsolate(script_uri, main, NULL, NULL, NULL, NULL, -1,
                        reinterpret_cast<kernel::Program*>(kernel_program),
                        flags, callback_data, error);
 }
@@ -6526,7 +6532,7 @@
 
   NOT_IN_PRODUCT(TimelineDurationScope tds2(T, Timeline::GetIsolateStream(),
                                             "WriteAppAOTSnapshot"));
-  AssemblyImageWriter image_writer(callback, callback_data);
+  AssemblyImageWriter image_writer(callback, callback_data, NULL, NULL);
   uint8_t* vm_snapshot_data_buffer = NULL;
   uint8_t* isolate_snapshot_data_buffer = NULL;
   FullSnapshotWriter writer(Snapshot::kFullAOT, &vm_snapshot_data_buffer,
@@ -6557,7 +6563,7 @@
 
   NOT_IN_PRODUCT(TimelineDurationScope tds2(T, Timeline::GetIsolateStream(),
                                             "WriteVMAOTSnapshot"));
-  AssemblyImageWriter image_writer(callback, callback_data);
+  AssemblyImageWriter image_writer(callback, callback_data, NULL, NULL);
   uint8_t* vm_snapshot_data_buffer = NULL;
   FullSnapshotWriter writer(Snapshot::kFullAOT, &vm_snapshot_data_buffer, NULL,
                             ApiReallocate, &image_writer, NULL);
@@ -6576,7 +6582,9 @@
                                  uint8_t** isolate_snapshot_data_buffer,
                                  intptr_t* isolate_snapshot_data_size,
                                  uint8_t** isolate_snapshot_instructions_buffer,
-                                 intptr_t* isolate_snapshot_instructions_size) {
+                                 intptr_t* isolate_snapshot_instructions_size,
+                                 const uint8_t* shared_data,
+                                 const uint8_t* shared_instructions) {
 #if defined(TARGET_ARCH_IA32)
   return Api::NewError("AOT compilation is not supported on IA32.");
 #elif defined(TARGET_ARCH_DBC)
@@ -6584,9 +6592,6 @@
 #elif !defined(DART_PRECOMPILER)
   return Api::NewError(
       "This VM was built without support for AOT compilation.");
-#elif defined(TARGET_OS_FUCHSIA)
-  return Api::NewError(
-      "AOT as blobs is not supported on Fuchsia; use dylibs instead.");
 #else
   DARTSCOPE(Thread::Current());
   API_TIMELINE_DURATION(T);
@@ -6606,13 +6611,20 @@
   CHECK_NULL(isolate_snapshot_instructions_buffer);
   CHECK_NULL(isolate_snapshot_instructions_size);
 
+  const void* shared_data_image = NULL;
+  if (shared_data != NULL) {
+    shared_data_image = Snapshot::SetupFromBuffer(shared_data)->DataImage();
+  }
+  const void* shared_instructions_image = shared_instructions;
+
   NOT_IN_PRODUCT(TimelineDurationScope tds2(T, Timeline::GetIsolateStream(),
                                             "WriteAppAOTSnapshot"));
   BlobImageWriter vm_image_writer(vm_snapshot_instructions_buffer,
-                                  ApiReallocate, 2 * MB /* initial_size */);
-  BlobImageWriter isolate_image_writer(isolate_snapshot_instructions_buffer,
-                                       ApiReallocate,
-                                       2 * MB /* initial_size */);
+                                  ApiReallocate, 2 * MB /* initial_size */,
+                                  NULL, NULL);
+  BlobImageWriter isolate_image_writer(
+      isolate_snapshot_instructions_buffer, ApiReallocate,
+      2 * MB /* initial_size */, shared_data_image, shared_instructions_image);
   FullSnapshotWriter writer(Snapshot::kFullAOT, vm_snapshot_data_buffer,
                             isolate_snapshot_data_buffer, ApiReallocate,
                             &vm_image_writer, &isolate_image_writer);
@@ -6670,10 +6682,11 @@
   NOT_IN_PRODUCT(TimelineDurationScope tds2(T, Timeline::GetIsolateStream(),
                                             "WriteCoreJITSnapshot"));
   BlobImageWriter vm_image_writer(vm_snapshot_instructions_buffer,
-                                  ApiReallocate, 2 * MB /* initial_size */);
+                                  ApiReallocate, 2 * MB /* initial_size */,
+                                  NULL, NULL);
   BlobImageWriter isolate_image_writer(isolate_snapshot_instructions_buffer,
-                                       ApiReallocate,
-                                       2 * MB /* initial_size */);
+                                       ApiReallocate, 2 * MB /* initial_size */,
+                                       NULL, NULL);
   FullSnapshotWriter writer(Snapshot::kFullJIT, vm_snapshot_data_buffer,
                             isolate_snapshot_data_buffer, ApiReallocate,
                             &vm_image_writer, &isolate_image_writer);
@@ -6723,8 +6736,8 @@
   NOT_IN_PRODUCT(TimelineDurationScope tds2(T, Timeline::GetIsolateStream(),
                                             "WriteAppJITSnapshot"));
   BlobImageWriter isolate_image_writer(isolate_snapshot_instructions_buffer,
-                                       ApiReallocate,
-                                       2 * MB /* initial_size */);
+                                       ApiReallocate, 2 * MB /* initial_size */,
+                                       NULL, NULL);
   FullSnapshotWriter writer(Snapshot::kFullJIT, NULL,
                             isolate_snapshot_data_buffer, ApiReallocate, NULL,
                             &isolate_image_writer);
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index a7d2eb9..377cff0 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -137,7 +137,7 @@
 TEST_CASE(DartAPI_DeepStackTraceInfo) {
   const char* kScriptChars =
       "foo(n) => n == 1 ? throw new Error() : foo(n-1);\n"
-      "testMain() => foo(50);\n";
+      "testMain() => foo(100);\n";
 
   Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
   Dart_Handle error = Dart_Invoke(lib, NewString("testMain"), 0, NULL);
@@ -151,10 +151,10 @@
   intptr_t frame_count = 0;
   result = Dart_StackTraceLength(stacktrace, &frame_count);
   EXPECT_VALID(result);
-  EXPECT_EQ(51, frame_count);
+  EXPECT_EQ(101, frame_count);
   // Test something bigger than the preallocated size to verify nothing was
   // truncated.
-  EXPECT(51 > StackTrace::kPreallocatedStackdepth);
+  EXPECT(101 > StackTrace::kPreallocatedStackdepth);
 
   Dart_Handle function_name;
   Dart_Handle script_url;
@@ -320,10 +320,10 @@
   intptr_t frame_count = 0;
   result = Dart_StackTraceLength(stacktrace, &frame_count);
   EXPECT_VALID(result);
-  EXPECT_EQ(52, frame_count);
+  EXPECT_EQ(102, frame_count);
   // Test something bigger than the preallocated size to verify nothing was
   // truncated.
-  EXPECT(52 > StackTrace::kPreallocatedStackdepth);
+  EXPECT(102 > StackTrace::kPreallocatedStackdepth);
 
   Dart_Handle function_name;
   Dart_Handle script_url;
@@ -412,7 +412,7 @@
   const char* kScriptChars =
       "inspectStack() native 'CurrentStackTraceNatve';\n"
       "foo(n) => n == 1 ? inspectStack() : foo(n-1);\n"
-      "testMain() => foo(50);\n";
+      "testMain() => foo(100);\n";
 
   Dart_Handle lib =
       TestCase::LoadTestScript(kScriptChars, &CurrentStackTraceNativeLookup);
@@ -3385,9 +3385,10 @@
   api_flags.enable_error_on_bad_override = true;
   api_flags.use_dart_frontend = FLAG_use_dart_frontend;
   char* err;
-  Dart_Isolate isolate = Dart_CreateIsolate(
-      NULL, NULL, bin::core_isolate_snapshot_data,
-      bin::core_isolate_snapshot_instructions, &api_flags, NULL, &err);
+  Dart_Isolate isolate =
+      Dart_CreateIsolate(NULL, NULL, bin::core_isolate_snapshot_data,
+                         bin::core_isolate_snapshot_instructions, NULL, NULL,
+                         &api_flags, NULL, &err);
   if (isolate == NULL) {
     OS::PrintErr("Creation of isolate failed '%s'\n", err);
     free(err);
@@ -5003,7 +5004,6 @@
 
 TEST_CASE(DartAPI_InvokeNoSuchMethod) {
   const char* kScriptChars =
-      "import 'dart:_internal' as _internal;\n"
       "class Expect {\n"
       "  static equals(a, b) {\n"
       "    if (a != b) {\n"
@@ -5014,7 +5014,11 @@
       "class TestClass {\n"
       "  static int fld1 = 0;\n"
       "  void noSuchMethod(Invocation invocation) {\n"
-      "    var name = _internal.Symbol.getName(invocation.memberName);\n"
+      // This relies on the Symbol.toString() method returning a String of the
+      // form 'Symbol("name")'. This is to avoid having to import
+      // dart:_internal just to get access to the name of the symbol.
+      "    var name = invocation.memberName.toString();\n"
+      "    name = name.split('\"')[1];\n"
       "    if (name == 'fld') {\n"
       "      Expect.equals(true, invocation.isGetter);\n"
       "      Expect.equals(false, invocation.isMethod);\n"
diff --git a/runtime/vm/dwarf.cc b/runtime/vm/dwarf.cc
index fc48ab7..8b2b14c 100644
--- a/runtime/vm/dwarf.cc
+++ b/runtime/vm/dwarf.cc
@@ -405,6 +405,10 @@
         token_positions.RemoveLast();
         break;
       }
+      case CodeSourceMapBuilder::kNullCheck: {
+        stream.Read<int32_t>();
+        break;
+      }
       default:
         UNREACHABLE();
     }
@@ -618,6 +622,10 @@
           token_positions.RemoveLast();
           break;
         }
+        case CodeSourceMapBuilder::kNullCheck: {
+          stream.Read<int32_t>();
+          break;
+        }
         default:
           UNREACHABLE();
       }
diff --git a/runtime/vm/gc_compactor.cc b/runtime/vm/gc_compactor.cc
index c35f86c..4aec300 100644
--- a/runtime/vm/gc_compactor.cc
+++ b/runtime/vm/gc_compactor.cc
@@ -69,15 +69,6 @@
            0;
   }
 
-  // Marks all bits after a given address. This is used to ensure that some
-  // objects do not move (classes).
-  void MarkAllFrom(uword start_addr) {
-    uword block_offset = start_addr & ~kBlockMask;
-    intptr_t first_unit_position = block_offset >> kObjectAlignmentLog2;
-    ASSERT(first_unit_position < kBitsPerWord);
-    live_bitvector_ = static_cast<uword>(-1) << first_unit_position;
-  }
-
   uword new_address() const { return new_address_; }
   void set_new_address(uword value) { new_address_ = value; }
 
@@ -147,9 +138,7 @@
   void SlidePage(HeapPage* page);
   uword PlanBlock(uword first_object, ForwardingPage* forwarding_page);
   uword SlideBlock(uword first_object, ForwardingPage* forwarding_page);
-  void PlanMoveToExactAddress(uword addr);
   void PlanMoveToContiguousSize(intptr_t size);
-  void SlideFreeUpTo(uword addr);
 
   Isolate* isolate_;
   GCCompactor* compactor_;
@@ -393,6 +382,9 @@
   }
 }
 
+// Plans the destination for a set of live objects starting with the first
+// live object that starts in a block, up to and including the last live
+// object that starts in that block.
 uword CompactorTask::PlanBlock(uword first_object,
                                ForwardingPage* forwarding_page) {
   uword block_start = first_object & kBlockMask;
@@ -400,7 +392,6 @@
   ForwardingBlock* forwarding_block = forwarding_page->BlockFor(first_object);
 
   // 1. Compute bitvector of surviving allocation units in the block.
-  bool has_class = false;
   intptr_t block_live_size = 0;
   intptr_t block_dead_size = 0;
   uword current = first_object;
@@ -408,9 +399,6 @@
     RawObject* obj = RawObject::FromAddr(current);
     intptr_t size = obj->Size();
     if (obj->IsMarked()) {
-      if (obj->GetClassId() == kClassCid) {
-        has_class = true;
-      }
       forwarding_block->RecordLive(current, size);
       ASSERT(static_cast<intptr_t>(forwarding_block->Lookup(current)) ==
              block_live_size);
@@ -421,26 +409,11 @@
     current += size;
   }
 
-  // 2. Find the next contiguous space that can fit the block.
-  if (has_class) {
-    // This will waste the space used by dead objects that are before the class
-    // object.
-    PlanMoveToExactAddress(first_object);
-    ASSERT(free_current_ == first_object);
-
-    // This is not MarkAll because the first part of a block might
-    // be the tail end of an object belonging to the previous block
-    // or the page header.
-    forwarding_block->MarkAllFrom(first_object);
-    ASSERT(forwarding_block->Lookup(first_object) == 0);
-
-    forwarding_block->set_new_address(free_current_);
-    free_current_ += block_live_size + block_dead_size;
-  } else {
-    PlanMoveToContiguousSize(block_live_size);
-    forwarding_block->set_new_address(free_current_);
-    free_current_ += block_live_size;
-  }
+  // 2. Find the next contiguous space that can fit the live objects that
+  // start in the block.
+  PlanMoveToContiguousSize(block_live_size);
+  forwarding_block->set_new_address(free_current_);
+  free_current_ += block_live_size;
 
   return current;  // First object in the next block
 }
@@ -451,23 +424,34 @@
   uword block_end = block_start + kBlockSize;
   ForwardingBlock* forwarding_block = forwarding_page->BlockFor(first_object);
 
-  // Add any space wasted at the end of a page or due to class pinning to the
-  // free list.
-  SlideFreeUpTo(forwarding_block->new_address());
-
   uword old_addr = first_object;
   while (old_addr < block_end) {
     RawObject* old_obj = RawObject::FromAddr(old_addr);
     intptr_t size = old_obj->Size();
     if (old_obj->IsMarked()) {
       uword new_addr = forwarding_block->Lookup(old_addr);
+      if (new_addr != free_current_) {
+        // The only situation where these two don't match is if we are moving
+        // to a new page.  But if we exactly hit the end of the previous page
+        // then free_current could be at the start of the next page, so we
+        // subtract 1.
+        ASSERT(HeapPage::Of(free_current_ - 1) != HeapPage::Of(new_addr));
+        intptr_t free_remaining = free_end_ - free_current_;
+        // Add any leftover at the end of a page to the free list.
+        if (free_remaining > 0) {
+          freelist_->Free(free_current_, free_remaining);
+        }
+        free_page_ = free_page_->next();
+        ASSERT(free_page_ != NULL);
+        free_current_ = free_page_->object_start();
+        free_end_ = free_page_->object_end();
+        ASSERT(free_current_ == new_addr);
+      }
       RawObject* new_obj = RawObject::FromAddr(new_addr);
 
       // Fast path for no movement. There's often a large block of objects at
       // the beginning that don't move.
       if (new_addr != old_addr) {
-        ASSERT(old_obj->GetClassId() != kClassCid);
-
         // Slide the object down.
         memmove(reinterpret_cast<void*>(new_addr),
                 reinterpret_cast<void*>(old_addr), size);
@@ -477,11 +461,8 @@
 
       ASSERT(free_current_ == new_addr);
       free_current_ += size;
-    } else if (forwarding_block->IsLive(old_addr)) {
-      // Gap we're keeping to prevent class movement.
-      ASSERT(free_current_ == old_addr);
-      freelist_->Free(old_addr, size);
-      free_current_ += size;
+    } else {
+      ASSERT(!forwarding_block->IsLive(old_addr));
     }
     old_addr += size;
   }
@@ -489,56 +470,6 @@
   return old_addr;  // First object in the next block.
 }
 
-void CompactorTask::SlideFreeUpTo(uword addr) {
-  if (free_current_ == addr) return;
-
-  // Skip pages until class's page.
-  ASSERT(free_page_ != NULL);
-  while (!free_page_->Contains(addr)) {
-    intptr_t free_remaining = free_end_ - free_current_;
-    if (free_remaining != 0) {
-      // Note we aren't bothering to check for a whole page to release.
-      freelist_->Free(free_current_, free_remaining);
-    }
-    // And advance to the next free page.
-    free_page_ = free_page_->next();
-    ASSERT(free_page_ != NULL);
-    free_current_ = free_page_->object_start();
-    free_end_ = free_page_->object_end();
-  }
-
-  // Skip within page until class's address.
-  intptr_t free_skip = addr - free_current_;
-  if (free_skip != 0) {
-    freelist_->Free(free_current_, free_skip);
-    free_current_ += free_skip;
-  }
-
-  // Class object won't move.
-  ASSERT(free_current_ == addr);
-}
-
-void CompactorTask::PlanMoveToExactAddress(uword addr) {
-  // Skip space to ensure class objects do not move. Computing the size
-  // of larger objects requires consulting their class, whose old body
-  // might be overwritten during the sliding.
-  // TODO(rmacnak): Keep class sizes off heap or class objects in
-  // non-moving pages.
-
-  // Skip pages until class's page.
-  ASSERT(free_page_ != NULL);
-  while (!free_page_->Contains(addr)) {
-    // And advance to the next free page.
-    free_page_ = free_page_->next();
-    ASSERT(free_page_ != NULL);
-    free_current_ = free_page_->object_start();
-    free_end_ = free_page_->object_end();
-  }
-
-  // Skip within page until class's address.
-  free_current_ = addr;
-}
-
 void CompactorTask::PlanMoveToContiguousSize(intptr_t size) {
   // Move the free cursor to ensure 'size' bytes of contiguous space.
   ASSERT(size <= kPageSize);
diff --git a/runtime/vm/gc_compactor.h b/runtime/vm/gc_compactor.h
index 6fe1f1c..7ae687f 100644
--- a/runtime/vm/gc_compactor.h
+++ b/runtime/vm/gc_compactor.h
@@ -44,9 +44,9 @@
     uword base;
     uword size;
   };
-  // There are up to 4 images to consider:
-  // {instructions, data} x {vm isolate, current isolate}
-  static const intptr_t kMaxImagePages = 4;
+  // There are up to 6 images to consider:
+  // {instructions, data} x {vm isolate, current isolate, shared}
+  static const intptr_t kMaxImagePages = 6;
   ImagePageRange image_page_ranges_[kMaxImagePages];
 };
 
diff --git a/runtime/vm/globals.h b/runtime/vm/globals.h
index 4fa43f2..c15516d 100644
--- a/runtime/vm/globals.h
+++ b/runtime/vm/globals.h
@@ -21,9 +21,8 @@
 #undef OVERFLOW  // From math.h conflicts in constants_ia32.h
 
 namespace dart {
-// Smi value range is from -(2^N) to (2^N)-1.
-// N=30 (32-bit build) or N=62 (64-bit build).
-const intptr_t kSmiBits = kBitsPerWord - 2;
+// Smi value range is from -(2^N) to (2^N)-1.  N=30
+const intptr_t kSmiBits = 30;
 const intptr_t kSmiMax = (static_cast<intptr_t>(1) << kSmiBits) - 1;
 const intptr_t kSmiMin = -(static_cast<intptr_t>(1) << kSmiBits);
 
diff --git a/runtime/vm/hash.h b/runtime/vm/hash.h
new file mode 100644
index 0000000..aa9c28d
--- /dev/null
+++ b/runtime/vm/hash.h
@@ -0,0 +1,30 @@
+// Copyright (c) 2018, 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.
+
+#ifndef RUNTIME_VM_HASH_H_
+#define RUNTIME_VM_HASH_H_
+
+namespace dart {
+
+static uint32_t CombineHashes(uint32_t hash, uint32_t other_hash) {
+  hash += other_hash;
+  hash += hash << 10;
+  hash ^= hash >> 6;  // Logical shift, unsigned hash.
+  return hash;
+}
+
+static uint32_t FinalizeHash(uint32_t hash, intptr_t hashbits) {
+  hash += hash << 3;
+  hash ^= hash >> 11;  // Logical shift, unsigned hash.
+  hash += hash << 15;
+  // FinalizeHash gets called with values for hashbits that are bigger than 31
+  // (like kBitsPerWord - 1).  Therefore we are careful to use a type
+  // (uintptr_t) big enough to avoid undefined behavior with the left shift.
+  hash &= (static_cast<uintptr_t>(1) << hashbits) - 1;
+  return (hash == 0) ? 1 : hash;
+}
+
+}  // namespace dart
+
+#endif  // RUNTIME_VM_HASH_H_
diff --git a/runtime/vm/image_snapshot.cc b/runtime/vm/image_snapshot.cc
index 89186a4..4210097 100644
--- a/runtime/vm/image_snapshot.cc
+++ b/runtime/vm/image_snapshot.cc
@@ -7,6 +7,8 @@
 #include "platform/assert.h"
 #include "vm/compiler/backend/code_statistics.h"
 #include "vm/dwarf.h"
+#include "vm/hash.h"
+#include "vm/hash_map.h"
 #include "vm/heap.h"
 #include "vm/json_writer.h"
 #include "vm/object.h"
@@ -28,8 +30,84 @@
             "Print sizes of all instruction objects to the given file");
 #endif
 
+intptr_t ObjectOffsetTrait::Hashcode(Key key) {
+  RawObject* obj = key;
+  ASSERT(!obj->IsSmi());
+
+  uword body = RawObject::ToAddr(obj) + sizeof(RawObject);
+  uword end = RawObject::ToAddr(obj) + obj->Size();
+
+  uint32_t hash = obj->GetClassId();
+  // Don't include the header. Objects in the image are pre-marked, but objects
+  // in the current isolate are not.
+  for (uword cursor = body; cursor < end; cursor += sizeof(uint32_t)) {
+    hash = CombineHashes(hash, *reinterpret_cast<uint32_t*>(cursor));
+  }
+
+  return FinalizeHash(hash, 30);
+}
+
+bool ObjectOffsetTrait::IsKeyEqual(Pair pair, Key key) {
+  RawObject* a = pair.object;
+  RawObject* b = key;
+  ASSERT(!a->IsSmi());
+  ASSERT(!b->IsSmi());
+
+  if (a->GetClassId() != b->GetClassId()) {
+    return false;
+  }
+
+  intptr_t heap_size = a->Size();
+  if (b->Size() != heap_size) {
+    return false;
+  }
+
+  // Don't include the header. Objects in the image are pre-marked, but objects
+  // in the current isolate are not.
+  uword body_a = RawObject::ToAddr(a) + sizeof(RawObject);
+  uword body_b = RawObject::ToAddr(b) + sizeof(RawObject);
+  uword body_size = heap_size - sizeof(RawObject);
+  return 0 == memcmp(reinterpret_cast<const void*>(body_a),
+                     reinterpret_cast<const void*>(body_b), body_size);
+}
+
+ImageWriter::ImageWriter(const void* shared_objects,
+                         const void* shared_instructions)
+    : next_data_offset_(0), next_text_offset_(0), objects_(), instructions_() {
+  ResetOffsets();
+  SetupShared(&shared_objects_, shared_objects);
+  SetupShared(&shared_instructions_, shared_instructions);
+}
+
+void ImageWriter::SetupShared(ObjectOffsetMap* map, const void* shared_image) {
+  if (shared_image == NULL) {
+    return;
+  }
+  Image image(shared_image);
+  uword obj_addr = reinterpret_cast<uword>(image.object_start());
+  uword end_addr = obj_addr + image.object_size();
+  while (obj_addr < end_addr) {
+    int32_t offset = obj_addr - reinterpret_cast<uword>(shared_image);
+    RawObject* raw_obj = RawObject::FromAddr(obj_addr);
+    ObjectOffsetPair pair;
+    pair.object = raw_obj;
+    pair.offset = offset;
+    map->Insert(pair);
+    obj_addr += raw_obj->Size();
+  }
+  ASSERT(obj_addr == end_addr);
+}
+
 int32_t ImageWriter::GetTextOffsetFor(RawInstructions* instructions,
                                       RawCode* code) {
+  ObjectOffsetPair* pair = shared_instructions_.Lookup(instructions);
+  if (pair != NULL) {
+    // Negative offsets tell the reader the offset is w/r/t the shared
+    // instructions image instead of the app-specific instructions image.
+    // Compare ImageReader::GetInstructionsAt.
+    return -pair->offset;
+  }
+
   intptr_t heap_size = instructions->Size();
   intptr_t offset = next_text_offset_;
   next_text_offset_ += heap_size;
@@ -37,6 +115,16 @@
   return offset;
 }
 
+bool ImageWriter::GetSharedDataOffsetFor(RawObject* raw_object,
+                                         uint32_t* offset) {
+  ObjectOffsetPair* pair = shared_objects_.Lookup(raw_object);
+  if (pair == NULL) {
+    return false;
+  }
+  *offset = pair->offset;
+  return true;
+}
+
 uint32_t ImageWriter::GetDataOffsetFor(RawObject* raw_object) {
   intptr_t heap_size = raw_object->Size();
   intptr_t offset = next_data_offset_;
@@ -136,10 +224,9 @@
     ASSERT(data.raw_code_ != NULL);
     data.code_ = &Code::Handle(zone, data.raw_code_);
 
-    // Update object id table with offsets that will refer to the VM snapshot,
-    // causing a subsequently written isolate snapshot to share instructions
-    // with the VM snapshot.
-    heap->SetObjectId(data.insns_->raw(), -data.offset_);
+    // Reset object id as an isolate snapshot after a VM snapshot will not use
+    // the VM snapshot's text image.
+    heap->SetObjectId(data.insns_->raw(), 0);
   }
   for (intptr_t i = 0; i < objects_.length(); i++) {
     ObjectData& data = objects_[i];
@@ -187,8 +274,10 @@
 }
 
 AssemblyImageWriter::AssemblyImageWriter(Dart_StreamingWriteCallback callback,
-                                         void* callback_data)
-    : ImageWriter(),
+                                         void* callback_data,
+                                         const void* shared_objects,
+                                         const void* shared_instructions)
+    : ImageWriter(shared_objects, shared_instructions),
       assembly_stream_(512 * KB, callback, callback_data),
       dwarf_(NULL) {
 #if defined(DART_PRECOMPILER)
@@ -432,6 +521,15 @@
   }
 }
 
+BlobImageWriter::BlobImageWriter(uint8_t** instructions_blob_buffer,
+                                 ReAlloc alloc,
+                                 intptr_t initial_size,
+                                 const void* shared_objects,
+                                 const void* shared_instructions)
+    : ImageWriter(shared_objects, shared_instructions),
+      instructions_blob_stream_(instructions_blob_buffer, alloc, initial_size) {
+}
+
 void BlobImageWriter::WriteText(WriteStream* clustered_stream, bool vm) {
   // This header provides the gap to make the instructions snapshot look like a
   // HeapPage.
@@ -475,40 +573,54 @@
   }
 }
 
-ImageReader::ImageReader(const uint8_t* instructions_buffer,
-                         const uint8_t* data_buffer)
-    : instructions_buffer_(instructions_buffer), data_buffer_(data_buffer) {
-  ASSERT(instructions_buffer != NULL);
-  ASSERT(data_buffer != NULL);
-  ASSERT(Utils::IsAligned(reinterpret_cast<uword>(instructions_buffer),
+ImageReader::ImageReader(const uint8_t* data_image,
+                         const uint8_t* instructions_image,
+                         const uint8_t* shared_data_image,
+                         const uint8_t* shared_instructions_image)
+    : data_image_(data_image),
+      instructions_image_(instructions_image),
+      shared_data_image_(shared_data_image),
+      shared_instructions_image_(shared_instructions_image) {
+  ASSERT(data_image != NULL);
+  ASSERT(instructions_image != NULL);
+  ASSERT(Utils::IsAligned(reinterpret_cast<uword>(instructions_image),
                           OS::PreferredCodeAlignment()));
-  vm_instructions_buffer_ = Dart::vm_snapshot_instructions();
+  ASSERT(Utils::IsAligned(reinterpret_cast<uword>(shared_instructions_image),
+                          OS::PreferredCodeAlignment()));
 }
 
 RawInstructions* ImageReader::GetInstructionsAt(int32_t offset) const {
   ASSERT(Utils::IsAligned(offset, OS::PreferredCodeAlignment()));
 
-  RawInstructions* result;
+  RawObject* result;
   if (offset < 0) {
-    result = reinterpret_cast<RawInstructions*>(
-        reinterpret_cast<uword>(vm_instructions_buffer_) - offset +
-        kHeapObjectTag);
+    result = RawObject::FromAddr(
+        reinterpret_cast<uword>(shared_instructions_image_) - offset);
   } else {
-    result = reinterpret_cast<RawInstructions*>(
-        reinterpret_cast<uword>(instructions_buffer_) + offset +
-        kHeapObjectTag);
+    result = RawObject::FromAddr(reinterpret_cast<uword>(instructions_image_) +
+                                 offset);
   }
   ASSERT(result->IsInstructions());
   ASSERT(result->IsMarked());
 
+  return Instructions::RawCast(result);
+}
+
+RawObject* ImageReader::GetObjectAt(uint32_t offset) const {
+  ASSERT(Utils::IsAligned(offset, kObjectAlignment));
+
+  RawObject* result =
+      RawObject::FromAddr(reinterpret_cast<uword>(data_image_) + offset);
+  ASSERT(result->IsMarked());
+
   return result;
 }
 
-RawObject* ImageReader::GetObjectAt(uint32_t offset) const {
-  ASSERT(Utils::IsAligned(offset, kWordSize));
+RawObject* ImageReader::GetSharedObjectAt(uint32_t offset) const {
+  ASSERT(Utils::IsAligned(offset, kObjectAlignment));
 
-  RawObject* result = reinterpret_cast<RawObject*>(
-      reinterpret_cast<uword>(data_buffer_) + offset + kHeapObjectTag);
+  RawObject* result =
+      RawObject::FromAddr(reinterpret_cast<uword>(shared_data_image_) + offset);
   ASSERT(result->IsMarked());
 
   return result;
diff --git a/runtime/vm/image_snapshot.h b/runtime/vm/image_snapshot.h
index 5e9fe3d..99a3e02 100644
--- a/runtime/vm/image_snapshot.h
+++ b/runtime/vm/image_snapshot.h
@@ -10,6 +10,7 @@
 #include "vm/datastream.h"
 #include "vm/globals.h"
 #include "vm/growable_array.h"
+#include "vm/hash_map.h"
 
 namespace dart {
 
@@ -48,42 +49,68 @@
 
 class ImageReader : public ZoneAllocated {
  public:
-  ImageReader(const uint8_t* instructions_buffer, const uint8_t* data_buffer);
+  ImageReader(const uint8_t* data_image,
+              const uint8_t* instructions_image,
+              const uint8_t* shared_data_image,
+              const uint8_t* shared_instructions_image);
 
   RawInstructions* GetInstructionsAt(int32_t offset) const;
   RawObject* GetObjectAt(uint32_t offset) const;
+  RawObject* GetSharedObjectAt(uint32_t offset) const;
 
  private:
-  const uint8_t* instructions_buffer_;
-  const uint8_t* data_buffer_;
-  const uint8_t* vm_instructions_buffer_;
+  const uint8_t* data_image_;
+  const uint8_t* instructions_image_;
+  const uint8_t* shared_data_image_;
+  const uint8_t* shared_instructions_image_;
 
   DISALLOW_COPY_AND_ASSIGN(ImageReader);
 };
 
-class ImageWriter : public ZoneAllocated {
+struct ObjectOffsetPair {
  public:
-  ImageWriter()
-      : next_text_offset_(0),
-        next_data_offset_(0),
-        instructions_(),
-        objects_() {
-    ResetOffsets();
-  }
+  ObjectOffsetPair() : ObjectOffsetPair(NULL, 0) {}
+  ObjectOffsetPair(RawObject* obj, int32_t off) : object(obj), offset(off) {}
+
+  RawObject* object;
+  int32_t offset;
+};
+
+class ObjectOffsetTrait {
+ public:
+  // Typedefs needed for the DirectChainedHashMap template.
+  typedef RawObject* Key;
+  typedef int32_t Value;
+  typedef ObjectOffsetPair Pair;
+
+  static Key KeyOf(Pair kv) { return kv.object; }
+  static Value ValueOf(Pair kv) { return kv.offset; }
+  static intptr_t Hashcode(Key key);
+  static inline bool IsKeyEqual(Pair pair, Key key);
+};
+
+typedef DirectChainedHashMap<ObjectOffsetTrait> ObjectOffsetMap;
+
+class ImageWriter : public ValueObject {
+ public:
+  ImageWriter(const void* shared_objects, const void* shared_instructions);
   virtual ~ImageWriter() {}
 
+  void SetupShared(ObjectOffsetMap* map, const void* shared_image);
   void ResetOffsets() {
-    next_text_offset_ = Image::kHeaderSize;
     next_data_offset_ = Image::kHeaderSize;
-    instructions_.Clear();
+    next_text_offset_ = Image::kHeaderSize;
     objects_.Clear();
+    instructions_.Clear();
   }
+
   int32_t GetTextOffsetFor(RawInstructions* instructions, RawCode* code);
+  bool GetSharedDataOffsetFor(RawObject* raw_object, uint32_t* offset);
   uint32_t GetDataOffsetFor(RawObject* raw_object);
 
   void Write(WriteStream* clustered_stream, bool vm);
-  intptr_t text_size() const { return next_text_offset_; }
   intptr_t data_size() const { return next_data_offset_; }
+  intptr_t text_size() const { return next_text_offset_; }
 
   void DumpStatistics();
 
@@ -120,10 +147,12 @@
     };
   };
 
-  intptr_t next_text_offset_;
   intptr_t next_data_offset_;
-  GrowableArray<InstructionsData> instructions_;
+  intptr_t next_text_offset_;
   GrowableArray<ObjectData> objects_;
+  GrowableArray<InstructionsData> instructions_;
+  ObjectOffsetMap shared_objects_;
+  ObjectOffsetMap shared_instructions_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(ImageWriter);
@@ -132,7 +161,9 @@
 class AssemblyImageWriter : public ImageWriter {
  public:
   AssemblyImageWriter(Dart_StreamingWriteCallback callback,
-                      void* callback_data);
+                      void* callback_data,
+                      const void* shared_objects,
+                      const void* shared_instructions);
   void Finalize();
 
   virtual void WriteText(WriteStream* clustered_stream, bool vm);
@@ -160,11 +191,9 @@
  public:
   BlobImageWriter(uint8_t** instructions_blob_buffer,
                   ReAlloc alloc,
-                  intptr_t initial_size)
-      : ImageWriter(),
-        instructions_blob_stream_(instructions_blob_buffer,
-                                  alloc,
-                                  initial_size) {}
+                  intptr_t initial_size,
+                  const void* shared_objects,
+                  const void* shared_instructions);
 
   virtual void WriteText(WriteStream* clustered_stream, bool vm);
 
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 4fe67e6..b444072 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -1979,6 +1979,18 @@
   return raw_class;
 }
 
+intptr_t Isolate::GetClassSizeForHeapWalkAt(intptr_t cid) {
+#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
+  if (IsReloading()) {
+    return reload_context()->GetClassSizeForHeapWalkAt(cid);
+  } else {
+    return class_table()->SizeAt(cid);
+  }
+#else
+  return class_table()->SizeAt(cid);
+#endif  // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
+}
+
 void Isolate::AddPendingDeopt(uword fp, uword pc) {
   // GrowableArray::Add is not atomic and may be interrupt by a profiler
   // stack walk.
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index b3a69f1..0febbfe 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -211,6 +211,7 @@
 
   // Prefers old classes when we are in the middle of a reload.
   RawClass* GetClassForHeapWalkAt(intptr_t cid);
+  intptr_t GetClassSizeForHeapWalkAt(intptr_t cid);
 
   static intptr_t ic_miss_code_offset() {
     return OFFSET_OF(Isolate, ic_miss_code_);
@@ -623,7 +624,6 @@
     ASSERT(value >= 0);
     return value > 0;
   }
-
   void IncrTopLevelParsingCount() {
     AtomicOperations::IncrementBy(&top_level_parsing_count_, 1);
   }
diff --git a/runtime/vm/isolate_reload.cc b/runtime/vm/isolate_reload.cc
index eb78a50..8dcf7d8 100644
--- a/runtime/vm/isolate_reload.cc
+++ b/runtime/vm/isolate_reload.cc
@@ -918,15 +918,15 @@
   saved_num_cids_ = I->class_table()->NumCids();
 
   // Copy of the class table.
-  RawClass** local_saved_class_table =
-      reinterpret_cast<RawClass**>(malloc(sizeof(RawClass*) * saved_num_cids_));
+  ClassAndSize* local_saved_class_table = reinterpret_cast<ClassAndSize*>(
+      malloc(sizeof(ClassAndSize) * saved_num_cids_));
 
   Class& cls = Class::Handle();
   UnorderedHashSet<ClassMapTraits> old_classes_set(old_classes_set_storage_);
   for (intptr_t i = 0; i < saved_num_cids_; i++) {
     if (class_table->IsValidIndex(i) && class_table->HasValidClassAt(i)) {
       // Copy the class into the saved class table and add it to the set.
-      local_saved_class_table[i] = class_table->At(i);
+      local_saved_class_table[i] = class_table->PairAt(i);
       if (i != kFreeListElement && i != kForwardingCorpse) {
         cls = class_table->At(i);
         bool already_present = old_classes_set.Insert(cls);
@@ -934,7 +934,7 @@
       }
     } else {
       // No class at this index, mark it as NULL.
-      local_saved_class_table[i] = NULL;
+      local_saved_class_table[i] = ClassAndSize(NULL);
     }
   }
   old_classes_set_storage_ = old_classes_set.Release().raw();
@@ -1197,11 +1197,11 @@
   // Overwrite classes in class table with the saved classes.
   for (intptr_t i = 0; i < saved_num_cids_; i++) {
     if (class_table->IsValidIndex(i)) {
-      class_table->SetAt(i, saved_class_table_[i]);
+      class_table->SetAt(i, saved_class_table_[i].get_raw_class());
     }
   }
 
-  RawClass** local_saved_class_table = saved_class_table_;
+  ClassAndSize* local_saved_class_table = saved_class_table_;
   saved_class_table_ = NULL;
   // Can't free this table immediately as another thread (e.g., the sweeper) may
   // be suspended between loading the table pointer and loading the table
@@ -1644,7 +1644,7 @@
   }
 
   // This is important: The saved class table (describing before objects)
-  // must be zapped to prevent the forwarding in GetClassForHeapWalkAt.
+  // must be zapped to prevent the forwarding in GetClassSizeForHeapWalkAt.
   // Instance will from now be described by the isolate's class table.
   free(saved_class_table_);
   saved_class_table_ = NULL;
@@ -1709,16 +1709,29 @@
 }
 
 RawClass* IsolateReloadContext::GetClassForHeapWalkAt(intptr_t cid) {
-  RawClass** class_table = AtomicOperations::LoadRelaxed(&saved_class_table_);
+  ClassAndSize* class_table =
+      AtomicOperations::LoadRelaxed(&saved_class_table_);
   if (class_table != NULL) {
     ASSERT(cid > 0);
     ASSERT(cid < saved_num_cids_);
-    return class_table[cid];
+    return class_table[cid].get_raw_class();
   } else {
     return isolate_->class_table()->At(cid);
   }
 }
 
+intptr_t IsolateReloadContext::GetClassSizeForHeapWalkAt(intptr_t cid) {
+  ClassAndSize* class_table =
+      AtomicOperations::LoadRelaxed(&saved_class_table_);
+  if (class_table != NULL) {
+    ASSERT(cid > 0);
+    ASSERT(cid < saved_num_cids_);
+    return class_table[cid].size();
+  } else {
+    return isolate_->class_table()->SizeAt(cid);
+  }
+}
+
 RawLibrary* IsolateReloadContext::saved_root_library() const {
   return saved_root_library_;
 }
diff --git a/runtime/vm/isolate_reload.h b/runtime/vm/isolate_reload.h
index 715802e..f811329 100644
--- a/runtime/vm/isolate_reload.h
+++ b/runtime/vm/isolate_reload.h
@@ -169,6 +169,7 @@
 
   // Prefers old classes when we are in the middle of a reload.
   RawClass* GetClassForHeapWalkAt(intptr_t cid);
+  intptr_t GetClassSizeForHeapWalkAt(intptr_t cid);
 
   void RegisterClass(const Class& new_cls);
 
@@ -280,7 +281,7 @@
   JSONStream* js_;
 
   intptr_t saved_num_cids_;
-  RawClass** saved_class_table_;
+  ClassAndSize* saved_class_table_;
   intptr_t num_saved_libs_;
 
   // Collect the necessary instance transformation for schema changes.
diff --git a/runtime/vm/isolate_reload_test.cc b/runtime/vm/isolate_reload_test.cc
index 20edba6..d8e1d5d 100644
--- a/runtime/vm/isolate_reload_test.cc
+++ b/runtime/vm/isolate_reload_test.cc
@@ -1210,11 +1210,18 @@
 
   EXPECT_VALID(TestCase::SetReloadTestScript(kReloadScript));
 
-  EXPECT_STREQ("instance", SimpleInvokeStr(lib, "main"));
+  const char* expected = "instance";
+  const char* result = SimpleInvokeStr(lib, "main");
+  EXPECT_STREQ(expected, result);
+
+  // Bail out if we've already failed so we don't crash in the tag handler.
+  if ((result == NULL) || (strcmp(expected, result) != 0)) {
+    return;
+  }
 
   lib = Dart_RootLibrary();
   EXPECT_NON_NULL(lib);
-  EXPECT_STREQ("instance", SimpleInvokeStr(lib, "main"));
+  EXPECT_STREQ(expected, SimpleInvokeStr(lib, "main"));
 }
 
 TEST_CASE(IsolateReload_PendingUnqualifiedCall_InstanceToStatic) {
@@ -1249,11 +1256,24 @@
 
   EXPECT_VALID(TestCase::SetReloadTestScript(kReloadScript));
 
-  EXPECT_STREQ("static", SimpleInvokeStr(lib, "main"));
+  const char* expected = "static";
+  const char* result = SimpleInvokeStr(lib, "main");
+  EXPECT_NOTNULL(result);
+
+  // Bail out if we've already failed so we don't crash in StringEquals.
+  if (result == NULL) {
+    return;
+  }
+  EXPECT_STREQ(expected, result);
+
+  // Bail out if we've already failed so we don't crash in the tag handler.
+  if (strcmp(expected, result) != 0) {
+    return;
+  }
 
   lib = Dart_RootLibrary();
   EXPECT_NON_NULL(lib);
-  EXPECT_STREQ("static", SimpleInvokeStr(lib, "main"));
+  EXPECT_STREQ(expected, SimpleInvokeStr(lib, "main"));
 }
 
 TEST_CASE(IsolateReload_PendingConstructorCall_AbstractToConcrete) {
@@ -1298,11 +1318,18 @@
 
   EXPECT_VALID(TestCase::SetReloadTestScript(kReloadScript));
 
-  EXPECT_STREQ("okay", SimpleInvokeStr(lib, "main"));
+  const char* expected = "okay";
+  const char* result = SimpleInvokeStr(lib, "main");
+  EXPECT_STREQ(expected, result);
+
+  // Bail out if we've already failed so we don't crash in the tag handler.
+  if ((result == NULL) || (strcmp(expected, result) != 0)) {
+    return;
+  }
 
   lib = Dart_RootLibrary();
   EXPECT_NON_NULL(lib);
-  EXPECT_STREQ("okay", SimpleInvokeStr(lib, "main"));
+  EXPECT_STREQ(expected, SimpleInvokeStr(lib, "main"));
 }
 
 TEST_CASE(IsolateReload_PendingConstructorCall_ConcreteToAbstract) {
@@ -1347,18 +1374,25 @@
 
   EXPECT_VALID(TestCase::SetReloadTestScript(kReloadScript));
 
-  EXPECT_STREQ("exception", SimpleInvokeStr(lib, "main"));
+  const char* expected = "exception";
+  const char* result = SimpleInvokeStr(lib, "main");
+  EXPECT_STREQ(expected, result);
+
+  // Bail out if we've already failed so we don't crash in the tag handler.
+  if ((result == NULL) || (strcmp(expected, result) != 0)) {
+    return;
+  }
 
   lib = Dart_RootLibrary();
   EXPECT_NON_NULL(lib);
-  EXPECT_STREQ("exception", SimpleInvokeStr(lib, "main"));
+  EXPECT_STREQ(expected, SimpleInvokeStr(lib, "main"));
 }
 
 TEST_CASE(IsolateReload_PendingStaticCall_DefinedToNSM) {
   const char* kScript =
       "import 'file:///test:isolate_reload_helper';\n"
       "class C {\n"
-      "  static foo() => 'static'\n"
+      "  static foo() => 'static';\n"
       "  test() {\n"
       "    reloadTest();\n"
       "    return C.foo();\n"
@@ -1393,11 +1427,25 @@
 
   EXPECT_VALID(TestCase::SetReloadTestScript(kReloadScript));
 
-  EXPECT_STREQ("exception", SimpleInvokeStr(lib, "main"));
+  const char* expected = "exception";
+  const char* result = SimpleInvokeStr(lib, "main");
+  EXPECT_NOTNULL(result);
 
+  // Bail out if we've already failed so we don't crash in StringEquals.
+  if (result == NULL) {
+    return;
+  }
+  EXPECT_STREQ(expected, result);
+
+  // Bail out if we've already failed so we don't crash in the tag handler.
+  if (strcmp(expected, result) != 0) {
+    return;
+  }
+
+  EXPECT_STREQ(expected, result);
   lib = Dart_RootLibrary();
   EXPECT_NON_NULL(lib);
-  EXPECT_STREQ("exception", SimpleInvokeStr(lib, "main"));
+  EXPECT_STREQ(expected, SimpleInvokeStr(lib, "main"));
 }
 
 TEST_CASE(IsolateReload_PendingStaticCall_NSMToDefined) {
@@ -1423,7 +1471,7 @@
   const char* kReloadScript =
       "import 'file:///test:isolate_reload_helper';\n"
       "class C {\n"
-      "  static foo() => 'static'\n"
+      "  static foo() => 'static';\n"
       "  test() {\n"
       "    reloadTest();\n"
       "    return C.foo();\n"
@@ -1439,11 +1487,18 @@
 
   EXPECT_VALID(TestCase::SetReloadTestScript(kReloadScript));
 
-  EXPECT_STREQ("static", SimpleInvokeStr(lib, "main"));
+  const char* expected = "static";
+  const char* result = SimpleInvokeStr(lib, "main");
+  EXPECT_STREQ(expected, result);
+
+  // Bail out if we've already failed so we don't crash in the tag handler.
+  if ((result == NULL) || (strcmp(expected, result) != 0)) {
+    return;
+  }
 
   lib = Dart_RootLibrary();
   EXPECT_NON_NULL(lib);
-  EXPECT_STREQ("static", SimpleInvokeStr(lib, "main"));
+  EXPECT_STREQ(expected, SimpleInvokeStr(lib, "main"));
 }
 
 TEST_CASE(IsolateReload_PendingSuperCall) {
diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h
index a5521fc..e426f4d 100644
--- a/runtime/vm/kernel_binary.h
+++ b/runtime/vm/kernel_binary.h
@@ -149,8 +149,9 @@
   kMapConstant = 5,
   kListConstant = 6,
   kInstanceConstant = 7,
-  kTearOffConstant = 8,
-  kTypeLiteralConstant = 9,
+  kPartialInstantiationConstant = 8,
+  kTearOffConstant = 9,
+  kTypeLiteralConstant = 10,
 };
 
 static const int SpecializedIntLiteralBias = 3;
diff --git a/runtime/vm/kernel_isolate.cc b/runtime/vm/kernel_isolate.cc
index 4445773..a8a9a1f 100644
--- a/runtime/vm/kernel_isolate.cc
+++ b/runtime/vm/kernel_isolate.cc
@@ -48,12 +48,10 @@
 //   1 - Update in-memory file system with in-memory sources (used by tests).
 //   2 - Accept last compilation result.
 //   3 - APP JIT snapshot training run for kernel_service.
-//   4 - Allows for `dart:_internal` to be imported (used by tests).
 const int KernelIsolate::kCompileTag = 0;
 const int KernelIsolate::kUpdateSourcesTag = 1;
 const int KernelIsolate::kAcceptTag = 2;
 const int KernelIsolate::kTrainTag = 3;
-const int KernelIsolate::kAllowDartInternalImportTag = 4;
 
 Dart_IsolateCreateCallback KernelIsolate::create_callback_ = NULL;
 Monitor* KernelIsolate::monitor_ = new Monitor();
@@ -611,23 +609,6 @@
                                         NULL, 0, source_files_count,
                                         source_files, true);
 }
-
-Dart_KernelCompilationResult KernelIsolate::AllowDartInternalImport() {
-  // This must be the main script to be loaded. Wait for Kernel isolate
-  // to finish initialization.
-  Dart_Port kernel_port = WaitForKernelPort();
-  if (kernel_port == ILLEGAL_PORT) {
-    Dart_KernelCompilationResult result;
-    result.status = Dart_KernelCompilationStatus_Unknown;
-    result.error = strdup("Error while initializing Kernel isolate");
-    return result;
-  }
-
-  KernelCompilationRequest request;
-  return request.SendAndWaitForResponse(
-      kAllowDartInternalImportTag, kernel_port, NULL, NULL, 0, 0, NULL, true);
-}
-
 #endif  // DART_PRECOMPILED_RUNTIME
 
 }  // namespace dart
diff --git a/runtime/vm/kernel_isolate.h b/runtime/vm/kernel_isolate.h
index 913b5c6..001aa41 100644
--- a/runtime/vm/kernel_isolate.h
+++ b/runtime/vm/kernel_isolate.h
@@ -22,7 +22,6 @@
   static const int kUpdateSourcesTag;
   static const int kAcceptTag;
   static const int kTrainTag;
-  static const int kAllowDartInternalImportTag;
 
   static void Run();
 
@@ -45,7 +44,6 @@
   static Dart_KernelCompilationResult UpdateInMemorySources(
       int source_files_count,
       Dart_SourceFile source_files[]);
-  static Dart_KernelCompilationResult AllowDartInternalImport();
 
  protected:
   static Monitor* monitor_;
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index c856133..7c31cf4 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -29,6 +29,7 @@
 #include "vm/double_conversion.h"
 #include "vm/exceptions.h"
 #include "vm/growable_array.h"
+#include "vm/hash.h"
 #include "vm/hash_table.h"
 #include "vm/heap.h"
 #include "vm/isolate_reload.h"
@@ -1835,6 +1836,8 @@
       return error.raw();
     }
 
+    isolate->class_table()->CopySizesFromClassObjects();
+
     ClassFinalizer::VerifyBootstrapClasses();
 
     // Set up the intrinsic state of all functions (core, math and typed data).
@@ -2908,14 +2911,19 @@
 }
 
 void Class::Finalize() const {
+  Isolate* isolate = Isolate::Current();
   ASSERT(Thread::Current()->IsMutatorThread());
-  ASSERT(!Isolate::Current()->all_classes_finalized());
+  ASSERT(!isolate->all_classes_finalized());
   ASSERT(!is_finalized());
   // Prefinalized classes have a VM internal representation and no Dart fields.
   // Their instance size  is precomputed and field offsets are known.
   if (!is_prefinalized()) {
     // Compute offsets of instance fields and instance size.
     CalculateFieldOffsets();
+    if (raw() == isolate->class_table()->At(id())) {
+      // Sets the new size in the class table.
+      isolate->class_table()->SetAt(id(), raw());
+    }
   }
   set_is_finalized();
 }
@@ -4828,24 +4836,6 @@
   return OS::SCreate(Thread::Current()->zone(), "unresolved class '%s'", cname);
 }
 
-static uint32_t CombineHashes(uint32_t hash, uint32_t other_hash) {
-  hash += other_hash;
-  hash += hash << 10;
-  hash ^= hash >> 6;  // Logical shift, unsigned hash.
-  return hash;
-}
-
-static uint32_t FinalizeHash(uint32_t hash, intptr_t hashbits) {
-  hash += hash << 3;
-  hash ^= hash >> 11;  // Logical shift, unsigned hash.
-  hash += hash << 15;
-  // FinalizeHash gets called with values for hashbits that are bigger than 31
-  // (like kBitsPerWord - 1).  Therefore we are careful to use a type
-  // (uintptr_t) big enough to avoid undefined behavior with the left shift.
-  hash &= (static_cast<uintptr_t>(1) << hashbits) - 1;
-  return (hash == 0) ? 1 : hash;
-}
-
 intptr_t TypeArguments::ComputeHash() const {
   if (IsNull()) return 0;
   const intptr_t num_types = Length();
@@ -22765,6 +22755,16 @@
                          const Function& function,
                          const Context& context,
                          Heap::Space space) {
+  return Closure::New(instantiator_type_arguments, function_type_arguments,
+                      Object::empty_type_arguments(), function, context, space);
+}
+
+RawClosure* Closure::New(const TypeArguments& instantiator_type_arguments,
+                         const TypeArguments& function_type_arguments,
+                         const TypeArguments& delayed_type_arguments,
+                         const Function& function,
+                         const Context& context,
+                         Heap::Space space) {
   Closure& result = Closure::Handle();
   {
     RawObject* raw =
@@ -22776,7 +22776,7 @@
     result.StorePointer(&result.raw_ptr()->function_type_arguments_,
                         function_type_arguments.raw());
     result.StorePointer(&result.raw_ptr()->delayed_type_arguments_,
-                        Object::empty_type_arguments().raw());
+                        delayed_type_arguments.raw());
     result.StorePointer(&result.raw_ptr()->function_, function.raw());
     result.StorePointer(&result.raw_ptr()->context_, context.raw());
   }
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index ea2c4d5..60e0288 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -915,6 +915,9 @@
     ASSERT(is_finalized() || is_prefinalized());
     return (raw_ptr()->instance_size_in_words_ * kWordSize);
   }
+  static intptr_t instance_size(RawClass* clazz) {
+    return (clazz->ptr()->instance_size_in_words_ * kWordSize);
+  }
   void set_instance_size(intptr_t value_in_bytes) const {
     ASSERT(kWordSize != 0);
     set_instance_size_in_words(value_in_bytes / kWordSize);
@@ -4422,8 +4425,11 @@
             RawPcDescriptors::MergedKindTry::DecodeTryIndex(merged_kind_try);
 
         cur_pc_offset_ += descriptors_.DecodeInteger(&byte_index_);
-        cur_deopt_id_ += descriptors_.DecodeInteger(&byte_index_);
-        cur_token_pos_ += descriptors_.DecodeInteger(&byte_index_);
+
+        if (!FLAG_precompiled_mode) {
+          cur_deopt_id_ += descriptors_.DecodeInteger(&byte_index_);
+          cur_token_pos_ += descriptors_.DecodeInteger(&byte_index_);
+        }
 
         if ((cur_kind_ & kind_mask_) != 0) {
           return true;  // Current is valid.
@@ -7907,7 +7913,16 @@
   virtual uword ComputeCanonicalTableHash() const;
 
   static const intptr_t kBytesPerElement = kWordSize;
-  static const intptr_t kMaxElements = kSmiMax / kBytesPerElement;
+  // The length field is a Smi so that sets one limit on the max Array length.
+  // But we also need to be able to represent the length in bytes in an
+  // intptr_t, which is a different limit.  Either may be smaller.  We can't
+  // use Utils::Minimum here because it is not a const expression.
+  static const intptr_t kElementLimitDueToIntptrMax = static_cast<intptr_t>(
+      (kIntptrMax - sizeof(RawArray) - kObjectAlignment + kBytesPerElement) /
+      kBytesPerElement);
+  static const intptr_t kMaxElements = kSmiMax < kElementLimitDueToIntptrMax
+                                           ? kSmiMax
+                                           : kElementLimitDueToIntptrMax;
   static const intptr_t kMaxNewSpaceElements =
       (Heap::kNewAllocatableSize - sizeof(RawArray)) / kBytesPerElement;
 
@@ -8791,6 +8806,13 @@
                          const Context& context,
                          Heap::Space space = Heap::kNew);
 
+  static RawClosure* New(const TypeArguments& instantiator_type_arguments,
+                         const TypeArguments& function_type_arguments,
+                         const TypeArguments& delayed_type_arguments,
+                         const Function& function,
+                         const Context& context,
+                         Heap::Space space = Heap::kNew);
+
   RawFunction* GetInstantiatedSignature(Zone* zone) const;
 
  private:
@@ -8860,7 +8882,7 @@
 // Internal stacktrace object used in exceptions for printing stack traces.
 class StackTrace : public Instance {
  public:
-  static const int kPreallocatedStackdepth = 30;
+  static const int kPreallocatedStackdepth = 90;
 
   intptr_t Length() const;
 
@@ -9146,6 +9168,7 @@
   if ((raw_value & kSmiTagMask) == kSmiTag) {
     return Smi::Class();
   }
+  ASSERT(!Isolate::Current()->compaction_in_progress());
   return Isolate::Current()->class_table()->At(raw()->GetClassId());
 }
 
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index f7ffc17..17eadb0 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -308,16 +308,10 @@
   EXPECT(Smi::IsValid(-15));
   EXPECT(Smi::IsValid(0xFFu));
 // Upper two bits must be either 00 or 11.
-#if defined(ARCH_IS_64_BIT)
-  EXPECT(!Smi::IsValid(kMaxInt64));
-  EXPECT(Smi::IsValid(0x3FFFFFFFFFFFFFFF));
-  EXPECT(Smi::IsValid(-1));
-#else
   EXPECT(!Smi::IsValid(kMaxInt32));
   EXPECT(Smi::IsValid(0x3FFFFFFF));
   EXPECT(Smi::IsValid(-1));
   EXPECT(!Smi::IsValid(0xFFFFFFFFu));
-#endif
 
   EXPECT_EQ(5, smi.AsInt64Value());
   EXPECT_EQ(5.0, smi.AsDoubleValue());
@@ -445,9 +439,6 @@
 }
 
 ISOLATE_UNIT_TEST_CASE(Mint) {
-// On 64-bit architectures a Smi is stored in a 64 bit word. A Midint cannot
-// be allocated if it does fit into a Smi.
-#if !defined(ARCH_IS_64_BIT)
   {
     Mint& med = Mint::Handle();
     EXPECT(med.IsNull());
@@ -517,7 +508,6 @@
   EXPECT_EQ(mint1.value(), mint_value);
   EXPECT_EQ(mint2.value(), mint_value);
   EXPECT_EQ(mint1.raw(), mint2.raw());
-#endif
 }
 
 ISOLATE_UNIT_TEST_CASE(Double) {
@@ -2747,22 +2737,6 @@
   EXPECT(Smi::Cast(result).Value() == kSmiTestValue);
 }
 
-#if defined(ARCH_IS_64_BIT)
-// Test for Embedded Smi object in the instructions.
-ISOLATE_UNIT_TEST_CASE(EmbedSmiIn64BitCode) {
-  extern void GenerateEmbedSmiInCode(Assembler * assembler, intptr_t value);
-  const intptr_t kSmiTestValue = DART_INT64_C(5) << 32;
-  Assembler _assembler_;
-  GenerateEmbedSmiInCode(&_assembler_, kSmiTestValue);
-  const Function& function =
-      Function::Handle(CreateFunction("Test_EmbedSmiIn64BitCode"));
-  const Code& code = Code::Handle(Code::FinalizeCode(function, &_assembler_));
-  function.AttachCode(code);
-  const Object& result =
-      Object::Handle(DartEntry::InvokeFunction(function, Array::empty_array()));
-  EXPECT(Smi::Cast(result).Value() == kSmiTestValue);
-}
-#endif  // ARCH_IS_64_BIT
 
 ISOLATE_UNIT_TEST_CASE(ExceptionHandlers) {
   const int kNumEntries = 4;
diff --git a/runtime/vm/pages.h b/runtime/vm/pages.h
index e83f354..06fbf27 100644
--- a/runtime/vm/pages.h
+++ b/runtime/vm/pages.h
@@ -77,6 +77,10 @@
                                        kPageMask);
   }
 
+  static HeapPage* Of(uintptr_t addr) {
+    return reinterpret_cast<HeapPage*>(addr & kPageMask);
+  }
+
  private:
   void set_object_end(uword value) {
     ASSERT((value & kObjectAlignmentMask) == kOldObjectAlignmentOffset);
diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
index cf7b0b4..5b3ba92 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler.cc
@@ -1045,6 +1045,10 @@
 }
 
 void Profiler::DumpStackTrace(void* context) {
+  if (context == NULL) {
+    DumpStackTrace();
+    return;
+  }
 #if defined(HOST_OS_LINUX) || defined(HOST_OS_MACOS) || defined(HOST_OS_ANDROID)
   ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
   mcontext_t mcontext = ucontext->uc_mcontext;
diff --git a/runtime/vm/raw_object.cc b/runtime/vm/raw_object.cc
index e78d53a..2f92257 100644
--- a/runtime/vm/raw_object.cc
+++ b/runtime/vm/raw_object.cc
@@ -49,6 +49,9 @@
   }
 }
 
+// Can't look at the class object because it can be called during
+// compaction when the class objects are moving. Can use the class
+// id in the header and the sizes in the Class Table.
 intptr_t RawObject::SizeFromClass() const {
   // Only reasonable to be called on heap objects.
   ASSERT(IsHeapObject());
@@ -187,9 +190,7 @@
                ptr()->tags_);
       }
 #endif  // DEBUG
-      RawClass* raw_class = isolate->GetClassForHeapWalkAt(class_id);
-      instance_size = raw_class->ptr()->instance_size_in_words_
-                      << kWordSizeLog2;
+      instance_size = isolate->GetClassSizeForHeapWalkAt(class_id);
     }
   }
   ASSERT(instance_size != 0);
@@ -555,9 +556,8 @@
   uint32_t tags = raw_obj->ptr()->tags_;
   intptr_t instance_size = SizeTag::decode(tags);
   if (instance_size == 0) {
-    RawClass* cls =
-        visitor->isolate()->GetClassForHeapWalkAt(raw_obj->GetClassId());
-    instance_size = cls->ptr()->instance_size_in_words_ << kWordSizeLog2;
+    instance_size =
+        visitor->isolate()->GetClassSizeForHeapWalkAt(raw_obj->GetClassId());
   }
 
   // Calculate the first and last raw object pointer fields.
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 5d52cbd..89875ca 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -499,6 +499,9 @@
   void Validate(Isolate* isolate) const;
   bool FindObject(FindObjectVisitor* visitor);
 
+  // This function may access the class-ID in the header, but it cannot access
+  // the actual class object, because the sliding compactor uses this function
+  // while the class objects are being moved.
   intptr_t VisitPointers(ObjectPointerVisitor* visitor) {
     // Fall back to virtual variant for predefined classes
     intptr_t class_id = GetClassId();
@@ -731,6 +734,7 @@
   friend class VerifyCanonicalVisitor;
   friend class ObjectGraph::Stack;  // GetClassId
   friend class Precompiler;         // GetClassId
+  friend class ObjectOffsetTrait;   // GetClassId
 
   DISALLOW_ALLOCATION();
   DISALLOW_IMPLICIT_CONSTRUCTORS(RawObject);
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index bac281c..e8af8b8 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -70,6 +70,8 @@
                        kAsReference);
     cls.StorePointer(&cls.raw_ptr()->dependent_code_, Array::null());
     ASSERT(!cls.IsInFullSnapshot());
+    // Also sets instance size in class table.
+    reader->isolate()->class_table()->SetAt(cls.id(), cls.raw());
   } else {
     cls ^= reader->ReadClassId(object_id);
     ASSERT((kind == Snapshot::kMessage) || cls.IsInFullSnapshot());
diff --git a/runtime/vm/regexp.cc b/runtime/vm/regexp.cc
index 4d99e0f..3d23411 100644
--- a/runtime/vm/regexp.cc
+++ b/runtime/vm/regexp.cc
@@ -3023,10 +3023,19 @@
                               Trace* current_trace,
                               PreloadState* state) {
   if (state->eats_at_least_ == PreloadState::kEatsAtLeastNotYetInitialized) {
-    // Save some time by looking at most one machine word ahead.
-    state->eats_at_least_ =
-        EatsAtLeast(compiler->one_byte() ? 4 : 2, kRecursionBudget,
-                    current_trace->at_start() == Trace::FALSE_VALUE);
+    // On ARM64, only read 16 bits ahead for now.  This ensures that boxing is
+    // trivial even with the new smaller Smis.  See
+    // https://github.com/dart-lang/sdk/issues/29951 and
+    // LoadCodeUnitsInstr::EmitNativeCode.
+#if defined(TARGET_ARCH_ARM64)
+    const int kMaxBytesLoaded = 2;
+#else
+    const int kMaxBytesLoaded = 4;
+#endif
+    const int kMaxTwoByteCharactersLoaded = kMaxBytesLoaded / 2;
+    state->eats_at_least_ = EatsAtLeast(
+        compiler->one_byte() ? kMaxBytesLoaded : kMaxTwoByteCharactersLoaded,
+        kRecursionBudget, current_trace->at_start() == Trace::FALSE_VALUE);
   }
   state->preload_characters_ =
       CalculatePreloadCharacters(compiler, state->eats_at_least_);
diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc
index 4838da1..fca1d73 100644
--- a/runtime/vm/runtime_entry.cc
+++ b/runtime/vm/runtime_entry.cc
@@ -171,15 +171,38 @@
 }
 
 DEFINE_RUNTIME_ENTRY(NullError, 0) {
-  // TODO(dartbug.com/30480): Fill in arguments of NoSuchMethodError.
+  DartFrameIterator iterator(thread,
+                             StackFrameIterator::kNoCrossThreadIteration);
+  const StackFrame* caller_frame = iterator.NextFrame();
+  ASSERT(caller_frame->IsDartFrame());
+  const Code& code = Code::Handle(zone, caller_frame->LookupDartCode());
+  const uword pc_offset = caller_frame->pc() - code.PayloadStart();
 
-  const String& member_name = String::Handle(String::New("???"));
+  const CodeSourceMap& map =
+      CodeSourceMap::Handle(zone, code.code_source_map());
+  ASSERT(!map.IsNull());
 
-  const Smi& invocation_type =
-      Smi::Handle(Smi::New(InvocationMirror::EncodeType(
-          InvocationMirror::kDynamic, InvocationMirror::kMethod)));
+  CodeSourceMapReader reader(map, Array::null_array(),
+                             Function::null_function());
+  const intptr_t name_index = reader.GetNullCheckNameIndexAt(pc_offset);
+  RELEASE_ASSERT(name_index >= 0);
 
-  const Array& args = Array::Handle(Array::New(6));
+  const ObjectPool& pool = ObjectPool::Handle(zone, code.object_pool());
+  const String& member_name =
+      String::CheckedHandle(zone, pool.ObjectAt(name_index));
+
+  InvocationMirror::Kind kind = InvocationMirror::kMethod;
+  if (Field::IsGetterName(member_name)) {
+    kind = InvocationMirror::kGetter;
+  } else if (Field::IsSetterName(member_name)) {
+    kind = InvocationMirror::kSetter;
+  }
+
+  const Smi& invocation_type = Smi::Handle(
+      zone,
+      Smi::New(InvocationMirror::EncodeType(InvocationMirror::kDynamic, kind)));
+
+  const Array& args = Array::Handle(zone, Array::New(6));
   args.SetAt(0, /* instance */ Object::null_object());
   args.SetAt(1, member_name);
   args.SetAt(2, invocation_type);
diff --git a/runtime/vm/simulator_arm64.cc b/runtime/vm/simulator_arm64.cc
index 3db2d65..926b75e 100644
--- a/runtime/vm/simulator_arm64.cc
+++ b/runtime/vm/simulator_arm64.cc
@@ -3199,13 +3199,21 @@
       set_vregisterd(vd, 1, 0);
     } else if (instr->Bits(16, 5) == 24) {
       // Format(instr, "fcvtzds'sf 'rd, 'vn");
+      const intptr_t max = instr->Bit(31) == 1 ? INT64_MAX : INT32_MAX;
+      const intptr_t min = instr->Bit(31) == 1 ? INT64_MIN : INT32_MIN;
       const double vn_val = bit_cast<double, int64_t>(get_vregisterd(vn, 0));
-      if (vn_val >= static_cast<double>(INT64_MAX)) {
-        set_register(instr, rd, INT64_MAX, instr->RdMode());
-      } else if (vn_val <= static_cast<double>(INT64_MIN)) {
-        set_register(instr, rd, INT64_MIN, instr->RdMode());
+      int64_t result;
+      if (vn_val >= static_cast<double>(max)) {
+        result = max;
+      } else if (vn_val <= static_cast<double>(min)) {
+        result = min;
       } else {
-        set_register(instr, rd, static_cast<int64_t>(vn_val), instr->RdMode());
+        result = static_cast<int64_t>(vn_val);
+      }
+      if (instr->Bit(31) == 1) {
+        set_register(instr, rd, result, instr->RdMode());
+      } else {
+        set_register(instr, rd, result & 0xffffffffll, instr->RdMode());
       }
     } else {
       UnimplementedInstruction(instr);
diff --git a/runtime/vm/simulator_dbc.cc b/runtime/vm/simulator_dbc.cc
index bd7be22..59edcb4 100644
--- a/runtime/vm/simulator_dbc.cc
+++ b/runtime/vm/simulator_dbc.cc
@@ -636,11 +636,11 @@
 // __builtin_s{add,sub,mul}_overflow() intrinsics here and below.
 // Note that they may clobber the output location even when there is overflow:
 // https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html
-DART_FORCE_INLINE static bool SignedAddWithOverflow(intptr_t lhs,
-                                                    intptr_t rhs,
+DART_FORCE_INLINE static bool SignedAddWithOverflow(int32_t lhs,
+                                                    int32_t rhs,
                                                     intptr_t* out) {
   intptr_t res = 1;
-#if defined(HOST_ARCH_IA32) || defined(HOST_ARCH_X64)
+#if defined(HOST_ARCH_IA32)
   asm volatile(
       "add %2, %1\n"
       "jo 1f;\n"
@@ -650,7 +650,19 @@
       : "+r"(res), "+r"(lhs)
       : "r"(rhs), "r"(out)
       : "cc");
-#elif defined(HOST_ARCH_ARM) || defined(HOST_ARCH_ARM64)
+#elif defined(HOST_ARCH_X64)
+  int64_t tmp;
+  asm volatile(
+      "addl %[rhs], %[lhs]\n"
+      "jo 1f;\n"
+      "xor %[res], %[res]\n"
+      "movslq %[lhs], %[tmp]\n"
+      "mov %[tmp], 0(%[out])\n"
+      "1: "
+      : [res] "+r"(res), [lhs] "+r"(lhs), [tmp] "=&r"(tmp)
+      : [rhs] "r"(rhs), [out] "r"(out)
+      : "cc");
+#elif defined(HOST_ARCH_ARM)
   asm volatile(
       "adds %1, %1, %2;\n"
       "bvs 1f;\n"
@@ -660,32 +672,13 @@
       : "+r"(res), "+r"(lhs)
       : "r"(rhs), "r"(out)
       : "cc");
-#else
-#error "Unsupported platform"
-#endif
-  return (res != 0);
-}
-
-DART_FORCE_INLINE static bool SignedSubWithOverflow(intptr_t lhs,
-                                                    intptr_t rhs,
-                                                    intptr_t* out) {
-  intptr_t res = 1;
-#if defined(HOST_ARCH_IA32) || defined(HOST_ARCH_X64)
+#elif defined(HOST_ARCH_ARM64)
   asm volatile(
-      "sub %2, %1\n"
-      "jo 1f;\n"
-      "xor %0, %0\n"
-      "mov %1, 0(%3)\n"
-      "1: "
-      : "+r"(res), "+r"(lhs)
-      : "r"(rhs), "r"(out)
-      : "cc");
-#elif defined(HOST_ARCH_ARM) || defined(HOST_ARCH_ARM64)
-  asm volatile(
-      "subs %1, %1, %2;\n"
+      "adds %w1, %w1, %w2;\n"
       "bvs 1f;\n"
+      "sxtw %x1, %w1;\n"
       "mov %0, #0;\n"
-      "str %1, [%3, #0]\n"
+      "str %x1, [%3, #0]\n"
       "1:"
       : "+r"(res), "+r"(lhs)
       : "r"(rhs), "r"(out)
@@ -696,11 +689,64 @@
   return (res != 0);
 }
 
-DART_FORCE_INLINE static bool SignedMulWithOverflow(intptr_t lhs,
-                                                    intptr_t rhs,
+DART_FORCE_INLINE static bool SignedSubWithOverflow(int32_t lhs,
+                                                    int32_t rhs,
                                                     intptr_t* out) {
   intptr_t res = 1;
-#if defined(HOST_ARCH_IA32) || defined(HOST_ARCH_X64)
+#if defined(HOST_ARCH_IA32)
+  asm volatile(
+      "sub %2, %1\n"
+      "jo 1f;\n"
+      "xor %0, %0\n"
+      "mov %1, 0(%3)\n"
+      "1: "
+      : "+r"(res), "+r"(lhs)
+      : "r"(rhs), "r"(out)
+      : "cc");
+#elif defined(HOST_ARCH_X64)
+  int64_t tmp;
+  asm volatile(
+      "subl %[rhs], %[lhs]\n"
+      "jo 1f;\n"
+      "xor %[res], %[res]\n"
+      "movslq %[lhs], %[tmp]\n"
+      "mov %[tmp], 0(%[out])\n"
+      "1: "
+      : [res] "+r"(res), [lhs] "+r"(lhs), [tmp] "=&r"(tmp)
+      : [rhs] "r"(rhs), [out] "r"(out)
+      : "cc");
+#elif defined(HOST_ARCH_ARM)
+  asm volatile(
+      "subs %1, %1, %2;\n"
+      "bvs 1f;\n"
+      "mov %0, #0;\n"
+      "str %1, [%3, #0]\n"
+      "1:"
+      : "+r"(res), "+r"(lhs)
+      : "r"(rhs), "r"(out)
+      : "cc");
+#elif defined(HOST_ARCH_ARM64)
+  asm volatile(
+      "subs %w1, %w1, %w2;\n"
+      "bvs 1f;\n"
+      "sxtw %x1, %w1;\n"
+      "mov %0, #0;\n"
+      "str %x1, [%3, #0]\n"
+      "1:"
+      : "+r"(res), "+r"(lhs)
+      : "r"(rhs), "r"(out)
+      : "cc");
+#else
+#error "Unsupported platform"
+#endif
+  return (res != 0);
+}
+
+DART_FORCE_INLINE static bool SignedMulWithOverflow(int32_t lhs,
+                                                    int32_t rhs,
+                                                    intptr_t* out) {
+  intptr_t res = 1;
+#if defined(HOST_ARCH_IA32)
   asm volatile(
       "imul %2, %1\n"
       "jo 1f;\n"
@@ -710,6 +756,18 @@
       : "+r"(res), "+r"(lhs)
       : "r"(rhs), "r"(out)
       : "cc");
+#elif defined(HOST_ARCH_X64)
+  int64_t tmp;
+  asm volatile(
+      "imull %[rhs], %[lhs]\n"
+      "jo 1f;\n"
+      "xor %[res], %[res]\n"
+      "movslq %[lhs], %[tmp]\n"
+      "mov %[tmp], 0(%[out])\n"
+      "1: "
+      : [res] "+r"(res), [lhs] "+r"(lhs), [tmp] "=&r"(tmp)
+      : [rhs] "r"(rhs), [out] "r"(out)
+      : "cc");
 #elif defined(HOST_ARCH_ARM)
   asm volatile(
       "smull %1, ip, %1, %2;\n"
@@ -724,12 +782,12 @@
 #elif defined(HOST_ARCH_ARM64)
   int64_t prod_lo = 0;
   asm volatile(
-      "mul %1, %2, %3\n"
-      "smulh %2, %2, %3\n"
-      "cmp %2, %1, ASR #63;\n"
+      "smull %x1, %w2, %w3\n"
+      "asr %x2, %x1, #63\n"
+      "cmp %x2, %x1, ASR #31;\n"
       "bne 1f;\n"
       "mov %0, #0;\n"
-      "str %1, [%4, #0]\n"
+      "str %x1, [%4, #0]\n"
       "1:"
       : "=r"(res), "+r"(prod_lo), "+r"(lhs)
       : "r"(rhs), "r"(out)
@@ -1971,11 +2029,7 @@
     if (rhs != 0) {
       const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]);
       const intptr_t res = (lhs >> kSmiTagSize) / (rhs >> kSmiTagSize);
-#if defined(ARCH_IS_64_BIT)
-      const intptr_t untaggable = 0x4000000000000000LL;
-#else
       const intptr_t untaggable = 0x40000000L;
-#endif  // defined(ARCH_IS_64_BIT)
       if (res != untaggable) {
         *reinterpret_cast<intptr_t*>(&FP[rA]) = res << kSmiTagSize;
         pc++;
@@ -2001,11 +2055,12 @@
   {
     BYTECODE(Shl, A_B_C);
     const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]) >> kSmiTagSize;
-    if (static_cast<uintptr_t>(rhs) < kBitsPerWord) {
-      const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]);
-      const intptr_t res = lhs << rhs;
+    const int kBitsPerInt32 = 32;
+    if (static_cast<uintptr_t>(rhs) < kBitsPerInt32) {
+      const int32_t lhs = reinterpret_cast<intptr_t>(FP[rB]);
+      const int32_t res = lhs << rhs;
       if (lhs == (res >> rhs)) {
-        *reinterpret_cast<intptr_t*>(&FP[rA]) = res;
+        *reinterpret_cast<intptr_t*>(&FP[rA]) = static_cast<intptr_t>(res);
         pc++;
       }
     }
@@ -2016,8 +2071,7 @@
     BYTECODE(Shr, A_B_C);
     const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]) >> kSmiTagSize;
     if (rhs >= 0) {
-      const intptr_t shift_amount =
-          (rhs >= kBitsPerWord) ? (kBitsPerWord - 1) : rhs;
+      const intptr_t shift_amount = (rhs >= 32) ? (32 - 1) : rhs;
       const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]) >> kSmiTagSize;
       *reinterpret_cast<intptr_t*>(&FP[rA]) = (lhs >> shift_amount)
                                               << kSmiTagSize;
diff --git a/runtime/vm/snapshot.h b/runtime/vm/snapshot.h
index 6dd74d4..60a944f 100644
--- a/runtime/vm/snapshot.h
+++ b/runtime/vm/snapshot.h
@@ -202,6 +202,14 @@
 
   const uint8_t* Addr() const { return reinterpret_cast<const uint8_t*>(this); }
 
+  const uint8_t* DataImage() const {
+    if (!IncludesCode(kind())) {
+      return NULL;
+    }
+    uword offset = Utils::RoundUp(length(), OS::kMaxPreferredCodeAlignment);
+    return Addr() + offset;
+  }
+
  private:
   // Prevent Snapshot from ever being allocated directly.
   Snapshot();
diff --git a/runtime/vm/snapshot_test.cc b/runtime/vm/snapshot_test.cc
index cff0584..22067a5 100644
--- a/runtime/vm/snapshot_test.cc
+++ b/runtime/vm/snapshot_test.cc
@@ -253,10 +253,6 @@
 // here covers most of the 64-bit range. On 32-bit platforms the smi
 // range covers most of the 32-bit range and values outside that
 // range are also represented as mints.
-#if defined(ARCH_IS_64_BIT)
-  EXPECT_EQ(Dart_CObject_kInt64, mint_cobject->type);
-  EXPECT_EQ(value, mint_cobject->value.as_int64);
-#else
   if (kMinInt32 < value && value < kMaxInt32) {
     EXPECT_EQ(Dart_CObject_kInt32, mint_cobject->type);
     EXPECT_EQ(value, mint_cobject->value.as_int32);
@@ -264,7 +260,6 @@
     EXPECT_EQ(Dart_CObject_kInt64, mint_cobject->type);
     EXPECT_EQ(value, mint_cobject->value.as_int64);
   }
-#endif
 }
 
 TEST_CASE(SerializeMints) {
@@ -1775,8 +1770,9 @@
   {
     // Use a script snapshot where a full snapshot is expected.
     char* error = NULL;
-    Dart_Isolate isolate = Dart_CreateIsolate(
-        "script-uri", "main", script_snapshot, NULL, NULL, NULL, &error);
+    Dart_Isolate isolate =
+        Dart_CreateIsolate("script-uri", "main", script_snapshot, NULL, NULL,
+                           NULL, NULL, NULL, &error);
     EXPECT(isolate == NULL);
     EXPECT(error != NULL);
     EXPECT_SUBSTRING(
diff --git a/runtime/vm/stub_code_arm64.cc b/runtime/vm/stub_code_arm64.cc
index f0354a8..401a611 100644
--- a/runtime/vm/stub_code_arm64.cc
+++ b/runtime/vm/stub_code_arm64.cc
@@ -1334,14 +1334,18 @@
   __ ldr(R1, Address(SP, +1 * kWordSize));  // Left.
   __ orr(TMP, R0, Operand(R1));
   __ BranchIfNotSmi(TMP, not_smi_or_overflow);
+  __ AssertSmiInRange(R0);
+  __ AssertSmiInRange(R1);
   switch (kind) {
     case Token::kADD: {
-      __ adds(R0, R1, Operand(R0));   // Adds.
+      __ addsw(R0, R1, Operand(R0));  // Adds.
+      __ sxtw(R0, R0);
       __ b(not_smi_or_overflow, VS);  // Branch if overflow.
       break;
     }
     case Token::kSUB: {
-      __ subs(R0, R1, Operand(R0));   // Subtract.
+      __ subsw(R0, R1, Operand(R0));  // Subtract.
+      __ sxtw(R0, R0);
       __ b(not_smi_or_overflow, VS);  // Branch if overflow.
       break;
     }
@@ -1383,6 +1387,8 @@
     __ StoreToOffset(R1, R6, count_offset);
   }
 
+  __ AssertSmiInRange(R0, Assembler::kValueCanBeHeapPointer);
+
   __ ret();
 }
 
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc
index fc8e781..b21d9db 100644
--- a/runtime/vm/stub_code_x64.cc
+++ b/runtime/vm/stub_code_x64.cc
@@ -1274,13 +1274,15 @@
   __ j(NOT_ZERO, not_smi_or_overflow);
   switch (kind) {
     case Token::kADD: {
-      __ addq(RAX, RCX);
+      __ addl(RAX, RCX);
       __ j(OVERFLOW, not_smi_or_overflow);
+      __ movsxd(RAX, RAX);
       break;
     }
     case Token::kSUB: {
-      __ subq(RAX, RCX);
+      __ subl(RAX, RCX);
       __ j(OVERFLOW, not_smi_or_overflow);
+      __ movsxd(RAX, RAX);
       break;
     }
     case Token::kEQ: {
diff --git a/runtime/vm/token_position.h b/runtime/vm/token_position.h
index c28f9a4..eadb562 100644
--- a/runtime/vm/token_position.h
+++ b/runtime/vm/token_position.h
@@ -18,7 +18,7 @@
 // ClassifyingTokenPositions N -> -1 - N
 //
 // Synthetically created AstNodes are given real source positions but encoded
-// as negative numbers from [kSmiMin32, -1 - N]. For example:
+// as negative numbers from [kSmiMin, -1 - N]. For example:
 //
 // A source position of 0 in a synthetic AstNode would be encoded as -2 - N.
 // A source position of 1 in a synthetic AstNode would be encoded as -3 - N.
@@ -86,7 +86,7 @@
 #undef DECLARE_VALUES
   static const intptr_t kMinSourcePos = 0;
   static const TokenPosition kMinSource;
-  static const intptr_t kMaxSourcePos = kSmiMax32 - kMaxSentinelDescriptors - 2;
+  static const intptr_t kMaxSourcePos = kSmiMax - kMaxSentinelDescriptors - 2;
   static const TokenPosition kMaxSource;
 
   // Decode from a snapshot.
diff --git a/runtime/vm/type_testing_stubs.cc b/runtime/vm/type_testing_stubs.cc
index 82f55a7..70c1e2c 100644
--- a/runtime/vm/type_testing_stubs.cc
+++ b/runtime/vm/type_testing_stubs.cc
@@ -184,7 +184,7 @@
 // TODO(kustermann): Use sorting/hashtables to speed this up.
 RawInstructions* TypeTestingStubFinder::LookupByAddresss(
     uword entry_point) const {
-  // First test the 2 common ones:
+  // First test the 4 common ones:
   code_ = StubCode::DefaultTypeTest_entry()->code();
   if (entry_point == code_.UncheckedEntryPoint()) {
     return code_.instructions();
@@ -208,11 +208,19 @@
 
 const char* TypeTestingStubFinder::StubNameFromAddresss(
     uword entry_point) const {
-  // First test the 2 common ones:
+  // First test the 4 common ones:
   code_ = StubCode::DefaultTypeTest_entry()->code();
   if (entry_point == code_.UncheckedEntryPoint()) {
     return "TypeTestingStub_Default";
   }
+  code_ = StubCode::TopTypeTypeTest_entry()->code();
+  if (entry_point == code_.UncheckedEntryPoint()) {
+    return "TypeTestingStub_Top";
+  }
+  code_ = StubCode::TypeRefTypeTest_entry()->code();
+  if (entry_point == code_.UncheckedEntryPoint()) {
+    return "TypeTestingStub_Ref";
+  }
   code_ = StubCode::UnreachableTypeTest_entry()->code();
   if (entry_point == code_.UncheckedEntryPoint()) {
     return "TypeTestingStub_Unreachable";
diff --git a/runtime/vm/unit_test.cc b/runtime/vm/unit_test.cc
index b107412..92e1838 100644
--- a/runtime/vm/unit_test.cc
+++ b/runtime/vm/unit_test.cc
@@ -94,8 +94,8 @@
   api_flags.use_dart_frontend = FLAG_use_dart_frontend;
   Dart_Isolate isolate = NULL;
   if (len == 0) {
-    isolate = Dart_CreateIsolate(name, NULL, data_buffer, instr_buffer,
-                                 &api_flags, data, &err);
+    isolate = Dart_CreateIsolate(name, NULL, data_buffer, instr_buffer, NULL,
+                                 NULL, &api_flags, data, &err);
   } else {
     kernel::Program* program = reinterpret_cast<kernel::Program*>(
         Dart_ReadKernelBinary(data_buffer, len, NoopRelease));
@@ -594,11 +594,6 @@
 
 Dart_Handle TestCase::LoadCoreTestScript(const char* script,
                                          Dart_NativeEntryResolver resolver) {
-  if (FLAG_use_dart_frontend) {
-    // Sets a flag in the CFE to not throw an error if `dart:_internal` is
-    // imported from a non-internal library.
-    KernelIsolate::AllowDartInternalImport();
-  }
   return LoadTestScript(script, resolver, CORELIB_TEST_URI);
 }
 
diff --git a/runtime/vm/virtual_memory_win.cc b/runtime/vm/virtual_memory_win.cc
index 15329e6..b31a2fe 100644
--- a/runtime/vm/virtual_memory_win.cc
+++ b/runtime/vm/virtual_memory_win.cc
@@ -62,20 +62,24 @@
 }
 
 VirtualMemory::~VirtualMemory() {
-  if (!vm_owns_region() || (reserved_.size() == 0)) {
+  // Note that the size of the reserved region might be set to 0 by
+  // Truncate(0, true) but that does not actually release the mapping
+  // itself. The only way to release the mapping is to invoke VirtualFree
+  // with original base pointer and MEM_RELEASE.
+  if (!vm_owns_region()) {
     return;
   }
   if (VirtualFree(reserved_.pointer(), 0, MEM_RELEASE) == 0) {
-    FATAL("VirtualFree failed");
+    FATAL1("VirtualFree failed: Error code %d\n", GetLastError());
   }
 }
 
 bool VirtualMemory::FreeSubSegment(void* address,
                                    intptr_t size) {
-  // On Windows only the entire segment returned by VirtualAlloc
-  // can be freed. Therefore we will have to waste these unused
-  // virtual memory sub-segments.
-  return false;
+  if (VirtualFree(address, size, MEM_DECOMMIT) == 0) {
+    FATAL1("VirtualFree failed: Error code %d\n", GetLastError());
+  }
+  return true;
 }
 
 void VirtualMemory::Protect(void* address, intptr_t size, Protection mode) {
diff --git a/sdk/BUILD.gn b/sdk/BUILD.gn
index 4d58c04..766a114 100644
--- a/sdk/BUILD.gn
+++ b/sdk/BUILD.gn
@@ -270,21 +270,6 @@
       ignore_patterns = "{}"
     } ]
 
-# This rule copies pub assets to lib/_internal/pub/asset
-copy_tree_specs += [ {
-      target = "copy_pub_assets"
-      visibility = [
-        ":create_common_sdk",
-        ":copy_7zip",
-      ]
-      deps = [
-        ":copy_libraries",
-      ]
-      source = "../third_party/pkg/pub/lib/src/asset"
-      dest = "$root_out_dir/dart-sdk/lib/_internal/pub/asset"
-      ignore_patterns = "{}"
-    } ]
-
 # This loop generates rules to copy libraries to lib/
 foreach(library, _full_sdk_libraries) {
   copy_tree_specs += [ {
@@ -305,7 +290,6 @@
         visibility = [ ":create_common_sdk" ]
         deps = [
           ":copy_libraries",
-          ":copy_pub_assets",
         ]
         source = "../third_party/7zip"
         dest = "$root_out_dir/dart-sdk/lib/_internal/pub/asset/7zip"
@@ -959,7 +943,6 @@
     ":copy_license",
     ":copy_libraries_specification",
     ":copy_platform_files",
-    ":copy_pub_assets",
     ":copy_readme",
     ":copy_vm_dill_files",
     ":write_revision_file",
diff --git a/sdk/lib/_internal/js_runtime/lib/js_array.dart b/sdk/lib/_internal/js_runtime/lib/js_array.dart
index 79d4c94..04e8f49 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_array.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_array.dart
@@ -523,7 +523,13 @@
 
   void sort([int compare(E a, E b)]) {
     checkMutable('sort');
-    Sort.sort(this, compare == null ? Comparable.compare : compare);
+    Sort.sort(this, compare ?? _compareAny);
+  }
+
+  static int _compareAny(a, b) {
+    // In strong mode Comparable.compare requires an implicit cast to ensure
+    // `a` and `b` are Comparable.
+    return Comparable.compare(a, b);
   }
 
   void shuffle([Random random]) {
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index b2b328e..e0024cf 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -17,6 +17,7 @@
 Language/Expressions/Function_Invocation/async_cleanup_t08: Skip # https://github.com/dart-lang/sdk/issues/28873
 Language/Expressions/Function_Invocation/async_generator_invokation_t08: Skip # Issue 25967
 Language/Expressions/Function_Invocation/async_generator_invokation_t10: Skip # Issue 25967
+Language/Expressions/Function_Invocation/async_invokation_t02: RuntimeError # sync-async is on by default.
 Language/Expressions/Function_Invocation/async_invokation_t04: RuntimeError, Pass # co19 issue 57
 Language/Expressions/Instance_Creation/New/evaluation_t19: RuntimeError # Please triage this failure
 Language/Expressions/Instance_Creation/New/evaluation_t20: RuntimeError # Please triage this failure
@@ -1366,12 +1367,15 @@
 WebPlatformTest/shadow-dom/shadow-trees/upper-boundary-encapsulation/ownerdocument-001_t01: RuntimeError # Please triage this failure
 
 [ $compiler == dart2js && $runtime == chrome && $csp && $minified ]
+LayoutTests/fast/css/fontface-properties_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/css/inherited-properties-rare-text_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/HTMLScriptElement/isURLAttribute_t01: SkipByDesign # Uses script injection
 LayoutTests/fast/dom/HTMLScriptElement/remove-source_t01: Pass # Please triage this failure
 LayoutTests/fast/dom/HTMLScriptElement/script-for-attribute-unexpected-execution_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/HTMLScriptElement/script-reexecution_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/HTMLTemplateElement/inertContents_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/dom/Range/create-contextual-fragment-script-unmark-already-started_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/dom/shadow/elementfrompoint_t01: RuntimeError # Please triage this failure
 LayoutTests/fast/files/workers/inline-worker-via-blob-url_t01: SkipByDesign # inlined script
 LayoutTests/fast/loader/scroll-position-restored-on-back_t01: Skip # Timeout. Please triage this failure
 WebPlatformTest/webstorage/event_local_key_t01: Skip # Timeout. Please triage this failure.
@@ -1493,7 +1497,7 @@
 LibTest/async/DeferredLibrary/DeferredLibrary_A01_t01: RuntimeError
 
 [ $compiler == dart2js && $runtime == d8 && $fast_startup ]
-LibTest/isolate/Isolate/spawn_A04_t04: Fail # Issue 27558
+LibTest/isolate/Isolate/spawn_A04_t04: Pass # Technically fails, but since sync-async was turned on, this test completes before it fails. Underlying issue: #27558
 
 [ $compiler == dart2js && $runtime == d8 && $fasta ]
 LayoutTests/*: SkipByDesign
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index 2dd3260..76eadd0 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -188,9 +188,6 @@
 LibTest/collection/ListMixin/ListMixin_class_A01_t02: Skip # co19 issue 673, These tests take too much memory (300 MB) for our 1 GB test machine co19 issue 673. http://code.google.com/p/co19/issues/detail?id=673
 LibTest/core/List/List_class_A01_t02: Skip # co19 issue 673, These tests take too much memory (300 MB) for our 1 GB test machine co19 issue 673. http://code.google.com/p/co19/issues/detail?id=673
 
-[ $arch != arm64 && $arch != simarm64 && $arch != simdbc && $arch != simdbc64 && $arch != x64 && ($runtime == dart_precompiled || $runtime == vm) ]
-LibTest/core/int/operator_left_shift_A01_t02: Fail # co19 issue 129
-
 [ $arch == ia32 && $mode == release && $runtime == vm && $system == linux ]
 service/dev_fs_spawn_test: Pass, Fail # Issue 28411
 
@@ -382,6 +379,9 @@
 LibTest/typed_data/Uint64List/Uint64List.view_A01_t02: CompileTimeError # Large integer literal
 WebPlatformTest/*: SkipByDesign # dart:html not supported on VM.
 
+[ $runtime == dart_precompiled || $runtime == vm ]
+LibTest/core/int/operator_left_shift_A01_t02: Fail # Can't represent 1 << 2147483647 without running out of memory.
+
 [ $runtime == flutter || $hot_reload || $hot_reload_rollback ]
 Language/Expressions/Assignment/prefix_object_t02: Skip # Requires deferred libraries
 Language/Expressions/Constants/constant_constructor_t03: Skip # Requires deferred libraries
diff --git a/tests/compiler/dart2js/end_to_end/data/dart2js_batch2_run.dart b/tests/compiler/dart2js/end_to_end/data/dart2js_batch2_run.dart
index b6de254..e63be3b 100644
--- a/tests/compiler/dart2js/end_to_end/data/dart2js_batch2_run.dart
+++ b/tests/compiler/dart2js/end_to_end/data/dart2js_batch2_run.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// ignore: INVALID_ANNOTATION
+// ignore: UNDEFINED_ANNOTATION
 @notExisting
 var x;
 
diff --git a/tests/compiler/dart2js/equivalence/equivalence_helper.dart b/tests/compiler/dart2js/equivalence/equivalence_helper.dart
index 75d497d..45437a9 100644
--- a/tests/compiler/dart2js/equivalence/equivalence_helper.dart
+++ b/tests/compiler/dart2js/equivalence/equivalence_helper.dart
@@ -951,6 +951,15 @@
         strategy.testConstants(
             exp1, exp2, 'message', exp1.message, exp2.message);
   }
+
+  @override
+  bool visitInstantiation(InstantiationConstantExpression exp1,
+      covariant InstantiationConstantExpression exp2) {
+    return strategy.testTypeLists(exp1, exp2, 'typeArguments',
+            exp1.typeArguments, exp2.typeArguments) &&
+        strategy.testConstants(
+            exp1, exp2, 'expression', exp1.expression, exp2.expression);
+  }
 }
 
 /// Visitor that checks for structural equivalence of [ConstantValue]s.
@@ -1086,6 +1095,15 @@
       covariant InterceptorConstantValue value2) {
     return strategy.testElements(value1, value2, 'cls', value1.cls, value2.cls);
   }
+
+  @override
+  bool visitInstantiation(InstantiationConstantValue value1,
+      covariant InstantiationConstantValue value2) {
+    return strategy.testTypeLists(value1, value2, 'typeArguments',
+            value1.typeArguments, value2.typeArguments) &&
+        strategy.testConstantValues(
+            value1, value2, 'function', value1.function, value2.function);
+  }
 }
 
 /// Tests the equivalence of [impact1] and [impact2] using [strategy].
diff --git a/tests/compiler/dart2js/model/constant_expression_evaluate_test.dart b/tests/compiler/dart2js/model/constant_expression_evaluate_test.dart
index 532dd9e..8fa15e2 100644
--- a/tests/compiler/dart2js/model/constant_expression_evaluate_test.dart
+++ b/tests/compiler/dart2js/model/constant_expression_evaluate_test.dart
@@ -34,7 +34,10 @@
   /// Tested constants.
   final List<ConstantData> constants;
 
-  const TestData(this.name, this.declarations, this.constants);
+  final bool strongModeOnly;
+
+  const TestData(this.name, this.declarations, this.constants,
+      {this.strongModeOnly: false});
 }
 
 class ConstantData {
@@ -46,12 +49,17 @@
   /// a [ConstantResult].
   final expectedResults;
 
+  /// Expected results for Dart 2 if different from [expectedResults].
+  final strongModeResults;
+
   /// A [MessageKind] or a list of [MessageKind]s containing the error messages
   /// expected as the result of evaluating the constant under the empty
   /// environment.
   final expectedErrors;
 
-  const ConstantData(this.code, this.expectedResults, [this.expectedErrors]);
+  const ConstantData(this.code, this.expectedResults,
+      {this.expectedErrors, strongModeResults})
+      : this.strongModeResults = strongModeResults ?? expectedResults;
 }
 
 class EvaluationError {
@@ -77,6 +85,10 @@
   }
 
   @override
+  DartType getTypeInContext(DartType type) =>
+      _environment.getTypeInContext(type);
+
+  @override
   ConstantConstructor getConstructorConstant(ConstructorEntity constructor) {
     return _environment.getConstructorConstant(constructor);
   }
@@ -152,21 +164,25 @@
     const ConstantData('Object', 'TypeConstant(Object)'),
     const ConstantData('null ?? 0', 'IntConstant(0)'),
     const ConstantData(
-        'const [0, 1]', 'ListConstant([IntConstant(0), IntConstant(1)])'),
+        'const [0, 1]', 'ListConstant([IntConstant(0), IntConstant(1)])',
+        strongModeResults:
+            'ListConstant(<int>[IntConstant(0), IntConstant(1)])'),
     const ConstantData('const <int>[0, 1]',
         'ListConstant(<int>[IntConstant(0), IntConstant(1)])'),
     const ConstantData(
         'const {0: 1, 2: 3}',
         'MapConstant({IntConstant(0): IntConstant(1), '
-        'IntConstant(2): IntConstant(3)})'),
+        'IntConstant(2): IntConstant(3)})',
+        strongModeResults:
+            'MapConstant(<int, int>{IntConstant(0): IntConstant(1), '
+            'IntConstant(2): IntConstant(3)})'),
     const ConstantData(
         'const <int, int>{0: 1, 2: 3}',
         'MapConstant(<int, int>{IntConstant(0): IntConstant(1), '
         'IntConstant(2): IntConstant(3)})'),
-    const ConstantData(
-        'const <int, int>{0: 1, 0: 2}',
+    const ConstantData('const <int, int>{0: 1, 0: 2}',
         'MapConstant(<int, int>{IntConstant(0): IntConstant(2)})',
-        MessageKind.EQUAL_MAP_ENTRY_KEY),
+        expectedErrors: MessageKind.EQUAL_MAP_ENTRY_KEY),
     const ConstantData(
         'const bool.fromEnvironment("foo", defaultValue: false)', const {
       const {}: 'BoolConstant(false)',
@@ -355,133 +371,137 @@
     const ConstantData(
         r'"$integer $string $boolean"', 'StringConstant("5 baz false")'),
     const ConstantData('0 ? true : false', 'NonConstant',
-        MessageKind.INVALID_CONSTANT_CONDITIONAL_TYPE),
+        expectedErrors: MessageKind.INVALID_CONSTANT_CONDITIONAL_TYPE),
     const ConstantData('integer ? true : false', 'NonConstant',
-        MessageKind.INVALID_CONSTANT_CONDITIONAL_TYPE),
+        expectedErrors: MessageKind.INVALID_CONSTANT_CONDITIONAL_TYPE),
     const ConstantData(r'"${const []}"', 'NonConstant',
-        MessageKind.INVALID_CONSTANT_INTERPOLATION_TYPE),
+        expectedErrors: MessageKind.INVALID_CONSTANT_INTERPOLATION_TYPE),
     const ConstantData(r'"${proxy}"', 'NonConstant',
-        MessageKind.INVALID_CONSTANT_INTERPOLATION_TYPE),
-    const ConstantData(r'"${proxy}${const []}"', 'NonConstant', const [
-      MessageKind.INVALID_CONSTANT_INTERPOLATION_TYPE,
-      MessageKind.INVALID_CONSTANT_INTERPOLATION_TYPE
-    ]),
-    const ConstantData(r'"${"${proxy}"}${const []}"', 'NonConstant', const [
-      MessageKind.INVALID_CONSTANT_INTERPOLATION_TYPE,
-      MessageKind.INVALID_CONSTANT_INTERPOLATION_TYPE
-    ]),
-    const ConstantData(
-        '0 + ""', 'NonConstant', MessageKind.INVALID_CONSTANT_NUM_ADD_TYPE),
-    const ConstantData(
-        '0 + string', 'NonConstant', MessageKind.INVALID_CONSTANT_NUM_ADD_TYPE),
-    const ConstantData(
-        '"" + 0', 'NonConstant', MessageKind.INVALID_CONSTANT_STRING_ADD_TYPE),
+        expectedErrors: MessageKind.INVALID_CONSTANT_INTERPOLATION_TYPE),
+    const ConstantData(r'"${proxy}${const []}"', 'NonConstant',
+        expectedErrors: const [
+          MessageKind.INVALID_CONSTANT_INTERPOLATION_TYPE,
+          MessageKind.INVALID_CONSTANT_INTERPOLATION_TYPE
+        ]),
+    const ConstantData(r'"${"${proxy}"}${const []}"', 'NonConstant',
+        expectedErrors: const [
+          MessageKind.INVALID_CONSTANT_INTERPOLATION_TYPE,
+          MessageKind.INVALID_CONSTANT_INTERPOLATION_TYPE
+        ]),
+    const ConstantData('0 + ""', 'NonConstant',
+        expectedErrors: MessageKind.INVALID_CONSTANT_NUM_ADD_TYPE),
+    const ConstantData('0 + string', 'NonConstant',
+        expectedErrors: MessageKind.INVALID_CONSTANT_NUM_ADD_TYPE),
+    const ConstantData('"" + 0', 'NonConstant',
+        expectedErrors: MessageKind.INVALID_CONSTANT_STRING_ADD_TYPE),
     const ConstantData('string + 0', 'NonConstant',
-        MessageKind.INVALID_CONSTANT_STRING_ADD_TYPE),
+        expectedErrors: MessageKind.INVALID_CONSTANT_STRING_ADD_TYPE),
     const ConstantData('true + ""', 'NonConstant',
-        MessageKind.INVALID_CONSTANT_STRING_ADD_TYPE),
+        expectedErrors: MessageKind.INVALID_CONSTANT_STRING_ADD_TYPE),
     const ConstantData('boolean + string', 'NonConstant',
-        MessageKind.INVALID_CONSTANT_STRING_ADD_TYPE),
-    const ConstantData(
-        'true + false', 'NonConstant', MessageKind.INVALID_CONSTANT_ADD_TYPES),
+        expectedErrors: MessageKind.INVALID_CONSTANT_STRING_ADD_TYPE),
+    const ConstantData('true + false', 'NonConstant',
+        expectedErrors: MessageKind.INVALID_CONSTANT_ADD_TYPES),
     const ConstantData('boolean + false', 'NonConstant',
-        MessageKind.INVALID_CONSTANT_ADD_TYPES),
+        expectedErrors: MessageKind.INVALID_CONSTANT_ADD_TYPES),
     const ConstantData('const [] == null', 'NonConstant',
-        MessageKind.INVALID_CONSTANT_BINARY_PRIMITIVE_TYPE),
+        expectedErrors: MessageKind.INVALID_CONSTANT_BINARY_PRIMITIVE_TYPE),
     const ConstantData('proxy == null', 'NonConstant',
-        MessageKind.INVALID_CONSTANT_BINARY_PRIMITIVE_TYPE),
-    const ConstantData(
-        '0 * ""', 'NonConstant', MessageKind.INVALID_CONSTANT_BINARY_NUM_TYPE),
+        expectedErrors: MessageKind.INVALID_CONSTANT_BINARY_PRIMITIVE_TYPE),
+    const ConstantData('0 * ""', 'NonConstant',
+        expectedErrors: MessageKind.INVALID_CONSTANT_BINARY_NUM_TYPE),
     const ConstantData('0 * string', 'NonConstant',
-        MessageKind.INVALID_CONSTANT_BINARY_NUM_TYPE),
-    const ConstantData(
-        '0 % ""', 'NonConstant', MessageKind.INVALID_CONSTANT_BINARY_NUM_TYPE),
+        expectedErrors: MessageKind.INVALID_CONSTANT_BINARY_NUM_TYPE),
+    const ConstantData('0 % ""', 'NonConstant',
+        expectedErrors: MessageKind.INVALID_CONSTANT_BINARY_NUM_TYPE),
     const ConstantData('0 % string', 'NonConstant',
-        MessageKind.INVALID_CONSTANT_BINARY_NUM_TYPE),
-    const ConstantData(
-        '0 << ""', 'NonConstant', MessageKind.INVALID_CONSTANT_BINARY_INT_TYPE),
+        expectedErrors: MessageKind.INVALID_CONSTANT_BINARY_NUM_TYPE),
+    const ConstantData('0 << ""', 'NonConstant',
+        expectedErrors: MessageKind.INVALID_CONSTANT_BINARY_INT_TYPE),
     const ConstantData('0 << string', 'NonConstant',
-        MessageKind.INVALID_CONSTANT_BINARY_INT_TYPE),
-    const ConstantData(
-        'null[0]', 'NonConstant', MessageKind.INVALID_CONSTANT_INDEX),
+        expectedErrors: MessageKind.INVALID_CONSTANT_BINARY_INT_TYPE),
+    const ConstantData('null[0]', 'NonConstant',
+        expectedErrors: MessageKind.INVALID_CONSTANT_INDEX),
     const ConstantData('const bool.fromEnvironment(0)', 'NonConstant',
-        MessageKind.INVALID_FROM_ENVIRONMENT_NAME_TYPE),
+        expectedErrors: MessageKind.INVALID_FROM_ENVIRONMENT_NAME_TYPE),
     const ConstantData('const bool.fromEnvironment(integer)', 'NonConstant',
-        MessageKind.INVALID_FROM_ENVIRONMENT_NAME_TYPE),
+        expectedErrors: MessageKind.INVALID_FROM_ENVIRONMENT_NAME_TYPE),
     const ConstantData(
-        'const bool.fromEnvironment("baz", defaultValue: 0)',
-        'NonConstant',
-        MessageKind.INVALID_BOOL_FROM_ENVIRONMENT_DEFAULT_VALUE_TYPE),
+        'const bool.fromEnvironment("baz", defaultValue: 0)', 'NonConstant',
+        expectedErrors:
+            MessageKind.INVALID_BOOL_FROM_ENVIRONMENT_DEFAULT_VALUE_TYPE),
     const ConstantData(
         'const bool.fromEnvironment("baz", defaultValue: integer)',
         'NonConstant',
-        MessageKind.INVALID_BOOL_FROM_ENVIRONMENT_DEFAULT_VALUE_TYPE),
+        expectedErrors:
+            MessageKind.INVALID_BOOL_FROM_ENVIRONMENT_DEFAULT_VALUE_TYPE),
     const ConstantData('const int.fromEnvironment(0)', 'NonConstant',
-        MessageKind.INVALID_FROM_ENVIRONMENT_NAME_TYPE),
+        expectedErrors: MessageKind.INVALID_FROM_ENVIRONMENT_NAME_TYPE),
     const ConstantData('const int.fromEnvironment(integer)', 'NonConstant',
-        MessageKind.INVALID_FROM_ENVIRONMENT_NAME_TYPE),
+        expectedErrors: MessageKind.INVALID_FROM_ENVIRONMENT_NAME_TYPE),
     const ConstantData(
-        'const int.fromEnvironment("baz", defaultValue: "")',
-        'NonConstant',
-        MessageKind.INVALID_INT_FROM_ENVIRONMENT_DEFAULT_VALUE_TYPE),
+        'const int.fromEnvironment("baz", defaultValue: "")', 'NonConstant',
+        expectedErrors:
+            MessageKind.INVALID_INT_FROM_ENVIRONMENT_DEFAULT_VALUE_TYPE),
     const ConstantData(
-        'const int.fromEnvironment("baz", defaultValue: string)',
-        'NonConstant',
-        MessageKind.INVALID_INT_FROM_ENVIRONMENT_DEFAULT_VALUE_TYPE),
+        'const int.fromEnvironment("baz", defaultValue: string)', 'NonConstant',
+        expectedErrors:
+            MessageKind.INVALID_INT_FROM_ENVIRONMENT_DEFAULT_VALUE_TYPE),
     const ConstantData('const String.fromEnvironment(0)', 'NonConstant',
-        MessageKind.INVALID_FROM_ENVIRONMENT_NAME_TYPE),
+        expectedErrors: MessageKind.INVALID_FROM_ENVIRONMENT_NAME_TYPE),
     const ConstantData('const String.fromEnvironment(integer)', 'NonConstant',
-        MessageKind.INVALID_FROM_ENVIRONMENT_NAME_TYPE),
+        expectedErrors: MessageKind.INVALID_FROM_ENVIRONMENT_NAME_TYPE),
     const ConstantData(
-        'const String.fromEnvironment("baz", defaultValue: 0)',
-        'NonConstant',
-        MessageKind.INVALID_STRING_FROM_ENVIRONMENT_DEFAULT_VALUE_TYPE),
+        'const String.fromEnvironment("baz", defaultValue: 0)', 'NonConstant',
+        expectedErrors:
+            MessageKind.INVALID_STRING_FROM_ENVIRONMENT_DEFAULT_VALUE_TYPE),
     const ConstantData(
         'const String.fromEnvironment("baz", defaultValue: integer)',
         'NonConstant',
-        MessageKind.INVALID_STRING_FROM_ENVIRONMENT_DEFAULT_VALUE_TYPE),
+        expectedErrors:
+            MessageKind.INVALID_STRING_FROM_ENVIRONMENT_DEFAULT_VALUE_TYPE),
     const ConstantData('true || 0', 'NonConstant',
-        MessageKind.INVALID_LOGICAL_OR_OPERAND_TYPE),
+        expectedErrors: MessageKind.INVALID_LOGICAL_OR_OPERAND_TYPE),
     const ConstantData('0 || true', 'NonConstant',
-        MessageKind.INVALID_LOGICAL_OR_OPERAND_TYPE),
+        expectedErrors: MessageKind.INVALID_LOGICAL_OR_OPERAND_TYPE),
     const ConstantData('true || integer', 'NonConstant',
-        MessageKind.INVALID_LOGICAL_OR_OPERAND_TYPE),
+        expectedErrors: MessageKind.INVALID_LOGICAL_OR_OPERAND_TYPE),
     const ConstantData('integer || true', 'NonConstant',
-        MessageKind.INVALID_LOGICAL_OR_OPERAND_TYPE),
+        expectedErrors: MessageKind.INVALID_LOGICAL_OR_OPERAND_TYPE),
     const ConstantData('true && 0', 'NonConstant',
-        MessageKind.INVALID_LOGICAL_AND_OPERAND_TYPE),
+        expectedErrors: MessageKind.INVALID_LOGICAL_AND_OPERAND_TYPE),
     const ConstantData('0 && true', 'NonConstant',
-        MessageKind.INVALID_LOGICAL_AND_OPERAND_TYPE),
+        expectedErrors: MessageKind.INVALID_LOGICAL_AND_OPERAND_TYPE),
     const ConstantData('integer && true', 'NonConstant',
-        MessageKind.INVALID_LOGICAL_AND_OPERAND_TYPE),
-    const ConstantData(
-        '!0', 'NonConstant', MessageKind.INVALID_CONSTANT_NOT_TYPE),
-    const ConstantData(
-        '!string', 'NonConstant', MessageKind.INVALID_CONSTANT_NOT_TYPE),
-    const ConstantData(
-        '-("")', 'NonConstant', MessageKind.INVALID_CONSTANT_NEGATE_TYPE),
-    const ConstantData(
-        '-(string)', 'NonConstant', MessageKind.INVALID_CONSTANT_NEGATE_TYPE),
+        expectedErrors: MessageKind.INVALID_LOGICAL_AND_OPERAND_TYPE),
+    const ConstantData('!0', 'NonConstant',
+        expectedErrors: MessageKind.INVALID_CONSTANT_NOT_TYPE),
+    const ConstantData('!string', 'NonConstant',
+        expectedErrors: MessageKind.INVALID_CONSTANT_NOT_TYPE),
+    const ConstantData('-("")', 'NonConstant',
+        expectedErrors: MessageKind.INVALID_CONSTANT_NEGATE_TYPE),
+    const ConstantData('-(string)', 'NonConstant',
+        expectedErrors: MessageKind.INVALID_CONSTANT_NEGATE_TYPE),
     const ConstantData('not_string.length', 'NonConstant',
-        MessageKind.INVALID_CONSTANT_STRING_LENGTH_TYPE),
+        expectedErrors: MessageKind.INVALID_CONSTANT_STRING_LENGTH_TYPE),
     const ConstantData('const Class1()', 'NonConstant',
-        MessageKind.INVALID_CONSTANT_STRING_LENGTH_TYPE),
+        expectedErrors: MessageKind.INVALID_CONSTANT_STRING_LENGTH_TYPE),
     const ConstantData('getter', 'NonConstant'),
-    const ConstantData(
-        'const Class2()', 'NonConstant', MessageKind.INVALID_ASSERT_VALUE),
+    const ConstantData('const Class2()', 'NonConstant',
+        expectedErrors: MessageKind.INVALID_ASSERT_VALUE),
     const ConstantData('const Class2.redirect()', 'NonConstant',
-        MessageKind.INVALID_ASSERT_VALUE),
+        expectedErrors: MessageKind.INVALID_ASSERT_VALUE),
     const ConstantData('const Class3()', 'NonConstant',
-        MessageKind.INVALID_ASSERT_VALUE_MESSAGE),
-    const ConstantData(
-        'const Class3.fact()', 'NonConstant', MessageKind.INVALID_ASSERT_VALUE),
-    const ConstantData(
-        'const Class4()', 'NonConstant', MessageKind.INVALID_ASSERT_VALUE),
+        expectedErrors: MessageKind.INVALID_ASSERT_VALUE_MESSAGE),
+    const ConstantData('const Class3.fact()', 'NonConstant',
+        expectedErrors: MessageKind.INVALID_ASSERT_VALUE),
+    const ConstantData('const Class4()', 'NonConstant',
+        expectedErrors: MessageKind.INVALID_ASSERT_VALUE),
     const ConstantData('const Class5(0)', 'NonConstant',
-        MessageKind.INVALID_ASSERT_VALUE_MESSAGE),
+        expectedErrors: MessageKind.INVALID_ASSERT_VALUE_MESSAGE),
     const ConstantData('const Class5(1)', 'ConstructedConstant(Class5())'),
     const ConstantData('const Class6(1)', 'NonConstant',
-        MessageKind.INVALID_ASSERT_VALUE_MESSAGE),
+        expectedErrors: MessageKind.INVALID_ASSERT_VALUE_MESSAGE),
     const ConstantData('const Class6(2)', 'ConstructedConstant(Class6())'),
   ]),
   const TestData('assert', '''
@@ -505,6 +525,31 @@
     const ConstantData(r'const D(0)',
         'ConstructedConstant(D(a=IntConstant(1),b=IntConstant(2)))'),
   ]),
+  const TestData(
+      'instantiations',
+      '''
+T identity<T>(T t) => t;
+class C<T> {
+  final T defaultValue;
+  final T Function(T t) identityFunction;
+
+  const C(this.defaultValue, this.identityFunction);
+}
+  ''',
+      const <ConstantData>[
+        const ConstantData('identity', 'FunctionConstant(identity)'),
+        const ConstantData(
+            'const C<int>(0, identity)',
+            'ConstructedConstant(C<int>(defaultValue=IntConstant(0),'
+            'identityFunction=InstantiationConstant([int],'
+            'FunctionConstant(identity))))'),
+        const ConstantData(
+            'const C<double>(0.5, identity)',
+            'ConstructedConstant(C<double>(defaultValue=DoubleConstant(0.5),'
+            'identityFunction=InstantiationConstant([double],'
+            'FunctionConstant(identity))))'),
+      ],
+      strongModeOnly: true)
 ];
 
 main(List<String> args) {
@@ -518,14 +563,20 @@
 
 Future testData(TestData data) async {
   StringBuffer sb = new StringBuffer();
-  sb.write('${data.declarations}\n');
+  sb.writeln('${data.declarations}');
   Map<String, ConstantData> constants = {};
+  List<String> names = <String>[];
   data.constants.forEach((ConstantData constantData) {
     String name = 'c${constants.length}';
-    sb.write('const $name = ${constantData.code};\n');
+    names.add(name);
+    sb.writeln('const $name = ${constantData.code};');
     constants[name] = constantData;
   });
-  sb.write('main() {}\n');
+  sb.writeln('main() {');
+  for (String name in names) {
+    sb.writeln('  print($name);');
+  }
+  sb.writeln('}');
   String source = sb.toString();
   print("--source '${data.name}'---------------------------------------------");
   print(source);
@@ -533,7 +584,8 @@
   Future runTest(
       List<String> options,
       EvaluationEnvironment getEnvironment(
-          Compiler compiler, FieldEntity field)) async {
+          Compiler compiler, FieldEntity field),
+      {bool strongMode: false}) async {
     CompilationResult result = await runCompiler(
         memorySourceFiles: {'main.dart': source}, options: options);
     Compiler compiler = result.compiler;
@@ -546,7 +598,8 @@
         ConstantExpression constant =
             elementEnvironment.getFieldConstant(field);
 
-        var expectedResults = data.expectedResults;
+        var expectedResults =
+            strongMode ? data.strongModeResults : data.expectedResults;
         if (expectedResults is String) {
           expectedResults = {const <String, String>{}: expectedResults};
         }
@@ -606,23 +659,42 @@
     'redirect',
   ];
 
-  if (!skipAstList.contains(data.name)) {
+  const skipStrongList = const [
+    // TODO(johnniwinther): Investigate why some types of the constructed
+    // objects don't match.
+    'redirect',
+    // TODO(johnniwinther): Investigate why different errors are reported in
+    // strong mode.
+    'errors',
+  ];
+
+  if (!skipAstList.contains(data.name) && !data.strongModeOnly) {
     print(
         '--test ast----------------------------------------------------------');
     await runTest(
-        [Flags.useOldFrontend, Flags.analyzeAll],
+        [Flags.useOldFrontend],
         (Compiler compiler, FieldEntity field) => new AstEvaluationEnvironment(
             compiler,
             constantRequired: field.isConst));
   }
-  if (!skipKernelList.contains(data.name)) {
+  if (!skipKernelList.contains(data.name) && !data.strongModeOnly) {
     print(
         '--test kernel-------------------------------------------------------');
-    await runTest([Flags.analyzeOnly], (Compiler compiler, FieldEntity field) {
+    await runTest([], (Compiler compiler, FieldEntity field) {
       KernelFrontEndStrategy frontendStrategy = compiler.frontendStrategy;
       KernelToElementMap elementMap = frontendStrategy.elementMap;
       return new KernelEvaluationEnvironment(elementMap, null, field,
           constantRequired: field.isConst);
     });
   }
+  if (!skipStrongList.contains(data.name)) {
+    print(
+        '--test kernel (strong mode)-----------------------------------------');
+    await runTest([Flags.strongMode], (Compiler compiler, FieldEntity field) {
+      KernelFrontEndStrategy frontendStrategy = compiler.frontendStrategy;
+      KernelToElementMap elementMap = frontendStrategy.elementMap;
+      return new KernelEvaluationEnvironment(elementMap, null, field,
+          constantRequired: field.isConst);
+    }, strongMode: true);
+  }
 }
diff --git a/tests/compiler/dart2js/model/constant_expression_test.dart b/tests/compiler/dart2js/model/constant_expression_test.dart
index 6babb67..efe465e 100644
--- a/tests/compiler/dart2js/model/constant_expression_test.dart
+++ b/tests/compiler/dart2js/model/constant_expression_test.dart
@@ -7,8 +7,9 @@
 import 'dart:async';
 import 'package:async_helper/async_helper.dart';
 import 'package:expect/expect.dart';
-import 'package:compiler/src/constants/expressions.dart';
+import 'package:compiler/src/commandline_options.dart';
 import 'package:compiler/src/compiler.dart';
+import 'package:compiler/src/constants/expressions.dart';
 import 'package:compiler/src/kernel/element_map_impl.dart';
 import 'package:compiler/src/elements/entities.dart';
 import '../memory_compiler.dart';
@@ -21,7 +22,10 @@
   /// Tested constants.
   final List<ConstantData> constants;
 
-  const TestData(this.declarations, this.constants);
+  final bool strongModeOnly;
+
+  const TestData(this.declarations, this.constants,
+      {this.strongModeOnly: false});
 }
 
 class ConstantData {
@@ -34,6 +38,9 @@
   /// ConstantExpression.getText() result if different from [code].
   final String text;
 
+  /// ConstantExpression.getText() result if different from [code].
+  final String strongText;
+
   /// The expected instance type for ConstructedConstantExpression.
   final String type;
 
@@ -41,9 +48,10 @@
   final Map<String, String> fields;
 
   const ConstantData(String code, this.kind,
-      {String text, this.type, this.fields})
+      {String text, String strongText, this.type, this.fields})
       : this.code = code,
-        this.text = text != null ? text : code;
+        this.text = text ?? code,
+        this.strongText = strongText ?? text ?? code;
 }
 
 const List<TestData> DATA = const [
@@ -56,7 +64,6 @@
     const ConstantData('"foo"', ConstantExpressionKind.STRING),
     const ConstantData('1 + 2', ConstantExpressionKind.BINARY),
     const ConstantData('1 == 2', ConstantExpressionKind.BINARY),
-    // TODO(sigmund): reenable (Issue 32511)
     const ConstantData('1 != 2', ConstantExpressionKind.UNARY,
         // a != b is encoded as !(a == b) by CFE.
         text: '!(1 == 2)'),
@@ -71,9 +78,11 @@
     const ConstantData('proxy', ConstantExpressionKind.FIELD),
     const ConstantData('Object', ConstantExpressionKind.TYPE),
     const ConstantData('#name', ConstantExpressionKind.SYMBOL),
-    const ConstantData('const [0, 1]', ConstantExpressionKind.LIST),
+    const ConstantData('const [0, 1]', ConstantExpressionKind.LIST,
+        strongText: 'const <int>[0, 1]'),
     const ConstantData('const <int>[0, 1]', ConstantExpressionKind.LIST),
-    const ConstantData('const {0: 1, 2: 3}', ConstantExpressionKind.MAP),
+    const ConstantData('const {0: 1, 2: 3}', ConstantExpressionKind.MAP,
+        strongText: 'const <int, int>{0: 1, 2: 3}'),
     const ConstantData(
         'const <int, int>{0: 1, 2: 3}', ConstantExpressionKind.MAP),
     const ConstantData('const bool.fromEnvironment("foo", defaultValue: false)',
@@ -157,7 +166,6 @@
     const ConstantData(
         'const A<int>(field1: 87)', ConstantExpressionKind.CONSTRUCTED,
         type: 'A<int>', fields: const {'field(A#field1)': '87'}),
-    // TODO(sigmund): reenable (Issue 32511)
     const ConstantData('const B()', ConstantExpressionKind.CONSTRUCTED,
         type: 'A<B<dynamic>>',
         fields: const {
@@ -197,25 +205,63 @@
         // Redirecting factories are replaced by their effective targets by CFE.
         text: 'const A<int>()'),
   ]),
+  const TestData('''
+T identity<T>(T t) => t;
+class C<T> {
+  final T defaultValue;
+  final T Function(T t) identityFunction;
+
+  const C(this.defaultValue, this.identityFunction);
+}
+  ''', const <ConstantData>[
+    const ConstantData('identity', ConstantExpressionKind.FUNCTION),
+    const ConstantData(
+        'const C<int>(0, identity)', ConstantExpressionKind.CONSTRUCTED,
+        type: 'C<int>', strongText: 'const C<int>(0, <int>(identity))'),
+    const ConstantData(
+        'const C<double>(0.5, identity)', ConstantExpressionKind.CONSTRUCTED,
+        type: 'C<double>',
+        strongText: 'const C<double>(0.5, <double>(identity))'),
+  ], strongModeOnly: true)
 ];
 
 main() {
-  asyncTest(() => Future.forEach(DATA, testData));
+  asyncTest(() async {
+    print('--test from kernel------------------------------------------------');
+    await runTest(strongMode: false);
+    print('--test from kernel (strong)---------------------------------------');
+    await runTest(strongMode: true);
+  });
 }
 
-Future testData(TestData data) async {
+Future runTest({bool strongMode}) async {
+  for (TestData data in DATA) {
+    await testData(data, strongMode: strongMode);
+  }
+}
+
+Future testData(TestData data, {bool strongMode}) async {
+  if (data.strongModeOnly && !strongMode) return;
+
   StringBuffer sb = new StringBuffer();
-  sb.write('${data.declarations}\n');
+  sb.writeln('${data.declarations}');
   Map<String, ConstantData> constants = {};
+  List<String> names = <String>[];
   data.constants.forEach((ConstantData constantData) {
     String name = 'c${constants.length}';
-    sb.write('const $name = ${constantData.code};\n');
+    names.add(name);
+    sb.writeln('const $name = ${constantData.code};');
     constants[name] = constantData;
   });
-  sb.write('main() {}\n');
+  sb.writeln('main() {');
+  for (String name in names) {
+    sb.writeln('  print($name);');
+  }
+  sb.writeln('}');
   String source = sb.toString();
   CompilationResult result = await runCompiler(
-      memorySourceFiles: {'main.dart': source}, options: ['--analyze-all']);
+      memorySourceFiles: {'main.dart': source},
+      options: strongMode ? [Flags.strongMode] : []);
   Compiler compiler = result.compiler;
   var elementEnvironment = compiler.frontendStrategy.elementEnvironment;
 
@@ -233,11 +279,12 @@
         constant.kind,
         "Unexpected kind '${constant.kind}' for constant "
         "`${constant.toDartText()}`, expected '${data.kind}'.");
+    String text = strongMode ? data.strongText : data.text;
     Expect.equals(
-        data.text,
+        text,
         constant.toDartText(),
         "Unexpected text '${constant.toDartText()}' for constant, "
-        "expected '${data.text}'.");
+        "expected '${text}'.");
     if (data.type != null) {
       String instanceType =
           constant.computeInstanceType(environment).toString();
diff --git a/tests/compiler/dart2js/old_frontend/mock_libraries.dart b/tests/compiler/dart2js/old_frontend/mock_libraries.dart
index a4e4158..f5f6e63 100644
--- a/tests/compiler/dart2js/old_frontend/mock_libraries.dart
+++ b/tests/compiler/dart2js/old_frontend/mock_libraries.dart
@@ -233,7 +233,10 @@
   'IrRepresentation': 'class IrRepresentation {}',
   'isJsIndexable': 'isJsIndexable(a, b) {}',
   'JavaScriptIndexingBehavior': 'abstract class JavaScriptIndexingBehavior {}',
-  'JSInvocationMirror': 'class JSInvocationMirror {}',
+  'JSInvocationMirror': r'''
+  class JSInvocationMirror {
+    get typeArguments => null;
+  }''',
   'listSuperNativeTypeCast': 'listSuperNativeTypeCast(value) {}',
   'listSuperNativeTypeCheck': 'listSuperNativeTypeCheck(value) {}',
   'listSuperTypeCast': 'listSuperTypeCast(value) {}',
diff --git a/tests/compiler/dart2js/rti/data/no_such_method1_strong.dart b/tests/compiler/dart2js/rti/data/no_such_method1_strong.dart
new file mode 100644
index 0000000..21ed9d8
--- /dev/null
+++ b/tests/compiler/dart2js/rti/data/no_such_method1_strong.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2018, 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:expect/expect.dart';
+
+class C {
+  /*element: C.noSuchMethod:selectors=[Selector(call, foo, arity=0, types=2)]*/
+  noSuchMethod(i) => i.typeArguments;
+}
+
+@NoInline()
+test(dynamic x) {
+  print(x.foo<int, String>());
+}
+
+main() {
+  test(new C());
+}
diff --git a/tests/compiler/dart2js/rti/data/no_such_method2_strong.dart b/tests/compiler/dart2js/rti/data/no_such_method2_strong.dart
new file mode 100644
index 0000000..6b39377
--- /dev/null
+++ b/tests/compiler/dart2js/rti/data/no_such_method2_strong.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2018, 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:expect/expect.dart';
+
+class C {
+  /*element: C.noSuchMethod:selectors=[Selector(call, foo, arity=0, types=2)]*/
+  noSuchMethod(i) => i.typeArguments;
+}
+
+class D {
+  /*element: D.foo:exp,needsArgs,selectors=[Selector(call, foo, arity=0, types=2)]*/
+  foo<U, V>() => [U, V];
+}
+
+@NoInline()
+test(dynamic x) {
+  print(x.foo<int, String>());
+}
+
+main() {
+  test(new C());
+  test(new D());
+}
diff --git a/tests/compiler/dart2js/rti/data/no_such_method3_strong.dart b/tests/compiler/dart2js/rti/data/no_such_method3_strong.dart
new file mode 100644
index 0000000..98883aa
--- /dev/null
+++ b/tests/compiler/dart2js/rti/data/no_such_method3_strong.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2018, 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:expect/expect.dart';
+
+class C {
+  /*element: C.noSuchMethod:*/
+  noSuchMethod(i) => null;
+}
+
+@NoInline()
+test(dynamic x) {
+  print(x.foo<int, String>());
+}
+
+main() {
+  test(new C());
+}
diff --git a/tests/compiler/dart2js/sourcemaps/data/invokes.dart b/tests/compiler/dart2js/sourcemaps/data/invokes.dart
index fa7bed0..53e84d3 100644
--- a/tests/compiler/dart2js/sourcemaps/data/invokes.dart
+++ b/tests/compiler/dart2js/sourcemaps/data/invokes.dart
@@ -122,7 +122,7 @@
   }
 
   invalidInvokes() {
-    // ignore: invocation_of_non_function
+    // ignore: not_enough_required_arguments
     C();
     // ignore: undefined_method
     dynamic();
diff --git a/tests/compiler/dart2js/sourcemaps/stacktrace/throw_in_async.dart b/tests/compiler/dart2js/sourcemaps/stacktrace/throw_in_async.dart
index b1cc65d..7ca81d3 100644
--- a/tests/compiler/dart2js/sourcemaps/stacktrace/throw_in_async.dart
+++ b/tests/compiler/dart2js/sourcemaps/stacktrace/throw_in_async.dart
@@ -11,5 +11,6 @@
 
 @NoInline()
 test() async {
+  await null;
   /*1:test*/ throw '>ExceptionMarker<';
 }
diff --git a/tests/compiler/dart2js/sourcemaps/stacktrace/throw_in_awaited_async.dart b/tests/compiler/dart2js/sourcemaps/stacktrace/throw_in_awaited_async.dart
index 47d2c2d..522bcf7 100644
--- a/tests/compiler/dart2js/sourcemaps/stacktrace/throw_in_awaited_async.dart
+++ b/tests/compiler/dart2js/sourcemaps/stacktrace/throw_in_awaited_async.dart
@@ -16,5 +16,6 @@
 
 @NoInline()
 test2() async {
+  await null;
   /*1:test2*/ throw '>ExceptionMarker<';
 }
diff --git a/tests/compiler/dart2js/sourcemaps/stacktrace/throw_in_constructor_from_async.dart b/tests/compiler/dart2js/sourcemaps/stacktrace/throw_in_constructor_from_async.dart
index 05db172..0120aa3 100644
--- a/tests/compiler/dart2js/sourcemaps/stacktrace/throw_in_constructor_from_async.dart
+++ b/tests/compiler/dart2js/sourcemaps/stacktrace/throw_in_constructor_from_async.dart
@@ -10,6 +10,7 @@
 }
 
 test() async {
+  await null;
   // ignore: UNUSED_LOCAL_VARIABLE
   var c = new /*1:test*/ Class();
 }
diff --git a/tests/compiler/dart2js/sourcemaps/stacktrace/throw_in_top_level_method_from_async.dart b/tests/compiler/dart2js/sourcemaps/stacktrace/throw_in_top_level_method_from_async.dart
index af5ea17..c172214 100644
--- a/tests/compiler/dart2js/sourcemaps/stacktrace/throw_in_top_level_method_from_async.dart
+++ b/tests/compiler/dart2js/sourcemaps/stacktrace/throw_in_top_level_method_from_async.dart
@@ -10,6 +10,7 @@
 
 @NoInline()
 test1() async {
+  await null;
   /*1:test1*/ test2();
 }
 
diff --git a/tests/compiler/dart2js_extra/27323_test.dart b/tests/compiler/dart2js_extra/27323_test.dart
new file mode 100644
index 0000000..8e2a919
--- /dev/null
+++ b/tests/compiler/dart2js_extra/27323_test.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2018, 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.
+
+// dart2jsOptions=--strong
+
+import 'package:expect/expect.dart';
+
+class C {
+  noSuchMethod(i) => i.typeArguments;
+}
+
+class D {
+  foo<U, V>() => [U, V];
+}
+
+@NoInline()
+test(dynamic x) {
+  dynamic typeArguments = x.foo<int, String>();
+  Expect.equals(int, typeArguments[0]);
+  Expect.equals(String, typeArguments[1]);
+}
+
+main() {
+  test(new C());
+  test(new D()); //# 01: ok
+}
diff --git a/tests/compiler/dart2js_extra/js_array_sort_default_test.dart b/tests/compiler/dart2js_extra/js_array_sort_default_test.dart
new file mode 100644
index 0000000..8f4e161
--- /dev/null
+++ b/tests/compiler/dart2js_extra/js_array_sort_default_test.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2018, 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.
+
+/// Tests that the default comparable function in JSArray.sort has a valid
+/// strong-mode type.
+void main() {
+  new List<dynamic>.from(['1', '2']).sort();
+}
diff --git a/tests/corelib_2/corelib_2.status b/tests/corelib_2/corelib_2.status
index ce101ae..6641868 100644
--- a/tests/corelib_2/corelib_2.status
+++ b/tests/corelib_2/corelib_2.status
@@ -613,5 +613,4 @@
 
 [ $hot_reload || $hot_reload_rollback ]
 bigint_parse_radix_test: Pass, Timeout # Issue 31659
-bigint_test: Pass, Crash # Issue 31660
 integer_parsed_mul_div_vm_test: Pass, Slow # Slow
diff --git a/tests/language/language.status b/tests/language/language.status
index 0916858..33b2122 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -12,11 +12,11 @@
 vm/regress_27201_test: SkipByDesign # Loads bad library, so will always crash.
 
 [ $compiler == precompiler ]
-deferred_global_test: Fail # Deferred loading happens eagerly. Issue #27587
+deferred_global_test: Skip # Deferred loading happens eagerly.
 deopt_inlined_function_lazy_test: Skip # Incompatible flag: --deoptimize-alot
 implicit_closure_test: Skip # Incompatible flag: --use_slow_path
 regress_23408_test: RuntimeError
-vm/regress_27201_test: Fail # Deferred loading happens eagerly. Issue #27587
+vm/regress_27201_test: Skip # Deferred loading happens eagerly.
 
 [ $mode == product ]
 assertion_test: SkipByDesign # Requires checked mode.
@@ -448,10 +448,10 @@
 redirecting_constructor_initializer_test: RuntimeError # Issue 23488
 
 [ $compiler == app_jit || $compiler == precompiler || $mode == product ]
-deferred_load_constants_test/02: Fail # Deferred loading happens eagerly. Issue #27587
-deferred_load_constants_test/03: Fail # Deferred loading happens eagerly. Issue #27587
-deferred_load_constants_test/05: Fail # Deferred loading happens eagerly. Issue #27587
-deferred_not_loaded_check_test: Fail # Deferred loading happens eagerly. Issue #27587
+deferred_load_constants_test/02: Skip # Deferred loading happens eagerly.
+deferred_load_constants_test/03: Skip # Deferred loading happens eagerly.
+deferred_load_constants_test/05: Skip # Deferred loading happens eagerly.
+deferred_not_loaded_check_test: Skip # Deferred loading happens eagerly.
 vm/regress_27201_test: Fail
 
 [ $compiler == app_jit || $runtime == dart_precompiled ]
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index 0453fe4..9a7255e 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -5,8 +5,11 @@
 [ $compiler != dart2analyzer ]
 switch_case_warn_test: Skip # Analyzer only, see language_analyzer2.status
 
-# VM specific tests that should not be run by dart2js.
 [ $compiler == dart2js ]
+async_await_test: RuntimeError # sync-async is on by default
+asyncstar_throw_in_catch_test: RuntimeError # sync-async is on by default
+await_nonfuture_test: RuntimeError # sync-async is on by default
+await_not_started_immediately_test: RuntimeError # sync-async is on by default
 full_stacktrace1_test: Pass, RuntimeError # Issue 12698
 full_stacktrace2_test: Pass, RuntimeError # Issue 12698
 full_stacktrace3_test: Pass, RuntimeError # Issue 12698
@@ -585,7 +588,6 @@
 
 [ $compiler == dart2js && $fasta && $host_checked ]
 async_test/setter1: Crash # 'file:*/pkg/compiler/lib/src/kernel/element_map_impl.dart': Failed assertion: line 939 pos 18: 'asyncMarker == AsyncMarker.SYNC': is not true.
-branches_test: Crash # 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart': Failed assertion: line 441 pos 16: 'identical(combiner.arguments.positional[0], rhs)': is not true.
 closure_self_reference_test: Crash # 'file:*/pkg/compiler/lib/src/ssa/nodes.dart': Failed assertion: line 641 pos 12: 'isClosed()': is not true.
 generic_methods_generic_function_parameter_test: Crash # 'file:*/pkg/compiler/lib/src/ssa/builder_kernel.dart': Failed assertion: line 1728 pos 16: 'type is MethodTypeVariableType': is not true.
 generic_methods_type_expression_test/01: Crash # 'file:*/pkg/compiler/lib/src/ssa/builder_kernel.dart': Failed assertion: line 1728 pos 16: 'type is MethodTypeVariableType': is not true.
@@ -593,8 +595,6 @@
 generic_methods_type_expression_test/none: Crash # 'file:*/pkg/compiler/lib/src/ssa/builder_kernel.dart': Failed assertion: line 1728 pos 16: 'type is MethodTypeVariableType': is not true.
 invocation_mirror_test: Crash # 'file:*/pkg/compiler/lib/src/ssa/builder_kernel.dart': Failed assertion: line 3014 pos 14: 'arguments.named.isEmpty': is not true.
 operator2_negative_test: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
-operator_test: Crash # 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart': Failed assertion: line 441 pos 16: 'identical(combiner.arguments.positional[0], rhs)': is not true.
-prefix5_negative_test: Crash # 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart': Failed assertion: line 441 pos 16: 'identical(combiner.arguments.positional[0], rhs)': is not true.
 sync_generator2_test/41: Crash # 'file:*/pkg/compiler/lib/src/kernel/element_map_impl.dart': Failed assertion: line 939 pos 18: 'asyncMarker == AsyncMarker.SYNC': is not true.
 sync_generator2_test/52: Crash # 'file:*/pkg/compiler/lib/src/kernel/element_map_impl.dart': Failed assertion: line 939 pos 18: 'asyncMarker == AsyncMarker.SYNC': is not true.
 syntax_test/04: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
diff --git a/tests/language/language_spec_parser.status b/tests/language/language_spec_parser.status
index 16dec52..5e35c74 100644
--- a/tests/language/language_spec_parser.status
+++ b/tests/language/language_spec_parser.status
@@ -19,7 +19,6 @@
 is_not_class4_negative_test: Fail # Negative, uses `a is A is A`.
 issue1578_negative_test: Fail # Negative, is line noise.
 issue_1751477_test: Skip # Times out: 9 levels, exponential blowup => 430 secs.
-label8_negative_test: Fail # Negative, uses misplaced label.
 list_literal_negative_test: Fail # Negative, uses `new List<int>[1, 2]`.
 map_literal_negative_test: Fail # Negative, uses `new Map<int>{..}`.
 new_expression1_negative_test: Fail # Negative, uses `new id`.
diff --git a/tests/language_2/break_outside_loop_test.dart b/tests/language_2/break_outside_loop_test.dart
new file mode 100644
index 0000000..5fab9e1
--- /dev/null
+++ b/tests/language_2/break_outside_loop_test.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2018, 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.
+// Dart test program to test check that we catch label errors.
+
+main() {
+  if (true) {
+    break; //# 01: compile-time error
+  }
+}
diff --git a/tests/language_2/label2_negative_test.dart b/tests/language_2/label2_negative_test.dart
deleted file mode 100644
index ab9d256..0000000
--- a/tests/language_2/label2_negative_test.dart
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright (c) 2011, 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.
-// Dart test program to test check that we catch label errors.
-
-
-class Label2NegativeTest {
-  static testMain() {
-    if (true) {
-      break; // Illegal: not embedded in a loop.
-    }
-  }
-}
-
-
-main() {
-  Label2NegativeTest.testMain();
-}
diff --git a/tests/language_2/label3_negative_test.dart b/tests/language_2/label3_negative_test.dart
deleted file mode 100644
index 56482ee..0000000
--- a/tests/language_2/label3_negative_test.dart
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2011, 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.
-// Dart test program to test check that we catch label errors.
-
-
-class Label3NegativeTest {
-  static testMain() {
-    L: while (false) {
-      if (true) break L; // Ok
-    }
-    continue L; // Illegal: L is out of scope.
-  }
-}
-
-
-main() {
-  Label3NegativeTest.testMain();
-}
diff --git a/tests/language_2/label3_test.dart b/tests/language_2/label3_test.dart
new file mode 100644
index 0000000..5685aab
--- /dev/null
+++ b/tests/language_2/label3_test.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2011, 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.
+
+main() {
+  L: while (false) {
+    if (true) break L; //# 01: ok
+  }
+  // Illegal: L is out of scope.
+  continue L; //# 02: compile-time error
+}
diff --git a/tests/language_2/label5_negative_test.dart b/tests/language_2/label5_negative_test.dart
deleted file mode 100644
index 520fbb44..0000000
--- a/tests/language_2/label5_negative_test.dart
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright (c) 2011, 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.
-// Dart test program to test check that we catch label errors.
-
-class Label5NegativeTest {
-  static testMain() {
-    var L = 33;
-    while (false) {
-      if (true) break L; // Illegal: L is not a label.
-    }
-  }
-}
-
-main() {
-  Label5NegativeTest.testMain();
-}
diff --git a/tests/language_2/label5_test.dart b/tests/language_2/label5_test.dart
new file mode 100644
index 0000000..2007cf4
--- /dev/null
+++ b/tests/language_2/label5_test.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2011, 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.
+
+main() {
+  var L = 33;
+  while (false) {
+    // Illegal: L is not a label.
+    if (true) break L; //# 01: compile-time error
+  }
+}
diff --git a/tests/language_2/label6_negative_test.dart b/tests/language_2/label6_negative_test.dart
deleted file mode 100644
index eee60ab2..0000000
--- a/tests/language_2/label6_negative_test.dart
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) 2011, 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.
-// Dart test program to test check that we catch label errors.
-
-class Label6NegativeTest {
-  static testMain() {
-    L:
-    while (false) {
-      break; //    ok;
-      break L; //  ok
-      void innerfunc() {
-        if (true) break L; // Illegal: jump target is outside of function
-      }
-
-      innerfunc();
-    }
-  }
-}
-
-main() {
-  Label6NegativeTest.testMain();
-}
diff --git a/tests/language_2/label6_test.dart b/tests/language_2/label6_test.dart
new file mode 100644
index 0000000..d46ca9b
--- /dev/null
+++ b/tests/language_2/label6_test.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2011, 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.
+
+main() {
+  L:
+  while (false) {
+    break; //# 01: ok
+    break L; //# 02: ok
+    void innerfunc() {
+      // Illegal: jump target is outside of function
+      if (true) break L; //# 03: compile-time error
+    }
+
+    innerfunc();
+  }
+}
diff --git a/tests/language_2/label8_negative_test.dart b/tests/language_2/label8_negative_test.dart
deleted file mode 100644
index ff35321..0000000
--- a/tests/language_2/label8_negative_test.dart
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2011, 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.
-// Labels aren't allowed in front of { for switch stmt
-
-
-class Label8NegativeTest {
-  static errorMethod() {
-    int i;
-    // grammar doesn't currently allow label on block for switch stmt.
-    switch(i) L: {
-      case 111:
-        while (doAgain()) {
-          break L;
-      }
-      i++;
-    }
-  }
-  static testMain() {
-    Label8NegativeTest.errorMethod();
-  }
-}
-
-
-main() {
-  Label8NegativeTest.testMain();
-}
diff --git a/tests/language_2/label8_test.dart b/tests/language_2/label8_test.dart
new file mode 100644
index 0000000..751d35b
--- /dev/null
+++ b/tests/language_2/label8_test.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2011, 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.
+
+main() {
+  int i;
+  // Grammar doesn't allow label on block for switch statement.
+  switch(i)
+    L: //# 01: compile-time error
+  {
+    case 111:
+      while (false) {
+        break L; //# 01: continued
+      }
+      i++;
+  }
+}
diff --git a/tests/language_2/language_2_analyzer.status b/tests/language_2/language_2_analyzer.status
index 55a2708..7bf5e3c 100644
--- a/tests/language_2/language_2_analyzer.status
+++ b/tests/language_2/language_2_analyzer.status
@@ -62,12 +62,6 @@
 is_not_class1_negative_test: CompileTimeError
 is_not_class4_negative_test: CompileTimeError
 issue1578_negative_test: CompileTimeError
-label2_negative_test: CompileTimeError
-label3_negative_test: CompileTimeError
-label5_negative_test: CompileTimeError
-label6_negative_test: CompileTimeError
-label8_negative_test: CompileTimeError
-library_negative_test: CompileTimeError
 list_literal2_negative_test: CompileTimeError
 list_literal_negative_test: CompileTimeError
 map_literal_negative_test: CompileTimeError
diff --git a/tests/language_2/language_2_dart2js.status b/tests/language_2/language_2_dart2js.status
index 7d81932..edb651c 100644
--- a/tests/language_2/language_2_dart2js.status
+++ b/tests/language_2/language_2_dart2js.status
@@ -282,7 +282,7 @@
 covariance_type_parameter_test/02: Crash # NoSuchMethodError: The method 'hasSubclass' was called on null.
 covariance_type_parameter_test/03: Crash # NoSuchMethodError: The method 'hasSubclass' was called on null.
 covariant_override/runtime_check_test: RuntimeError
-covariant_subtyping_test: CompileTimeError
+covariant_subtyping_test: RuntimeError
 cyclic_constructor_test/01: Crash # Stack Overflow
 deferred_constraints_constants_test/default_argument2: Crash # Unsupported operation: KernelDeferredLoadTask.addMirrorElementsForLibrary
 deferred_constraints_constants_test/none: Crash # Unsupported operation: KernelDeferredLoadTask.addMirrorElementsForLibrary
@@ -1038,7 +1038,6 @@
 bad_override_test/05: MissingCompileTimeError
 bit_operations_test: RuntimeError
 branch_canonicalization_test: RuntimeError
-branches_test: Crash # 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart': Failed assertion: line 441 pos 16: 'identical(combiner.arguments.positional[0], rhs)': is not true.
 call_method_implicit_tear_off_implements_function_test/02: RuntimeError
 call_method_implicit_tear_off_implements_function_test/04: RuntimeError
 call_method_implicit_tear_off_test/02: RuntimeError
@@ -1093,7 +1092,7 @@
 covariance_type_parameter_test/02: RuntimeError
 covariance_type_parameter_test/03: RuntimeError
 covariant_override/tear_off_type_test: RuntimeError
-covariant_subtyping_test: CompileTimeError
+covariant_subtyping_test: RuntimeError
 cyclic_constructor_test/01: Crash # Issue 30856
 cyclic_type_test/00: RuntimeError
 cyclic_type_test/02: RuntimeError
@@ -1413,7 +1412,6 @@
 number_identity2_test: RuntimeError
 numbers_test: RuntimeError, OK # non JS number semantics
 operator2_negative_test: Crash # 'file:*/pkg/compiler/lib/src/kernel/env.dart': Failed assertion: line 322 pos 16: '!name.contains('#')': is not true.
-operator_test: Crash # 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart': Failed assertion: line 441 pos 16: 'identical(combiner.arguments.positional[0], rhs)': is not true.
 overridden_no_such_method_test: RuntimeError
 override_field_method1_negative_test: Fail
 override_field_method2_negative_test: Fail
@@ -1446,7 +1444,6 @@
 partial_tearoff_instantiation_test/06: Crash # Assertion failure: kind=special,memberName=instantiate,callStructure:CallStructure(arity=0, types=1)
 partial_tearoff_instantiation_test/07: Crash # Assertion failure: kind=special,memberName=instantiate,callStructure:CallStructure(arity=0, types=1)
 partial_tearoff_instantiation_test/08: Crash # Assertion failure: kind=special,memberName=instantiate,callStructure:CallStructure(arity=0, types=1)
-prefix5_negative_test: Crash # 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart': Failed assertion: line 441 pos 16: 'identical(combiner.arguments.positional[0], rhs)': is not true.
 redirecting_factory_default_values_test/01: MissingCompileTimeError
 redirecting_factory_default_values_test/02: MissingCompileTimeError
 redirecting_factory_infinite_steps_test/01: MissingCompileTimeError
@@ -1716,7 +1713,7 @@
 covariance_type_parameter_test/02: RuntimeError
 covariance_type_parameter_test/03: RuntimeError
 covariant_override/tear_off_type_test: RuntimeError
-covariant_subtyping_test: CompileTimeError
+covariant_subtyping_test: RuntimeError
 cyclic_constructor_test/01: Crash # Issue 30856
 cyclic_type_variable_test/01: MissingCompileTimeError
 cyclic_type_variable_test/02: MissingCompileTimeError
@@ -2192,6 +2189,7 @@
 
 [ $compiler == dart2js && $fasta && $strong ]
 const_constructor3_test/04: MissingCompileTimeError # OK - Subtype check uses JS number semantics.
+covariant_subtyping_test: Crash
 ct_const_test: RuntimeError
 
 [ $compiler == dart2js && $fasta && !$strong ]
diff --git a/tests/language_2/language_2_dartdevc.status b/tests/language_2/language_2_dartdevc.status
index b611f55..47cd057 100644
--- a/tests/language_2/language_2_dartdevc.status
+++ b/tests/language_2/language_2_dartdevc.status
@@ -97,8 +97,6 @@
 issue31596_test: CompileTimeError
 issue32353_test: RuntimeError
 label_test: RuntimeError
-lazy_static3_test: RuntimeError # Issue 30852
-lazy_static8_test: RuntimeError # Issue 30852
 left_shift_test: RuntimeError # Ints and doubles are unified.
 library_env_test/has_io_support: RuntimeError # Intended to fail, bool.fromEnvironment("dart.library.async") is false
 library_env_test/has_mirror_support: RuntimeError # Intended to fail, bool.fromEnvironment("dart.library.async") is false
@@ -350,7 +348,7 @@
 constructor_redirect1_negative_test/01: MissingCompileTimeError
 constructor_redirect2_negative_test: MissingCompileTimeError
 constructor_redirect_test/01: MissingCompileTimeError
-covariant_subtyping_test: CompileTimeError
+covariant_subtyping_test: RuntimeError
 cyclic_constructor_test/01: MissingCompileTimeError
 cyclic_type_variable_test/01: MissingCompileTimeError
 cyclic_type_variable_test/02: MissingCompileTimeError
@@ -427,7 +425,6 @@
 issue31596_super_test/03: CompileTimeError
 issue31596_super_test/04: MissingCompileTimeError
 issue31596_super_test/05: RuntimeError
-issue32353_test: RuntimeError # Issue 32428
 library_env_test/has_io_support: RuntimeError # Unsupported operation: bool.fromEnvironment can only be used as a const constructor
 library_env_test/has_mirror_support: RuntimeError # Unsupported operation: bool.fromEnvironment can only be used as a const constructor
 library_env_test/has_no_html_support: RuntimeError # Unsupported operation: bool.fromEnvironment can only be used as a const constructor
@@ -518,7 +515,6 @@
 mixin_invalid_bound_test/08: MissingCompileTimeError
 mixin_invalid_bound_test/09: MissingCompileTimeError
 mixin_invalid_bound_test/10: MissingCompileTimeError
-mixin_regress_13688_test: RuntimeError # Issue 32427
 mixin_super_2_test/01: MissingCompileTimeError
 mixin_super_2_test/03: MissingCompileTimeError
 mixin_super_bound_test/01: MissingCompileTimeError
@@ -569,13 +565,11 @@
 override_inheritance_mixed_test/08: MissingCompileTimeError
 override_inheritance_mixed_test/09: MissingCompileTimeError
 override_method_with_field_test/01: MissingCompileTimeError
-recursive_mixin_test: RuntimeError # Issue 32428
 redirecting_factory_default_values_test/01: MissingCompileTimeError
 redirecting_factory_default_values_test/02: MissingCompileTimeError
 redirecting_factory_infinite_steps_test/01: MissingCompileTimeError
 redirecting_factory_malbounded_test/01: MissingCompileTimeError
 redirecting_factory_reflection_test: RuntimeError # UnimplementedError: node <InvalidExpression> `invalid-expression`
-regress_22666_test: RuntimeError # Issue 32427
 regress_23089_test: Crash # Crashes in KernelClassBuilder.buildTypeArguments
 regress_23408_test: CompileTimeError # Issue 31533
 regress_24283_test: RuntimeError # Expect.equals(expected: <-1>, actual: <4294967295>) fails.
@@ -583,7 +577,6 @@
 regress_29405_test: CompileTimeError # Issue 31402 Error: A value of type '#lib2::Foo' can't be assigned to a variable of type '(#lib2::Foo) → void'.
 regress_29784_test/01: MissingCompileTimeError
 regress_29784_test/02: MissingCompileTimeError
-regress_29949_test: RuntimeError # Issue 32429
 regress_30339_test: CompileTimeError
 regress_30339_test: RuntimeError # Uncaught Expect.isTrue(false) fails.
 setter4_test: MissingCompileTimeError
@@ -683,7 +676,6 @@
 ct_const_test: RuntimeError # Issue 2992; RangeError: Maximum call stack size exceeded
 custom_await_stack_trace_test: RuntimeError # Issue 29920; Uncaught Expect.equals(at index 0: Expected <Blah \x0ABloop\x0ABleep\x0A...>
 cyclic_type2_test: RuntimeError # Issue 29920; Uncaught ReferenceError: V is not defined
-cyclic_type_test/00: RuntimeError # Issue 32564: <dynamic> not printed.
 cyclic_type_test/02: RuntimeError # Issue 29920; Uncaught RangeError: Maximum call stack size exceeded
 cyclic_type_test/03: RuntimeError # Issue 29920; Uncaught ReferenceError: U is not defined
 cyclic_type_test/04: RuntimeError # Issue 29920; Uncaught ReferenceError: U is not defined
@@ -698,7 +690,6 @@
 exception_test: RuntimeError # DDC doesn't implement NullThrownError?; Expect.isTrue(false) fails.
 expect_test: RuntimeError # Issue 29920; Expect.identical did not fail
 f_bounded_quantification3_test: RuntimeError # Issue 29920; Uncaught Error: type arguments should not be null: (F1, F2) => {
-f_bounded_quantification4_test: RuntimeError # Issue 32564: <dynamic> not printed.
 field3_test/01: MissingCompileTimeError
 field_increment_bailout_test: RuntimeError # Issue 29920; UnimplementedError: JsInstanceMirror.delegate unimplemented
 field_initialization_order_test/none: RuntimeError # Expect.equals(expected: <b.a.ai.bi.>, actual: <b.bi.a.ai.>) fails.
@@ -727,8 +718,6 @@
 invocation_mirror_test: RuntimeError # Type 'NativeJavaScriptObject' is not a subtype of type 'int' in strong mode
 issue21159_test: RuntimeError # Issue 30701; TypeError: method.bind is not a function
 issue23244_test: RuntimeError # Issue 29920; Uncaught Unsupported operation: only top-level functions can be spawned.
-lazy_static3_test: RuntimeError # Issue 30852; Expect.equals(expected: <null>, actual: <499>) fails.
-lazy_static8_test: RuntimeError # Issue 30852; Expect.equals(expected: <42>, actual: <2>) fails.
 least_upper_bound_expansive_test/none: RuntimeError # 30908; Uncaught RangeError: Maximum call stack size exceeded
 left_shift_test: RuntimeError # Ints and doubles are unified.; Expect.equals(expected: <1>, actual: <-4294967295>) fails.
 library_env_test/has_html_support: RuntimeError # Issue 30907; Unsupported operation: bool.fromEnvironment can only be used as a const constructor
@@ -741,7 +730,6 @@
 many_overridden_no_such_method_test: RuntimeError # UnimplementedError: JsInstanceMirror.delegate unimplemented; UnimplementedError: JsInstanceMirror.delegate unimplemented
 method_override7_test/03: MissingCompileTimeError # Issue 30514
 mint_arithmetic_test: RuntimeError # Issue 29920; Expect.equals(expected: <4294967297>, actual: <1>) fails.
-mixin_mixin6_test: RuntimeError # Issue 32564: <dynamic> not printed.
 modulo_test: RuntimeError # Ints and doubles are unified.; Expect.throws fails: Did not throw
 multiline_newline_test/04: MissingCompileTimeError
 multiline_newline_test/04r: MissingCompileTimeError
diff --git a/tests/language_2/language_2_kernel.status b/tests/language_2/language_2_kernel.status
index 52eae2d..3e8a0a8 100644
--- a/tests/language_2/language_2_kernel.status
+++ b/tests/language_2/language_2_kernel.status
@@ -13,6 +13,7 @@
 [ $compiler == dartkp ]
 class_cycle_test/02: MissingCompileTimeError
 class_cycle_test/03: MissingCompileTimeError
+covariant_subtyping_test: RuntimeError
 duplicate_implements_test/01: MissingCompileTimeError
 duplicate_implements_test/02: MissingCompileTimeError
 generic_methods_generic_function_result_test/01: MissingCompileTimeError
@@ -82,7 +83,6 @@
 constructor_redirect1_negative_test/01: MissingCompileTimeError
 constructor_redirect2_negative_test: MissingCompileTimeError
 constructor_redirect_test/01: MissingCompileTimeError # Fasta bug: Initializer refers to this.
-covariant_subtyping_test: CompileTimeError
 cyclic_constructor_test/01: MissingCompileTimeError # Fasta bug: Cyclic constructor redirection.
 cyclic_type_variable_test/01: MissingCompileTimeError
 cyclic_type_variable_test/02: MissingCompileTimeError
@@ -572,6 +572,7 @@
 const_string_test: RuntimeError
 constructor12_test: RuntimeError
 constructor3_test: Fail, OK, Pass
+covariant_subtyping_test: RuntimeError
 ct_const2_test: Pass, Crash # Flaky
 ct_const_test: RuntimeError
 cyclic_type2_test: RuntimeError, CompileTimeError
@@ -717,6 +718,7 @@
 assertion_initializer_const_error2_test/cc09: MissingCompileTimeError # Not reporting failed assert() at compile time.
 assertion_initializer_const_error2_test/cc10: MissingCompileTimeError # Not reporting failed assert() at compile time.
 assertion_initializer_const_error2_test/cc11: MissingCompileTimeError # Not reporting failed assert() at compile time.
+covariant_subtyping_test: RuntimeError
 redirecting_factory_reflection_test: RuntimeError
 
 # Enabling of dartk for sim{arm,arm64,dbc64} revelaed these test failures, which
@@ -931,7 +933,6 @@
 for_in_side_effects_test/01: MissingCompileTimeError
 function_propagation_test: RuntimeError
 function_subtype_inline2_test: RuntimeError
-function_type_alias6_test/none: RuntimeError
 generic_instanceof2_test: RuntimeError
 generic_is_check_test: RuntimeError
 generic_methods_recursive_bound_test/03: Crash, Pass
diff --git a/tests/language_2/language_2_precompiled.status b/tests/language_2/language_2_precompiled.status
index 8ff6cb8..a771e2d 100644
--- a/tests/language_2/language_2_precompiled.status
+++ b/tests/language_2/language_2_precompiled.status
@@ -247,7 +247,7 @@
 covariant_subtyping_tearoff1_test: RuntimeError
 covariant_subtyping_tearoff2_test: RuntimeError
 covariant_subtyping_tearoff3_test: RuntimeError
-covariant_subtyping_test: CompileTimeError
+covariant_subtyping_test: RuntimeError
 covariant_subtyping_unsafe_call1_test: RuntimeError
 covariant_subtyping_unsafe_call2_test: RuntimeError
 covariant_subtyping_unsafe_call3_test: RuntimeError
diff --git a/tests/language_2/language_2_spec_parser.status b/tests/language_2/language_2_spec_parser.status
index e223c59..7788992 100644
--- a/tests/language_2/language_2_spec_parser.status
+++ b/tests/language_2/language_2_spec_parser.status
@@ -35,12 +35,6 @@
 is_not_class4_negative_test: Fail # Negative, uses `a is A is A`.
 issue1578_negative_test: Fail # Negative, is line noise.
 issue_1751477_test: Skip # Times out: 9 levels, exponential blowup => 430 secs.
-label2_negative_test: Skip # Negative, not syntax.
-label3_negative_test: Skip # Negative, not syntax.
-label5_negative_test: Skip # Negative, not syntax.
-label6_negative_test: Skip # Negative, not syntax.
-label8_negative_test: Fail # Negative, uses misplaced label.
-library_negative_test: Skip # Negative, not syntax.
 list_literal2_negative_test: Skip # Negative, not syntax.
 list_literal_negative_test: Fail # Negative, uses `new List<int>[1, 2]`.
 map_literal2_negative_test: Skip # Negative, not syntax.
diff --git a/tests/language_2/language_2_vm.status b/tests/language_2/language_2_vm.status
index 8e3a8e3..8b95fdf9 100644
--- a/tests/language_2/language_2_vm.status
+++ b/tests/language_2/language_2_vm.status
@@ -1335,6 +1335,7 @@
 generic_methods_generic_function_parameter_test: Pass # Issue 25869
 generic_methods_new_test: Pass # Issue 25869
 generic_methods_test: Pass # Issue 25869
+library_test/01: MissingCompileTimeError
 nosuchmethod_forwarding/nosuchmethod_forwarding_arguments_test: RuntimeError
 nosuchmethod_forwarding/nosuchmethod_forwarding_test/05: RuntimeError
 nosuchmethod_forwarding/nosuchmethod_forwarding_test/06: RuntimeError
diff --git a/tests/language_2/library_negative_test.dart b/tests/language_2/library_negative_test.dart
deleted file mode 100644
index e15b159..0000000
--- a/tests/language_2/library_negative_test.dart
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-// This test should fail to load because the app file references a
-// library spec file that does not exist.
-
-library LibraryNegativeTest.dart;
-
-import "nonexisting_library.lib";
-
-main(args) {
-  LibraryNegativeTest.testMain(args);
-}
-
-class LibraryNegativeTest {
-  static testMain() {
-    print("Er, hello world? This should not be printed!");
-  }
-}
-
-main() {
-  LibraryNegativeTest.testMain();
-}
diff --git a/tests/language_2/library_test.dart b/tests/language_2/library_test.dart
new file mode 100644
index 0000000..6dd7428
--- /dev/null
+++ b/tests/language_2/library_test.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2011, 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 "nonexistent_library.dart"; //# 01: compile-time error
+
+main() {
+  print("Er, hello world? This should not be printed!");
+}
diff --git a/tests/language_2/mixin_and_extension_member_test.dart b/tests/language_2/mixin_and_extension_member_test.dart
index 8565366..3f96a4a 100644
--- a/tests/language_2/mixin_and_extension_member_test.dart
+++ b/tests/language_2/mixin_and_extension_member_test.dart
@@ -27,6 +27,6 @@
 main() {
   List x = new ListMock();
   x.add(42);
-  Expect.equals(x[0], 42);
-  Expect.equals(x.first, 9999);
+  Expect.equals(42, x[0]);
+  Expect.equals(9999, x.first);
 }
diff --git a/tests/language_2/redirecting_factory_reflection_test.dart b/tests/language_2/redirecting_factory_reflection_test.dart
index b1ae524..cf5d60b 100644
--- a/tests/language_2/redirecting_factory_reflection_test.dart
+++ b/tests/language_2/redirecting_factory_reflection_test.dart
@@ -18,5 +18,7 @@
 main() {
   ClassMirror m = reflectClass(A);
   var i = m.newInstance(Symbol.empty, []).reflectee;
-  Expect.equals(i.t.toString(), 'A');
+  var s = i.t.toString();
+  Expect.isTrue(s == 'A' || s == 'A<dynamic>',
+      'mirrors should create the correct reified generic type');
 }
diff --git a/tests/language_2/type_literal_test.dart b/tests/language_2/type_literal_test.dart
index 94e3750..37e59d1 100644
--- a/tests/language_2/type_literal_test.dart
+++ b/tests/language_2/type_literal_test.dart
@@ -19,6 +19,8 @@
   Type get typeArg => T;
 }
 
+class G<A, B> {}
+
 typedef int Func(bool b);
 typedef int GenericFunc<T>(T t);
 
@@ -36,14 +38,16 @@
   testType(Foo, "Foo");
 
   // Generic classes.
-  testType(Box, "Box");
+  testType(Box, "Box", "<dynamic>");
   testType(new Box<Foo>().typeArg, "Foo");
   testType(new Box<dynamic>().typeArg, "dynamic");
   testType(new Box<Box<Foo>>().typeArg, "Box<Foo>");
+  testType(G, "G", "<dynamic, dynamic>");
+  testType(new Box<G<int, String>>().typeArg, "G<int, String>");
 
   // Typedef.
   testType(Func, "Func");
-  testType(GenericFunc, "GenericFunc");
+  testType(GenericFunc, "GenericFunc", "<dynamic>");
   testType(new Box<GenericFunc<int>>().typeArg, "GenericFunc<int>");
 
   // Literals are canonicalized.
@@ -66,7 +70,15 @@
   Expect.equals("result", prefix.Foo.method());
 }
 
-void testType(Type type, String string) {
-  Expect.equals(string, type.toString());
+void testType(Type type, String string, [String genericArgs]) {
+  if (genericArgs != null) {
+    var s = type.toString();
+    Expect.isTrue(
+        s == string || s == '$string$genericArgs',
+        'type `$type`.toString() should be `$string`, '
+        'optionally with $genericArgs suffix.');
+  } else {
+    Expect.equals(string, type.toString());
+  }
   Expect.isTrue(type is Type);
 }
diff --git a/tests/language_2/vm/regress_32971_test.dart b/tests/language_2/vm/regress_32971_test.dart
new file mode 100644
index 0000000..6f5863b
--- /dev/null
+++ b/tests/language_2/vm/regress_32971_test.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2018, 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.
+
+// Test verifying that default switch cast is cloned correctly by the
+// mixin transformation.
+
+import "package:expect/expect.dart";
+
+void main() {
+  final o = new A();
+  Expect.isTrue(o.f());
+  Expect.isTrue(o.g());
+}
+
+class A extends B with M {}
+
+class B {
+  bool f() {
+    switch (true) {
+      default:
+        return true;
+    }
+    return false;
+  }
+}
+
+class M {
+  bool g() {
+    switch (true) {
+      default:
+        return true;
+    }
+    return false;
+  }
+}
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index 45b680a..7a7c744 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -15,6 +15,7 @@
 *: Skip
 
 [ $compiler == dart2js ]
+async/async_await_sync_completer_test: RuntimeError # sync-async is on by default.
 async/schedule_microtask6_test: RuntimeError # global error handling is not supported. Issue 5958
 convert/base64_test/01: Fail, OK # Uses bit-wise operations to detect invalid values. Some large invalid values accepted by dart2js.
 convert/chunked_conversion_utf88_test: Slow, Pass
diff --git a/tests/lib_2/lib_2_analyzer.status b/tests/lib_2/lib_2_analyzer.status
index f79c3c3..8a7efd5 100644
--- a/tests/lib_2/lib_2_analyzer.status
+++ b/tests/lib_2/lib_2_analyzer.status
@@ -20,6 +20,9 @@
 [ $compiler == dart2analyzer && !$preview_dart_2 ]
 mirrors/metadata_nested_constructor_call_test/none: CompileTimeError
 
+[ $compiler == dart2analyzer && !$preview_dart_2 && !$strong ]
+mirrors/metadata_allowed_values_test/16: MissingCompileTimeError
+
 [ $compiler == dart2analyzer && $strong ]
 mirrors/deferred_mirrors_metadata_test: StaticWarning # Issue 28969
 mirrors/deferred_type_test: CompileTimeError, OK # Deliberately refers to a deferred type in a declaration.
@@ -37,6 +40,7 @@
 mirrors/generic_bounded_test/02: MissingCompileTimeError
 mirrors/generic_interface_test/01: MissingCompileTimeError
 mirrors/generics_test/01: MissingCompileTimeError
+mirrors/metadata_allowed_values_test/16: MissingCompileTimeError
 mirrors/redirecting_factory_different_type_test/01: MissingCompileTimeError
 mirrors/reflect_class_test/01: MissingCompileTimeError
 mirrors/reflect_class_test/02: MissingCompileTimeError
diff --git a/tests/lib_2/lib_2_dartdevc.status b/tests/lib_2/lib_2_dartdevc.status
index 1d2d4a3..4e43310 100644
--- a/tests/lib_2/lib_2_dartdevc.status
+++ b/tests/lib_2/lib_2_dartdevc.status
@@ -15,7 +15,6 @@
 convert/codec1_test: RuntimeError
 convert/utf82_test: RuntimeError
 html/debugger_test: CompileTimeError
-js/prototype_access_test: RuntimeError
 
 [ $runtime == chrome && ($compiler == dartdevc || $compiler == dartdevk) ]
 html/element_animate_test/timing_dict: RuntimeError # Issue 29922
diff --git a/tests/standalone/app_snapshot_share_test.dart b/tests/standalone/app_snapshot_share_test.dart
new file mode 100644
index 0000000..3e80c75
--- /dev/null
+++ b/tests/standalone/app_snapshot_share_test.dart
@@ -0,0 +1,94 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:io";
+
+void main(List<String> args) {
+  if (args.contains("--child")) {
+    print("Hello, sharing world!");
+    return;
+  }
+
+  if (!Platform.executable.endsWith("dart_precompiled_runtime")) {
+    return; // Running in JIT or Windows: AOT binaries not available.
+  }
+
+  if (Platform.isAndroid) {
+    return; // SDK tree and dart_bootstrap not available on the test device.
+  }
+
+  var buildDir =
+      Platform.executable.substring(0, Platform.executable.lastIndexOf('/'));
+  var tempDir = Directory.systemTemp.createTempSync("app-shared");
+  var snapshot1Path = tempDir.uri.resolve("hello1.snapshot").toFilePath();
+  var snapshot2Path = tempDir.uri.resolve("hello2.snapshot").toFilePath();
+  var scriptPath = new Directory(buildDir)
+      .uri
+      .resolve("../../tests/standalone/app_snapshot_share_test.dart")
+      .toFilePath();
+
+  var exec = "$buildDir/dart_bootstrap";
+  args = new List<String>();
+  args.add("--deterministic");
+  args.add("--use-blobs");
+  args.add("--snapshot-kind=app-aot");
+  args.add("--snapshot=$snapshot1Path");
+  args.add(scriptPath);
+  print("+ $exec $args");
+  var result = Process.runSync(exec, args);
+  print("Exit code: ${result.exitCode}");
+  print("stdout:");
+  print(result.stdout);
+  print("stderr:");
+  print(result.stderr);
+  if (result.exitCode != 0) {
+    throw "Bad exit code";
+  }
+
+  exec = "$buildDir/dart_bootstrap";
+  args = new List<String>();
+  args.add("--deterministic");
+  args.add("--use-blobs");
+  args.add("--snapshot-kind=app-aot");
+  args.add("--snapshot=$snapshot2Path");
+  args.add("--shared-blobs=$snapshot1Path");
+  args.add(scriptPath);
+  print("+ $exec $args");
+  result = Process.runSync(exec, args);
+  print("Exit code: ${result.exitCode}");
+  print("stdout:");
+  print(result.stdout);
+  print("stderr:");
+  print(result.stderr);
+  if (result.exitCode != 0) {
+    throw "Bad exit code";
+  }
+
+  var sizeWithoutSharing = new File(snapshot1Path).statSync().size;
+  var deltaWhenSharing = new File(snapshot2Path).statSync().size;
+  print("sizeWithoutSharing: $sizeWithoutSharing");
+  print("deltaWhenSharing: $deltaWhenSharing");
+  if (deltaWhenSharing >= sizeWithoutSharing) {
+    throw "Sharing did not shrink size";
+  }
+
+  exec = "$buildDir/dart_precompiled_runtime";
+  args = new List<String>();
+  args.add("--shared-blobs=$snapshot1Path");
+  args.add(snapshot2Path);
+  args.add("--child");
+  print("+ $exec $args");
+  result = Process.runSync(exec, args);
+  print("Exit code: ${result.exitCode}");
+  print("stdout:");
+  print(result.stdout);
+  print("stderr:");
+  print(result.stderr);
+  if (result.exitCode != 0) {
+    throw "Bad exit code";
+  }
+  if (!result.stdout.contains("Hello, sharing world!")) {
+    throw "Missing output";
+  }
+}
diff --git a/tests/standalone_2/app_snapshot_share_test.dart b/tests/standalone_2/app_snapshot_share_test.dart
new file mode 100644
index 0000000..f623875
--- /dev/null
+++ b/tests/standalone_2/app_snapshot_share_test.dart
@@ -0,0 +1,94 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:io";
+
+void main(List<String> args) {
+  if (args.contains("--child")) {
+    print("Hello, sharing world!");
+    return;
+  }
+
+  if (!Platform.executable.endsWith("dart_precompiled_runtime")) {
+    return; // Running in JIT or Windows: AOT binaries not available.
+  }
+
+  if (Platform.isAndroid) {
+    return; // SDK tree and dart_bootstrap not available on the test device.
+  }
+
+  var buildDir =
+      Platform.executable.substring(0, Platform.executable.lastIndexOf('/'));
+  var tempDir = Directory.systemTemp.createTempSync("app-shared");
+  var snapshot1Path = tempDir.uri.resolve("hello1.snapshot").toFilePath();
+  var snapshot2Path = tempDir.uri.resolve("hello2.snapshot").toFilePath();
+  var scriptPath = new Directory(buildDir)
+      .uri
+      .resolve("../../tests/standalone_2/app_snapshot_share_test.dart")
+      .toFilePath();
+
+  var exec = "$buildDir/dart_bootstrap";
+  args = new List<String>();
+  args.add("--deterministic");
+  args.add("--use-blobs");
+  args.add("--snapshot-kind=app-aot");
+  args.add("--snapshot=$snapshot1Path");
+  args.add(scriptPath);
+  print("+ $exec $args");
+  var result = Process.runSync(exec, args);
+  print("Exit code: ${result.exitCode}");
+  print("stdout:");
+  print(result.stdout);
+  print("stderr:");
+  print(result.stderr);
+  if (result.exitCode != 0) {
+    throw "Bad exit code";
+  }
+
+  exec = "$buildDir/dart_bootstrap";
+  args = new List<String>();
+  args.add("--deterministic");
+  args.add("--use-blobs");
+  args.add("--snapshot-kind=app-aot");
+  args.add("--snapshot=$snapshot2Path");
+  args.add("--shared-blobs=$snapshot1Path");
+  args.add(scriptPath);
+  print("+ $exec $args");
+  result = Process.runSync(exec, args);
+  print("Exit code: ${result.exitCode}");
+  print("stdout:");
+  print(result.stdout);
+  print("stderr:");
+  print(result.stderr);
+  if (result.exitCode != 0) {
+    throw "Bad exit code";
+  }
+
+  var sizeWithoutSharing = new File(snapshot1Path).statSync().size;
+  var deltaWhenSharing = new File(snapshot2Path).statSync().size;
+  print("sizeWithoutSharing: $sizeWithoutSharing");
+  print("deltaWhenSharing: $deltaWhenSharing");
+  if (deltaWhenSharing >= sizeWithoutSharing) {
+    throw "Sharing did not shrink size";
+  }
+
+  exec = "$buildDir/dart_precompiled_runtime";
+  args = new List<String>();
+  args.add("--shared-blobs=$snapshot1Path");
+  args.add(snapshot2Path);
+  args.add("--child");
+  print("+ $exec $args");
+  result = Process.runSync(exec, args);
+  print("Exit code: ${result.exitCode}");
+  print("stdout:");
+  print(result.stdout);
+  print("stderr:");
+  print(result.stderr);
+  if (result.exitCode != 0) {
+    throw "Bad exit code";
+  }
+  if (!result.stdout.contains("Hello, sharing world!")) {
+    throw "Missing output";
+  }
+}
diff --git a/tools/VERSION b/tools/VERSION
index 5c6fbcc..0a3d56d 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 0
 PATCH 0
-PRERELEASE 50
+PRERELEASE 51
 PRERELEASE_PATCH 0
diff --git a/tools/observatory_tool.py b/tools/observatory_tool.py
index 654f1f6..28be29b 100755
--- a/tools/observatory_tool.py
+++ b/tools/observatory_tool.py
@@ -8,18 +8,17 @@
 import os
 import platform
 import shutil
-import socket
 import subprocess
 import sys
 import utils
 
 SCRIPT_DIR = os.path.dirname(sys.argv[0])
 DART_ROOT = os.path.realpath(os.path.join(SCRIPT_DIR, '..'))
-PUB_PATH = os.path.join(DART_ROOT, 'third_party', 'pkg',
-                        'pub', 'bin', 'pub.dart')
+DART2JS_PATH = os.path.join(DART_ROOT, 'pkg', 'compiler', 'bin', 'dart2js.dart')
 IGNORE_PATTERNS = shutil.ignore_patterns(
     '$sdk',
     '*.concat.js',
+    '*.dart',
     '*.log',
     '*.map',
     '*.precompiled.js',
@@ -49,7 +48,7 @@
 
 https://github.com/dart-lang/sdk/wiki/The-checked-in-SDK-in-tools
 
-To use the dart_bootstrap binary please update the PubCommand function
+To use the dart_bootstrap binary please update the Build function
 in the tools/observatory_tool.py script.
 
 """
@@ -70,17 +69,8 @@
 # True, and return the return code.
 def RunCommand(command, always_silent=False):
   try:
-    # Dart IO respects the following environment variables to configure the
-    # HttpClient proxy: https://api.dartlang.org/stable/1.22.1/dart-io/HttpClient/findProxyFromEnvironment.html
-    # We strip these to avoid problems with pub build and transformers.
-    no_http_proxy_env = os.environ.copy()
-    no_http_proxy_env.pop('http_proxy', None)
-    no_http_proxy_env.pop('HTTP_PROXY', None)
-    no_http_proxy_env.pop('https_proxy', None)
-    no_http_proxy_env.pop('HTTPS_PROXY', None)
     subprocess.check_output(command,
-                            stderr=subprocess.STDOUT,
-                            env=no_http_proxy_env)
+                            stderr=subprocess.STDOUT)
     return 0
   except subprocess.CalledProcessError as e:
     if not always_silent:
@@ -89,23 +79,15 @@
       DisplayFailureMessage()
     return e.returncode
 
-def CreateTimestampFile(options):
-  if options.stamp != '':
-    dir_name = os.path.dirname(options.stamp)
-    if dir_name != '':
-      if not os.path.exists(dir_name):
-        os.mkdir(dir_name)
-    open(options.stamp, 'w').close()
-
 def BuildArguments():
   result = argparse.ArgumentParser(usage=usage)
   result.add_argument("--dart-executable", help="dart executable", default=None)
-  result.add_argument("--pub-executable", help="pub executable", default=None)
+  result.add_argument("--dart2js-executable", help="dart2js executable",
+                      default=None)
   result.add_argument("--directory", help="observatory root", default=None)
-  result.add_argument("--command", help="[get, build, deploy]", default=None)
+  result.add_argument("--command", help="[build, deploy]", default=None)
   result.add_argument("--silent", help="silence all output", default=None)
   result.add_argument("--sdk", help="Use prebuilt sdk", default=None)
-  result.add_argument("--stamp", help="Write a stamp file", default='')
   return result
 
 def ProcessOptions(options, args):
@@ -130,113 +112,97 @@
   if options.command is None or options.directory is None:
     return False
 
-  # Set a default value for pub_snapshot.
-  options.pub_snapshot = None
-
-  # If we have a working pub executable, try and use that.
-  # TODO(whesse): Drop the pub-executable option if it isn't used.
-  if options.pub_executable is not None:
+  # If a dart2js execuble was provided, try and use that.
+  # TODO(whesse): Drop the dart2js-executable option if it isn't used.
+  if options.dart2js_executable is not None:
     try:
-      if 0 == RunCommand([options.pub_executable, '--version'],
+      if 0 == RunCommand([options.dart2js_executable, '--version'],
                          always_silent=True):
         return True
     except OSError as e:
       pass
-  options.pub_executable = None
+  options.dart2js_executable = None
 
+  # Use the checked in dart2js executable.
   if options.sdk and utils.CheckedInSdkCheckExecutable():
-    # Use the checked in pub executable.
-    options.pub_snapshot = os.path.join(utils.CheckedInSdkPath(),
-                                        'bin',
-                                        'snapshots',
-                                        'pub.dart.snapshot');
+    dart2js_binary = 'dart2js.bat' if utils.IsWindows() else 'dart2js'
+    options.dart2js_executable = os.path.join(utils.CheckedInSdkPath(),
+                                             'bin',
+                                             dart2js_binary)
     try:
-      if 0 == RunCommand([utils.CheckedInSdkExecutable(),
-                          options.pub_snapshot,
-                          '--version'], always_silent=True):
+      if 0 == RunCommand([options.dart2js_executable, '--version'],
+                         always_silent=True):
         return True
     except OSError as e:
       pass
-  options.pub_snapshot = None
+  options.dart2js_executable = None
 
-  # We need a dart executable.
+  # We need a dart executable and will run from source
   return (options.dart_executable is not None)
 
 def ChangeDirectory(directory):
   os.chdir(directory);
 
-def PubCommand(dart_executable,
-               pub_executable,
-               pub_snapshot,
-               command,
-               silent):
-  if pub_executable is not None:
-    executable = [pub_executable]
-  elif pub_snapshot is not None:
-    executable = [utils.CheckedInSdkExecutable(), pub_snapshot]
+# - Copy over the filtered web directory
+# - Merge in the .js file
+# - Copy over the filtered dependency lib directories
+# - Copy over the filtered observatory package
+def Deploy(output_dir, web_dir, observatory_lib, js_file, pub_packages_dir):
+  shutil.rmtree(output_dir)
+  os.makedirs(output_dir)
+
+  output_web_dir = os.path.join(output_dir, 'web')
+  shutil.copytree(web_dir, output_web_dir, ignore=IGNORE_PATTERNS)
+  os.utime(os.path.join(output_web_dir, 'index.html'), None)
+
+  shutil.copy(js_file, output_web_dir)
+
+  packages_dir = os.path.join(output_web_dir, 'packages')
+  os.makedirs(packages_dir)
+  for subdir in os.listdir(pub_packages_dir):
+    libdir = os.path.join(pub_packages_dir, subdir, 'lib')
+    if os.path.isdir(libdir):
+      shutil.copytree(libdir, os.path.join(packages_dir, subdir),
+                      ignore=IGNORE_PATTERNS)
+  shutil.copytree(observatory_lib, os.path.join(packages_dir, 'observatory'),
+                  ignore=IGNORE_PATTERNS)
+
+def Build(dart_executable,
+          dart2js_executable,
+          script_path,
+          output_path,
+          packages_path,
+          silent):
+  if dart2js_executable is not None:
+    command = [dart2js_executable]
   else:
     if not silent:
       DisplayBootstrapWarning()
-    executable = [dart_executable, PUB_PATH]
-    # Prevent the bootstrap Dart executable from running in regular
-    # development flow.
-    # REMOVE THE FOLLOWING LINE TO USE the dart_bootstrap binary.
-    # return False
+    command = [dart_executable, DART2JS_PATH]
+  command += ['-DOBS_VER=' + utils.GetVersion(no_git_hash=True)]
+  command += [script_path, '-o', output_path, '--packages=%s' % packages_path]
+  # Add the defaults pub used
+  command += ['--minify']
   if not silent:
-    print >> sys.stderr, ('Running command "%s"') % (executable + command)
-  return RunCommand(executable + command)
-
-def Deploy(input_dir, output_dir):
-  shutil.rmtree(output_dir)
-  shutil.copytree(input_dir, output_dir, ignore=IGNORE_PATTERNS)
-  index_file = os.path.join(output_dir, 'web', 'index.html')
-  os.utime(index_file, None)
-  return 0
-
-def RewritePubSpec(input_path, output_path, search, replace):
-  with open(input_path, 'rb') as input_file:
-    input_data = input_file.read()
-    input_data = input_data.replace(search, replace)
-    with open(output_path, 'wb+') as output_file:
-      output_file.write(input_data)
+    print >> sys.stderr, 'Running command "%s"' % command
+  return RunCommand(command)
 
 def ExecuteCommand(options, args):
   cmd = options.command
-  if (cmd == 'get'):
-    # Always remove pubspec.lock before running 'pub get'.
-    try:
-      os.remove('pubspec.lock');
-    except OSError as e:
-      pass
-    return PubCommand(options.dart_executable,
-                      options.pub_executable,
-                      options.pub_snapshot,
-                      ['get', '--offline'],
-                      options.silent)
-  elif (cmd == 'build'):
-    return PubCommand(options.dart_executable,
-                      options.pub_executable,
-                      options.pub_snapshot,
-                      ['build',
-                       '-DOBS_VER=' + utils.GetVersion(no_git_hash=True),
-                       '--output', args[0]],
-                      options.silent)
+  if (cmd == 'build'):
+    return Build(options.dart_executable,
+                 options.dart2js_executable,
+                 args[0],
+                 args[1],
+                 args[2],
+                 options.silent)
   elif (cmd == 'deploy'):
-    Deploy('build', 'deployed')
-  elif (cmd == 'rewrite'):
-    RewritePubSpec(args[0], args[1], args[2], args[3])
+    Deploy(args[0], args[1], args[2], args[3], args[4])
   else:
     print >> sys.stderr, ('ERROR: command "%s" not supported') % (cmd)
     return -1;
 
 def main():
-  # Sanity check that localhost can be resolved.
-  try:
-    socket.gethostbyname('localhost')
-  except:
-    print("The hostname 'localhost' could not be resolved. Please fix your"
-          "/etc/hosts file and try again")
-    return -1
   # Parse the options.
   parser = BuildArguments()
   (options, args) = parser.parse_known_args()
@@ -246,24 +212,16 @@
   # Calculate absolute paths before changing directory.
   if (options.dart_executable != None):
     options.dart_executable = os.path.abspath(options.dart_executable)
-  if (options.pub_executable != None):
-    options.pub_executable = os.path.abspath(options.pub_executable)
-  if (options.pub_snapshot != None):
-    options.pub_snapshot = os.path.abspath(options.pub_snapshot)
-  if (options.stamp != ''):
-    options.stamp = os.path.abspath(options.stamp)
+  if (options.dart2js_executable != None):
+    options.dart2js_executable = os.path.abspath(options.dart2js_executable)
   if len(args) == 1:
     args[0] = os.path.abspath(args[0])
   try:
     # Pub must be run from the project's root directory.
     ChangeDirectory(options.directory)
-    result = ExecuteCommand(options, args)
-    if result == 0:
-      CreateTimestampFile(options)
-    return result
+    return ExecuteCommand(options, args)
   except:
     DisplayFailureMessage()
 
-
 if __name__ == '__main__':
   sys.exit(main());
diff --git a/tools/testing/dart/compiler_configuration.dart b/tools/testing/dart/compiler_configuration.dart
index 0b7c602..0b5b805 100644
--- a/tools/testing/dart/compiler_configuration.dart
+++ b/tools/testing/dart/compiler_configuration.dart
@@ -1004,6 +1004,8 @@
     }
     if (_isStrong) {
       arguments.add('--strong');
+    } else {
+      arguments.add('--no-strong');
     }
 
     // Since this is not a real compilation, no artifacts are produced.
diff --git a/tools/testing/dart/multitest.dart b/tools/testing/dart/multitest.dart
index ed10d09..f918d98 100644
--- a/tools/testing/dart/multitest.dart
+++ b/tools/testing/dart/multitest.dart
@@ -281,11 +281,10 @@
   }
 }
 
-// Find all relative imports and copy them into the dir that contains
-// the generated tests.
+/// Finds all relative imports and copies them into the directory with the
+/// generated tests.
 Set<String> _findAllRelativeImports(Path topLibrary) {
-  var toSearch = [topLibrary].toSet();
-  var foundImports = new Set<String>();
+  var found = new Set<String>();
   var libraryDir = topLibrary.directoryPath;
   var relativeImportRegExp = new RegExp(
       '^(?:@.*\\s+)?' // Allow for a meta-data annotation.
@@ -294,36 +293,36 @@
       '(?!(dart:|dart-ext:|data:|package:|/))' // Look-ahead: not in package.
       '([^"\']*)' // The path to the imported file.
       '["\']');
-  while (!toSearch.isEmpty) {
-    var thisPass = toSearch;
-    toSearch = new Set<Path>();
-    for (var filename in thisPass) {
-      var f = new File(filename.toNativePath());
-      for (var line in f.readAsLinesSync()) {
-        var match = relativeImportRegExp.firstMatch(line);
 
-        if (match != null) {
-          var relativePath = new Path(match.group(3));
-          if (foundImports.contains(relativePath.toString())) {
-            continue;
-          }
+  processFile(Path filePath) {
+    var file = new File(filePath.toNativePath());
+    for (var line in file.readAsLinesSync()) {
+      var match = relativeImportRegExp.firstMatch(line);
+      if (match == null) continue;
+      var relativePath = match.group(3);
 
-          if (relativePath.toString().contains('..')) {
-            // This is just for safety reasons, we don't want
-            // to unintentionally clobber files relative to the destination
-            // dir when copying them over.
-            print("relative paths containing '..' are not allowed.");
-            exit(1);
-          }
+      // If a multitest deliberately imports a non-existent file, don't try to
+      // include it.
+      if (relativePath.contains("nonexistent")) continue;
 
-          foundImports.add(relativePath.toString());
-          toSearch.add(libraryDir.join(relativePath));
-        }
+      // Handle import cycles.
+      if (!found.add(relativePath)) continue;
+
+      if (relativePath.contains("..")) {
+        // This is just for safety reasons, we don't want to unintentionally
+        // clobber files relative to the destination dir when copying them
+        // over.
+        print("Relative import in multitest containing '..' is not allowed.");
+        exit(1);
       }
+
+      processFile(libraryDir.append(relativePath));
     }
   }
 
-  return foundImports;
+  processFile(topLibrary);
+
+  return found;
 }
 
 String _suiteNameFromPath(Path suiteDir) {
diff --git a/tools/testing/dart/options.dart b/tools/testing/dart/options.dart
index 93f6d44..f20dbfd 100644
--- a/tools/testing/dart/options.dart
+++ b/tools/testing/dart/options.dart
@@ -166,11 +166,8 @@
         'Only run tests that are not marked `Slow` or `Timeout`.'),
     new _Option.bool('enable_asserts',
         'Pass the --enable-asserts flag to dart2js or to the vm.'),
-    new _Option.bool(
-        'no-preview_dart_2', 'Pass the --no-preview-dart-2 flag to analyzer.',
-        hide: true),
-    new _Option.bool(
-        'preview_dart_2', 'Pass the --preview-dart-2 flag to analyzer.',
+    new _Option.bool('preview_dart_2',
+        'Pass the --preview-dart-2 flag to analyzer, or pass --no-preview-dart-2 if false.',
         hide: true),
     // TODO(sigmund): replace dart2js_with_kernel with preview-dart-2.
     new _Option.bool(
@@ -644,7 +641,7 @@
                 isVerbose: data["verbose"] as bool,
                 listTests: data["list"] as bool,
                 listStatusFiles: data["list_status_files"] as bool,
-                noPreviewDart2: data["no-preview_dart_2"] as bool,
+                noPreviewDart2: !(data["preview_dart_2"] as bool),
                 previewDart2: data["preview_dart_2"] as bool,
                 printTiming: data["time"] as bool,
                 printReport: data["report"] as bool,