Version 2.0.0-dev.63.0

Merge '84f077842bb9736e398a71d2af6a0f65527b9878' into dev
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d84689d..beb9682 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,29 @@
+## 2.0.0-dev.XX.0
+(Add new changes here, and they will be copied to the
+ change section for the next dev version)
+
+### Language
+
+#### Strong Mode
+
+### Dart VM
+
+### Tool Changes
+
+#### Pub
+
+#### Other Tools
+
+### Core library changes
+
+## 2.0.0-dev.63.0
+
+### Tool Changes
+
+#### Pub
+
+* Fix an error which prevented `pub publish` due to the package validation.
+
 ## 2.0.0-dev.62.0
 
 ### Language
diff --git a/DEPS b/DEPS
index a7da2e0..94230ce 100644
--- a/DEPS
+++ b/DEPS
@@ -94,7 +94,7 @@
   "intl_tag": "0.15.2",
   "jinja2_rev": "2222b31554f03e62600cd7e383376a7c187967a1",
   "json_rpc_2_tag": "2.0.6",
-  "linter_tag": "0.1.52",
+  "linter_tag": "0.1.53",
   "logging_tag": "0.11.3+1",
   "markdown_tag": "2.0.0",
   "matcher_tag": "0.12.1+4",
@@ -110,7 +110,7 @@
   "ply_rev": "604b32590ffad5cbb82e4afef1d305512d06ae93",
   "pool_tag": "1.3.4",
   "protobuf_tag": "0.7.1",
-  "pub_rev": "881a0c3fbe63af07dd043b3f5e6cbe74eacb377c",
+  "pub_rev": "8b9526c915bf21627a20cd0104cb6c2be25a879f",
   "pub_semver_tag": "1.4.1",
   "quiver_tag": "5aaa3f58c48608af5b027444d561270b53f15dbf",
   "resource_rev":"af5a5bf65511943398146cf146e466e5f0b95cb9",
diff --git a/docs/language/dartLangSpec.tex b/docs/language/dartLangSpec.tex
index f06888f..aa78dff 100644
--- a/docs/language/dartLangSpec.tex
+++ b/docs/language/dartLangSpec.tex
@@ -56,6 +56,8 @@
 % - Introduce `subterm` and `immediate subterm`.
 % - Introduce `top type`.
 % - Specify configurable imports.
+% - Specify the dynamic type of the Iterable/Future/Stream returned from
+%   invocations of functions marked sync*/async/async*.
 %
 % 1.15
 % - Change how language specification describes control flow.
@@ -4907,7 +4909,13 @@
 }
 
 \LMHash{}
-If $f$ is marked \SYNC* (\ref{functions}), then a fresh instance $i$ implementing the built-in class \code{Iterable} is associated with the invocation and immediately returned.
+If $f$ is marked \SYNC* (\ref{functions}),
+then a fresh instance (\ref{generativeConstructors}) $i$
+implementing \code{Iterable<$U$>} is immediately returned,
+where $U$ is determined as follows:
+Let $T$ be the actual return type of $f$ (\ref{actualTypeOfADeclaration}).
+If $T$ is \code{Iterable<$S$>} for some type $S$, then $U$ is $S$,
+otherwise $U$ is \code{Object}.
 
 \commentary{
 A Dart implementation will need to provide a specific implementation of \code{Iterable} that will be returned by \SYNC* methods.
@@ -4957,7 +4965,10 @@
 % The alternative would be to cache the results of an iterator in the iterable, and check the cache at each \YIELD{}.  This would have strange issues as well. The yielded value might differ from the expression in the yield. And it is a potential memory leak as the cache is kept alive by any iterator.
 
 \LMHash{}
-If $f$ is marked \ASYNC{} (\ref{functions}), then a fresh instance (\ref{generativeConstructors}) $o$ implementing the built-in class \code{Future} is associated with the invocation.
+If $f$ is marked \ASYNC{} (\ref{functions}),
+then a fresh instance (\ref{generativeConstructors}) $o$ is associated with the invocation,
+where the dynamic type of $o$ implements \code{Future<$flatten(T)$>},
+and $T$ is the actual return type of $f$ (\ref{actualTypeOfADeclaration}).
 Then the body of $f$ is executed until it either suspends or completes, at which point $o$ is returned.
 \commentary{
 The body of $f$ may suspend during the evaluation of an \AWAIT{} expression or execution of an asynchronous \FOR{} loop.
@@ -4976,7 +4987,13 @@
 }
 
 \LMHash{}
-If $f$ is marked \ASYNC* (\ref{functions}), then a fresh instance $s$ implementing the built-in class \code{Stream} is associated with the invocation and immediately returned.
+If $f$ is marked \ASYNC* (\ref{functions}),
+then a fresh instance (\ref{generativeConstructors}) $s$
+implementing \code{Stream<$U$>} is immediately returned,
+where $U$ is determined as follows:
+Let $T$ be the actual return type of $f$ (\ref{actualTypeOfADeclaration}).
+If $T$ is \code{Stream<$S$>} for some type $S$, then $U$ is $S$,
+otherwise $U$ is \code{Object}.
 When $s$ is listened to, execution of the body of $f$ will begin.
 When execution of the body of $f$ completes:
 \begin{itemize}
diff --git a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
index 8fd931b..52473f1 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
@@ -1404,8 +1404,6 @@
   }
 
   Future<Null> _addProposal_flutterConvertToStatefulWidget() async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     ClassDeclaration widgetClass =
         node.getAncestor((n) => n is ClassDeclaration);
     TypeName superclass = widgetClass?.extendsClause?.superclass;
@@ -1447,27 +1445,93 @@
     String widgetName = widgetClassElement.displayName;
     String stateName = widgetName + 'State';
 
-    var buildLinesRange = utils.getLinesRange(range.node(buildMethod));
-    var buildText = utils.getRangeText(buildLinesRange);
+    // Find fields assigned in constructors.
+    var fieldsAssignedInConstructors = new Set<FieldElement>();
+    for (var member in widgetClass.members) {
+      if (member is ConstructorDeclaration) {
+        member.accept(new _SimpleIdentifierRecursiveAstVisitor((node) {
+          if (node.parent is FieldFormalParameter) {
+            Element element = node.staticElement;
+            if (element is FieldFormalParameterElement) {
+              fieldsAssignedInConstructors.add(element.field);
+            }
+          }
+          if (node.parent is ConstructorFieldInitializer) {
+            Element element = node.staticElement;
+            if (element is FieldElement) {
+              fieldsAssignedInConstructors.add(element);
+            }
+          }
+          if (node.inSetterContext()) {
+            Element element = node.staticElement;
+            if (element is PropertyAccessorElement) {
+              PropertyInducingElement field = element.variable;
+              if (field is FieldElement) {
+                fieldsAssignedInConstructors.add(field);
+              }
+            }
+          }
+        }));
+      }
+    }
 
-    // Update the build() text to insert `widget.` before references to
-    // the widget class members.
-    final List<SourceEdit> buildTextEdits = [];
-    buildMethod.body.accept(new _SimpleIdentifierRecursiveAstVisitor((node) {
-      if (node.staticElement?.enclosingElement == widgetClassElement) {
-        var offset = node.offset - buildLinesRange.offset;
-        AstNode parent = node.parent;
-        if (parent is InterpolationExpression &&
-            parent.leftBracket.type ==
-                TokenType.STRING_INTERPOLATION_IDENTIFIER) {
-          buildTextEdits.add(new SourceEdit(offset, 0, '{widget.'));
-          buildTextEdits.add(new SourceEdit(offset + node.length, 0, '}'));
-        } else {
-          buildTextEdits.add(new SourceEdit(offset, 0, 'widget.'));
+    // Prepare nodes to move.
+    var nodesToMove = new Set<ClassMember>();
+    var elementsToMove = new Set<Element>();
+    for (var member in widgetClass.members) {
+      if (member is FieldDeclaration && !member.isStatic) {
+        for (VariableDeclaration fieldNode in member.fields.variables) {
+          FieldElement fieldElement = fieldNode.element;
+          if (!fieldsAssignedInConstructors.contains(fieldElement)) {
+            nodesToMove.add(member);
+            elementsToMove.add(fieldElement);
+            elementsToMove.add(fieldElement.getter);
+            if (fieldElement.setter != null) {
+              elementsToMove.add(fieldElement.setter);
+            }
+          }
         }
       }
-    }));
-    buildText = SourceEdit.applySequence(buildText, buildTextEdits.reversed);
+      if (member is MethodDeclaration && !member.isStatic) {
+        nodesToMove.add(member);
+        elementsToMove.add(member.element);
+      }
+    }
+
+    /// Return the code for the [movedNode] which is suitable to be used
+    /// inside the `State` class, so that references to the widget fields and
+    /// methods, that are not moved, are qualified with the corresponding
+    /// instance `widget.`, or static `MyWidgetClass.` qualifier.
+    String rewriteWidgetMemberReferences(AstNode movedNode) {
+      var linesRange = utils.getLinesRange(range.node(movedNode));
+      var text = utils.getRangeText(linesRange);
+
+      // Insert `widget.` before references to the widget instance members.
+      final List<SourceEdit> edits = [];
+      movedNode.accept(new _SimpleIdentifierRecursiveAstVisitor((node) {
+        if (node.inDeclarationContext()) {
+          return;
+        }
+        var element = node.staticElement;
+        if (element is ExecutableElement &&
+            element?.enclosingElement == widgetClassElement &&
+            !elementsToMove.contains(element)) {
+          var offset = node.offset - linesRange.offset;
+          var qualifier = element.isStatic ? widgetName : 'widget';
+
+          AstNode parent = node.parent;
+          if (parent is InterpolationExpression &&
+              parent.leftBracket.type ==
+                  TokenType.STRING_INTERPOLATION_IDENTIFIER) {
+            edits.add(new SourceEdit(offset, 0, '{$qualifier.'));
+            edits.add(new SourceEdit(offset + node.length, 0, '}'));
+          } else {
+            edits.add(new SourceEdit(offset, 0, '$qualifier.'));
+          }
+        }
+      }));
+      return SourceEdit.applySequence(text, edits.reversed);
+    }
 
     var statefulWidgetClass = await sessionHelper.getClass(
         flutter.WIDGETS_LIBRARY_URI, 'StatefulWidget');
@@ -1480,23 +1544,94 @@
 
     DartChangeBuilder changeBuilder = new DartChangeBuilder(session);
     await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) async {
-      // TODO(brianwilkerson) Determine whether this await is necessary.
-      await null;
       builder.addReplacement(range.node(superclass), (builder) {
         builder.writeType(statefulWidgetClass.type);
       });
-      builder.addReplacement(buildLinesRange, (builder) {
-        builder.writeln('  @override');
-        builder.writeln('  $stateName createState() {');
-        builder.writeln('    return new $stateName();');
-        builder.writeln('  }');
-      });
+
+      int replaceOffset = 0;
+      bool hasBuildMethod = false;
+
+      /// Replace code between [replaceOffset] and [replaceEnd] with
+      /// `createState()`, empty line, or nothing.
+      void replaceInterval(int replaceEnd,
+          {bool replaceWithEmptyLine: false,
+          bool hasEmptyLineBeforeCreateState: false,
+          bool hasEmptyLineAfterCreateState: true}) {
+        int replaceLength = replaceEnd - replaceOffset;
+        builder.addReplacement(
+          new SourceRange(replaceOffset, replaceLength),
+          (builder) {
+            if (hasBuildMethod) {
+              if (hasEmptyLineBeforeCreateState) {
+                builder.writeln();
+              }
+              builder.writeln('  @override');
+              builder.writeln('  $stateName createState() {');
+              builder.writeln('    return new $stateName();');
+              builder.writeln('  }');
+              if (hasEmptyLineAfterCreateState) {
+                builder.writeln();
+              }
+              hasBuildMethod = false;
+            } else if (replaceWithEmptyLine) {
+              builder.writeln();
+            }
+          },
+        );
+        replaceOffset = 0;
+      }
+
+      // Remove continuous ranges of lines of nodes being moved.
+      bool lastToRemoveIsField = false;
+      int endOfLastNodeToKeep = 0;
+      for (var node in widgetClass.members) {
+        if (nodesToMove.contains(node)) {
+          if (replaceOffset == 0) {
+            var linesRange = utils.getLinesRange(range.node(node));
+            replaceOffset = linesRange.offset;
+          }
+          if (node == buildMethod) {
+            hasBuildMethod = true;
+          }
+          lastToRemoveIsField = node is FieldDeclaration;
+        } else {
+          var linesRange = utils.getLinesRange(range.node(node));
+          endOfLastNodeToKeep = linesRange.end;
+          if (replaceOffset != 0) {
+            replaceInterval(linesRange.offset,
+                replaceWithEmptyLine:
+                    lastToRemoveIsField && node is! FieldDeclaration);
+          }
+        }
+      }
+
+      // Remove nodes at the end of the widget class.
+      if (replaceOffset != 0) {
+        // Remove from the last node to keep, so remove empty lines.
+        if (endOfLastNodeToKeep != 0) {
+          replaceOffset = endOfLastNodeToKeep;
+        }
+        replaceInterval(widgetClass.rightBracket.offset,
+            hasEmptyLineBeforeCreateState: endOfLastNodeToKeep != 0,
+            hasEmptyLineAfterCreateState: false);
+      }
+
+      // Create the State subclass.
       builder.addInsertion(widgetClass.end, (builder) {
         builder.writeln();
         builder.writeln();
         builder.writeClassDeclaration(stateName, superclass: stateType,
             membersWriter: () {
-          builder.write(buildText);
+          bool writeEmptyLine = false;
+          for (var member in nodesToMove) {
+            if (writeEmptyLine) {
+              builder.writeln();
+            }
+            String text = rewriteWidgetMemberReferences(member);
+            builder.write(text);
+            // Write empty lines between members, but not before the first.
+            writeEmptyLine = true;
+          }
         });
       });
     });
diff --git a/pkg/analysis_server/test/services/correction/assist_test.dart b/pkg/analysis_server/test/services/correction/assist_test.dart
index 986c6ae..e165000 100644
--- a/pkg/analysis_server/test/services/correction/assist_test.dart
+++ b/pkg/analysis_server/test/services/correction/assist_test.dart
@@ -3058,6 +3058,314 @@
 ''');
   }
 
+  test_flutterConvertToStatefulWidget_OK_empty() async {
+    addFlutterPackage();
+    await resolveTestUnit(r'''
+import 'package:flutter/material.dart';
+
+class /*caret*/MyWidget extends StatelessWidget {
+  @override
+  Widget build(BuildContext context) {
+    return new Container();
+  }
+}
+''');
+    _setCaretLocation();
+    await assertHasAssist(
+        DartAssistKind.FLUTTER_CONVERT_TO_STATEFUL_WIDGET, r'''
+import 'package:flutter/material.dart';
+
+class /*caret*/MyWidget extends StatefulWidget {
+  @override
+  MyWidgetState createState() {
+    return new MyWidgetState();
+  }
+}
+
+class MyWidgetState extends State<MyWidget> {
+  @override
+  Widget build(BuildContext context) {
+    return new Container();
+  }
+}
+''');
+  }
+
+  test_flutterConvertToStatefulWidget_OK_fields() async {
+    addFlutterPackage();
+    await resolveTestUnit(r'''
+import 'package:flutter/material.dart';
+
+class /*caret*/MyWidget extends StatelessWidget {
+  static String staticField1;
+  final String instanceField1;
+  final String instanceField2;
+  String instanceField3;
+  static String staticField2;
+  String instanceField4;
+  String instanceField5;
+  static String staticField3;
+
+  MyWidget(this.instanceField1) : instanceField2 = '' {
+    instanceField3 = '';
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    instanceField4 = instanceField1;
+    return new Row(
+      children: [
+        new Text(instanceField1),
+        new Text(instanceField2),
+        new Text(instanceField3),
+        new Text(instanceField4),
+        new Text(instanceField5),
+        new Text(staticField1),
+        new Text(staticField2),
+        new Text(staticField3),
+      ],
+    );
+  }
+}
+''');
+    _setCaretLocation();
+    await assertHasAssist(
+        DartAssistKind.FLUTTER_CONVERT_TO_STATEFUL_WIDGET, r'''
+import 'package:flutter/material.dart';
+
+class /*caret*/MyWidget extends StatefulWidget {
+  static String staticField1;
+  final String instanceField1;
+  final String instanceField2;
+  String instanceField3;
+  static String staticField2;
+  static String staticField3;
+
+  MyWidget(this.instanceField1) : instanceField2 = '' {
+    instanceField3 = '';
+  }
+
+  @override
+  MyWidgetState createState() {
+    return new MyWidgetState();
+  }
+}
+
+class MyWidgetState extends State<MyWidget> {
+  String instanceField4;
+
+  String instanceField5;
+
+  @override
+  Widget build(BuildContext context) {
+    instanceField4 = widget.instanceField1;
+    return new Row(
+      children: [
+        new Text(widget.instanceField1),
+        new Text(widget.instanceField2),
+        new Text(widget.instanceField3),
+        new Text(instanceField4),
+        new Text(instanceField5),
+        new Text(MyWidget.staticField1),
+        new Text(MyWidget.staticField2),
+        new Text(MyWidget.staticField3),
+      ],
+    );
+  }
+}
+''');
+  }
+
+  test_flutterConvertToStatefulWidget_OK_getters() async {
+    addFlutterPackage();
+    await resolveTestUnit(r'''
+import 'package:flutter/material.dart';
+
+class /*caret*/MyWidget extends StatelessWidget {
+  @override
+  Widget build(BuildContext context) {
+    return new Row(
+      children: [
+        new Text(staticGetter1),
+        new Text(staticGetter2),
+        new Text(instanceGetter1),
+        new Text(instanceGetter2),
+      ],
+    );
+  }
+
+  static String get staticGetter1 => '';
+
+  String get instanceGetter1 => '';
+
+  static String get staticGetter2 => '';
+
+  String get instanceGetter2 => '';
+}
+''');
+    _setCaretLocation();
+    await assertHasAssist(
+        DartAssistKind.FLUTTER_CONVERT_TO_STATEFUL_WIDGET, r'''
+import 'package:flutter/material.dart';
+
+class /*caret*/MyWidget extends StatefulWidget {
+  @override
+  MyWidgetState createState() {
+    return new MyWidgetState();
+  }
+
+  static String get staticGetter1 => '';
+
+  static String get staticGetter2 => '';
+}
+
+class MyWidgetState extends State<MyWidget> {
+  @override
+  Widget build(BuildContext context) {
+    return new Row(
+      children: [
+        new Text(MyWidget.staticGetter1),
+        new Text(MyWidget.staticGetter2),
+        new Text(instanceGetter1),
+        new Text(instanceGetter2),
+      ],
+    );
+  }
+
+  String get instanceGetter1 => '';
+
+  String get instanceGetter2 => '';
+}
+''');
+  }
+
+  test_flutterConvertToStatefulWidget_OK_methods() async {
+    addFlutterPackage();
+    await resolveTestUnit(r'''
+import 'package:flutter/material.dart';
+
+class /*caret*/MyWidget extends StatelessWidget {
+  static String staticField;
+  final String instanceField1;
+  String instanceField2;
+
+  MyWidget(this.instanceField1);
+
+  @override
+  Widget build(BuildContext context) {
+    return new Row(
+      children: [
+        new Text(instanceField1),
+        new Text(instanceField2),
+        new Text(staticField),
+      ],
+    );
+  }
+
+  void instanceMethod1() {
+    instanceMethod1();
+    instanceMethod2();
+    staticMethod1();
+  }
+
+  static void staticMethod1() {
+    print('static 1');
+  }
+
+  void instanceMethod2() {
+    print('instance 2');
+  }
+
+  static void staticMethod2() {
+    print('static 2');
+  }
+}
+''');
+    _setCaretLocation();
+    await assertHasAssist(
+        DartAssistKind.FLUTTER_CONVERT_TO_STATEFUL_WIDGET, r'''
+import 'package:flutter/material.dart';
+
+class /*caret*/MyWidget extends StatefulWidget {
+  static String staticField;
+  final String instanceField1;
+
+  MyWidget(this.instanceField1);
+
+  @override
+  MyWidgetState createState() {
+    return new MyWidgetState();
+  }
+
+  static void staticMethod1() {
+    print('static 1');
+  }
+
+  static void staticMethod2() {
+    print('static 2');
+  }
+}
+
+class MyWidgetState extends State<MyWidget> {
+  String instanceField2;
+
+  @override
+  Widget build(BuildContext context) {
+    return new Row(
+      children: [
+        new Text(widget.instanceField1),
+        new Text(instanceField2),
+        new Text(MyWidget.staticField),
+      ],
+    );
+  }
+
+  void instanceMethod1() {
+    instanceMethod1();
+    instanceMethod2();
+    MyWidget.staticMethod1();
+  }
+
+  void instanceMethod2() {
+    print('instance 2');
+  }
+}
+''');
+  }
+
+  test_flutterConvertToStatefulWidget_OK_tail() async {
+    addFlutterPackage();
+    await resolveTestUnit(r'''
+import 'package:flutter/material.dart';
+
+class /*caret*/MyWidget extends StatelessWidget {
+  @override
+  Widget build(BuildContext context) {
+    return new Container();
+  }
+}
+''');
+    _setCaretLocation();
+    await assertHasAssist(
+        DartAssistKind.FLUTTER_CONVERT_TO_STATEFUL_WIDGET, r'''
+import 'package:flutter/material.dart';
+
+class /*caret*/MyWidget extends StatefulWidget {
+  @override
+  MyWidgetState createState() {
+    return new MyWidgetState();
+  }
+}
+
+class MyWidgetState extends State<MyWidget> {
+  @override
+  Widget build(BuildContext context) {
+    return new Container();
+  }
+}
+''');
+  }
+
   test_flutterMoveWidgetDown_BAD_last() async {
     addFlutterPackage();
     await resolveTestUnit('''
diff --git a/pkg/analyzer/lib/analyzer.dart b/pkg/analyzer/lib/analyzer.dart
index ab46a8d..18a2e6c 100644
--- a/pkg/analyzer/lib/analyzer.dart
+++ b/pkg/analyzer/lib/analyzer.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+@deprecated
 import 'dart:io';
 
 import 'package:analyzer/dart/ast/ast.dart';
diff --git a/pkg/analyzer/lib/src/dart/analysis/search.dart b/pkg/analyzer/lib/src/dart/analysis/search.dart
index d308de5..59dcb83 100644
--- a/pkg/analyzer/lib/src/dart/analysis/search.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/search.dart
@@ -145,15 +145,15 @@
     await _driver.discoverAvailableFiles();
 
     try {
-      for (String path in _driver.knownFiles) {
-        if (onlyForFile != null && path != onlyForFile) {
+      List<FileState> knownFiles = _driver.fsState.knownFiles.toList();
+      for (FileState file in knownFiles) {
+        if (onlyForFile != null && file.path != onlyForFile) {
           continue;
         }
-        if (files.contains(path)) {
+        if (files.contains(file.path)) {
           continue;
         }
 
-        FileState file = _driver.fsState.getFileForPath(path);
         int fileIndex;
 
         void addDeclaration(String name, DeclarationKind kind, int offset,
@@ -380,10 +380,10 @@
     await _driver.discoverAvailableFiles();
 
     List<SubtypeResult> results = [];
-    for (String path in _driver.knownFiles) {
-      FileState file = _driver.fsState.getFileForPath(path);
+    List<FileState> knownFiles = _driver.fsState.knownFiles.toList();
+    for (FileState file in knownFiles) {
       if (file.subtypedNames.contains(name)) {
-        AnalysisDriverUnitIndex index = await _driver.getIndex(path);
+        AnalysisDriverUnitIndex index = await _driver.getIndex(file.path);
         if (index != null) {
           for (AnalysisDriverSubtype subtype in index.subtypes) {
             if (subtype.supertypes.contains(id)) {
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index 410a1f0..b65aa46 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -1409,14 +1409,11 @@
     if (errorOccurred) {
       return null;
     }
-    DartType elementType = _typeProvider.dynamicType;
-    NodeList<TypeAnnotation> typeArgs = node.typeArguments?.arguments;
-    if (typeArgs?.length == 1) {
-      DartType type = visitTypeAnnotation(typeArgs[0])?.toTypeValue();
-      if (type != null) {
-        elementType = type;
-      }
-    }
+    var nodeType = node.staticType;
+    DartType elementType =
+        nodeType is InterfaceType && nodeType.typeArguments.isNotEmpty
+            ? nodeType.typeArguments[0]
+            : _typeProvider.dynamicType;
     InterfaceType listType = _typeProvider.listType.instantiate([elementType]);
     return new DartObjectImpl(listType, new ListState(elements));
   }
@@ -1445,17 +1442,12 @@
     }
     DartType keyType = _typeProvider.dynamicType;
     DartType valueType = _typeProvider.dynamicType;
-    NodeList<TypeAnnotation> typeArgs = node.typeArguments?.arguments;
-    if (typeArgs?.length == 2) {
-      DartType keyTypeCandidate =
-          visitTypeAnnotation(typeArgs[0])?.toTypeValue();
-      if (keyTypeCandidate != null) {
-        keyType = keyTypeCandidate;
-      }
-      DartType valueTypeCandidate =
-          visitTypeAnnotation(typeArgs[1])?.toTypeValue();
-      if (valueTypeCandidate != null) {
-        valueType = valueTypeCandidate;
+    var nodeType = node.staticType;
+    if (nodeType is InterfaceType) {
+      var typeArguments = nodeType.typeArguments;
+      if (typeArguments.length >= 2) {
+        keyType = typeArguments[0];
+        valueType = typeArguments[1];
       }
     }
     InterfaceType mapType =
diff --git a/pkg/analyzer/lib/src/dart/constant/utilities.dart b/pkg/analyzer/lib/src/dart/constant/utilities.dart
index 7e47780..95c7f18 100644
--- a/pkg/analyzer/lib/src/dart/constant/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/constant/utilities.dart
@@ -83,6 +83,7 @@
   @override
   ListLiteral visitListLiteral(ListLiteral node) {
     ListLiteral literal = super.visitListLiteral(node);
+    literal.staticType = node.staticType;
     if (previewDart2 && node.constKeyword == null && node.isConst) {
       literal.constKeyword = new KeywordToken(Keyword.CONST, node.offset);
     }
@@ -92,6 +93,7 @@
   @override
   MapLiteral visitMapLiteral(MapLiteral node) {
     MapLiteral literal = super.visitMapLiteral(node);
+    literal.staticType = node.staticType;
     if (previewDart2 && node.constKeyword == null && node.isConst) {
       literal.constKeyword = new KeywordToken(Keyword.CONST, node.offset);
     }
diff --git a/pkg/analyzer/lib/src/fasta/ast_building_factory.dart b/pkg/analyzer/lib/src/fasta/ast_building_factory.dart
index 7e08aa0..2a7ab90 100644
--- a/pkg/analyzer/lib/src/fasta/ast_building_factory.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_building_factory.dart
@@ -186,6 +186,28 @@
   }
 
   @override
+  Generator<Expression, Statement, Arguments> delayedAssignment(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+      Token token,
+      Generator<Expression, Statement, Arguments> generator,
+      Expression value,
+      String assignmentOperator) {
+    // TODO(brianwilkerson) Implement this.
+    throw new UnimplementedError();
+  }
+
+  @override
+  Generator<Expression, Statement, Arguments> delayedPostfixIncrement(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+      Token token,
+      Generator<Expression, Statement, Arguments> generator,
+      kernel.Name binaryOperator,
+      kernel.Procedure interfaceTarget) {
+    // TODO(brianwilkerson) Implement this.
+    throw new UnimplementedError();
+  }
+
+  @override
   Statement doStatement(Token doKeyword, Statement body, Token whileKeyword,
           ParenthesizedExpression condition, Token semicolon) =>
       astFactory.doStatement(
diff --git a/pkg/analyzer/test/generated/checked_mode_compile_time_error_code_test.dart b/pkg/analyzer/test/generated/checked_mode_compile_time_error_code_test.dart
index 746ca53..1d350f0 100644
--- a/pkg/analyzer/test/generated/checked_mode_compile_time_error_code_test.dart
+++ b/pkg/analyzer/test/generated/checked_mode_compile_time_error_code_test.dart
@@ -492,6 +492,18 @@
     verify([source]);
   }
 
+  test_listLiteral_inferredElementType() async {
+    resetWith(options: new AnalysisOptionsImpl()..strongMode = true);
+    Source source = addSource('''
+const Object x = [1];
+const List<String> y = x;
+''');
+    await computeAnalysisResult(source);
+    assertErrors(
+        source, [CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH]);
+    verify([source]);
+  }
+
   test_mapKeyTypeNotAssignable() async {
     Source source = addSource("var v = const <String, int > {1 : 2};");
     await computeAnalysisResult(source);
@@ -502,6 +514,30 @@
     verify([source]);
   }
 
+  test_mapLiteral_inferredKeyType() async {
+    resetWith(options: new AnalysisOptionsImpl()..strongMode = true);
+    Source source = addSource('''
+const Object x = {1: 1};
+const Map<String, dynamic> y = x;
+''');
+    await computeAnalysisResult(source);
+    assertErrors(
+        source, [CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH]);
+    verify([source]);
+  }
+
+  test_mapLiteral_inferredValueType() async {
+    resetWith(options: new AnalysisOptionsImpl()..strongMode = true);
+    Source source = addSource('''
+const Object x = {1: 1};
+const Map<dynamic, String> y = x;
+''');
+    await computeAnalysisResult(source);
+    assertErrors(
+        source, [CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH]);
+    verify([source]);
+  }
+
   test_mapValueTypeNotAssignable() async {
     Source source = addSource("var v = const <String, String> {'a' : 2};");
     await computeAnalysisResult(source);
diff --git a/pkg/analyzer/test/generated/non_error_resolver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_test.dart
index 0724a03..f425dce 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_test.dart
@@ -4860,7 +4860,7 @@
 @B.named8()
 main() {}
 ''');
-    final aSource = addNamedSource("/a.dart", r'''
+    addNamedSource("/a.dart", r'''
 class Unbounded<T> {
   const Unbounded();
   const Unbounded.named();
@@ -4870,7 +4870,7 @@
   const Bounded.named();
 }
 ''');
-    final bSource = addNamedSource("/b.dart", r'''
+    addNamedSource("/b.dart", r'''
 import 'a.dart';
 import 'a.dart' as p;
 
diff --git a/pkg/analyzer/test/generated/parser_fasta_test.dart b/pkg/analyzer/test/generated/parser_fasta_test.dart
index fabf804..8c02681 100644
--- a/pkg/analyzer/test/generated/parser_fasta_test.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_test.dart
@@ -378,22 +378,6 @@
     // Fasta no longer supports type comment based syntax
     // super.test_method_invalidTypeParameterExtendsComment();
   }
-
-  @override
-  @failingTest
-  void test_missingFunctionParameters_topLevel_void_block() {
-    // TODO(brianwilkerson) Wrong errors:
-    // Expected 1 errors of type ParserErrorCode.MISSING_FUNCTION_PARAMETERS, found 0
-    super.test_missingFunctionParameters_topLevel_void_block();
-  }
-
-  @override
-  @failingTest
-  void test_missingFunctionParameters_topLevel_void_expression() {
-    // TODO(brianwilkerson) Wrong errors:
-    // Expected 1 errors of type ParserErrorCode.MISSING_FUNCTION_PARAMETERS, found 0
-    super.test_missingFunctionParameters_topLevel_void_expression();
-  }
 }
 
 /**
diff --git a/pkg/analyzer/test/src/summary/resynthesize_ast_test.dart b/pkg/analyzer/test/src/summary/resynthesize_ast_test.dart
index 2965261..891b523 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_ast_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_ast_test.dart
@@ -183,7 +183,13 @@
 
   @failingTest // See dartbug.com/32290
   test_const_constructor_inferred_args() =>
-      test_const_constructor_inferred_args();
+      super.test_const_constructor_inferred_args();
+
+  @failingTest // See dartbug.com/33441
+  test_const_list_inferredType() => super.test_const_list_inferredType();
+
+  @failingTest // See dartbug.com/33441
+  test_const_map_inferredType() => super.test_const_map_inferredType();
 
   @override
   @failingTest
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index dd8e30b..88a7e76 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -3297,6 +3297,35 @@
     }
   }
 
+  test_const_list_inferredType() async {
+    if (!isStrongMode) return;
+    // The summary needs to contain enough information so that when the constant
+    // is resynthesized, the constant value can get the type that was computed
+    // by type inference.
+    var library = await checkLibrary('''
+const Object x = const [1];
+''');
+    checkElementText(library, '''
+const Object x = const <
+        int/*location: dart:core;int*/>[1];
+''');
+  }
+
+  test_const_map_inferredType() async {
+    if (!isStrongMode) return;
+    // The summary needs to contain enough information so that when the constant
+    // is resynthesized, the constant value can get the type that was computed
+    // by type inference.
+    var library = await checkLibrary('''
+const Object x = const {1: 1.0};
+''');
+    checkElementText(library, '''
+const Object x = const <
+        int/*location: dart:core;int*/,
+        double/*location: dart:core;double*/>{1: 1.0};
+''');
+  }
+
   test_const_parameterDefaultValue_initializingFormal_functionTyped() async {
     var library = await checkLibrary(r'''
 class C {
diff --git a/pkg/analyzer/test/src/summary/resynthesize_kernel_test.dart b/pkg/analyzer/test/src/summary/resynthesize_kernel_test.dart
index 707aa7e..9a2a5e1 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_kernel_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_kernel_test.dart
@@ -147,7 +147,7 @@
 
   @failingTest // See dartbug.com/32290
   test_const_constructor_inferred_args() =>
-      test_const_constructor_inferred_args();
+      super.test_const_constructor_inferred_args();
 
   @failingTest
   @FastaProblem('https://github.com/dart-lang/sdk/issues/30258')
diff --git a/pkg/analyzer/test/src/task/strong/checker_test.dart b/pkg/analyzer/test/src/task/strong/checker_test.dart
index 2228fa0..9aa47e4 100644
--- a/pkg/analyzer/test/src/task/strong/checker_test.dart
+++ b/pkg/analyzer/test/src/task/strong/checker_test.dart
@@ -349,6 +349,7 @@
 ''');
   }
 
+  @failingTest // See dartbug.com/33440
   test_constantGenericTypeArg_explicit() async {
     // Regression test for https://github.com/dart-lang/sdk/issues/26141
     await checkFile('''
@@ -375,6 +376,7 @@
     ''');
   }
 
+  @failingTest // See dartbug.com/32918
   test_constantGenericTypeArg_infer() async {
     // Regression test for https://github.com/dart-lang/sdk/issues/26141
     await checkFile('''
diff --git a/pkg/front_end/lib/src/api_prototype/standard_file_system.dart b/pkg/front_end/lib/src/api_prototype/standard_file_system.dart
index c64cfd8..e780e81 100644
--- a/pkg/front_end/lib/src/api_prototype/standard_file_system.dart
+++ b/pkg/front_end/lib/src/api_prototype/standard_file_system.dart
@@ -9,6 +9,8 @@
 
 import 'file_system.dart';
 
+import '../fasta/compiler_context.dart' show CompilerContext;
+
 /// Concrete implementation of [FileSystem] handling standard URI schemes.
 ///
 /// file: URIs are handled using file I/O.
@@ -60,6 +62,7 @@
   @override
   Future<List<int>> readAsBytes() async {
     try {
+      CompilerContext.recordDependency(uri);
       return await new io.File.fromUri(uri).readAsBytes();
     } on io.FileSystemException catch (exception) {
       throw _toFileSystemException(exception);
@@ -69,6 +72,7 @@
   @override
   Future<String> readAsString() async {
     try {
+      CompilerContext.recordDependency(uri);
       return await new io.File.fromUri(uri).readAsString();
     } on io.FileSystemException catch (exception) {
       throw _toFileSystemException(exception);
diff --git a/pkg/front_end/lib/src/fasta/compiler_context.dart b/pkg/front_end/lib/src/fasta/compiler_context.dart
index 2eda950..e979f14 100644
--- a/pkg/front_end/lib/src/fasta/compiler_context.dart
+++ b/pkg/front_end/lib/src/fasta/compiler_context.dart
@@ -47,7 +47,9 @@
   /// programs.
   final Map<Uri, Source> uriToSource = <Uri, Source>{};
 
-  final List errors = <Object>[];
+  final List<Object> errors = <Object>[];
+
+  final List<Uri> dependencies = <Uri>[];
 
   FileSystem get fileSystem => options.fileSystem;
 
@@ -87,8 +89,18 @@
     errors.add(severity);
   }
 
+  static void recordDependency(Uri uri) {
+    if (uri.scheme != "file") {
+      throw new ArgumentError("Expected a file-URI, but got: '$uri'.");
+    }
+    CompilerContext context = Zone.current[compilerContextKey];
+    if (context != null) {
+      context.dependencies.add(uri);
+    }
+  }
+
   static CompilerContext get current {
-    var context = Zone.current[compilerContextKey];
+    CompilerContext context = Zone.current[compilerContextKey];
     if (context == null) {
       // Note: we throw directly and don't use internalProblem, because
       // internalProblem depends on having a compiler context available.
@@ -127,5 +139,6 @@
   void clear() {
     StringToken.canonicalizer.clear();
     errors.clear();
+    dependencies.clear();
   }
 }
diff --git a/pkg/front_end/lib/src/fasta/get_dependencies.dart b/pkg/front_end/lib/src/fasta/get_dependencies.dart
index 4fa99af..c7b7ba3 100644
--- a/pkg/front_end/lib/src/fasta/get_dependencies.dart
+++ b/pkg/front_end/lib/src/fasta/get_dependencies.dart
@@ -24,7 +24,6 @@
 
 import 'uri_translator.dart' show UriTranslator;
 
-// TODO(sigmund): reimplement this API using the directive listener intead.
 Future<List<Uri>> getDependencies(Uri script,
     {Uri sdk,
     Uri packages,
@@ -57,6 +56,6 @@
     kernelTarget.read(script);
     await dillTarget.buildOutlines();
     await kernelTarget.loader.buildOutlines();
-    return await kernelTarget.loader.getDependencies();
+    return new List<Uri>.from(c.dependencies);
   });
 }
diff --git a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
index c69b304..a7228a9 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
@@ -18,7 +18,20 @@
         templateNotAType,
         templateUnresolvedPrefixInTypeAnnotation;
 
-import '../names.dart' show lengthName;
+import '../names.dart'
+    show
+        ampersandName,
+        barName,
+        caretName,
+        divisionName,
+        leftShiftName,
+        lengthName,
+        minusName,
+        multiplyName,
+        mustacheName,
+        percentName,
+        plusName,
+        rightShiftName;
 
 import '../parser.dart' show lengthForToken, lengthOfSpan, offsetForToken;
 
@@ -35,9 +48,12 @@
         TypeDeclarationBuilder,
         UnlinkedDeclaration;
 
+import 'kernel_api.dart' show printQualifiedNameOn;
+
 import 'kernel_ast_api.dart'
     show
         DartType,
+        DynamicType,
         Initializer,
         InvalidType,
         Member,
@@ -61,8 +77,6 @@
 
 export 'kernel_expression_generator.dart'
     show
-        DelayedAssignment,
-        DelayedPostfixIncrement,
         IncompleteErrorGenerator,
         IncompletePropertyAccessGenerator,
         IncompleteSendGenerator,
@@ -862,3 +876,197 @@
     sink.write(declaration.name);
   }
 }
+
+abstract class ContextAwareGenerator<Expression, Statement, Arguments>
+    implements Generator<Expression, Statement, Arguments> {
+  Generator<Expression, Statement, Arguments> get generator;
+
+  @override
+  String get plainNameForRead {
+    return unsupported("plainNameForRead", token.charOffset, helper.uri);
+  }
+
+  @override
+  Expression doInvocation(int charOffset, Arguments arguments) {
+    return unhandled("${runtimeType}", "doInvocation", charOffset, uri);
+  }
+
+  @override
+  Expression buildAssignment(Expression value, {bool voidContext: false}) {
+    return makeInvalidWrite(value);
+  }
+
+  @override
+  Expression buildNullAwareAssignment(
+      Expression value, DartType type, int offset,
+      {bool voidContext: false}) {
+    return makeInvalidWrite(value);
+  }
+
+  @override
+  Expression buildCompoundAssignment(Name binaryOperator, Expression value,
+      {int offset: -1,
+      bool voidContext: false,
+      Procedure interfaceTarget,
+      bool isPreIncDec: false}) {
+    return makeInvalidWrite(value);
+  }
+
+  @override
+  Expression buildPrefixIncrement(Name binaryOperator,
+      {int offset: -1, bool voidContext: false, Procedure interfaceTarget}) {
+    return makeInvalidWrite(null);
+  }
+
+  @override
+  Expression buildPostfixIncrement(Name binaryOperator,
+      {int offset: -1, bool voidContext: false, Procedure interfaceTarget}) {
+    return makeInvalidWrite(null);
+  }
+
+  @override
+  makeInvalidRead() {
+    return unsupported("makeInvalidRead", token.charOffset, helper.uri);
+  }
+
+  @override
+  Expression makeInvalidWrite(Expression value) {
+    return helper.deprecated_buildCompileTimeError(
+        "Can't be used as left-hand side of assignment.",
+        offsetForToken(token));
+  }
+}
+
+abstract class DelayedAssignment<Expression, Statement, Arguments>
+    implements ContextAwareGenerator<Expression, Statement, Arguments> {
+  factory DelayedAssignment(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+      Token token,
+      Generator<Expression, Statement, Arguments> generator,
+      Expression value,
+      String assignmentOperator) {
+    return helper.forest
+        .delayedAssignment(helper, token, generator, value, assignmentOperator);
+  }
+
+  Expression get value;
+
+  String get assignmentOperator;
+
+  @override
+  String get debugName => "DelayedAssignment";
+
+  @override
+  Expression buildSimpleRead() {
+    return handleAssignment(false);
+  }
+
+  @override
+  Expression buildForEffect() {
+    return handleAssignment(true);
+  }
+
+  Expression handleAssignment(bool voidContext) {
+    if (helper.constantContext != ConstantContext.none) {
+      return helper.deprecated_buildCompileTimeError(
+          "Not a constant expression.", offsetForToken(token));
+    }
+    if (identical("=", assignmentOperator)) {
+      return generator.buildAssignment(value, voidContext: voidContext);
+    } else if (identical("+=", assignmentOperator)) {
+      return generator.buildCompoundAssignment(plusName, value,
+          offset: offsetForToken(token), voidContext: voidContext);
+    } else if (identical("-=", assignmentOperator)) {
+      return generator.buildCompoundAssignment(minusName, value,
+          offset: offsetForToken(token), voidContext: voidContext);
+    } else if (identical("*=", assignmentOperator)) {
+      return generator.buildCompoundAssignment(multiplyName, value,
+          offset: offsetForToken(token), voidContext: voidContext);
+    } else if (identical("%=", assignmentOperator)) {
+      return generator.buildCompoundAssignment(percentName, value,
+          offset: offsetForToken(token), voidContext: voidContext);
+    } else if (identical("&=", assignmentOperator)) {
+      return generator.buildCompoundAssignment(ampersandName, value,
+          offset: offsetForToken(token), voidContext: voidContext);
+    } else if (identical("/=", assignmentOperator)) {
+      return generator.buildCompoundAssignment(divisionName, value,
+          offset: offsetForToken(token), voidContext: voidContext);
+    } else if (identical("<<=", assignmentOperator)) {
+      return generator.buildCompoundAssignment(leftShiftName, value,
+          offset: offsetForToken(token), voidContext: voidContext);
+    } else if (identical(">>=", assignmentOperator)) {
+      return generator.buildCompoundAssignment(rightShiftName, value,
+          offset: offsetForToken(token), voidContext: voidContext);
+    } else if (identical("??=", assignmentOperator)) {
+      return generator.buildNullAwareAssignment(
+          value, const DynamicType(), offsetForToken(token),
+          voidContext: voidContext);
+    } else if (identical("^=", assignmentOperator)) {
+      return generator.buildCompoundAssignment(caretName, value,
+          offset: offsetForToken(token), voidContext: voidContext);
+    } else if (identical("|=", assignmentOperator)) {
+      return generator.buildCompoundAssignment(barName, value,
+          offset: offsetForToken(token), voidContext: voidContext);
+    } else if (identical("~/=", assignmentOperator)) {
+      return generator.buildCompoundAssignment(mustacheName, value,
+          offset: offsetForToken(token), voidContext: voidContext);
+    } else {
+      return unhandled(
+          assignmentOperator, "handleAssignment", token.charOffset, helper.uri);
+    }
+  }
+
+  @override
+  Initializer buildFieldInitializer(Map<String, int> initializedFields) {
+    if (!identical("=", assignmentOperator) ||
+        !generator.isThisPropertyAccess) {
+      return generator.buildFieldInitializer(initializedFields);
+    }
+    return helper.buildFieldInitializer(
+        false, generator.plainNameForRead, offsetForToken(token), value);
+  }
+}
+
+abstract class DelayedPostfixIncrement<Expression, Statement, Arguments>
+    implements ContextAwareGenerator<Expression, Statement, Arguments> {
+  factory DelayedPostfixIncrement(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+      Token token,
+      Generator<Expression, Statement, Arguments> generator,
+      Name binaryOperator,
+      Procedure interfaceTarget) {
+    return helper.forest.delayedPostfixIncrement(
+        helper, token, generator, binaryOperator, interfaceTarget);
+  }
+
+  Name get binaryOperator;
+
+  Procedure get interfaceTarget;
+
+  @override
+  String get debugName => "DelayedPostfixIncrement";
+
+  @override
+  Expression buildSimpleRead() {
+    return generator.buildPostfixIncrement(binaryOperator,
+        offset: offsetForToken(token),
+        voidContext: false,
+        interfaceTarget: interfaceTarget);
+  }
+
+  @override
+  Expression buildForEffect() {
+    return generator.buildPostfixIncrement(binaryOperator,
+        offset: offsetForToken(token),
+        voidContext: true,
+        interfaceTarget: interfaceTarget);
+  }
+
+  @override
+  void printOn(StringSink sink) {
+    sink.write(", binaryOperator: ");
+    sink.write(binaryOperator.name);
+    sink.write(", interfaceTarget: ");
+    printQualifiedNameOn(interfaceTarget, sink);
+  }
+}
diff --git a/pkg/front_end/lib/src/fasta/kernel/fangorn.dart b/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
index a976f3b..1700191 100644
--- a/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
@@ -46,6 +46,8 @@
 import 'kernel_expression_generator.dart'
     show
         KernelDeferredAccessGenerator,
+        KernelDelayedAssignment,
+        KernelDelayedPostfixIncrement,
         KernelIndexedAccessGenerator,
         KernelLargeIntAccessGenerator,
         KernelLoadLibraryGenerator,
@@ -775,6 +777,28 @@
       UnlinkedDeclaration declaration) {
     return new KernelUnlinkedGenerator(helper, token, declaration);
   }
+
+  @override
+  KernelDelayedAssignment delayedAssignment(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+      Token token,
+      Generator<Expression, Statement, Arguments> generator,
+      Expression value,
+      String assignmentOperator) {
+    return new KernelDelayedAssignment(
+        helper, token, generator, value, assignmentOperator);
+  }
+
+  @override
+  KernelDelayedPostfixIncrement delayedPostfixIncrement(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+      Token token,
+      Generator<Expression, Statement, Arguments> generator,
+      Name binaryOperator,
+      Procedure interfaceTarget) {
+    return new KernelDelayedPostfixIncrement(
+        helper, token, generator, binaryOperator, interfaceTarget);
+  }
 }
 
 class _VariablesDeclaration extends Statement {
diff --git a/pkg/front_end/lib/src/fasta/kernel/forest.dart b/pkg/front_end/lib/src/fasta/kernel/forest.dart
index ac39797..4d80798 100644
--- a/pkg/front_end/lib/src/fasta/kernel/forest.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/forest.dart
@@ -472,6 +472,20 @@
       Location location,
       UnlinkedDeclaration declaration);
 
+  Generator<Expression, Statement, Arguments> delayedAssignment(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+      Location location,
+      Generator<Expression, Statement, Arguments> generator,
+      Expression value,
+      String assignmentOperator);
+
+  Generator<Expression, Statement, Arguments> delayedPostfixIncrement(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+      Location location,
+      Generator<Expression, Statement, Arguments> generator,
+      kernel.Name binaryOperator,
+      kernel.Procedure interfaceTarget);
+
   // TODO(ahe): Remove this method when all users are moved here.
   kernel.Arguments castArguments(Arguments arguments) {
     dynamic a = arguments;
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator.dart
index bc2d940..de2683d 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator.dart
@@ -18,23 +18,7 @@
 
 import '../messages.dart' show Message, noLength;
 
-import '../names.dart'
-    show
-        ampersandName,
-        barName,
-        callName,
-        caretName,
-        divisionName,
-        equalsName,
-        indexGetName,
-        indexSetName,
-        leftShiftName,
-        minusName,
-        multiplyName,
-        mustacheName,
-        percentName,
-        plusName,
-        rightShiftName;
+import '../names.dart' show callName, equalsName, indexGetName, indexSetName;
 
 import '../parser.dart' show lengthForToken, lengthOfSpan, offsetForToken;
 
@@ -46,7 +30,10 @@
 
 import 'expression_generator.dart'
     show
+        ContextAwareGenerator,
         DeferredAccessGenerator,
+        DelayedAssignment,
+        DelayedPostfixIncrement,
         ErroneousExpressionGenerator,
         ExpressionGenerator,
         Generator,
@@ -79,7 +66,6 @@
     show
         Constructor,
         DartType,
-        DynamicType,
         Field,
         Initializer,
         InvalidType,
@@ -1512,6 +1498,71 @@
   }
 }
 
+abstract class KernelContextAwareGenerator extends KernelGenerator
+    with ContextAwareGenerator<Expression, Statement, Arguments> {
+  @override
+  final Generator<Expression, Statement, Arguments> generator;
+
+  KernelContextAwareGenerator(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+      Token token,
+      this.generator)
+      : super(helper, token);
+
+  @override
+  Expression _makeRead(ShadowComplexAssignment complexAssignment) {
+    return unsupported("_makeRead", offsetForToken(token), uri);
+  }
+
+  @override
+  Expression _makeWrite(Expression value, bool voidContext,
+      ShadowComplexAssignment complexAssignment) {
+    return unsupported("_makeWrite", offsetForToken(token), uri);
+  }
+}
+
+class KernelDelayedAssignment extends KernelContextAwareGenerator
+    with DelayedAssignment<Expression, Statement, Arguments> {
+  @override
+  final Expression value;
+
+  @override
+  String assignmentOperator;
+
+  KernelDelayedAssignment(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+      Token token,
+      Generator<Expression, Statement, Arguments> generator,
+      this.value,
+      this.assignmentOperator)
+      : super(helper, token, generator);
+
+  @override
+  void printOn(StringSink sink) {
+    sink.write(", value: ");
+    printNodeOn(value, sink);
+    sink.write(", assignmentOperator: ");
+    sink.write(assignmentOperator);
+  }
+}
+
+class KernelDelayedPostfixIncrement extends KernelContextAwareGenerator
+    with DelayedPostfixIncrement<Expression, Statement, Arguments> {
+  @override
+  final Name binaryOperator;
+
+  @override
+  final Procedure interfaceTarget;
+
+  KernelDelayedPostfixIncrement(
+      ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
+      Token token,
+      Generator<Expression, Statement, Arguments> generator,
+      this.binaryOperator,
+      this.interfaceTarget)
+      : super(helper, token, generator);
+}
+
 Expression makeLet(VariableDeclaration variable, Expression body) {
   if (variable == null) return body;
   return new Let(variable, body);
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator_impl.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator_impl.dart
index 1f93a18..1acf3cd 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator_impl.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator_impl.dart
@@ -436,194 +436,3 @@
         "Can't assign to a parenthesized expression.", offsetForToken(token));
   }
 }
-
-abstract class ContextAwareGenerator
-    extends Generator<Expression, Statement, Arguments> {
-  final Generator generator;
-
-  ContextAwareGenerator(
-      ExpressionGeneratorHelper<dynamic, dynamic, dynamic> helper,
-      Token token,
-      this.generator)
-      : super(helper, token);
-
-  String get plainNameForRead {
-    return unsupported("plainNameForRead", token.charOffset, helper.uri);
-  }
-
-  Expression doInvocation(int charOffset, Arguments arguments) {
-    return unhandled("${runtimeType}", "doInvocation", charOffset, uri);
-  }
-
-  Expression buildSimpleRead();
-
-  Expression buildForEffect();
-
-  Expression buildAssignment(Expression value, {bool voidContext: false}) {
-    return makeInvalidWrite(value);
-  }
-
-  Expression buildNullAwareAssignment(
-      Expression value, DartType type, int offset,
-      {bool voidContext: false}) {
-    return makeInvalidWrite(value);
-  }
-
-  Expression buildCompoundAssignment(Name binaryOperator, Expression value,
-      {int offset: TreeNode.noOffset,
-      bool voidContext: false,
-      Procedure interfaceTarget,
-      bool isPreIncDec: false}) {
-    return makeInvalidWrite(value);
-  }
-
-  Expression buildPrefixIncrement(Name binaryOperator,
-      {int offset: TreeNode.noOffset,
-      bool voidContext: false,
-      Procedure interfaceTarget}) {
-    return makeInvalidWrite(null);
-  }
-
-  Expression buildPostfixIncrement(Name binaryOperator,
-      {int offset: TreeNode.noOffset,
-      bool voidContext: false,
-      Procedure interfaceTarget}) {
-    return makeInvalidWrite(null);
-  }
-
-  makeInvalidRead() {
-    return unsupported("makeInvalidRead", token.charOffset, helper.uri);
-  }
-
-  Expression makeInvalidWrite(Expression value) {
-    return helper.deprecated_buildCompileTimeError(
-        "Can't be used as left-hand side of assignment.",
-        offsetForToken(token));
-  }
-}
-
-class DelayedAssignment extends ContextAwareGenerator {
-  final Expression value;
-
-  final String assignmentOperator;
-
-  DelayedAssignment(ExpressionGeneratorHelper<dynamic, dynamic, dynamic> helper,
-      Token token, Generator generator, this.value, this.assignmentOperator)
-      : super(helper, token, generator);
-
-  String get debugName => "DelayedAssignment";
-
-  Expression buildSimpleRead() {
-    return handleAssignment(false);
-  }
-
-  Expression buildForEffect() {
-    return handleAssignment(true);
-  }
-
-  Expression handleAssignment(bool voidContext) {
-    if (helper.constantContext != ConstantContext.none) {
-      return helper.deprecated_buildCompileTimeError(
-          "Not a constant expression.", offsetForToken(token));
-    }
-    if (identical("=", assignmentOperator)) {
-      return generator.buildAssignment(value, voidContext: voidContext);
-    } else if (identical("+=", assignmentOperator)) {
-      return generator.buildCompoundAssignment(plusName, value,
-          offset: offsetForToken(token), voidContext: voidContext);
-    } else if (identical("-=", assignmentOperator)) {
-      return generator.buildCompoundAssignment(minusName, value,
-          offset: offsetForToken(token), voidContext: voidContext);
-    } else if (identical("*=", assignmentOperator)) {
-      return generator.buildCompoundAssignment(multiplyName, value,
-          offset: offsetForToken(token), voidContext: voidContext);
-    } else if (identical("%=", assignmentOperator)) {
-      return generator.buildCompoundAssignment(percentName, value,
-          offset: offsetForToken(token), voidContext: voidContext);
-    } else if (identical("&=", assignmentOperator)) {
-      return generator.buildCompoundAssignment(ampersandName, value,
-          offset: offsetForToken(token), voidContext: voidContext);
-    } else if (identical("/=", assignmentOperator)) {
-      return generator.buildCompoundAssignment(divisionName, value,
-          offset: offsetForToken(token), voidContext: voidContext);
-    } else if (identical("<<=", assignmentOperator)) {
-      return generator.buildCompoundAssignment(leftShiftName, value,
-          offset: offsetForToken(token), voidContext: voidContext);
-    } else if (identical(">>=", assignmentOperator)) {
-      return generator.buildCompoundAssignment(rightShiftName, value,
-          offset: offsetForToken(token), voidContext: voidContext);
-    } else if (identical("??=", assignmentOperator)) {
-      return generator.buildNullAwareAssignment(
-          value, const DynamicType(), offsetForToken(token),
-          voidContext: voidContext);
-    } else if (identical("^=", assignmentOperator)) {
-      return generator.buildCompoundAssignment(caretName, value,
-          offset: offsetForToken(token), voidContext: voidContext);
-    } else if (identical("|=", assignmentOperator)) {
-      return generator.buildCompoundAssignment(barName, value,
-          offset: offsetForToken(token), voidContext: voidContext);
-    } else if (identical("~/=", assignmentOperator)) {
-      return generator.buildCompoundAssignment(mustacheName, value,
-          offset: offsetForToken(token), voidContext: voidContext);
-    } else {
-      return unhandled(
-          assignmentOperator, "handleAssignment", token.charOffset, helper.uri);
-    }
-  }
-
-  @override
-  Initializer buildFieldInitializer(Map<String, int> initializedFields) {
-    if (!identical("=", assignmentOperator) ||
-        !generator.isThisPropertyAccess) {
-      return generator.buildFieldInitializer(initializedFields);
-    }
-    return helper.buildFieldInitializer(
-        false, generator.plainNameForRead, offsetForToken(token), value);
-  }
-
-  @override
-  void printOn(StringSink sink) {
-    sink.write(", value: ");
-    printNodeOn(value, sink);
-    sink.write(", assignmentOperator: ");
-    sink.write(assignmentOperator);
-  }
-}
-
-class DelayedPostfixIncrement extends ContextAwareGenerator {
-  final Name binaryOperator;
-
-  final Procedure interfaceTarget;
-
-  DelayedPostfixIncrement(
-      ExpressionGeneratorHelper<dynamic, dynamic, dynamic> helper,
-      Token token,
-      Generator generator,
-      this.binaryOperator,
-      this.interfaceTarget)
-      : super(helper, token, generator);
-
-  String get debugName => "DelayedPostfixIncrement";
-
-  Expression buildSimpleRead() {
-    return generator.buildPostfixIncrement(binaryOperator,
-        offset: offsetForToken(token),
-        voidContext: false,
-        interfaceTarget: interfaceTarget);
-  }
-
-  Expression buildForEffect() {
-    return generator.buildPostfixIncrement(binaryOperator,
-        offset: offsetForToken(token),
-        voidContext: true,
-        interfaceTarget: interfaceTarget);
-  }
-
-  @override
-  void printOn(StringSink sink) {
-    sink.write(", binaryOperator: ");
-    sink.write(binaryOperator.name);
-    sink.write(", interfaceTarget: ");
-    printQualifiedNameOn(interfaceTarget, sink);
-  }
-}
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_formal_parameter_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_formal_parameter_builder.dart
index 1830ea2..752a461 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_formal_parameter_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_formal_parameter_builder.dart
@@ -46,10 +46,6 @@
           isFieldFormal: hasThis,
           isCovariant: isCovariant)
         ..fileOffset = charOffset;
-      if (type == null && hasThis) {
-        library.loader.typeInferenceEngine
-            .recordInitializingFormal(declaration);
-      }
     }
     return declaration;
   }
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart
index 935acb9..c78baa0 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart
@@ -444,6 +444,15 @@
     return isRedirectingGenerativeConstructorImplementation(constructor);
   }
 
+  bool get isEligibleForTopLevelInference {
+    if (formals != null) {
+      for (var formal in formals) {
+        if (formal.type == null && formal.hasThis) return true;
+      }
+    }
+    return false;
+  }
+
   Constructor build(SourceLibraryBuilder library) {
     if (constructor.name == null) {
       constructor.function = buildFunction(library);
@@ -455,6 +464,14 @@
       constructor.isExternal = isExternal;
       constructor.name = new Name(name, library.target);
     }
+    if (!library.disableTypeInference && isEligibleForTopLevelInference) {
+      for (KernelFormalParameterBuilder formal in formals) {
+        if (formal.type == null && formal.hasThis) {
+          formal.declaration.type = null;
+        }
+      }
+      library.loader.typeInferenceEngine.toBeInferred[constructor] = library;
+    }
     return constructor;
   }
 
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 f72a8a2..36ec248 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
@@ -34,7 +34,10 @@
         InstrumentationValueForTypeArgs;
 
 import '../fasta_codes.dart'
-    show noLength, templateCantUseSuperBoundedTypeForInstanceCreation;
+    show
+        noLength,
+        templateCantInferTypeDueToCircularity,
+        templateCantUseSuperBoundedTypeForInstanceCreation;
 
 import '../problems.dart' show unhandled, unsupported;
 
@@ -607,6 +610,36 @@
 
   @override
   DartType _inferExpression(ShadowTypeInferrer inferrer, DartType typeContext) {
+    var library = inferrer.engine.beingInferred[target];
+    if (library != null) {
+      // There is a cyclic dependency where inferring the types of the
+      // initializing formals of a constructor required us to infer the
+      // corresponding field type which required us to know the type of the
+      // constructor.
+      var name = target.enclosingClass.name;
+      if (target.name.name != '') name += '.${target.name.name}';
+      library.addProblem(
+          templateCantInferTypeDueToCircularity.withArguments(name),
+          target.fileOffset,
+          name.length,
+          target.fileUri);
+      for (var declaration in target.function.positionalParameters) {
+        declaration.type ??= const DynamicType();
+      }
+      for (var declaration in target.function.namedParameters) {
+        declaration.type ??= const DynamicType();
+      }
+    } else if ((library = inferrer.engine.toBeInferred[target]) != null) {
+      inferrer.engine.toBeInferred.remove(target);
+      inferrer.engine.beingInferred[target] = library;
+      for (var declaration in target.function.positionalParameters) {
+        inferrer.engine.inferInitializingFormal(declaration, target);
+      }
+      for (var declaration in target.function.namedParameters) {
+        inferrer.engine.inferInitializingFormal(declaration, target);
+      }
+      inferrer.engine.beingInferred.remove(target);
+    }
     var inferredType = inferrer.inferInvocation(
         typeContext,
         fileOffset,
@@ -807,7 +840,7 @@
 /// Concrete shadow object representing a field in kernel form.
 class ShadowField extends Field implements ShadowMember {
   @override
-  InferenceNode _inferenceNode;
+  InferenceNode inferenceNode;
 
   ShadowTypeInferrer _typeInferrer;
 
@@ -823,13 +856,13 @@
   }
 
   static bool hasTypeInferredFromInitializer(ShadowField field) =>
-      field._inferenceNode is FieldInitializerInferenceNode;
+      field.inferenceNode is FieldInitializerInferenceNode;
 
   static bool isImplicitlyTyped(ShadowField field) => field._isImplicitlyTyped;
 
   static void setInferenceNode(ShadowField field, InferenceNode node) {
-    assert(field._inferenceNode == null);
-    field._inferenceNode = node;
+    assert(field.inferenceNode == null);
+    field.inferenceNode = node;
   }
 }
 
@@ -1428,18 +1461,18 @@
 abstract class ShadowMember implements Member {
   Uri get fileUri;
 
-  InferenceNode get _inferenceNode;
+  InferenceNode get inferenceNode;
 
-  void set _inferenceNode(InferenceNode value);
+  void set inferenceNode(InferenceNode value);
 
   void setInferredType(
       TypeInferenceEngine engine, Uri uri, DartType inferredType);
 
   static void resolveInferenceNode(Member member) {
     if (member is ShadowMember) {
-      if (member._inferenceNode != null) {
-        member._inferenceNode.resolve();
-        member._inferenceNode = null;
+      if (member.inferenceNode != null) {
+        member.inferenceNode.resolve();
+        member.inferenceNode = null;
       }
     }
   }
@@ -1568,7 +1601,7 @@
 /// Concrete shadow object representing a procedure in kernel form.
 class ShadowProcedure extends Procedure implements ShadowMember {
   @override
-  InferenceNode _inferenceNode;
+  InferenceNode inferenceNode;
 
   final bool _hasImplicitReturnType;
 
@@ -1757,9 +1790,9 @@
     if (write is StaticSet) {
       writeContext = write.target.setterType;
       writeMember = write.target;
-      if (writeMember is ShadowField && writeMember._inferenceNode != null) {
-        writeMember._inferenceNode.resolve();
-        writeMember._inferenceNode = null;
+      if (writeMember is ShadowField && writeMember.inferenceNode != null) {
+        writeMember.inferenceNode.resolve();
+        writeMember.inferenceNode = null;
       }
     }
     var inferredResult = _inferRhs(inferrer, readType, writeContext);
@@ -1776,9 +1809,9 @@
   @override
   DartType _inferExpression(ShadowTypeInferrer inferrer, DartType typeContext) {
     var target = this.target;
-    if (target is ShadowField && target._inferenceNode != null) {
-      target._inferenceNode.resolve();
-      target._inferenceNode = null;
+    if (target is ShadowField && target.inferenceNode != null) {
+      target.inferenceNode.resolve();
+      target.inferenceNode = null;
     }
     var type = target.getterType;
     if (target is Procedure && target.kind == ProcedureKind.Method) {
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
index 5a912e3..c436163 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -514,10 +514,12 @@
       Constructor constructor, Map<TypeParameter, DartType> substitutionMap) {
     VariableDeclaration copyFormal(VariableDeclaration formal) {
       // TODO(ahe): Handle initializers.
-      return new VariableDeclaration(formal.name,
-          type: substitute(formal.type, substitutionMap),
-          isFinal: formal.isFinal,
-          isConst: formal.isConst);
+      var copy = new VariableDeclaration(formal.name,
+          isFinal: formal.isFinal, isConst: formal.isConst);
+      if (formal.type != null) {
+        copy.type = substitute(formal.type, substitutionMap);
+      }
+      return copy;
     }
 
     List<VariableDeclaration> positionalParameters = <VariableDeclaration>[];
diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart
index 0501d8b..8937d33 100644
--- a/pkg/front_end/lib/src/fasta/parser/parser.dart
+++ b/pkg/front_end/lib/src/fasta/parser/parser.dart
@@ -776,18 +776,7 @@
     if (!optional('(', leftParen)) {
       reportRecoverableError(
           leftParen, fasta.templateExpectedButGot.withArguments('('));
-
-      int offset = leftParen.charOffset;
-      BeginToken openParen =
-          new SyntheticBeginToken(TokenType.OPEN_PAREN, offset);
-      Token next = openParen
-          .setNext(new SyntheticStringToken(TokenType.IDENTIFIER, '', offset));
-      next = next.setNext(new SyntheticToken(TokenType.CLOSE_PAREN, offset));
-      openParen.endGroup = next;
-
-      token.setNext(openParen);
-      next.setNext(leftParen);
-      leftParen = openParen;
+      leftParen = rewriter.insertParens(token, true);
     }
     token = parseDottedName(leftParen);
     Token next = token.next;
@@ -1150,10 +1139,7 @@
     Token next = token.next;
     if (!optional('(', next)) {
       reportRecoverableError(next, missingParameterMessage(kind));
-      Token replacement = link(
-          new SyntheticBeginToken(TokenType.OPEN_PAREN, next.charOffset),
-          new SyntheticToken(TokenType.CLOSE_PAREN, next.charOffset));
-      rewriter.insertTokenAfter(token, replacement);
+      rewriter.insertParens(token, false);
     }
     return parseFormalParameters(token, kind);
   }
@@ -2469,7 +2455,7 @@
       token = name;
       listener.handleNoTypeVariables(token.next);
     }
-    checkFormals(name, isGetter, token.next, MemberKind.TopLevelMethod);
+    checkFormals(token, name, isGetter, MemberKind.TopLevelMethod);
     token = parseFormalParametersOpt(token, MemberKind.TopLevelMethod);
     AsyncModifier savedAsyncModifier = asyncState;
     Token asyncToken = token.next;
@@ -2499,10 +2485,11 @@
     return token;
   }
 
-  void checkFormals(Token name, bool isGetter, Token token, MemberKind kind) {
-    if (optional("(", token)) {
+  void checkFormals(Token token, Token name, bool isGetter, MemberKind kind) {
+    Token next = token.next;
+    if (optional("(", next)) {
       if (isGetter) {
-        reportRecoverableError(token, fasta.messageGetterWithFormals);
+        reportRecoverableError(next, fasta.messageGetterWithFormals);
       }
     } else if (!isGetter) {
       if (optional('operator', name)) {
@@ -2513,7 +2500,9 @@
           name = next.next;
         }
       }
+      // Recovery
       reportRecoverableError(name, missingParameterMessage(kind));
+      rewriter.insertParens(token, false);
     }
   }
 
@@ -3157,7 +3146,7 @@
     MemberKind kind = staticToken != null
         ? MemberKind.StaticMethod
         : MemberKind.NonStaticMethod;
-    checkFormals(name, isGetter, token.next, kind);
+    checkFormals(token, name, isGetter, kind);
     Token beforeParam = token;
     token = parseFormalParametersOpt(token, kind);
     token = parseInitializersOpt(token);
@@ -4203,10 +4192,7 @@
       // TODO(danrubel): Consider removing the 2nd error message.
       reportRecoverableError(
           next, fasta.templateExpectedToken.withArguments(')'));
-      BeginToken replacement = link(
-          new SyntheticBeginToken(TokenType.OPEN_PAREN, next.charOffset),
-          new SyntheticToken(TokenType.CLOSE_PAREN, next.charOffset));
-      rewriter.insertTokenAfter(token, replacement).next;
+      rewriter.insertParens(token, false);
     }
     Token begin = token.next;
     token = parseExpressionInParenthesis(token);
@@ -4474,10 +4460,7 @@
     if (!optional('(', next)) {
       reportRecoverableError(
           token, fasta.templateExpectedButGot.withArguments('('));
-      BeginToken replacement = link(
-          new SyntheticBeginToken(TokenType.OPEN_PAREN, next.offset),
-          new SyntheticToken(TokenType.CLOSE_PAREN, next.offset));
-      rewriter.insertTokenAfter(token, replacement);
+      rewriter.insertParens(token, false);
     }
     token = parseArguments(token);
     return token;
@@ -5507,15 +5490,7 @@
         Token openParens = catchKeyword.next;
         if (!optional("(", openParens)) {
           reportRecoverableError(openParens, fasta.messageCatchSyntax);
-          BeginToken open = new SyntheticBeginToken(
-              TokenType.OPEN_PAREN, openParens.charOffset);
-          Token identifier = open.setNext(new SyntheticStringToken(
-              TokenType.IDENTIFIER, '', openParens.charOffset));
-          Token close = identifier.setNext(
-              new SyntheticToken(TokenType.CLOSE_PAREN, openParens.charOffset));
-          open.endGroup = close;
-          rewriter.insertTokenAfter(catchKeyword, open);
-          openParens = open;
+          openParens = rewriter.insertParens(catchKeyword, true);
         }
 
         Token exceptionName = openParens.next;
@@ -5774,18 +5749,7 @@
       // Recovery
       reportRecoverableError(
           leftParenthesis, fasta.templateExpectedButGot.withArguments('('));
-      int offset = leftParenthesis.offset;
-
-      BeginToken openParen =
-          token.setNext(new SyntheticBeginToken(TokenType.OPEN_PAREN, offset));
-      Token identifier = openParen
-          .setNext(new SyntheticStringToken(TokenType.IDENTIFIER, '', offset));
-      Token closeParen =
-          identifier.setNext(new SyntheticToken(TokenType.CLOSE_PAREN, offset));
-      openParen.endGroup = closeParen;
-      closeParen.setNext(leftParenthesis);
-
-      leftParenthesis = openParen;
+      leftParenthesis = rewriter.insertParens(token, true);
     }
     token = leftParenthesis;
     Token commaToken = null;
diff --git a/pkg/front_end/lib/src/fasta/parser/token_stream_rewriter.dart b/pkg/front_end/lib/src/fasta/parser/token_stream_rewriter.dart
index 529c38e..38b68b6 100644
--- a/pkg/front_end/lib/src/fasta/parser/token_stream_rewriter.dart
+++ b/pkg/front_end/lib/src/fasta/parser/token_stream_rewriter.dart
@@ -6,6 +6,7 @@
     show
         BeginToken,
         SimpleToken,
+        SyntheticBeginToken,
         SyntheticStringToken,
         SyntheticToken,
         Token,
@@ -39,6 +40,25 @@
   /// Initialize a newly created re-writer.
   TokenStreamRewriter();
 
+  /// Insert a synthetic open and close parenthesis and return the new synthetic
+  /// open parenthesis. If [insertIdentifier] is true, then a synthetic
+  /// identifier is included between the open and close parenthesis.
+  Token insertParens(Token token, bool includeIdentifier) {
+    Token next = token.next;
+    int offset = next.charOffset;
+    BeginToken leftParen =
+        next = new SyntheticBeginToken(TokenType.OPEN_PAREN, offset);
+    if (includeIdentifier) {
+      next = next.setNext(
+          new SyntheticStringToken(TokenType.IDENTIFIER, '', offset, 0));
+    }
+    next = next.setNext(new SyntheticToken(TokenType.CLOSE_PAREN, offset));
+    leftParen.endGroup = next;
+    next.setNext(token.next);
+    token.setNext(leftParen);
+    return leftParen;
+  }
+
   /// Insert a synthetic identifier after [token] and return the new identifier.
   Token insertSyntheticIdentifier(Token token) {
     Token identifier = new SyntheticStringToken(
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index f3952c9..1a037f4 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -815,8 +815,6 @@
     ticker.logMs("Performed top level inference");
   }
 
-  List<Uri> getDependencies() => sourceBytes.keys.toList();
-
   Expression instantiateInvocation(Expression receiver, String name,
       Arguments arguments, int offset, bool isSuper) {
     return target.backendTarget.instantiateInvocation(
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
index 5a52a48..9fe590f 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
@@ -4,16 +4,16 @@
 
 import 'package:kernel/ast.dart'
     show
-        Class,
+        Constructor,
         DartType,
         DartTypeVisitor,
         DynamicType,
         FunctionType,
         InterfaceType,
-        Location,
         TypeParameter,
         TypeParameterType,
-        TypedefType;
+        TypedefType,
+        VariableDeclaration;
 import 'package:kernel/class_hierarchy.dart';
 import 'package:kernel/core_types.dart';
 
@@ -21,12 +21,9 @@
 
 import '../builder/library_builder.dart';
 
-import '../deprecated_problems.dart' show Crash;
-
 import '../kernel/kernel_shadow_ast.dart';
 
-import '../messages.dart'
-    show getLocationFromNode, noLength, templateCantInferTypeDueToCircularity;
+import '../messages.dart' show noLength, templateCantInferTypeDueToCircularity;
 
 import '../source/source_library_builder.dart';
 
@@ -211,7 +208,20 @@
 
   final staticInferenceNodes = <FieldInitializerInferenceNode>[];
 
-  final initializingFormals = <ShadowVariableDeclaration>[];
+  /// A map containing constructors with initializing formals whose types
+  /// need to be inferred.
+  ///
+  /// This is represented as a map from a constructor to its library
+  /// builder because the builder is used to report errors due to cyclic
+  /// inference dependencies.
+  final Map<Constructor, LibraryBuilder> toBeInferred = {};
+
+  /// A map containing constructors in the process of being inferred.
+  ///
+  /// This is used to detect cyclic inference dependencies.  It is represented
+  /// as a map from a constructor to its library builder because the builder
+  /// is used to report errors.
+  final Map<Constructor, LibraryBuilder> beingInferred = {};
 
   final Instrumentation instrumentation;
 
@@ -248,20 +258,37 @@
   }
 
   /// Performs the third phase of top level inference, which is to visit all
-  /// initializing formals and infer their types (if necessary) from the
-  /// corresponding fields.
+  /// constructors still needing inference and infer the types of their
+  /// initializing formals from the corresponding fields.
   void finishTopLevelInitializingFormals() {
-    for (ShadowVariableDeclaration formal in initializingFormals) {
-      try {
-        formal.type = _inferInitializingFormalType(formal);
-      } catch (e, s) {
-        Location location = getLocationFromNode(formal);
-        if (location == null) {
-          rethrow;
-        } else {
-          throw new Crash(location.file, formal.fileOffset, e, s);
+    // Field types have all been inferred so there cannot be a cyclic
+    // dependency.
+    for (Constructor constructor in toBeInferred.keys) {
+      for (var declaration in constructor.function.positionalParameters) {
+        inferInitializingFormal(declaration, constructor);
+      }
+      for (var declaration in constructor.function.namedParameters) {
+        inferInitializingFormal(declaration, constructor);
+      }
+    }
+    toBeInferred.clear();
+  }
+
+  void inferInitializingFormal(VariableDeclaration formal, Constructor parent) {
+    if (formal.type == null) {
+      for (ShadowField field in parent.enclosingClass.fields) {
+        if (field.name.name == formal.name) {
+          if (field.inferenceNode != null) {
+            field.inferenceNode.resolve();
+          }
+          formal.type = field.type;
+          return;
         }
       }
+      // We did not find the corresponding field, so the program is erroneous.
+      // The error should have been reported elsewhere and type inference
+      // should continue by inferring dynamic.
+      formal.type = const DynamicType();
     }
   }
 
@@ -274,12 +301,6 @@
         new TypeSchemaEnvironment(coreTypes, hierarchy, strongMode);
   }
 
-  /// Records that the given initializing [formal] will need top level type
-  /// inference.
-  void recordInitializingFormal(ShadowVariableDeclaration formal) {
-    initializingFormals.add(formal);
-  }
-
   /// Records that the given static [field] will need top level type inference.
   void recordStaticFieldInferenceCandidate(
       ShadowField field, LibraryBuilder library) {
@@ -287,20 +308,4 @@
     ShadowField.setInferenceNode(field, node);
     staticInferenceNodes.add(node);
   }
-
-  DartType _inferInitializingFormalType(ShadowVariableDeclaration formal) {
-    assert(ShadowVariableDeclaration.isImplicitlyTyped(formal));
-    var enclosingClass = formal.parent?.parent?.parent;
-    if (enclosingClass is Class) {
-      for (var field in enclosingClass.fields) {
-        if (field.name.name == formal.name) {
-          return field.type;
-        }
-      }
-    }
-    // No matching field, or something else has gone wrong (e.g. initializing
-    // formal outside of a class declaration).  The error should be reported
-    // elsewhere, so just infer `dynamic`.
-    return const DynamicType();
-  }
 }
diff --git a/pkg/front_end/lib/src/kernel_generator_impl.dart b/pkg/front_end/lib/src/kernel_generator_impl.dart
index 8b78836..b699884 100644
--- a/pkg/front_end/lib/src/kernel_generator_impl.dart
+++ b/pkg/front_end/lib/src/kernel_generator_impl.dart
@@ -144,7 +144,7 @@
     return new CompilerResult(
         summary: summary,
         component: component,
-        deps: kernelTarget.loader.getDependencies());
+        deps: new List<Uri>.from(CompilerContext.current.dependencies));
   } on deprecated_InputError catch (e) {
     options.report(
         deprecated_InputError.toMessage(e), Severity.internalProblem);
diff --git a/pkg/front_end/lib/src/api_prototype/scheme_based_file_system.dart b/pkg/front_end/lib/src/scheme_based_file_system.dart
similarity index 94%
rename from pkg/front_end/lib/src/api_prototype/scheme_based_file_system.dart
rename to pkg/front_end/lib/src/scheme_based_file_system.dart
index c992ea7..c2b3981 100644
--- a/pkg/front_end/lib/src/api_prototype/scheme_based_file_system.dart
+++ b/pkg/front_end/lib/src/scheme_based_file_system.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.
 
-import 'file_system.dart';
+import 'api_prototype/file_system.dart';
 
 /// A [FileSystem] that delegates to other file systems based on the URI scheme.
 class SchemeBasedFileSystem implements FileSystem {
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
index d308900..8c56c40 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -116,7 +116,6 @@
 DuplicatedExportInType/analyzerCode: Fail
 DuplicatedExportInType/example: Fail
 DuplicatedImportInType/analyzerCode: Fail
-DuplicatedImportInType/example: Fail
 DuplicatedModifier/script1: Fail
 DuplicatedName/analyzerCode: Fail
 DuplicatedName/example: Fail
@@ -249,7 +248,6 @@
 MissingMain/analyzerCode: Fail
 MissingMain/example: Fail
 MissingPartOf/analyzerCode: Fail
-MissingPartOf/example: Fail
 MissingPrefixInDeferredImport/example: Fail
 MixinInferenceNoMatchingClass/analyzerCode: Fail
 MixinInferenceNoMatchingClass/example: Fail
@@ -299,15 +297,12 @@
 PartOfLibraryNameMismatch/analyzerCode: Fail
 PartOfLibraryNameMismatch/example: Fail
 PartOfSelf/analyzerCode: Fail
-PartOfSelf/example: Fail
 PartOfTwoLibraries/analyzerCode: Fail # Issue 33227
-PartOfTwoLibraries/example: Fail # Needs multiple files
 PartOfUriMismatch/analyzerCode: Fail
 PartOfUriMismatch/example: Fail
 PartOfUseUri/analyzerCode: Fail
 PartOfUseUri/example: Fail
 PartTwice/analyzerCode: Fail
-PartTwice/example: Fail
 PatchClassTypeVariablesMismatch/analyzerCode: Fail
 PatchClassTypeVariablesMismatch/example: Fail
 PatchDeclarationMismatch/analyzerCode: Fail
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index af33dd73..534bfdf 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -1410,6 +1410,10 @@
 DuplicatedImportInType:
   template: "'#name' is imported from both '#uri' and '#uri2'."
   severity: ERROR_LEGACY_WARNING
+  script:
+    lib1.dart: "class A {}"
+    lib2.dart: "class A {}"
+    main.dart: "import 'lib1.dart'; import 'lib2.dart'; A a;"
 
 CyclicClassHierarchy:
   template: "'#name' is a supertype of itself via '#string'."
@@ -1579,6 +1583,8 @@
 
 PartOfSelf:
   template: "A file can't be a part of itself."
+  script:
+    main.dart: "part 'main.dart';"
 
 TypeVariableDuplicatedName:
   template: "A type variable can't have the same name as another."
@@ -1703,11 +1709,18 @@
 
 PartTwice:
   template: "Can't use '#uri' as a part more than once."
+  script:
+    part.dart: "part of 'main.dart';"
+    main.dart: "part 'part.dart'; part 'part.dart';"
 
 PartOfTwoLibraries:
   template: "A file can't be part of more than one library."
   tip: "Try moving the shared declarations into the libraries, or into a new library."
   severity: ERROR
+  script:
+    main.dart: "library lib; import 'lib.dart'; part 'part.dart';"
+    lib.dart: "library lib; part 'part.dart';"
+    part.dart: "part of lib;"
 
 PartOfTwoLibrariesContext:
   template: "Used as a part in this library."
@@ -1765,6 +1778,9 @@
 
 MissingPartOf:
   template: "Can't use '#uri' as a part, because it has no 'part of' declaration."
+  script:
+    part.dart: ""
+    main.dart: "part 'part.dart';"
 
 SupertypeIsFunction:
   template: "Can't use a function type as supertype."
diff --git a/pkg/front_end/pubspec.yaml b/pkg/front_end/pubspec.yaml
index 4ba2dc2..86c698f 100644
--- a/pkg/front_end/pubspec.yaml
+++ b/pkg/front_end/pubspec.yaml
@@ -20,6 +20,7 @@
 dev_dependencies:
   analyzer: '>=0.31.0 <0.33.0'
   args: '>=0.13.0 <2.0.0'
+  build_integration: ^0.0.1
   dart_style: '^1.0.7'
   json_rpc_2: ^2.0.4
   mockito: ^2.0.2
diff --git a/pkg/front_end/test/fasta/generator_to_string_test.dart b/pkg/front_end/test/fasta/generator_to_string_test.dart
index 8d1dad4..4901f63 100644
--- a/pkg/front_end/test/fasta/generator_to_string_test.dart
+++ b/pkg/front_end/test/fasta/generator_to_string_test.dart
@@ -54,11 +54,11 @@
 
 import 'package:front_end/src/fasta/kernel/kernel_expression_generator.dart'
     show
-        DelayedAssignment,
-        DelayedPostfixIncrement,
         IncompleteErrorGenerator,
         IncompletePropertyAccessGenerator,
         KernelDeferredAccessGenerator,
+        KernelDelayedAssignment,
+        KernelDelayedPostfixIncrement,
         KernelIndexedAccessGenerator,
         KernelLargeIntAccessGenerator,
         KernelLoadLibraryGenerator,
@@ -140,12 +140,12 @@
     check(
         "DelayedAssignment(offset: 4, value: expression,"
         " assignmentOperator: +=)",
-        new DelayedAssignment(
+        new KernelDelayedAssignment(
             helper, token, generator, expression, assignmentOperator));
     check(
         "DelayedPostfixIncrement(offset: 4, binaryOperator: +,"
         " interfaceTarget: $uri::#class1::myInterfaceTarget)",
-        new DelayedPostfixIncrement(
+        new KernelDelayedPostfixIncrement(
             helper, token, generator, binaryOperator, interfaceTarget));
     check(
         "VariableUseGenerator(offset: 4, variable: dynamic #t1;\n,"
diff --git a/pkg/front_end/test/fasta/messages_test.dart b/pkg/front_end/test/fasta/messages_test.dart
index e1a706c..d5d759d 100644
--- a/pkg/front_end/test/fasta/messages_test.dart
+++ b/pkg/front_end/test/fasta/messages_test.dart
@@ -157,10 +157,11 @@
             if (node is YamlList) {
               int i = 0;
               for (YamlNode script in node.nodes) {
-                examples.add(new ScriptExample("script${++i}", name, script));
+                examples
+                    .add(new ScriptExample("script${++i}", name, script, this));
               }
             } else {
-              examples.add(new ScriptExample("script", name, node));
+              examples.add(new ScriptExample("script", name, node, this));
             }
             break;
 
@@ -301,6 +302,10 @@
   YamlNode get node;
 
   Uint8List get bytes;
+
+  Map<String, Uint8List> get scripts {
+    return {"main.dart": bytes};
+  }
 }
 
 class BytesExample extends Example {
@@ -380,15 +385,33 @@
   @override
   final YamlNode node;
 
-  final String script;
+  final Object script;
 
-  ScriptExample(String name, String code, this.node)
+  ScriptExample(String name, String code, this.node, MessageTestSuite suite)
       : script = node.value,
-        super(name, code);
+        super(name, code) {
+    if (script is! String && script is! Map) {
+      throw suite.formatProblems(
+          "A script must be either a String or a Map in $code:",
+          this, <List>[]);
+    }
+  }
 
   @override
-  Uint8List get bytes {
-    return new Uint8List.fromList(utf8.encode(script));
+  Uint8List get bytes => throw "Unsupported: ScriptExample.bytes";
+
+  @override
+  Map<String, Uint8List> get scripts {
+    Object script = this.script;
+    if (script is Map) {
+      var scriptFiles = <String, Uint8List>{};
+      script.forEach((fileName, value) {
+        scriptFiles[fileName] = new Uint8List.fromList(utf8.encode(value));
+      });
+      return scriptFiles;
+    } else {
+      return {"main.dart": new Uint8List.fromList(utf8.encode(script))};
+    }
   }
 }
 
@@ -414,12 +437,16 @@
 
   Future<Result<Null>> run(Example example, MessageTestSuite suite) async {
     if (example == null) return pass(null);
-    String name = "${example.expectedCode}/${example.name}";
-    Uri uri = suite.fileSystem.currentDirectory.resolve("${name}.dart");
-    suite.fileSystem.entityForUri(uri).writeAsBytesSync(example.bytes);
-    Uri output = uri.resolve("${uri.path}.dill");
+    String dir = "${example.expectedCode}/${example.name}";
+    example.scripts.forEach((String fileName, Uint8List bytes) {
+      Uri uri = suite.fileSystem.currentDirectory.resolve("$dir/$fileName");
+      suite.fileSystem.entityForUri(uri).writeAsBytesSync(bytes);
+    });
+    Uri main = suite.fileSystem.currentDirectory.resolve("$dir/main.dart");
+    Uri output =
+        suite.fileSystem.currentDirectory.resolve("$dir/main.dart.dill");
 
-    print("Compiling $uri");
+    print("Compiling $main");
     List<List> problems = <List>[];
 
     await suite.compiler.batchCompile(
@@ -432,7 +459,7 @@
             problems.add([problem, severity]);
           }
           ..strongMode = true,
-        uri,
+        main,
         output);
 
     List<List> unexpectedProblems = <List>[];
diff --git a/pkg/front_end/test/scheme_based_file_system_test.dart b/pkg/front_end/test/scheme_based_file_system_test.dart
index be40f65..e6b374b 100644
--- a/pkg/front_end/test/scheme_based_file_system_test.dart
+++ b/pkg/front_end/test/scheme_based_file_system_test.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:front_end/src/api_prototype/file_system.dart';
-import 'package:front_end/src/api_prototype/scheme_based_file_system.dart';
+import 'package:front_end/src/scheme_based_file_system.dart';
 
 import 'package:test/test.dart';
 
diff --git a/pkg/front_end/testcases/circularity-via-initializing-formal.dart b/pkg/front_end/testcases/circularity-via-initializing-formal.dart
new file mode 100644
index 0000000..939cb91
--- /dev/null
+++ b/pkg/front_end/testcases/circularity-via-initializing-formal.dart
@@ -0,0 +1,18 @@
+// 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 is intended to trigger a circular top-level type-inference
+// dependency involving an initializing formal where the circularity is detected
+// when inferring the type of the constructor.
+//
+// The compiler should generate an error message and it should be properly
+// formatted including offset and lenght of the constructor.
+var x = new C._circular(null);
+
+class C {
+  var f = new C._circular(null);
+  C._circular(this.f);
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/circularity-via-initializing-formal.dart.direct.expect b/pkg/front_end/testcases/circularity-via-initializing-formal.dart.direct.expect
new file mode 100644
index 0000000..245a701
--- /dev/null
+++ b/pkg/front_end/testcases/circularity-via-initializing-formal.dart.direct.expect
@@ -0,0 +1,12 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  field dynamic f = new self::C::_circular(null);
+  constructor _circular(dynamic f) → void
+    : self::C::f = f, super core::Object::•()
+    ;
+}
+static field dynamic x = new self::C::_circular(null);
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/circularity-via-initializing-formal.dart.direct.transformed.expect b/pkg/front_end/testcases/circularity-via-initializing-formal.dart.direct.transformed.expect
new file mode 100644
index 0000000..245a701
--- /dev/null
+++ b/pkg/front_end/testcases/circularity-via-initializing-formal.dart.direct.transformed.expect
@@ -0,0 +1,12 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  field dynamic f = new self::C::_circular(null);
+  constructor _circular(dynamic f) → void
+    : self::C::f = f, super core::Object::•()
+    ;
+}
+static field dynamic x = new self::C::_circular(null);
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/circularity-via-initializing-formal.dart.outline.expect b/pkg/front_end/testcases/circularity-via-initializing-formal.dart.outline.expect
new file mode 100644
index 0000000..9bdea4e
--- /dev/null
+++ b/pkg/front_end/testcases/circularity-via-initializing-formal.dart.outline.expect
@@ -0,0 +1,12 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  field dynamic f;
+  constructor _circular(dynamic f) → void
+    ;
+}
+static field dynamic x;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/circularity-via-initializing-formal.dart.strong.expect b/pkg/front_end/testcases/circularity-via-initializing-formal.dart.strong.expect
new file mode 100644
index 0000000..6fa3d2b
--- /dev/null
+++ b/pkg/front_end/testcases/circularity-via-initializing-formal.dart.strong.expect
@@ -0,0 +1,16 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  field self::C f = new self::C::_circular(null);
+  constructor _circular(self::C f) → void
+    : self::C::f = f, super core::Object::•()
+    ;
+}
+static field self::C x = new self::C::_circular(null);
+static const field dynamic #errors = const <dynamic>["pkg/front_end/testcases/circularity-via-initializing-formal.dart:15:3: Error: Can't infer the type of 'C._circular': circularity found during type inference.
+Specify the type explicitly.
+  C._circular(this.f);
+  ^^^^^^^^^^^"]/* from null */;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/circularity-via-initializing-formal.dart.strong.transformed.expect b/pkg/front_end/testcases/circularity-via-initializing-formal.dart.strong.transformed.expect
new file mode 100644
index 0000000..6fa3d2b
--- /dev/null
+++ b/pkg/front_end/testcases/circularity-via-initializing-formal.dart.strong.transformed.expect
@@ -0,0 +1,16 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  field self::C f = new self::C::_circular(null);
+  constructor _circular(self::C f) → void
+    : self::C::f = f, super core::Object::•()
+    ;
+}
+static field self::C x = new self::C::_circular(null);
+static const field dynamic #errors = const <dynamic>["pkg/front_end/testcases/circularity-via-initializing-formal.dart:15:3: Error: Can't infer the type of 'C._circular': circularity found during type inference.
+Specify the type explicitly.
+  C._circular(this.f);
+  ^^^^^^^^^^^"]/* from null */;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/regress/issue_31155.dart.direct.expect b/pkg/front_end/testcases/regress/issue_31155.dart.direct.expect
index 4776f6a..cf914a5 100644
--- a/pkg/front_end/testcases/regress/issue_31155.dart.direct.expect
+++ b/pkg/front_end/testcases/regress/issue_31155.dart.direct.expect
@@ -32,5 +32,12 @@
   var f = Map<A, B> {};
                   ^", "pkg/front_end/testcases/regress/issue_31155.dart:11:23: Error: Expected a class member, but got ';'.
   var f = Map<A, B> {};
-                      ^"]/* from null */;
+                      ^", "pkg/front_end/testcases/regress/issue_31155.dart:11:11: Error: A function expression can't have a name.
+  var f = Map<A, B> {};
+          ^^^", "pkg/front_end/testcases/regress/issue_31155.dart:11:14: Error: A function declaration needs an explicit list of parameters.
+Try adding a parameter list to the function declaration.
+  var f = Map<A, B> {};
+             ^", "pkg/front_end/testcases/regress/issue_31155.dart:11:14: Error: Expected a function body, but got '<'.
+  var f = Map<A, B> {};
+             ^"]/* from null */;
 static method main() → void {}
diff --git a/pkg/front_end/testcases/regress/issue_31155.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_31155.dart.direct.transformed.expect
index 4776f6a..cf914a5 100644
--- a/pkg/front_end/testcases/regress/issue_31155.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_31155.dart.direct.transformed.expect
@@ -32,5 +32,12 @@
   var f = Map<A, B> {};
                   ^", "pkg/front_end/testcases/regress/issue_31155.dart:11:23: Error: Expected a class member, but got ';'.
   var f = Map<A, B> {};
-                      ^"]/* from null */;
+                      ^", "pkg/front_end/testcases/regress/issue_31155.dart:11:11: Error: A function expression can't have a name.
+  var f = Map<A, B> {};
+          ^^^", "pkg/front_end/testcases/regress/issue_31155.dart:11:14: Error: A function declaration needs an explicit list of parameters.
+Try adding a parameter list to the function declaration.
+  var f = Map<A, B> {};
+             ^", "pkg/front_end/testcases/regress/issue_31155.dart:11:14: Error: Expected a function body, but got '<'.
+  var f = Map<A, B> {};
+             ^"]/* from null */;
 static method main() → void {}
diff --git a/pkg/front_end/testcases/regress/issue_31155.dart.strong.expect b/pkg/front_end/testcases/regress/issue_31155.dart.strong.expect
index e088ade..da8a488 100644
--- a/pkg/front_end/testcases/regress/issue_31155.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_31155.dart.strong.expect
@@ -35,5 +35,12 @@
   var f = Map<A, B> {};
                   ^", "pkg/front_end/testcases/regress/issue_31155.dart:11:23: Error: Expected a class member, but got ';'.
   var f = Map<A, B> {};
-                      ^"]/* from null */;
+                      ^", "pkg/front_end/testcases/regress/issue_31155.dart:11:11: Error: A function expression can't have a name.
+  var f = Map<A, B> {};
+          ^^^", "pkg/front_end/testcases/regress/issue_31155.dart:11:14: Error: A function declaration needs an explicit list of parameters.
+Try adding a parameter list to the function declaration.
+  var f = Map<A, B> {};
+             ^", "pkg/front_end/testcases/regress/issue_31155.dart:11:14: Error: Expected a function body, but got '<'.
+  var f = Map<A, B> {};
+             ^"]/* from null */;
 static method main() → void {}
diff --git a/pkg/front_end/testcases/regress/issue_31155.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_31155.dart.strong.transformed.expect
index 3e6b682..f332e29 100644
--- a/pkg/front_end/testcases/regress/issue_31155.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_31155.dart.strong.transformed.expect
@@ -35,5 +35,12 @@
   var f = Map<A, B> {};
                   ^", "pkg/front_end/testcases/regress/issue_31155.dart:11:23: Error: Expected a class member, but got ';'.
   var f = Map<A, B> {};
-                      ^"]/* from null */;
+                      ^", "pkg/front_end/testcases/regress/issue_31155.dart:11:11: Error: A function expression can't have a name.
+  var f = Map<A, B> {};
+          ^^^", "pkg/front_end/testcases/regress/issue_31155.dart:11:14: Error: A function declaration needs an explicit list of parameters.
+Try adding a parameter list to the function declaration.
+  var f = Map<A, B> {};
+             ^", "pkg/front_end/testcases/regress/issue_31155.dart:11:14: Error: Expected a function body, but got '<'.
+  var f = Map<A, B> {};
+             ^"]/* from null */;
 static method main() → void {}
diff --git a/pkg/front_end/tool/_fasta/command_line.dart b/pkg/front_end/tool/_fasta/command_line.dart
index daceb3cd..8408682 100644
--- a/pkg/front_end/tool/_fasta/command_line.dart
+++ b/pkg/front_end/tool/_fasta/command_line.dart
@@ -6,9 +6,17 @@
 
 import 'dart:io' show exit;
 
+import 'package:build_integration/file_system/single_root.dart'
+    show SingleRootFileSystem;
+
 import 'package:front_end/src/api_prototype/compiler_options.dart'
     show CompilerOptions;
 
+import 'package:front_end/src/api_prototype/file_system.dart' show FileSystem;
+
+import 'package:front_end/src/api_prototype/standard_file_system.dart'
+    show StandardFileSystem;
+
 import 'package:front_end/src/base/processed_options.dart'
     show ProcessedOptions;
 
@@ -29,10 +37,13 @@
 
 import 'package:front_end/src/fasta/severity.dart' show Severity;
 
+import 'package:front_end/src/scheme_based_file_system.dart'
+    show SchemeBasedFileSystem;
+
 import 'package:kernel/target/targets.dart'
     show Target, getTarget, TargetFlags, targets;
 
-Uri resolveFile(String path) => Uri.base.resolveUri(new Uri.file(path));
+import 'resolve_input_uri.dart' show resolveInputUri;
 
 class CommandLineProblem {
   final Message message;
@@ -159,7 +170,9 @@
                     "but expected one of: 'true', 'false', 'yes', or 'no'.");
               }
             } else if (valueSpecification == Uri) {
-              parsedValue = resolveFile(value);
+              // TODO(ahe): resolve Uris lazily, so that schemes provided by
+              // other flags can be used for parsed command-line arguments too.
+              parsedValue = resolveInputUri(value);
             } else if (valueSpecification == String) {
               parsedValue = value;
             } else if (valueSpecification is String) {
@@ -210,6 +223,8 @@
   "--packages": Uri,
   "--platform": Uri,
   "--sdk": Uri,
+  "--single-root-scheme": String,
+  "--single-root-base": Uri,
   "--strong": "--strong-mode",
   "--strong-mode": false,
   "--sync-async": true,
@@ -279,6 +294,24 @@
 
   final bool compileSdk = options.containsKey("--compile-sdk");
 
+  final String singleRootScheme = options["--single-root-scheme"];
+  final Uri singleRootBase = options["--single-root-base"];
+
+  FileSystem fileSystem = StandardFileSystem.instance;
+  List<String> extraSchemes = const [];
+  if (singleRootScheme != null) {
+    extraSchemes = [singleRootScheme];
+    fileSystem = new SchemeBasedFileSystem({
+      'file': fileSystem,
+      'data': fileSystem,
+      // TODO(askesc): remove also when fixing StandardFileSystem (empty schemes
+      // should have been handled elsewhere).
+      '': fileSystem,
+      singleRootScheme: new SingleRootFileSystem(
+          singleRootScheme, singleRootBase, fileSystem),
+    });
+  }
+
   if (programName == "compile_platform") {
     if (arguments.length != 4) {
       return throw new CommandLineProblem.deprecated(
@@ -296,8 +329,10 @@
     return new ProcessedOptions(
         new CompilerOptions()
           ..sdkSummary = options["--platform"]
-          ..librariesSpecificationUri = resolveFile(arguments[1])
+          ..librariesSpecificationUri =
+              resolveInputUri(arguments[1], extraSchemes: extraSchemes)
           ..setExitCodeOnProblem = true
+          ..fileSystem = fileSystem
           ..packagesFileUri = packages
           ..strongMode = strongMode
           ..target = target
@@ -308,12 +343,13 @@
           ..verbose = verbose
           ..verify = verify,
         <Uri>[Uri.parse(arguments[0])],
-        resolveFile(arguments[2]));
+        resolveInputUri(arguments[2], extraSchemes: extraSchemes));
   } else if (arguments.isEmpty) {
     return throw new CommandLineProblem.deprecated("No Dart file specified.");
   }
 
-  final Uri defaultOutput = resolveFile("${arguments.first}.dill");
+  final Uri defaultOutput =
+      resolveInputUri("${arguments.first}.dill", extraSchemes: extraSchemes);
 
   final Uri output = options["-o"] ?? options["--output"] ?? defaultOutput;
 
@@ -326,6 +362,7 @@
 
   CompilerOptions compilerOptions = new CompilerOptions()
     ..compileSdk = compileSdk
+    ..fileSystem = fileSystem
     ..sdkRoot = sdk
     ..sdkSummary = platform
     ..packagesFileUri = packages
@@ -343,7 +380,7 @@
   List<Uri> inputs = <Uri>[];
   if (areRestArgumentsInputs) {
     for (String argument in arguments) {
-      inputs.add(resolveFile(argument));
+      inputs.add(resolveInputUri(argument, extraSchemes: extraSchemes));
     }
   }
   return new ProcessedOptions(compilerOptions, inputs, output);
diff --git a/pkg/front_end/tool/_fasta/compile_platform.dart b/pkg/front_end/tool/_fasta/compile_platform.dart
index fd26f5f..4f02bd0 100644
--- a/pkg/front_end/tool/_fasta/compile_platform.dart
+++ b/pkg/front_end/tool/_fasta/compile_platform.dart
@@ -8,6 +8,8 @@
 
 import 'dart:io' show File, Platform, exitCode;
 
+import 'package:kernel/target/targets.dart' show Target, TargetFlags, getTarget;
+
 import 'package:vm/bytecode/gen_bytecode.dart'
     show generateBytecode, isKernelBytecodeEnabledForPlatform;
 
@@ -16,17 +18,17 @@
 import 'package:front_end/src/fasta/deprecated_problems.dart'
     show deprecated_InputError;
 
+import 'package:front_end/src/fasta/get_dependencies.dart' show getDependencies;
+
 import 'package:front_end/src/fasta/kernel/utils.dart'
     show writeComponentToFile;
 
 import 'package:front_end/src/fasta/severity.dart' show Severity;
 
-import 'package:front_end/src/kernel_generator_impl.dart'
-    show generateKernelInternal;
-
 import 'package:front_end/src/fasta/util/relativize.dart' show relativizeUri;
 
-import 'package:front_end/src/fasta/get_dependencies.dart' show getDependencies;
+import 'package:front_end/src/kernel_generator_impl.dart'
+    show generateKernelInternal;
 
 import 'additional_targets.dart' show installAdditionalTargets;
 
@@ -87,14 +89,33 @@
   c.options.ticker.logMs("Wrote component to ${fullOutput.toFilePath()}");
 
   List<Uri> deps = result.deps.toList();
-  deps.addAll(await getDependencies(Platform.script,
-      platform: outlineOutput, target: c.options.target));
+  for (Uri dependency
+      in await computeHostDependencies(outlineOutput.resolve("./"))) {
+    // Add the dependencies of the compiler's own sources.
+    if (dependency != outlineOutput) {
+      // We're computing the dependencies for [outlineOutput], so we shouldn't
+      // include it in the deps file.
+      deps.add(dependency);
+    }
+  }
   await writeDepsFile(
       fullOutput, new File(new File.fromUri(fullOutput).path + ".d").uri, deps);
 }
 
+Future<List<Uri>> computeHostDependencies(Uri platformLocation) async {
+  // Returns a list of source files that make up the Fasta compiler (the files
+  // the Dart VM reads to run Fasta). Until Fasta is self-hosting (in strong
+  // mode), this is only an approximation, albeit accurate.  Once Fasta is
+  // self-hosting, this isn't an approximation. Regardless, strong mode
+  // shouldn't affect which files are read.
+  Uri hostPlatform = platformLocation.resolve("vm_outline_strong.dill");
+  Target hostTarget = getTarget("vm", new TargetFlags(strongMode: true));
+  return getDependencies(Platform.script,
+      platform: hostPlatform, target: hostTarget);
+}
+
 Future writeDepsFile(
-    Uri output, Uri depsFile, Iterable<Uri> allDependencies) async {
+    Uri output, Uri depsFile, List<Uri> allDependencies) async {
   if (allDependencies.isEmpty) return;
   String toRelativeFilePath(Uri uri) {
     // Ninja expects to find file names relative to the current working
@@ -122,9 +143,20 @@
   StringBuffer sb = new StringBuffer();
   sb.write(toRelativeFilePath(output));
   sb.write(":");
-  for (Uri uri in allDependencies) {
-    sb.write(" \\\n  ");
-    sb.write(toRelativeFilePath(uri));
+  List<String> paths = new List<String>(allDependencies.length);
+  for (int i = 0; i < allDependencies.length; i++) {
+    paths[i] = toRelativeFilePath(allDependencies[i]);
+  }
+  // Sort the relative paths to ease analyzing future changes to this code.
+  paths.sort();
+  String previous;
+  for (String path in paths) {
+    // Check for and omit duplicates.
+    if (path != previous) {
+      previous = path;
+      sb.write(" \\\n  ");
+      sb.write(path);
+    }
   }
   sb.writeln();
   await new File.fromUri(depsFile).writeAsString("$sb");
diff --git a/pkg/front_end/tool/_fasta/compile_platform_legacy_test.dart b/pkg/front_end/tool/_fasta/compile_platform_legacy_test.dart
index 76ffc18..47a5f9c 100644
--- a/pkg/front_end/tool/_fasta/compile_platform_legacy_test.dart
+++ b/pkg/front_end/tool/_fasta/compile_platform_legacy_test.dart
@@ -20,7 +20,7 @@
   asyncTest(() async {
     await withTemporaryDirectory("compile_platform_test_", (Uri tmp) async {
       Uri platformDill = tmp.resolve("vm_platform.dill");
-      Uri outlineDill = tmp.resolve("vm_outline.dill");
+      Uri outlineDill = tmp.resolve("vm_outline_strong.dill");
       ProcessResult result = await Process.run(dartVm.toFilePath(), <String>[
         compilePlatform.toFilePath(),
         "-v",
diff --git a/pkg/front_end/tool/_fasta/compile_platform_test.dart b/pkg/front_end/tool/_fasta/compile_platform_test.dart
index 84ef2df..b09d1c6 100644
--- a/pkg/front_end/tool/_fasta/compile_platform_test.dart
+++ b/pkg/front_end/tool/_fasta/compile_platform_test.dart
@@ -20,7 +20,7 @@
   asyncTest(() async {
     await withTemporaryDirectory("compile_platform_test_", (Uri tmp) async {
       Uri platformDill = tmp.resolve("vm_platform.dill");
-      Uri outlineDill = tmp.resolve("vm_outline.dill");
+      Uri outlineDill = tmp.resolve("vm_outline_strong.dill");
       ProcessResult result = await Process.run(dartVm.toFilePath(), <String>[
         compilePlatform.toFilePath(),
         "-v",
diff --git a/pkg/front_end/tool/_fasta/entry_points.dart b/pkg/front_end/tool/_fasta/entry_points.dart
index b2a1d8f..3af6703 100644
--- a/pkg/front_end/tool/_fasta/entry_points.dart
+++ b/pkg/front_end/tool/_fasta/entry_points.dart
@@ -100,7 +100,8 @@
   run() async {
     await for (String line in lines) {
       try {
-        if (await batchCompileArguments(jsonDecode(line))) {
+        if (await batchCompileArguments(
+            new List<String>.from(jsonDecode(line)))) {
           stdout.writeln(">>> TEST OK");
         } else {
           stdout.writeln(">>> TEST FAIL");
diff --git a/pkg/front_end/tool/_fasta/resolve_input_uri.dart b/pkg/front_end/tool/_fasta/resolve_input_uri.dart
new file mode 100644
index 0000000..f0b49d5
--- /dev/null
+++ b/pkg/front_end/tool/_fasta/resolve_input_uri.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.
+
+/// Resolve [string] as a [Uri].  If the input [string] starts with a supported
+/// scheme, it is resolved as a Uri of that scheme, otherwise the [string]
+/// is treated as a file system (possibly relative) path.
+///
+/// Three schemes are always supported by default: `dart`, `package`, and
+/// `data`. Additional supported schemes can be specified via [extraSchemes].
+Uri resolveInputUri(String string, {List<String> extraSchemes: const []}) {
+  if (string.startsWith('dart:')) return Uri.parse(string);
+  if (string.startsWith('data:')) return Uri.parse(string);
+  if (string.startsWith('package:')) return Uri.parse(string);
+  for (var scheme in extraSchemes) {
+    if (string.startsWith('$scheme:')) return Uri.parse(string);
+  }
+  return Uri.base.resolveUri(new Uri.file(string));
+}
diff --git a/pkg/front_end/tool/_fasta/resolve_input_uri_test.dart b/pkg/front_end/tool/_fasta/resolve_input_uri_test.dart
new file mode 100644
index 0000000..7020ffc
--- /dev/null
+++ b/pkg/front_end/tool/_fasta/resolve_input_uri_test.dart
@@ -0,0 +1,31 @@
+// 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:test/test.dart';
+
+import 'resolve_input_uri.dart';
+
+main() {
+  test('data URI scheme is supported by default', () {
+    expect(resolveInputUri('data:,foo').scheme, 'data');
+  });
+
+  test('internal dart schemes are recognized by default', () {
+    expect(resolveInputUri('dart:foo').scheme, 'dart');
+    expect(resolveInputUri('package:foo').scheme, 'package');
+  });
+
+  test('unknown schemes are not recognized by default', () {
+    expect(resolveInputUri('test:foo').scheme, 'file');
+    expect(resolveInputUri('org-dartlang-foo:bar').scheme, 'file');
+  });
+
+  test('more schemes can be supported', () {
+    expect(resolveInputUri('test:foo', extraSchemes: ['test']).scheme, 'test');
+    expect(
+        resolveInputUri('org-dartlang-foo:bar',
+            extraSchemes: ['org-dartlang-foo']).scheme,
+        'org-dartlang-foo');
+  });
+}
diff --git a/pkg/kernel/lib/transformations/constants.dart b/pkg/kernel/lib/transformations/constants.dart
index b8a3aa8..cf18494 100644
--- a/pkg/kernel/lib/transformations/constants.dart
+++ b/pkg/kernel/lib/transformations/constants.dart
@@ -287,6 +287,10 @@
 
   // Handle use-sites of constants (and "inline" constant expressions):
 
+  visitSymbolLiteral(SymbolLiteral node) {
+    return new ConstantExpression(constantEvaluator.evaluate(node));
+  }
+
   visitStaticGet(StaticGet node) {
     final Member target = node.target;
     if (target is Field && target.isConst) {
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 1ff41ca..0c49070 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -49,6 +49,7 @@
 front_end/tool/incremental_perf_test: Slow, Pass
 kernel/test/closures_test: Slow, Pass
 kernel/testcases/*: Skip # These are not tests but input for tests.
+vm/test/frontend_server_test: Slow, Pass
 vm/test/transformations/type_flow/transformer_test: Slow, Pass
 vm/testcases/*: SkipByDesign # These are not tests but input for tests.
 
diff --git a/pkg/vm/lib/bytecode/gen_bytecode.dart b/pkg/vm/lib/bytecode/gen_bytecode.dart
index 797bc67..4e218c8 100644
--- a/pkg/vm/lib/bytecode/gen_bytecode.dart
+++ b/pkg/vm/lib/bytecode/gen_bytecode.dart
@@ -152,6 +152,11 @@
 
     if (locals.hasTypeArgsVar) {
       asm.emitPush(locals.typeArgsVarIndexInFrame);
+    } else if (enclosingMember is Procedure &&
+        (enclosingMember as Procedure).isFactory) {
+      // Null type arguments are passed to factory constructors even if class
+      // is not generic. TODO(alexmarkov): Clean this up.
+      _genPushNull();
     }
     if (locals.hasReceiver) {
       asm.emitPush(locals.getVarIndexInFrame(locals.receiverVar));
diff --git a/pkg/vm/lib/frontend_server.dart b/pkg/vm/lib/frontend_server.dart
index e484146..9d5797b 100644
--- a/pkg/vm/lib/frontend_server.dart
+++ b/pkg/vm/lib/frontend_server.dart
@@ -373,39 +373,40 @@
     // be invalidated by the normal approach anyway.
     if (_generator.initialized) return null;
 
+    final File f = new File(_initializeFromDill);
+    if (!f.existsSync()) return null;
+
+    Component component;
     try {
-      final File f = new File(_initializeFromDill);
-      if (!f.existsSync()) return null;
+      component = loadComponentSourceFromBytes(f.readAsBytesSync());
+    } catch (e) {
+      // If we cannot load the dill file we shouldn't initialize from it.
+      _generator = _createGenerator(null);
+      return null;
+    }
 
-      final Component component =
-          loadComponentSourceFromBytes(f.readAsBytesSync());
-      for (Uri uri in component.uriToSource.keys) {
-        if ('$uri' == '') continue;
+    nextUri:
+    for (Uri uri in component.uriToSource.keys) {
+      if (uri == null || '$uri' == '') continue nextUri;
 
-        final List<int> oldBytes = component.uriToSource[uri].source;
-        final FileSystemEntity entity =
-            _compilerOptions.fileSystem.entityForUri(uri);
-        if (!await entity.exists()) {
+      final List<int> oldBytes = component.uriToSource[uri].source;
+      final FileSystemEntity entity =
+          _compilerOptions.fileSystem.entityForUri(uri);
+      if (!await entity.exists()) {
+        _generator.invalidate(uri);
+        continue nextUri;
+      }
+      final List<int> newBytes = await entity.readAsBytes();
+      if (oldBytes.length != newBytes.length) {
+        _generator.invalidate(uri);
+        continue nextUri;
+      }
+      for (int i = 0; i < oldBytes.length; ++i) {
+        if (oldBytes[i] != newBytes[i]) {
           _generator.invalidate(uri);
-          continue;
-        }
-        final List<int> newBytes = await entity.readAsBytes();
-        if (oldBytes.length != newBytes.length) {
-          _generator.invalidate(uri);
-          continue;
-        }
-        for (int i = 0; i < oldBytes.length; ++i) {
-          if (oldBytes[i] != newBytes[i]) {
-            _generator.invalidate(uri);
-            continue;
-          }
+          continue nextUri;
         }
       }
-    } catch (e) {
-      // If there's a failure in the above block we might not have invalidated
-      // correctly. Create a new generator that doesn't initialize from dill to
-      // avoid missing any changes.
-      _generator = _createGenerator(null);
     }
   }
 
diff --git a/pkg/vm/test/frontend_server_test.dart b/pkg/vm/test/frontend_server_test.dart
index 997bdf9..7efa188 100644
--- a/pkg/vm/test/frontend_server_test.dart
+++ b/pkg/vm/test/frontend_server_test.dart
@@ -6,6 +6,8 @@
 import 'package:args/src/arg_results.dart';
 import 'package:kernel/binary/ast_to_binary.dart';
 import 'package:kernel/ast.dart' show Component;
+import 'package:kernel/kernel.dart' show loadComponentFromBinary;
+import 'package:kernel/verifier.dart' show verifyComponent;
 import 'package:mockito/mockito.dart';
 import 'package:path/path.dart' as path;
 import 'package:test/test.dart';
@@ -786,6 +788,168 @@
       expect(path.basename(depContentsParsed[0]), path.basename(dillFile.path));
       expect(depContentsParsed[1], isNotEmpty);
     });
+
+    test('mimic flutter benchmark', () async {
+      // This is based on what flutters "hot_mode_dev_cycle__benchmark" does.
+      var dillFile = new File('${tempDir.path}/full.dill');
+      var incrementalDillFile = new File('${tempDir.path}/incremental.dill');
+      expect(dillFile.existsSync(), equals(false));
+      final List<String> args = <String>[
+        '--sdk-root=${sdkRoot.toFilePath()}',
+        '--strong',
+        '--incremental',
+        '--platform=${platformKernel.path}',
+        '--output-dill=${dillFile.path}',
+        '--output-incremental-dill=${incrementalDillFile.path}'
+      ];
+      File dart2js = new File.fromUri(
+          Platform.script.resolve("../../../pkg/compiler/bin/dart2js.dart"));
+      expect(dart2js.existsSync(), equals(true));
+      File dart2jsOtherFile = new File.fromUri(Platform.script
+          .resolve("../../../pkg/compiler/lib/src/compiler.dart"));
+      expect(dart2jsOtherFile.existsSync(), equals(true));
+
+      int libraryCount = -1;
+      int sourceCount = -1;
+
+      for (int serverCloses = 0; serverCloses < 2; ++serverCloses) {
+        print("Restart #$serverCloses");
+        final StreamController<List<int>> streamController =
+            new StreamController<List<int>>();
+        final StreamController<List<int>> stdoutStreamController =
+            new StreamController<List<int>>();
+        final IOSink ioSink = new IOSink(stdoutStreamController.sink);
+        StreamController<String> receivedResults =
+            new StreamController<String>();
+
+        String boundaryKey;
+        stdoutStreamController.stream
+            .transform(utf8.decoder)
+            .transform(const LineSplitter())
+            .listen((String s) {
+          const String RESULT_OUTPUT_SPACE = 'result ';
+          if (boundaryKey == null) {
+            if (s.startsWith(RESULT_OUTPUT_SPACE)) {
+              boundaryKey = s.substring(RESULT_OUTPUT_SPACE.length);
+            }
+          } else {
+            if (s.startsWith(boundaryKey)) {
+              receivedResults.add(s.substring(boundaryKey.length + 1));
+              boundaryKey = null;
+            }
+          }
+        });
+
+        int exitcode =
+            await starter(args, input: streamController.stream, output: ioSink);
+        expect(exitcode, equals(0));
+        streamController.add('compile ${dart2js.path}\n'.codeUnits);
+        int count = 0;
+        Completer<bool> allDone = new Completer<bool>();
+        receivedResults.stream.listen((String outputFilenameAndErrorCount) {
+          int delim = outputFilenameAndErrorCount.lastIndexOf(' ');
+          expect(delim > 0, equals(true));
+          String outputFilename =
+              outputFilenameAndErrorCount.substring(0, delim);
+          print("$outputFilename -- count $count");
+          if (count == 0) {
+            // First request is to 'compile', which results in full kernel file.
+            expect(dillFile.existsSync(), equals(true));
+            expect(outputFilename, dillFile.path);
+
+            // Dill file can be loaded and includes data.
+            Component component = loadComponentFromBinary(dillFile.path);
+            if (serverCloses == 0) {
+              libraryCount = component.libraries.length;
+              sourceCount = component.uriToSource.length;
+              expect(libraryCount > 100, equals(true));
+              expect(sourceCount >= libraryCount, equals(true),
+                  reason: "Expects >= source entries than libraries.");
+            } else {
+              expect(component.libraries.length, equals(libraryCount),
+                  reason: "Expects the same number of libraries "
+                      "when compiling after a restart");
+              expect(component.uriToSource.length, equals(sourceCount),
+                  reason: "Expects the same number of sources "
+                      "when compiling after a restart");
+            }
+
+            // Include platform and verify.
+            component = loadComponentFromBinary(platformKernel.path, component);
+            expect(component.mainMethod, isNotNull);
+            verifyComponent(component);
+
+            count += 1;
+
+            // Restart with no changes
+            streamController.add('accept\n'.codeUnits);
+            streamController.add('reset\n'.codeUnits);
+            streamController.add('recompile ${dart2js.path} x$count\n'
+                'x$count\n'
+                .codeUnits);
+          } else if (count == 1) {
+            // Restart. Expect full kernel file.
+            expect(dillFile.existsSync(), equals(true));
+            expect(outputFilename, dillFile.path);
+
+            // Dill file can be loaded and includes data.
+            Component component = loadComponentFromBinary(dillFile.path);
+            expect(component.libraries.length, equals(libraryCount),
+                reason: "Expect the same number of libraries after a reset.");
+            expect(component.uriToSource.length, equals(sourceCount),
+                reason: "Expect the same number of sources after a reset.");
+
+            // Include platform and verify.
+            component = loadComponentFromBinary(platformKernel.path, component);
+            expect(component.mainMethod, isNotNull);
+            verifyComponent(component);
+
+            count += 1;
+
+            // Reload with no changes
+            streamController.add('accept\n'.codeUnits);
+            streamController.add('recompile ${dart2js.path} x$count\n'
+                'x$count\n'
+                .codeUnits);
+          } else if (count == 2) {
+            // Partial file. Expect to be empty.
+            expect(incrementalDillFile.existsSync(), equals(true));
+            expect(outputFilename, incrementalDillFile.path);
+
+            // Dill file can be loaded and includes no data.
+            Component component =
+                loadComponentFromBinary(incrementalDillFile.path);
+            expect(component.libraries.length, equals(0));
+
+            count += 1;
+
+            // Reload with 1 change
+            streamController.add('accept\n'.codeUnits);
+            streamController.add('recompile ${dart2js.path} x$count\n'
+                '${dart2jsOtherFile.path}\n'
+                'x$count\n'
+                .codeUnits);
+          } else if (count == 3) {
+            // Partial file. Expect to not be empty.
+            expect(incrementalDillFile.existsSync(), equals(true));
+            expect(outputFilename, incrementalDillFile.path);
+
+            // Dill file can be loaded and includes some data.
+            Component component =
+                loadComponentFromBinary(incrementalDillFile.path);
+            expect(component.libraries, isNotEmpty);
+            expect(component.uriToSource.length >= component.libraries.length,
+                equals(true),
+                reason: "Expects >= source entries than libraries.");
+
+            count += 1;
+
+            allDone.complete(true);
+          }
+        });
+        expect(await allDone.future, true);
+      }
+    }, timeout: new Timeout.factor(8));
   });
   return 0;
 }
diff --git a/pkg/vm/test/incremental_compiler_test.dart b/pkg/vm/test/incremental_compiler_test.dart
index 3736600..3eaa3a3 100644
--- a/pkg/vm/test/incremental_compiler_test.dart
+++ b/pkg/vm/test/incremental_compiler_test.dart
@@ -103,16 +103,6 @@
         }
       });
 
-      vm.stderr
-          .transform(utf8.decoder)
-          .transform(splitter)
-          .toList()
-          .then((err) {
-        print(err.join('\n'));
-        expect(err.isEmpty, isTrue,
-            reason: "Should be no errors, but got ${err.join('\n')}");
-      });
-
       String portLine = await portLineCompleter.future;
 
       final RegExp observatoryPortRegExp =
diff --git a/pkg/vm/testcases/bytecode/instance_creation.dart b/pkg/vm/testcases/bytecode/instance_creation.dart
index 5821f59..85ea5d71 100644
--- a/pkg/vm/testcases/bytecode/instance_creation.dart
+++ b/pkg/vm/testcases/bytecode/instance_creation.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// ignore_for_file: native_function_body_in_non_sdk_code
+
 class Base<T1, T2> {
   T1 t1;
   T2 t2;
@@ -67,6 +69,10 @@
   new I.test_factory2(param: 42);
 }
 
+class J {
+  factory J() native "agent_J";
+}
+
 main() {
   foo1();
   foo2();
diff --git a/pkg/vm/testcases/bytecode/instance_creation.dart.expect b/pkg/vm/testcases/bytecode/instance_creation.dart.expect
index 32c2c32..be92aa5 100644
--- a/pkg/vm/testcases/bytecode/instance_creation.dart.expect
+++ b/pkg/vm/testcases/bytecode/instance_creation.dart.expect
@@ -1,6 +1,7 @@
 library #lib;
 import self as self;
 import "dart:core" as core;
+import "dart:_internal" as _in;
 
 class Base<T1 extends core::Object = dynamic, T2 extends core::Object = dynamic> extends core::Object {
   generic-covariant-impl field self::Base::T1 t1 = null;
@@ -385,6 +386,22 @@
 ]  static factory test_factory2({dynamic param = null}) → self::I
     return new self::I::•(param);
 }
+class J extends core::Object {
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#0
+  NativeCall           CP#1
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Null
+  [1] = NativeEntry agent_J
+}
+]  @_in::ExternalName::•("agent_J")
+  external static factory •() → self::J;
+}
 [@vm.bytecode=
 Bytecode {
   Entry                1
diff --git a/runtime/bin/file_win.cc b/runtime/bin/file_win.cc
index abc364d..9c486cc 100644
--- a/runtime/bin/file_win.cc
+++ b/runtime/bin/file_win.cc
@@ -17,6 +17,7 @@
 #include <sys/utime.h>  // NOLINT
 
 #include "bin/builtin.h"
+#include "bin/directory.h"
 #include "bin/log.h"
 #include "bin/namespace.h"
 #include "bin/utils.h"
@@ -472,6 +473,21 @@
     Utf8ToWideScope system_old_path(old_path);
     Utf8ToWideScope system_new_path(new_path);
     DWORD flags = MOVEFILE_WRITE_THROUGH | MOVEFILE_REPLACE_EXISTING;
+    // Links on Windows appear as special directories. MoveFileExW's
+    // MOVEFILE_REPLACE_EXISTING does not allow for replacement of directories,
+    // so we need to remove it before renaming a link.
+    if (Directory::Exists(namespc, new_path) == Directory::EXISTS) {
+      bool result = true;
+      if (GetType(namespc, new_path, false) == kIsLink) {
+        result = DeleteLink(namespc, new_path);
+      } else {
+        result = Delete(namespc, new_path);
+      }
+      // Bail out if the Delete calls fail.
+      if (!result) {
+        return false;
+      }
+    }
     int move_status =
         MoveFileExW(system_old_path.wide(), system_new_path.wide(), flags);
     return (move_status != 0);
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index 4bddd36a..bc95b54 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -1505,7 +1505,7 @@
 }
 
 int main(int argc, char** argv) {
-  const int EXTRA_VM_ARGUMENTS = 2;
+  const int EXTRA_VM_ARGUMENTS = 4;
   CommandLineOptions vm_options(argc + EXTRA_VM_ARGUMENTS);
 
   // Initialize the URL mapping array.
@@ -1516,6 +1516,16 @@
   CommandLineOptions entry_points_files_array(argc);
   entry_points_files = &entry_points_files_array;
 
+  // When running from the command line we assume that we are optimizing for
+  // throughput, and therefore use a larger new gen semi space size and a faster
+  // new gen growth factor unless others have been specified.
+  if (kWordSize <= 4) {
+    vm_options.AddArgument("--new_gen_semi_max_size=16");
+  } else {
+    vm_options.AddArgument("--new_gen_semi_max_size=32");
+  }
+  vm_options.AddArgument("--new_gen_growth_factor=4");
+
   // Parse command line arguments.
   if (ParseArguments(argc, argv, &vm_options, &app_script_name) < 0) {
     PrintUsage();
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index b3c71de..1859422 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -1159,7 +1159,7 @@
 
 void main(int argc, char** argv) {
   char* script_name;
-  const int EXTRA_VM_ARGUMENTS = 8;
+  const int EXTRA_VM_ARGUMENTS = 10;
   CommandLineOptions vm_options(argc + EXTRA_VM_ARGUMENTS);
   CommandLineOptions dart_options(argc);
   bool print_flags_seen = false;
@@ -1183,6 +1183,16 @@
   Options::set_dfe(&dfe);
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
+  // When running from the command line we assume that we are optimizing for
+  // throughput, and therefore use a larger new gen semi space size and a faster
+  // new gen growth factor unless others have been specified.
+  if (kWordSize <= 4) {
+    vm_options.AddArgument("--new_gen_semi_max_size=16");
+  } else {
+    vm_options.AddArgument("--new_gen_semi_max_size=32");
+  }
+  vm_options.AddArgument("--new_gen_growth_factor=4");
+
   // Parse command line arguments.
   if (Options::ParseArguments(argc, argv, vm_run_app_snapshot, &vm_options,
                               &script_name, &dart_options, &print_flags_seen,
diff --git a/runtime/bin/run_vm_tests.cc b/runtime/bin/run_vm_tests.cc
index b255370..9f54ee1 100644
--- a/runtime/bin/run_vm_tests.cc
+++ b/runtime/bin/run_vm_tests.cc
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-#include <stdio.h>
-
 #include "bin/console.h"
 #include "bin/dartutils.h"
 #include "bin/dfe.h"
@@ -54,15 +52,15 @@
 static int run_matches = 0;
 
 void TestCase::Run() {
-  OS::Print("Running test: %s\n", name());
+  bin::Log::Print("Running test: %s\n", name());
   (*run_)();
-  OS::Print("Done: %s\n", name());
+  bin::Log::Print("Done: %s\n", name());
 }
 
 void RawTestCase::Run() {
-  OS::Print("Running test: %s\n", name());
+  bin::Log::Print("Running test: %s\n", name());
   (*run_)();
-  OS::Print("Done: %s\n", name());
+  bin::Log::Print("Done: %s\n", name());
 }
 
 void TestCaseBase::RunTest() {
@@ -70,7 +68,7 @@
     this->Run();
     run_matches++;
   } else if (run_filter == kList) {
-    OS::Print("%s\n", this->name());
+    bin::Log::Print("%s\n", this->name());
     run_matches++;
   }
 }
@@ -79,17 +77,17 @@
   if ((run_filter == kAllBenchmarks) ||
       (strcmp(run_filter, this->name()) == 0)) {
     this->Run();
-    OS::Print("%s(%s): %" Pd64 "\n", this->name(), this->score_kind(),
-              this->score());
+    bin::Log::Print("%s(%s): %" Pd64 "\n", this->name(), this->score_kind(),
+                    this->score());
     run_matches++;
   } else if (run_filter == kList) {
-    OS::Print("%s\n", this->name());
+    bin::Log::Print("%s\n", this->name());
     run_matches++;
   }
 }
 
 static void PrintUsage() {
-  OS::PrintErr(
+  bin::Log::PrintErr(
       "Usage: one of the following\n"
       "  run_vm_tests --list\n"
       "  run_vm_tests [--dfe=<snapshot file name>] --benchmarks\n"
@@ -212,7 +210,7 @@
 
   // Perform platform specific initialization.
   if (!dart::bin::Platform::Initialize()) {
-    OS::PrintErr("Initialization failed\n");
+    bin::Log::PrintErr("Initialization failed\n");
     return 1;
   }
 
@@ -240,7 +238,7 @@
   if (strstr(argv[arg_pos], "--dfe") == argv[arg_pos]) {
     const char* delim = strstr(argv[1], "=");
     if (delim == NULL || strlen(delim + 1) == 0) {
-      OS::PrintErr("Invalid value for the option: %s\n", argv[1]);
+      bin::Log::PrintErr("Invalid value for the option: %s\n", argv[1]);
       PrintUsage();
       return 1;
     }
@@ -294,7 +292,7 @@
   TestCaseBase::RunAllRaw();
   // Print a warning message if no tests or benchmarks were matched.
   if (run_matches == 0) {
-    OS::PrintErr("No tests matched: %s\n", run_filter);
+    bin::Log::PrintErr("No tests matched: %s\n", run_filter);
     return 1;
   }
   if (Expect::failed()) {
diff --git a/runtime/lib/double.cc b/runtime/lib/double.cc
index 4fc5baa..3aaeaa9 100644
--- a/runtime/lib/double.cc
+++ b/runtime/lib/double.cc
@@ -23,7 +23,7 @@
   ASSERT(TypeArguments::CheckedHandle(arguments->NativeArgAt(0)).IsNull());
   const Integer& value = Integer::CheckedHandle(arguments->NativeArgAt(1));
   if (FLAG_trace_intrinsified_natives) {
-    OS::Print("Double_doubleFromInteger %s\n", value.ToCString());
+    OS::PrintErr("Double_doubleFromInteger %s\n", value.ToCString());
   }
   return Double::New(value.AsDoubleValue());
 }
@@ -33,7 +33,7 @@
   GET_NON_NULL_NATIVE_ARGUMENT(Double, right_object, arguments->NativeArgAt(1));
   double right = right_object.value();
   if (FLAG_trace_intrinsified_natives) {
-    OS::Print("Double_add %f + %f\n", left, right);
+    OS::PrintErr("Double_add %f + %f\n", left, right);
   }
   return Double::New(left + right);
 }
@@ -43,7 +43,7 @@
   GET_NON_NULL_NATIVE_ARGUMENT(Double, right_object, arguments->NativeArgAt(1));
   double right = right_object.value();
   if (FLAG_trace_intrinsified_natives) {
-    OS::Print("Double_sub %f - %f\n", left, right);
+    OS::PrintErr("Double_sub %f - %f\n", left, right);
   }
   return Double::New(left - right);
 }
@@ -53,7 +53,7 @@
   GET_NON_NULL_NATIVE_ARGUMENT(Double, right_object, arguments->NativeArgAt(1));
   double right = right_object.value();
   if (FLAG_trace_intrinsified_natives) {
-    OS::Print("Double_mul %f * %f\n", left, right);
+    OS::PrintErr("Double_mul %f * %f\n", left, right);
   }
   return Double::New(left * right);
 }
@@ -63,7 +63,7 @@
   GET_NON_NULL_NATIVE_ARGUMENT(Double, right_object, arguments->NativeArgAt(1));
   double right = right_object.value();
   if (FLAG_trace_intrinsified_natives) {
-    OS::Print("Double_div %f / %f\n", left, right);
+    OS::PrintErr("Double_div %f / %f\n", left, right);
   }
   return Double::New(left / right);
 }
@@ -88,7 +88,7 @@
 DEFINE_NATIVE_ENTRY(Double_hashCode, 1) {
   double val = Double::CheckedHandle(arguments->NativeArgAt(0)).value();
   if (FLAG_trace_intrinsified_natives) {
-    OS::Print("Double_hashCode %f\n", val);
+    OS::PrintErr("Double_hashCode %f\n", val);
   }
   if (val >= static_cast<double>(kMinInt64) &&
       val <= static_cast<double>(kMaxInt64)) {
@@ -107,7 +107,7 @@
   GET_NON_NULL_NATIVE_ARGUMENT(Double, right_object, arguments->NativeArgAt(1));
   double right = right_object.value();
   if (FLAG_trace_intrinsified_natives) {
-    OS::Print("Double_trunc_div %f ~/ %f\n", left, right);
+    OS::PrintErr("Double_trunc_div %f ~/ %f\n", left, right);
   }
   return DoubleToInteger(trunc(left / right),
                          "Result of truncating division is Infinity or NaN");
@@ -132,8 +132,8 @@
   GET_NON_NULL_NATIVE_ARGUMENT(Double, right, arguments->NativeArgAt(1));
   bool result = right.IsNull() ? false : (left.value() > right.value());
   if (FLAG_trace_intrinsified_natives) {
-    OS::Print("Double_greaterThan %s > %s\n", left.ToCString(),
-              right.ToCString());
+    OS::PrintErr("Double_greaterThan %s > %s\n", left.ToCString(),
+                 right.ToCString());
   }
   return Bool::Get(result).raw();
 }
@@ -149,7 +149,8 @@
   GET_NON_NULL_NATIVE_ARGUMENT(Double, right, arguments->NativeArgAt(1));
   bool result = right.IsNull() ? false : (left.value() == right.value());
   if (FLAG_trace_intrinsified_natives) {
-    OS::Print("Double_equal %s == %s\n", left.ToCString(), right.ToCString());
+    OS::PrintErr("Double_equal %s == %s\n", left.ToCString(),
+                 right.ToCString());
   }
   return Bool::Get(result).raw();
 }
diff --git a/runtime/lib/integers.cc b/runtime/lib/integers.cc
index 4b93733..2b9f0d4 100644
--- a/runtime/lib/integers.cc
+++ b/runtime/lib/integers.cc
@@ -39,8 +39,8 @@
   ASSERT(CheckInteger(right));
   ASSERT(CheckInteger(left));
   if (FLAG_trace_intrinsified_natives) {
-    OS::Print("Integer_bitAndFromInteger %s & %s\n", right.ToCString(),
-              left.ToCString());
+    OS::PrintErr("Integer_bitAndFromInteger %s & %s\n", right.ToCString(),
+                 left.ToCString());
   }
   const Integer& result = Integer::Handle(left.BitOp(Token::kBIT_AND, right));
   // A null result indicates that a bigint operation is required.
@@ -53,8 +53,8 @@
   ASSERT(CheckInteger(right));
   ASSERT(CheckInteger(left));
   if (FLAG_trace_intrinsified_natives) {
-    OS::Print("Integer_bitOrFromInteger %s | %s\n", left.ToCString(),
-              right.ToCString());
+    OS::PrintErr("Integer_bitOrFromInteger %s | %s\n", left.ToCString(),
+                 right.ToCString());
   }
   const Integer& result = Integer::Handle(left.BitOp(Token::kBIT_OR, right));
   // A null result indicates that a bigint operation is required.
@@ -67,8 +67,8 @@
   ASSERT(CheckInteger(right));
   ASSERT(CheckInteger(left));
   if (FLAG_trace_intrinsified_natives) {
-    OS::Print("Integer_bitXorFromInteger %s ^ %s\n", left.ToCString(),
-              right.ToCString());
+    OS::PrintErr("Integer_bitXorFromInteger %s ^ %s\n", left.ToCString(),
+                 right.ToCString());
   }
   const Integer& result = Integer::Handle(left.BitOp(Token::kBIT_XOR, right));
   // A null result indicates that a bigint operation is required.
@@ -81,8 +81,8 @@
   ASSERT(CheckInteger(right_int));
   ASSERT(CheckInteger(left_int));
   if (FLAG_trace_intrinsified_natives) {
-    OS::Print("Integer_addFromInteger %s + %s\n", left_int.ToCString(),
-              right_int.ToCString());
+    OS::PrintErr("Integer_addFromInteger %s + %s\n", left_int.ToCString(),
+                 right_int.ToCString());
   }
   const Integer& result =
       Integer::Handle(left_int.ArithmeticOp(Token::kADD, right_int));
@@ -96,8 +96,8 @@
   ASSERT(CheckInteger(right_int));
   ASSERT(CheckInteger(left_int));
   if (FLAG_trace_intrinsified_natives) {
-    OS::Print("Integer_subFromInteger %s - %s\n", left_int.ToCString(),
-              right_int.ToCString());
+    OS::PrintErr("Integer_subFromInteger %s - %s\n", left_int.ToCString(),
+                 right_int.ToCString());
   }
   const Integer& result =
       Integer::Handle(left_int.ArithmeticOp(Token::kSUB, right_int));
@@ -111,8 +111,8 @@
   ASSERT(CheckInteger(right_int));
   ASSERT(CheckInteger(left_int));
   if (FLAG_trace_intrinsified_natives) {
-    OS::Print("Integer_mulFromInteger %s * %s\n", left_int.ToCString(),
-              right_int.ToCString());
+    OS::PrintErr("Integer_mulFromInteger %s * %s\n", left_int.ToCString(),
+                 right_int.ToCString());
   }
   const Integer& result =
       Integer::Handle(left_int.ArithmeticOp(Token::kMUL, right_int));
@@ -138,8 +138,8 @@
   ASSERT(CheckInteger(right_int));
   ASSERT(CheckInteger(left_int));
   if (FLAG_trace_intrinsified_natives) {
-    OS::Print("Integer_moduloFromInteger %s mod %s\n", left_int.ToCString(),
-              right_int.ToCString());
+    OS::PrintErr("Integer_moduloFromInteger %s mod %s\n", left_int.ToCString(),
+                 right_int.ToCString());
   }
   if (right_int.IsZero()) {
     // Should have been caught before calling into runtime.
@@ -157,8 +157,8 @@
   ASSERT(CheckInteger(right));
   ASSERT(CheckInteger(left));
   if (FLAG_trace_intrinsified_natives) {
-    OS::Print("Integer_greaterThanFromInteger %s > %s\n", left.ToCString(),
-              right.ToCString());
+    OS::PrintErr("Integer_greaterThanFromInteger %s > %s\n", left.ToCString(),
+                 right.ToCString());
   }
   return Bool::Get(left.CompareWith(right) == 1).raw();
 }
@@ -169,8 +169,8 @@
   ASSERT(CheckInteger(left));
   ASSERT(CheckInteger(right));
   if (FLAG_trace_intrinsified_natives) {
-    OS::Print("Integer_equalToInteger %s == %s\n", left.ToCString(),
-              right.ToCString());
+    OS::PrintErr("Integer_equalToInteger %s == %s\n", left.ToCString(),
+                 right.ToCString());
   }
   return Bool::Get(left.CompareWith(right) == 0).raw();
 }
@@ -260,8 +260,8 @@
   const Smi& left = Smi::CheckedHandle(arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Smi, right, arguments->NativeArgAt(1));
   if (FLAG_trace_intrinsified_natives) {
-    OS::Print("Smi_bitAndFromSmi %s & %s\n", left.ToCString(),
-              right.ToCString());
+    OS::PrintErr("Smi_bitAndFromSmi %s & %s\n", left.ToCString(),
+                 right.ToCString());
   }
   const Smi& left_value = Smi::Cast(left);
   const Smi& right_value = Smi::Cast(right);
@@ -285,8 +285,8 @@
   ASSERT(CheckInteger(amount));
   ASSERT(CheckInteger(value));
   if (FLAG_trace_intrinsified_natives) {
-    OS::Print("Smi_shlFromInt: %s << %s\n", value.ToCString(),
-              amount.ToCString());
+    OS::PrintErr("Smi_shlFromInt: %s << %s\n", value.ToCString(),
+                 amount.ToCString());
   }
   const Integer& result =
       Integer::Handle(ShiftOperationHelper(Token::kSHL, value, amount));
@@ -297,7 +297,7 @@
 DEFINE_NATIVE_ENTRY(Smi_bitNegate, 1) {
   const Smi& operand = Smi::CheckedHandle(arguments->NativeArgAt(0));
   if (FLAG_trace_intrinsified_natives) {
-    OS::Print("Smi_bitNegate: %s\n", operand.ToCString());
+    OS::PrintErr("Smi_bitNegate: %s\n", operand.ToCString());
   }
   intptr_t result = ~operand.Value();
   ASSERT(Smi::IsValid(result));
@@ -307,7 +307,7 @@
 DEFINE_NATIVE_ENTRY(Smi_bitLength, 1) {
   const Smi& operand = Smi::CheckedHandle(arguments->NativeArgAt(0));
   if (FLAG_trace_intrinsified_natives) {
-    OS::Print("Smi_bitLength: %s\n", operand.ToCString());
+    OS::PrintErr("Smi_bitLength: %s\n", operand.ToCString());
   }
   int64_t value = operand.AsInt64Value();
   intptr_t result = Utils::BitLength(value);
@@ -321,7 +321,7 @@
   const Mint& operand = Mint::CheckedHandle(arguments->NativeArgAt(0));
   ASSERT(CheckInteger(operand));
   if (FLAG_trace_intrinsified_natives) {
-    OS::Print("Mint_bitNegate: %s\n", operand.ToCString());
+    OS::PrintErr("Mint_bitNegate: %s\n", operand.ToCString());
   }
   int64_t result = ~operand.value();
   return Integer::New(result);
@@ -331,7 +331,7 @@
   const Mint& operand = Mint::CheckedHandle(arguments->NativeArgAt(0));
   ASSERT(CheckInteger(operand));
   if (FLAG_trace_intrinsified_natives) {
-    OS::Print("Mint_bitLength: %s\n", operand.ToCString());
+    OS::PrintErr("Mint_bitLength: %s\n", operand.ToCString());
   }
   int64_t value = operand.AsInt64Value();
   intptr_t result = Utils::BitLength(value);
diff --git a/runtime/lib/object.cc b/runtime/lib/object.cc
index dd04cd4..c3a6a6c 100644
--- a/runtime/lib/object.cc
+++ b/runtime/lib/object.cc
@@ -144,15 +144,15 @@
       type, instantiator_type_arguments, function_type_arguments, &bound_error);
   if (FLAG_trace_type_checks) {
     const char* result_str = is_instance_of ? "true" : "false";
-    OS::Print("Native Object.instanceOf: result %s\n", result_str);
+    OS::PrintErr("Native Object.instanceOf: result %s\n", result_str);
     const AbstractType& instance_type =
         AbstractType::Handle(zone, instance.GetType(Heap::kNew));
-    OS::Print("  instance type: %s\n",
-              String::Handle(zone, instance_type.Name()).ToCString());
-    OS::Print("  test type: %s\n",
-              String::Handle(zone, type.Name()).ToCString());
+    OS::PrintErr("  instance type: %s\n",
+                 String::Handle(zone, instance_type.Name()).ToCString());
+    OS::PrintErr("  test type: %s\n",
+                 String::Handle(zone, type.Name()).ToCString());
     if (!bound_error.IsNull()) {
-      OS::Print("  bound error: %s\n", bound_error.ToErrorCString());
+      OS::PrintErr("  bound error: %s\n", bound_error.ToErrorCString());
     }
   }
   if (!is_instance_of && !bound_error.IsNull()) {
@@ -223,15 +223,15 @@
                             function_type_arguments, &bound_error);
   if (FLAG_trace_type_checks) {
     const char* result_str = is_instance_of ? "true" : "false";
-    OS::Print("Object.as: result %s\n", result_str);
+    OS::PrintErr("Object.as: result %s\n", result_str);
     const AbstractType& instance_type =
         AbstractType::Handle(zone, instance.GetType(Heap::kNew));
-    OS::Print("  instance type: %s\n",
-              String::Handle(zone, instance_type.Name()).ToCString());
-    OS::Print("  cast type: %s\n",
-              String::Handle(zone, type.Name()).ToCString());
+    OS::PrintErr("  instance type: %s\n",
+                 String::Handle(zone, instance_type.Name()).ToCString());
+    OS::PrintErr("  cast type: %s\n",
+                 String::Handle(zone, type.Name()).ToCString());
     if (!bound_error.IsNull()) {
-      OS::Print("  bound error: %s\n", bound_error.ToErrorCString());
+      OS::PrintErr("  bound error: %s\n", bound_error.ToErrorCString());
     }
   }
   if (!is_instance_of) {
diff --git a/runtime/lib/profiler.cc b/runtime/lib/profiler.cc
index 1ff14ba..d892a5c 100644
--- a/runtime/lib/profiler.cc
+++ b/runtime/lib/profiler.cc
@@ -31,7 +31,7 @@
 DEFINE_NATIVE_ENTRY(UserTag_makeCurrent, 1) {
   const UserTag& self = UserTag::CheckedHandle(arguments->NativeArgAt(0));
   if (FLAG_trace_intrinsified_natives) {
-    OS::Print("UserTag_makeCurrent: %s\n", self.ToCString());
+    OS::PrintErr("UserTag_makeCurrent: %s\n", self.ToCString());
   }
   const UserTag& old = UserTag::Handle(isolate->current_tag());
   self.MakeActive();
@@ -40,14 +40,14 @@
 
 DEFINE_NATIVE_ENTRY(UserTag_defaultTag, 0) {
   if (FLAG_trace_intrinsified_natives) {
-    OS::Print("UserTag_defaultTag\n");
+    OS::PrintErr("UserTag_defaultTag\n");
   }
   return isolate->default_tag();
 }
 
 DEFINE_NATIVE_ENTRY(Profiler_getCurrentTag, 0) {
   if (FLAG_trace_intrinsified_natives) {
-    OS::Print("Profiler_getCurrentTag\n");
+    OS::PrintErr("Profiler_getCurrentTag\n");
   }
   return isolate->current_tag();
 }
diff --git a/runtime/vm/BUILD.gn b/runtime/vm/BUILD.gn
index dd24564..a3f1640 100644
--- a/runtime/vm/BUILD.gn
+++ b/runtime/vm/BUILD.gn
@@ -302,26 +302,20 @@
 }
 
 compile_platform("vm_legacy_platform") {
-  sources = [
-    "../../sdk/lib/libraries.json",
-  ]
+  libraries_specification_uri = "../../sdk/lib/libraries.json"
 
   outputs = [
     "$root_out_dir/vm_platform.dill",
     "$root_out_dir/vm_outline.dill",
   ]
 
-  inputs = [
-    "../../sdk/lib/libraries.yaml",
-  ]
-
   args = [ "dart:core" ]
 }
 
 compile_platform("vm_platform") {
-  sources = [
-    "../../sdk/lib/libraries.json",
-  ]
+  add_implicit_vm_platform_dependency = false
+
+  libraries_specification_uri = "../../sdk/lib/libraries.json"
 
   outputs = [
     "$root_out_dir/vm_platform_strong.dill",
diff --git a/runtime/vm/bit_vector.cc b/runtime/vm/bit_vector.cc
index bb1df4d..c48324b 100644
--- a/runtime/vm/bit_vector.cc
+++ b/runtime/vm/bit_vector.cc
@@ -105,11 +105,11 @@
 }
 
 void BitVector::Print() const {
-  OS::Print("[");
+  OS::PrintErr("[");
   for (intptr_t i = 0; i < length_; i++) {
-    OS::Print(Contains(i) ? "1" : "0");
+    OS::PrintErr(Contains(i) ? "1" : "0");
   }
-  OS::Print("]");
+  OS::PrintErr("]");
 }
 
 }  // namespace dart
diff --git a/runtime/vm/bitmap.cc b/runtime/vm/bitmap.cc
index fd1d343..79bab3c 100644
--- a/runtime/vm/bitmap.cc
+++ b/runtime/vm/bitmap.cc
@@ -70,9 +70,9 @@
 void BitmapBuilder::Print() const {
   for (intptr_t i = 0; i < Length(); i++) {
     if (Get(i)) {
-      OS::Print("1");
+      OS::PrintErr("1");
     } else {
-      OS::Print("0");
+      OS::PrintErr("0");
     }
   }
 }
diff --git a/runtime/vm/bitmap_test.cc b/runtime/vm/bitmap_test.cc
index 98a5e17..2d28f8b 100644
--- a/runtime/vm/bitmap_test.cc
+++ b/runtime/vm/bitmap_test.cc
@@ -39,7 +39,7 @@
   // Create a StackMap object from the builder and verify its contents.
   const StackMap& stackmap1 = StackMap::Handle(StackMap::New(0, builder1, 0));
   EXPECT_EQ(1024, stackmap1.Length());
-  OS::Print("%s\n", stackmap1.ToCString());
+  OS::PrintErr("%s\n", stackmap1.ToCString());
   value = true;
   for (int32_t i = 0; i < 1024; i++) {
     EXPECT_EQ(value, stackmap1.IsObject(i));
diff --git a/runtime/vm/bootstrap.h b/runtime/vm/bootstrap.h
index fe782ce..88e2407 100644
--- a/runtime/vm/bootstrap.h
+++ b/runtime/vm/bootstrap.h
@@ -28,7 +28,7 @@
                                    intptr_t kernel_buffer_size);
 
   static void SetupNativeResolver();
-  static bool IsBootstapResolver(Dart_NativeEntryResolver resolver);
+  static bool IsBootstrapResolver(Dart_NativeEntryResolver resolver);
 
   // Source path mapping for library URI and 'parts'.
   static const char* async_source_paths_[];
diff --git a/runtime/vm/bootstrap_natives.cc b/runtime/vm/bootstrap_natives.cc
index 0b6b193..fb3d08b 100644
--- a/runtime/vm/bootstrap_natives.cc
+++ b/runtime/vm/bootstrap_natives.cc
@@ -136,7 +136,7 @@
   library.set_native_entry_symbol_resolver(symbol_resolver);
 }
 
-bool Bootstrap::IsBootstapResolver(Dart_NativeEntryResolver resolver) {
+bool Bootstrap::IsBootstrapResolver(Dart_NativeEntryResolver resolver) {
   return (resolver ==
           reinterpret_cast<Dart_NativeEntryResolver>(BootstrapNatives::Lookup));
 }
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index bceab3b..5ae8029 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -190,7 +190,7 @@
 #if !defined(DART_PRECOMPILED_RUNTIME)
 void ClassFinalizer::VerifyBootstrapClasses() {
   if (FLAG_trace_class_finalization) {
-    OS::Print("VerifyBootstrapClasses START.\n");
+    OS::PrintErr("VerifyBootstrapClasses START.\n");
   }
   ObjectStore* object_store = Isolate::Current()->object_store();
 
@@ -249,7 +249,7 @@
     OS::Exit(255);
   }
   if (FLAG_trace_class_finalization) {
-    OS::Print("VerifyBootstrapClasses END.\n");
+    OS::PrintErr("VerifyBootstrapClasses END.\n");
   }
   Isolate::Current()->heap()->Verify();
 }
diff --git a/runtime/vm/class_table.cc b/runtime/vm/class_table.cc
index 447ea45..c07f14a 100644
--- a/runtime/vm/class_table.cc
+++ b/runtime/vm/class_table.cc
@@ -252,7 +252,7 @@
     cls = At(i);
     if (cls.raw() != reinterpret_cast<RawClass*>(0)) {
       name = cls.Name();
-      OS::Print("%" Pd ": %s\n", i, name.ToCString());
+      OS::PrintErr("%" Pd ": %s\n", i, name.ToCString());
     }
   }
 }
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index 869d283..378b2e6 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -4987,7 +4987,7 @@
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
   if (FLAG_print_snapshot_sizes_verbose) {
-    OS::Print("             Cluster   Objs     Size Fraction Cumulative\n");
+    OS::PrintErr("             Cluster   Objs     Size Fraction Cumulative\n");
     GrowableArray<SerializationCluster*> clusters_by_size;
     for (intptr_t cid = 1; cid < num_cids_; cid++) {
       SerializationCluster* cluster = clusters_by_cid_[cid];
@@ -5007,9 +5007,9 @@
       SerializationCluster* cluster = clusters_by_size[i];
       double fraction = static_cast<double>(cluster->size()) / total_size;
       cumulative_fraction += fraction;
-      OS::Print("%20s %6" Pd " %8" Pd " %lf %lf\n", cluster->name(),
-                cluster->num_objects(), cluster->size(), fraction,
-                cumulative_fraction);
+      OS::PrintErr("%20s %6" Pd " %8" Pd " %lf %lf\n", cluster->name(),
+                   cluster->num_objects(), cluster->size(), fraction,
+                   cumulative_fraction);
     }
   }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/code_descriptors_test.cc b/runtime/vm/code_descriptors_test.cc
index b67e93d..65f1890 100644
--- a/runtime/vm/code_descriptors_test.cc
+++ b/runtime/vm/code_descriptors_test.cc
@@ -305,8 +305,8 @@
   intptr_t i = 0;
   while (it.MoveNext()) {
     if (token_positions[i] != it.TokenPos().value()) {
-      OS::Print("[%" Pd "]: Expected: %" Pd " != %" Pd "\n", i,
-                token_positions[i], it.TokenPos().value());
+      OS::PrintErr("[%" Pd "]: Expected: %" Pd " != %" Pd "\n", i,
+                   token_positions[i], it.TokenPos().value());
     }
     EXPECT(token_positions[i] == it.TokenPos().value());
     i++;
diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc
index ff286b6..fb0068d 100644
--- a/runtime/vm/compiler/aot/precompiler.cc
+++ b/runtime/vm/compiler/aot/precompiler.cc
@@ -344,6 +344,7 @@
       I->object_store()->set_completer_class(null_class);
       I->object_store()->set_symbol_class(null_class);
       I->object_store()->set_compiletime_error_class(null_class);
+      I->object_store()->set_growable_list_factory(null_function);
       I->object_store()->set_simple_instance_of_function(null_function);
       I->object_store()->set_simple_instance_of_true_function(null_function);
       I->object_store()->set_simple_instance_of_false_function(null_function);
diff --git a/runtime/vm/compiler/backend/flow_graph.cc b/runtime/vm/compiler/backend/flow_graph.cc
index 5f55e9f..1f079f6 100644
--- a/runtime/vm/compiler/backend/flow_graph.cc
+++ b/runtime/vm/compiler/backend/flow_graph.cc
@@ -274,8 +274,8 @@
       merged->Add(successor->postorder_number());
       changed = true;
       if (FLAG_trace_optimization) {
-        OS::Print("Merged blocks B%" Pd " and B%" Pd "\n", block->block_id(),
-                  successor->block_id());
+        OS::PrintErr("Merged blocks B%" Pd " and B%" Pd "\n", block->block_id(),
+                     successor->block_id());
       }
     }
     // The new block inherits the block id of the last successor to maintain
@@ -580,25 +580,25 @@
 }
 
 static void PrintBitVector(const char* tag, BitVector* v) {
-  OS::Print("%s:", tag);
+  OS::PrintErr("%s:", tag);
   for (BitVector::Iterator it(v); !it.Done(); it.Advance()) {
-    OS::Print(" %" Pd "", it.Current());
+    OS::PrintErr(" %" Pd "", it.Current());
   }
-  OS::Print("\n");
+  OS::PrintErr("\n");
 }
 
 void LivenessAnalysis::Dump() {
   const intptr_t block_count = postorder_.length();
   for (intptr_t i = 0; i < block_count; i++) {
     BlockEntryInstr* block = postorder_[i];
-    OS::Print("block @%" Pd " -> ", block->block_id());
+    OS::PrintErr("block @%" Pd " -> ", block->block_id());
 
     Instruction* last = block->last_instruction();
     for (intptr_t j = 0; j < last->SuccessorCount(); j++) {
       BlockEntryInstr* succ = last->SuccessorAt(j);
-      OS::Print(" @%" Pd "", succ->block_id());
+      OS::PrintErr(" @%" Pd "", succ->block_id());
     }
-    OS::Print("\n");
+    OS::PrintErr("\n");
 
     PrintBitVector("  live out", live_out_[i]);
     PrintBitVector("  kill", kill_[i]);
@@ -1450,8 +1450,8 @@
       BlockEntryInstr* pred = block->PredecessorAt(i);
       if (block->Dominates(pred)) {
         if (FLAG_trace_optimization) {
-          OS::Print("Back edge B%" Pd " -> B%" Pd "\n", pred->block_id(),
-                    block->block_id());
+          OS::PrintErr("Back edge B%" Pd " -> B%" Pd "\n", pred->block_id(),
+                       block->block_id());
         }
         BitVector* loop_info = FindLoop(pred, block);
         // Loops that share the same loop header are treated as one loop.
@@ -1474,10 +1474,10 @@
   if (FLAG_trace_optimization) {
     for (intptr_t i = 0; i < loop_headers->length(); ++i) {
       BlockEntryInstr* header = (*loop_headers)[i];
-      OS::Print("Loop header B%" Pd "\n", header->block_id());
+      OS::PrintErr("Loop header B%" Pd "\n", header->block_id());
       for (BitVector::Iterator it(header->loop_info()); !it.Done();
            it.Advance()) {
-        OS::Print("  B%" Pd "\n", preorder_[it.Current()]->block_id());
+        OS::PrintErr("  B%" Pd "\n", preorder_[it.Current()]->block_id());
       }
     }
   }
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 1b2910b..9890b36 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -2829,7 +2829,7 @@
       comp->RemoveFromGraph();
       SetComparison(comp);
       if (FLAG_trace_optimization) {
-        OS::Print("Merging comparison v%" Pd "\n", comp->ssa_temp_index());
+        OS::PrintErr("Merging comparison v%" Pd "\n", comp->ssa_temp_index());
       }
       // Clear the comparison's temp index and ssa temp index since the
       // value of the comparison is not used outside the branch anymore.
@@ -2850,7 +2850,7 @@
     }
     if (bit_and != NULL) {
       if (FLAG_trace_optimization) {
-        OS::Print("Merging test smi v%" Pd "\n", bit_and->ssa_temp_index());
+        OS::PrintErr("Merging test smi v%" Pd "\n", bit_and->ssa_temp_index());
       }
       TestSmiInstr* test = new TestSmiInstr(
           comparison()->token_pos(),
@@ -4630,7 +4630,7 @@
   const Library& library = Library::Handle(zone, cls.library());
 
   Dart_NativeEntryResolver resolver = library.native_entry_resolver();
-  bool is_bootstrap_native = Bootstrap::IsBootstapResolver(resolver);
+  bool is_bootstrap_native = Bootstrap::IsBootstrapResolver(resolver);
   set_is_bootstrap_native(is_bootstrap_native);
 
   const int num_params =
diff --git a/runtime/vm/compiler/backend/range_analysis_test.cc b/runtime/vm/compiler/backend/range_analysis_test.cc
index 52c8694..c67708f 100644
--- a/runtime/vm/compiler/backend/range_analysis_test.cc
+++ b/runtime/vm/compiler/backend/range_analysis_test.cc
@@ -38,11 +38,11 @@
     max = Clamp(max);                                                          \
     EXPECT(min.Equals(res_min));                                               \
     if (FLAG_support_il_printer && !min.Equals(res_min)) {                     \
-      OS::Print("%s\n", min.ToCString());                                      \
+      OS::PrintErr("%s\n", min.ToCString());                                   \
     }                                                                          \
     EXPECT(max.Equals(res_max));                                               \
     if (FLAG_support_il_printer && !max.Equals(res_max)) {                     \
-      OS::Print("%s\n", max.ToCString());                                      \
+      OS::PrintErr("%s\n", max.ToCString());                                   \
     }                                                                          \
   }
 
@@ -317,11 +317,11 @@
     Range::Add(left_range, right_range, &min, &max, NULL);                     \
     EXPECT(min.Equals(result_min));                                            \
     if (FLAG_support_il_printer && !min.Equals(result_min)) {                  \
-      OS::Print("%s != %s\n", min.ToCString(), result_min.ToCString());        \
+      OS::PrintErr("%s != %s\n", min.ToCString(), result_min.ToCString());     \
     }                                                                          \
     EXPECT(max.Equals(result_max));                                            \
     if (FLAG_support_il_printer && !max.Equals(result_max)) {                  \
-      OS::Print("%s != %s\n", max.ToCString(), result_max.ToCString());        \
+      OS::PrintErr("%s != %s\n", max.ToCString(), result_max.ToCString());     \
     }                                                                          \
   }
 
@@ -397,11 +397,11 @@
     Range::Sub(left_range, right_range, &min, &max, NULL);                     \
     EXPECT(min.Equals(result_min));                                            \
     if (FLAG_support_il_printer && !min.Equals(result_min)) {                  \
-      OS::Print("%s != %s\n", min.ToCString(), result_min.ToCString());        \
+      OS::PrintErr("%s != %s\n", min.ToCString(), result_min.ToCString());     \
     }                                                                          \
     EXPECT(max.Equals(result_max));                                            \
     if (FLAG_support_il_printer && !max.Equals(result_max)) {                  \
-      OS::Print("%s != %s\n", max.ToCString(), result_max.ToCString());        \
+      OS::PrintErr("%s != %s\n", max.ToCString(), result_max.ToCString());     \
     }                                                                          \
   }
 
@@ -450,11 +450,11 @@
     Range::And(left_range, right_range, &min, &max);                           \
     EXPECT(min.Equals(result_min));                                            \
     if (FLAG_support_il_printer && !min.Equals(result_min)) {                  \
-      OS::Print("%s != %s\n", min.ToCString(), result_min.ToCString());        \
+      OS::PrintErr("%s != %s\n", min.ToCString(), result_min.ToCString());     \
     }                                                                          \
     EXPECT(max.Equals(result_max));                                            \
     if (FLAG_support_il_printer && !max.Equals(result_max)) {                  \
-      OS::Print("%s != %s\n", max.ToCString(), result_max.ToCString());        \
+      OS::PrintErr("%s != %s\n", max.ToCString(), result_max.ToCString());     \
     }                                                                          \
   }
 
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index b100719..68ac2f7 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -3,11 +3,14 @@
 // BSD-style license that can be found in the LICENSE file.
 
 #include "vm/compiler/frontend/kernel_binary_flowgraph.h"
+
+#include "vm/bootstrap.h"
 #include "vm/code_descriptors.h"
 #include "vm/compiler/aot/precompiler.h"
 #include "vm/compiler/assembler/disassembler_kbc.h"
 #include "vm/compiler/frontend/prologue_builder.h"
 #include "vm/compiler/jit/compiler.h"
+#include "vm/dart_entry.h"
 #include "vm/longjump.h"
 #include "vm/object_store.h"
 #include "vm/resolver.h"
@@ -994,6 +997,7 @@
     kContextOffset,
     kClosureFunction,
     kEndClosureFunctionScope,
+    kNativeEntry,
   };
 
   enum InvocationKind {
@@ -1332,6 +1336,10 @@
         pool.SetObjectAt(i, obj);
         return i;  // The caller will close the scope.
       } break;
+      case ConstantPoolTag::kNativeEntry: {
+        name = H.DartString(builder_->ReadStringReference()).raw();
+        obj = NativeEntry(function, name);
+      } break;
       default:
         UNREACHABLE();
     }
@@ -1412,6 +1420,87 @@
     bytecode.set_exception_handlers(Object::empty_exception_handlers());
   }
 }
+
+RawTypedData* BytecodeMetadataHelper::NativeEntry(const Function& function,
+                                                  const String& external_name) {
+  Zone* zone = builder_->zone_;
+  MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(function);
+  // This list of recognized methods must be kept in sync with the list of
+  // methods handled specially by the NativeCall bytecode in the interpreter.
+  switch (kind) {
+    case MethodRecognizer::kObjectEquals:
+    case MethodRecognizer::kStringBaseLength:
+    case MethodRecognizer::kStringBaseIsEmpty:
+    case MethodRecognizer::kGrowableArrayLength:
+    case MethodRecognizer::kObjectArrayLength:
+    case MethodRecognizer::kImmutableArrayLength:
+    case MethodRecognizer::kTypedDataLength:
+    case MethodRecognizer::kClassIDgetID:
+    case MethodRecognizer::kGrowableArrayCapacity:
+    case MethodRecognizer::kListFactory:
+    case MethodRecognizer::kObjectArrayAllocate:
+    case MethodRecognizer::kLinkedHashMap_getIndex:
+    case MethodRecognizer::kLinkedHashMap_setIndex:
+    case MethodRecognizer::kLinkedHashMap_getData:
+    case MethodRecognizer::kLinkedHashMap_setData:
+    case MethodRecognizer::kLinkedHashMap_getHashMask:
+    case MethodRecognizer::kLinkedHashMap_setHashMask:
+    case MethodRecognizer::kLinkedHashMap_getUsedData:
+    case MethodRecognizer::kLinkedHashMap_setUsedData:
+    case MethodRecognizer::kLinkedHashMap_getDeletedKeys:
+    case MethodRecognizer::kLinkedHashMap_setDeletedKeys:
+      break;
+    default:
+      kind = MethodRecognizer::kUnknown;
+  }
+  NativeFunctionWrapper trampoline = NULL;
+  NativeFunction native_function = NULL;
+  intptr_t argc_tag = 0;
+  if (kind == MethodRecognizer::kUnknown) {
+    if (FLAG_link_natives_lazily) {
+      trampoline = &NativeEntry::BootstrapNativeCallWrapper;
+      native_function =
+          reinterpret_cast<NativeFunction>(&NativeEntry::LinkNativeCall);
+    } else {
+      const Class& cls = Class::Handle(zone, function.Owner());
+      const Library& library = Library::Handle(zone, cls.library());
+      Dart_NativeEntryResolver resolver = library.native_entry_resolver();
+      const bool is_bootstrap_native = Bootstrap::IsBootstrapResolver(resolver);
+      const int num_params =
+          NativeArguments::ParameterCountForResolution(function);
+      bool is_auto_scope = true;
+      native_function = NativeEntry::ResolveNative(library, external_name,
+                                                   num_params, &is_auto_scope);
+      ASSERT(native_function != NULL);  // TODO(regis): Should we throw instead?
+      if (is_bootstrap_native) {
+        trampoline = &NativeEntry::BootstrapNativeCallWrapper;
+      } else if (is_auto_scope) {
+        trampoline = &NativeEntry::AutoScopeNativeCallWrapper;
+      } else {
+        trampoline = &NativeEntry::NoScopeNativeCallWrapper;
+      }
+    }
+    argc_tag = NativeArguments::ComputeArgcTag(function);
+  }
+  // TODO(regis): Introduce a new VM class subclassing Object and containing
+  // these four untagged values.
+#ifdef ARCH_IS_32_BIT
+  const TypedData& native_entry = TypedData::Handle(
+      zone, TypedData::New(kTypedDataUint32ArrayCid, 4, Heap::kOld));
+  native_entry.SetUint32(0 << 2, static_cast<uint32_t>(kind));
+  native_entry.SetUint32(1 << 2, reinterpret_cast<uint32_t>(trampoline));
+  native_entry.SetUint32(2 << 2, reinterpret_cast<uint32_t>(native_function));
+  native_entry.SetUint32(3 << 2, static_cast<uint32_t>(argc_tag));
+#else
+  const TypedData& native_entry = TypedData::Handle(
+      zone, TypedData::New(kTypedDataUint64ArrayCid, 4, Heap::kOld));
+  native_entry.SetUint64(0 << 3, static_cast<uint64_t>(kind));
+  native_entry.SetUint64(1 << 3, reinterpret_cast<uint64_t>(trampoline));
+  native_entry.SetUint64(2 << 3, reinterpret_cast<uint64_t>(native_function));
+  native_entry.SetUint64(3 << 3, static_cast<uint64_t>(argc_tag));
+#endif
+  return native_entry.raw();
+}
 #endif  // defined(DART_USE_INTERPRETER)
 
 StreamingScopeBuilder::StreamingScopeBuilder(ParsedFunction* parsed_function)
@@ -4259,6 +4348,13 @@
     const TypeArguments& type_arguments,
     const Function& constructor,
     const Object& argument) {
+  // We use a kernel2kernel constant evaluator in Dart 2.0 AOT compilation, so
+  // we should never end up evaluating constants using the VM's constant
+  // evaluator.
+  if (I->strong() && FLAG_precompiled_mode) {
+    UNREACHABLE();
+  }
+
   // Factories have one extra argument: the type arguments.
   // Constructors have 1 extra arguments: receiver.
   const int kTypeArgsLen = 0;
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
index 662514f..7c2b7b5 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
@@ -686,6 +686,8 @@
                            intptr_t from_index);
   RawCode* ReadBytecode(const ObjectPool& pool);
   void ReadExceptionsTable(const Code& bytecode);
+  RawTypedData* NativeEntry(const Function& function,
+                            const String& external_name);
 #endif
 };
 
diff --git a/runtime/vm/compiler/jit/jit_call_specializer.cc b/runtime/vm/compiler/jit/jit_call_specializer.cc
index 0359572..fa0ae29 100644
--- a/runtime/vm/compiler/jit/jit_call_specializer.cc
+++ b/runtime/vm/compiler/jit/jit_call_specializer.cc
@@ -205,10 +205,12 @@
       if (FLAG_trace_optimization || FLAG_trace_field_guards) {
         THR_Print("Disabling unboxing of %s\n", field.ToCString());
         if (!setter.IsNull()) {
-          OS::Print("  setter usage count: %" Pd "\n", setter.usage_counter());
+          OS::PrintErr("  setter usage count: %" Pd "\n",
+                       setter.usage_counter());
         }
         if (!getter.IsNull()) {
-          OS::Print("  getter usage count: %" Pd "\n", getter.usage_counter());
+          OS::PrintErr("  getter usage count: %" Pd "\n",
+                       getter.usage_counter());
         }
       }
       ASSERT(field.IsOriginal());
diff --git a/runtime/vm/compiler/method_recognizer.h b/runtime/vm/compiler/method_recognizer.h
index 952a9d7..bb61216 100644
--- a/runtime/vm/compiler/method_recognizer.h
+++ b/runtime/vm/compiler/method_recognizer.h
@@ -44,6 +44,7 @@
   V(_TypedList, _setFloat64, ByteArrayBaseSetFloat64, Dynamic, 0x38a80b0d)     \
   V(_TypedList, _setFloat32x4, ByteArrayBaseSetFloat32x4, Dynamic, 0x40052c4e) \
   V(_TypedList, _setInt32x4, ByteArrayBaseSetInt32x4, Dynamic, 0x07b89f54)     \
+  V(::, _toClampedUint8, ConvertIntToClampedUint8, Smi, 0x564b0435)            \
   V(_StringBase, _interpolate, StringBaseInterpolate, Dynamic, 0x01ecb15a)     \
   V(_IntegerImplementation, toDouble, IntegerToDouble, Double, 0x05da96ed)     \
   V(_Double, _add, DoubleAdd, Double, 0x2a38277b)                              \
@@ -437,7 +438,6 @@
   V(::, _toInt, ConvertMaskedInt, 0x713908fd)                                  \
   V(::, _toInt8, ConvertIntToInt8, 0x7484a780)                                 \
   V(::, _toUint8, ConvertIntToUint8, 0x0a15b522)                               \
-  V(::, _toClampedUint8, ConvertIntToClampedUint8, 0x564b0435)                 \
   V(::, _toInt16, ConvertIntToInt16, 0x0a83fcc6)                               \
   V(::, _toUint16, ConvertIntToUint16, 0x6087d1af)                             \
   V(::, _toInt32, ConvertIntToInt32, 0x62b451b9)                               \
diff --git a/runtime/vm/constants_kbc.h b/runtime/vm/constants_kbc.h
index 52ceebf..312ca7f 100644
--- a/runtime/vm/constants_kbc.h
+++ b/runtime/vm/constants_kbc.h
@@ -165,10 +165,10 @@
 //    with arguments SP[-(1+ArgC)], ..., SP[-1].
 //    The ICData indicates whether the first argument is a type argument vector.
 //
-//  - NativeCall ArgA, ArgB, ArgC
+//  - NativeCall D
 //
-//    Invoke native function at pool[ArgB] with argc_tag at pool[ArgC] using
-//    wrapper at pool[ArgA].
+//    Invoke native function described by array at pool[D].
+//    array[0] is wrapper, array[1] is function, array[2] is argc_tag.
 //
 //  - PushPolymorphicInstanceCall ArgC, D
 //
@@ -791,7 +791,7 @@
   V(InstanceCall2Opt,                    A_D, num, num, ___)                   \
   V(PushPolymorphicInstanceCall,         A_D, num, num, ___)                   \
   V(PushPolymorphicInstanceCallByRange,  A_D, num, num, ___)                   \
-  V(NativeCall,                        A_B_C, num, num, num)                   \
+  V(NativeCall,                            D, lit, ___, ___)                   \
   V(OneByteStringFromCharCode,           A_X, reg, xeg, ___)                   \
   V(StringToCharCode,                    A_X, reg, xeg, ___)                   \
   V(AddTOS,                                0, ___, ___, ___)                   \
diff --git a/runtime/vm/custom_isolate_test.cc b/runtime/vm/custom_isolate_test.cc
index 77b2181f..5351e10 100644
--- a/runtime/vm/custom_isolate_test.cc
+++ b/runtime/vm/custom_isolate_test.cc
@@ -164,7 +164,7 @@
 };
 
 void StartEvent::Process() {
-  OS::Print(">> StartEvent with isolate(%p)--\n", isolate());
+  OS::PrintErr(">> StartEvent with isolate(%p)--\n", isolate());
   Dart_EnterIsolate(isolate());
   Dart_EnterScope();
   Dart_Handle result;
@@ -193,7 +193,7 @@
 };
 
 void MessageEvent::Process() {
-  OS::Print("$$ MessageEvent with isolate(%p)\n", isolate());
+  OS::PrintErr("$$ MessageEvent with isolate(%p)\n", isolate());
   Dart_EnterIsolate(isolate());
   Dart_EnterScope();
 
@@ -201,7 +201,7 @@
   EXPECT_VALID(result);
 
   if (!Dart_HasLivePorts()) {
-    OS::Print("<< Shutting down isolate(%p)\n", isolate());
+    OS::PrintErr("<< Shutting down isolate(%p)\n", isolate());
     event_queue->RemoveEventsForIsolate(isolate());
     Dart_SetMessageNotifyCallback(NULL);
     Dart_ExitScope();
@@ -214,8 +214,8 @@
 }
 
 static void NotifyMessage(Dart_Isolate dest_isolate) {
-  OS::Print("-- Notify isolate(%p) of pending message --\n", dest_isolate);
-  OS::Print("-- Adding MessageEvent to queue --\n");
+  OS::PrintErr("-- Notify isolate(%p) of pending message --\n", dest_isolate);
+  OS::PrintErr("-- Adding MessageEvent to queue --\n");
   event_queue->Add(new MessageEvent(dest_isolate));
 }
 
@@ -247,12 +247,12 @@
     free(saved_echo);
   }
   saved_echo = strdup(c_str);
-  OS::Print("-- (isolate=%p) %s\n", Dart_CurrentIsolate(), c_str);
+  OS::PrintErr("-- (isolate=%p) %s\n", Dart_CurrentIsolate(), c_str);
   Dart_ExitScope();
 }
 
 static void CustomIsolateImpl_start(Dart_NativeArguments args) {
-  OS::Print("-- Enter: CustomIsolateImpl_start --\n");
+  OS::PrintErr("-- Enter: CustomIsolateImpl_start --\n");
 
   // We would probably want to pass in the this pointer too, so we
   // could associate the CustomIsolateImpl instance with the
@@ -287,7 +287,7 @@
   Dart_Handle err = Dart_SendPortGetId(main_send_port, &main_port_id);
   EXPECT_VALID(err);
 
-  OS::Print("-- Adding StartEvent to queue --\n");
+  OS::PrintErr("-- Adding StartEvent to queue --\n");
   event_queue->Add(new StartEvent(new_isolate, isolate_main));
 
   // Restore the original isolate.
@@ -300,7 +300,7 @@
   EXPECT_VALID(send_port);
   Dart_SetReturnValue(args, send_port);
 
-  OS::Print("-- Exit: CustomIsolateImpl_start --\n");
+  OS::PrintErr("-- Exit: CustomIsolateImpl_start --\n");
   Dart_ExitScope();
 }
 
@@ -335,14 +335,14 @@
   Dart_ExitScope();
   Dart_ExitIsolate();
 
-  OS::Print("-- Starting event loop --\n");
+  OS::PrintErr("-- Starting event loop --\n");
   Event* event = event_queue->Get();
   while (event) {
     event->Process();
     delete event;
     event = event_queue->Get();
   }
-  OS::Print("-- Finished event loop --\n");
+  OS::PrintErr("-- Finished event loop --\n");
   EXPECT_STREQ("Received: 43", saved_echo);
   free(saved_echo);
 
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index 6318284..06adc84 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -246,15 +246,15 @@
       }
 #endif  // !defined(PRODUCT)
       if (FLAG_trace_isolates) {
-        OS::Print("Size of vm isolate snapshot = %" Pd "\n",
-                  snapshot->length());
+        OS::PrintErr("Size of vm isolate snapshot = %" Pd "\n",
+                     snapshot->length());
         vm_isolate_->heap()->PrintSizes();
         MegamorphicCacheTable::PrintSizes(vm_isolate_);
         intptr_t size;
         intptr_t capacity;
         Symbols::GetStats(vm_isolate_, &size, &capacity);
-        OS::Print("VM Isolate: Number of symbols : %" Pd "\n", size);
-        OS::Print("VM Isolate: Symbol table capacity : %" Pd "\n", capacity);
+        OS::PrintErr("VM Isolate: Number of symbols : %" Pd "\n", size);
+        OS::PrintErr("VM Isolate: Symbol table capacity : %" Pd "\n", capacity);
       }
     } else {
 #if defined(DART_PRECOMPILED_RUNTIME)
@@ -553,7 +553,7 @@
       return ApiError::New(message);
     }
     if (FLAG_trace_isolates) {
-      OS::Print("Size of isolate snapshot = %" Pd "\n", snapshot->length());
+      OS::PrintErr("Size of isolate snapshot = %" Pd "\n", snapshot->length());
     }
     FullSnapshotReader reader(snapshot, snapshot_instructions, shared_data,
                               shared_instructions, T);
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index ee787e4..f0ada37 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -6338,7 +6338,7 @@
 
     const Error& err = Error::Handle(lib.Patch(patch_script));
     if (!err.IsNull()) {
-      OS::Print("Patching error: %s\n", err.ToErrorCString());
+      OS::PrintErr("Patching error: %s\n", err.ToErrorCString());
       EXPECT(false);
     }
   }
@@ -8819,7 +8819,7 @@
   EXPECT_VALID(result);
   result = Dart_Invoke(lib, NewString("foozoo"), 0, NULL);
   EXPECT(Dart_IsError(result));
-  OS::Print("Patched class executed\n");
+  OS::PrintErr("Patched class executed\n");
 }
 
 TEST_CASE(DartAPI_LoadLibraryPatch_Error3) {
diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc
index c157f1a..82afa1e 100644
--- a/runtime/vm/dart_entry.cc
+++ b/runtime/vm/dart_entry.cc
@@ -25,16 +25,6 @@
 RawObject* DartEntry::InvokeFunction(const Function& function,
                                      const Array& arguments) {
   ASSERT(Thread::Current()->IsMutatorThread());
-
-  // We use a kernel2kernel constant evaluator in Dart 2.0 AOT compilation
-  // and never start the VM service isolate. So we should never end up invoking
-  // any dart code in the Dart 2.0 AOT compiler.
-#if !defined(DART_PRECOMPILED_RUNTIME)
-  if (Isolate::Current()->strong() && FLAG_precompiled_mode) {
-    UNREACHABLE();
-  }
-#endif  // !defined(DART_PRECOMPILED_RUNTIME)
-
   const int kTypeArgsLen = 0;  // No support to pass type args to generic func.
   const Array& arguments_descriptor =
       Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, arguments.Length()));
@@ -120,6 +110,15 @@
                                      const Array& arguments,
                                      const Array& arguments_descriptor,
                                      uword current_sp) {
+  // We use a kernel2kernel constant evaluator in Dart 2.0 AOT compilation
+  // and never start the VM service isolate. So we should never end up invoking
+  // any dart code in the Dart 2.0 AOT compiler.
+#if !defined(DART_PRECOMPILED_RUNTIME)
+  if (Isolate::Current()->strong() && FLAG_precompiled_mode) {
+    UNREACHABLE();
+  }
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+
   // Get the entrypoint corresponding to the function specified, this
   // will result in a compilation of the function if it is not already
   // compiled.
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index e922ec77..bb87152 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -2906,7 +2906,7 @@
           intptr_t line_number;
           intptr_t column_number;
           script.GetTokenLocation(breakpoint_pos, &line_number, &column_number);
-          OS::Print(
+          OS::PrintErr(
               "Resolved BP for "
               "function '%s' at line %" Pd " col %" Pd "\n",
               func.ToFullyQualifiedCString(), line_number, column_number);
@@ -2923,12 +2923,12 @@
     intptr_t column_number;
     script.GetTokenLocation(token_pos, &line_number, &column_number);
     if (func.IsNull()) {
-      OS::Print(
+      OS::PrintErr(
           "Registering pending breakpoint for "
           "an uncompiled function literal at line %" Pd " col %" Pd "\n",
           line_number, column_number);
     } else {
-      OS::Print(
+      OS::PrintErr(
           "Registering pending breakpoint for "
           "uncompiled function '%s' at line %" Pd " col %" Pd "\n",
           func.ToFullyQualifiedCString(), line_number, column_number);
@@ -3072,7 +3072,7 @@
     BreakpointLocation* latent_bpt =
         GetLatentBreakpoint(script_url, line_number, column_number);
     if (FLAG_verbose_debug) {
-      OS::Print(
+      OS::PrintErr(
           "Set latent breakpoint in url '%s' at "
           "line %" Pd " col %" Pd "\n",
           script_url.ToCString(), line_number, column_number);
@@ -3081,7 +3081,7 @@
   }
   if (scripts.Length() > 1) {
     if (FLAG_verbose_debug) {
-      OS::Print("Multiple scripts match url '%s'\n", script_url.ToCString());
+      OS::PrintErr("Multiple scripts match url '%s'\n", script_url.ToCString());
     }
     return NULL;
   }
@@ -3091,15 +3091,15 @@
   if (!first_token_idx.IsReal()) {
     // Script does not contain the given line number.
     if (FLAG_verbose_debug) {
-      OS::Print("Script '%s' does not contain line number %" Pd "\n",
-                script_url.ToCString(), line_number);
+      OS::PrintErr("Script '%s' does not contain line number %" Pd "\n",
+                   script_url.ToCString(), line_number);
     }
     return NULL;
   } else if (!last_token_idx.IsReal()) {
     // Line does not contain any tokens.
     if (FLAG_verbose_debug) {
-      OS::Print("No executable code at line %" Pd " in '%s'\n", line_number,
-                script_url.ToCString());
+      OS::PrintErr("No executable code at line %" Pd " in '%s'\n", line_number,
+                   script_url.ToCString());
     }
     return NULL;
   }
@@ -3112,8 +3112,8 @@
     first_token_idx.Next();
   }
   if ((bpt == NULL) && FLAG_verbose_debug) {
-    OS::Print("No executable code at line %" Pd " in '%s'\n", line_number,
-              script_url.ToCString());
+    OS::PrintErr("No executable code at line %" Pd " in '%s'\n", line_number,
+                 script_url.ToCString());
   }
   return bpt;
 }
@@ -3449,7 +3449,7 @@
     skip_next_step_ = skip_next_step;
     SetAsyncSteppingFramePointer();
     if (FLAG_verbose_debug) {
-      OS::Print("HandleSteppingRequest- kStepInto\n");
+      OS::PrintErr("HandleSteppingRequest- kStepInto\n");
     }
   } else if (resume_action_ == kStepOver) {
     DeoptimizeWorld();
@@ -3459,7 +3459,7 @@
     stepping_fp_ = stack_trace->FrameAt(0)->fp();
     SetAsyncSteppingFramePointer();
     if (FLAG_verbose_debug) {
-      OS::Print("HandleSteppingRequest- kStepOver %" Px "\n", stepping_fp_);
+      OS::PrintErr("HandleSteppingRequest- kStepOver %" Px "\n", stepping_fp_);
     }
   } else if (resume_action_ == kStepOut) {
     if (FLAG_async_debugger) {
@@ -3488,7 +3488,7 @@
       }
     }
     if (FLAG_verbose_debug) {
-      OS::Print("HandleSteppingRequest- kStepOut %" Px "\n", stepping_fp_);
+      OS::PrintErr("HandleSteppingRequest- kStepOut %" Px "\n", stepping_fp_);
     }
   } else if (resume_action_ == kStepRewind) {
     if (FLAG_trace_rewind) {
@@ -3874,11 +3874,11 @@
   ASSERT(!HasActiveBreakpoint(frame->pc()));
 
   if (FLAG_verbose_debug) {
-    OS::Print(">>> single step break at %s:%" Pd " (func %s token %s)\n",
-              String::Handle(frame->SourceUrl()).ToCString(),
-              frame->LineNumber(),
-              String::Handle(frame->QualifiedFunctionName()).ToCString(),
-              frame->TokenPos().ToCString());
+    OS::PrintErr(">>> single step break at %s:%" Pd " (func %s token %s)\n",
+                 String::Handle(frame->SourceUrl()).ToCString(),
+                 frame->LineNumber(),
+                 String::Handle(frame->QualifiedFunctionName()).ToCString(),
+                 frame->TokenPos().ToCString());
   }
 
   CacheStackTraces(CollectStackTrace(), CollectAsyncCausalStackTrace(),
@@ -3923,12 +3923,12 @@
 
     // Hit a synthetic async breakpoint.
     if (FLAG_verbose_debug) {
-      OS::Print(">>> hit synthetic breakpoint at %s:%" Pd
-                " "
-                "(token %s) (address %#" Px ")\n",
-                String::Handle(cbpt->SourceUrl()).ToCString(),
-                cbpt->LineNumber(), cbpt->token_pos().ToCString(),
-                top_frame->pc());
+      OS::PrintErr(">>> hit synthetic breakpoint at %s:%" Pd
+                   " "
+                   "(token %s) (address %#" Px ")\n",
+                   String::Handle(cbpt->SourceUrl()).ToCString(),
+                   cbpt->LineNumber(), cbpt->token_pos().ToCString(),
+                   top_frame->pc());
     }
 
     ASSERT(synthetic_async_breakpoint_ == NULL);
@@ -3946,12 +3946,12 @@
   }
 
   if (FLAG_verbose_debug) {
-    OS::Print(">>> hit breakpoint %" Pd " at %s:%" Pd
-              " (token %s) "
-              "(address %#" Px ")\n",
-              bpt_hit->id(), String::Handle(cbpt->SourceUrl()).ToCString(),
-              cbpt->LineNumber(), cbpt->token_pos().ToCString(),
-              top_frame->pc());
+    OS::PrintErr(">>> hit breakpoint %" Pd " at %s:%" Pd
+                 " (token %s) "
+                 "(address %#" Px ")\n",
+                 bpt_hit->id(), String::Handle(cbpt->SourceUrl()).ToCString(),
+                 cbpt->LineNumber(), cbpt->token_pos().ToCString(),
+                 top_frame->pc());
   }
 
   CacheStackTraces(stack_trace, CollectAsyncCausalStackTrace(),
@@ -4105,8 +4105,8 @@
         // be compiled already.
         ASSERT(!inner_function.HasCode());
         if (FLAG_verbose_debug) {
-          OS::Print("Pending BP remains unresolved in inner function '%s'\n",
-                    inner_function.ToFullyQualifiedCString());
+          OS::PrintErr("Pending BP remains unresolved in inner function '%s'\n",
+                       inner_function.ToFullyQualifiedCString());
         }
         continue;
       }
@@ -4125,8 +4125,8 @@
                                  loc->requested_column_number());
         if (!bp_pos.IsDebugPause()) {
           if (FLAG_verbose_debug) {
-            OS::Print("Failed resolving breakpoint for function '%s'\n",
-                      String::Handle(func.name()).ToCString());
+            OS::PrintErr("Failed resolving breakpoint for function '%s'\n",
+                         String::Handle(func.name()).ToCString());
           }
           continue;
         }
@@ -4136,17 +4136,17 @@
         Breakpoint* bpt = loc->breakpoints();
         while (bpt != NULL) {
           if (FLAG_verbose_debug) {
-            OS::Print("Resolved BP %" Pd
-                      " to pos %s, "
-                      "line %" Pd " col %" Pd
-                      ", "
-                      "function '%s' (requested range %s-%s, "
-                      "requested col %" Pd ")\n",
-                      bpt->id(), loc->token_pos().ToCString(),
-                      loc->LineNumber(), loc->ColumnNumber(),
-                      func.ToFullyQualifiedCString(), requested_pos.ToCString(),
-                      requested_end_pos.ToCString(),
-                      loc->requested_column_number());
+            OS::PrintErr(
+                "Resolved BP %" Pd
+                " to pos %s, "
+                "line %" Pd " col %" Pd
+                ", "
+                "function '%s' (requested range %s-%s, "
+                "requested col %" Pd ")\n",
+                bpt->id(), loc->token_pos().ToCString(), loc->LineNumber(),
+                loc->ColumnNumber(), func.ToFullyQualifiedCString(),
+                requested_pos.ToCString(), requested_end_pos.ToCString(),
+                loc->requested_column_number());
           }
           SendBreakpointEvent(ServiceEvent::kBreakpointResolved, bpt);
           bpt = bpt->next();
@@ -4156,12 +4156,12 @@
       if (FLAG_verbose_debug) {
         Breakpoint* bpt = loc->breakpoints();
         while (bpt != NULL) {
-          OS::Print("Setting breakpoint %" Pd " at line %" Pd " col %" Pd
-                    ""
-                    " for %s '%s'\n",
-                    bpt->id(), loc->LineNumber(), loc->ColumnNumber(),
-                    func.IsClosureFunction() ? "closure" : "function",
-                    String::Handle(func.name()).ToCString());
+          OS::PrintErr("Setting breakpoint %" Pd " at line %" Pd " col %" Pd
+                       ""
+                       " for %s '%s'\n",
+                       bpt->id(), loc->LineNumber(), loc->ColumnNumber(),
+                       func.IsClosureFunction() ? "closure" : "function",
+                       String::Handle(func.name()).ToCString());
           bpt = bpt->next();
         }
       }
@@ -4213,10 +4213,10 @@
           Breakpoint* bpt = matched_loc->breakpoints();
           while (bpt != NULL) {
             if (FLAG_verbose_debug) {
-              OS::Print("No code found at line %" Pd
-                        ": "
-                        "dropping latent breakpoint %" Pd " in '%s'\n",
-                        line_number, bpt->id(), url.ToCString());
+              OS::PrintErr("No code found at line %" Pd
+                           ": "
+                           "dropping latent breakpoint %" Pd " in '%s'\n",
+                           line_number, bpt->id(), url.ToCString());
             }
             Breakpoint* prev = bpt;
             bpt = bpt->next();
@@ -4245,7 +4245,7 @@
             while (bpt != NULL) {
               bpt->set_bpt_location(unresolved_loc);
               if (FLAG_verbose_debug) {
-                OS::Print(
+                OS::PrintErr(
                     "Converted latent breakpoint "
                     "%" Pd " in '%s' at line %" Pd " col %" Pd "\n",
                     bpt->id(), url.ToCString(), line_number, column_number);
@@ -4273,7 +4273,7 @@
       if (FLAG_verbose_debug) {
         Breakpoint* bpt = loc->breakpoints();
         while (bpt != NULL) {
-          OS::Print(
+          OS::PrintErr(
               "No match found for latent breakpoint id "
               "%" Pd " with url '%s'\n",
               bpt->id(), url.ToCString());
diff --git a/runtime/vm/exceptions_test.cc b/runtime/vm/exceptions_test.cc
index 55ca394..fcd8869 100644
--- a/runtime/vm/exceptions_test.cc
+++ b/runtime/vm/exceptions_test.cc
@@ -17,8 +17,8 @@
   const Instance& expected = Instance::CheckedHandle(arguments->NativeArgAt(0));
   const Instance& actual = Instance::CheckedHandle(arguments->NativeArgAt(1));
   if (!expected.CanonicalizeEquals(actual)) {
-    OS::Print("expected: '%s' actual: '%s'\n", expected.ToCString(),
-              actual.ToCString());
+    OS::PrintErr("expected: '%s' actual: '%s'\n", expected.ToCString(),
+                 actual.ToCString());
     FATAL("Unhandled_equals fails.\n");
   }
 }
diff --git a/runtime/vm/flag_list.h b/runtime/vm/flag_list.h
index 7dd0cc2..50afd6e 100644
--- a/runtime/vm/flag_list.h
+++ b/runtime/vm/flag_list.h
@@ -118,8 +118,10 @@
     "Maximum number of polymorphic check, otherwise it is megamorphic.")       \
   P(max_equality_polymorphic_checks, int, 32,                                  \
     "Maximum number of polymorphic checks in equality operator,")              \
-  P(new_gen_semi_max_size, int, (kWordSize <= 4) ? 16 : 32,                    \
+  P(new_gen_semi_max_size, int, (kWordSize <= 4) ? 8 : 16,                     \
     "Max size of new gen semi space in MB")                                    \
+  P(new_gen_semi_initial_size, int, (kWordSize <= 4) ? 1 : 2,                  \
+    "Initial size of new gen semi space in MB")                                \
   P(optimization_counter_threshold, int, 30000,                                \
     "Function's usage-counter value before it is optimized, -1 means never")   \
   P(old_gen_heap_size, int, kDefaultMaxOldGenHeapSize,                         \
diff --git a/runtime/vm/flags.cc b/runtime/vm/flags.cc
index 9120a8e..7b454b3 100644
--- a/runtime/vm/flags.cc
+++ b/runtime/vm/flags.cc
@@ -105,34 +105,35 @@
 
   void Print() {
     if (IsUnrecognized()) {
-      OS::Print("%s: unrecognized\n", name_);
+      OS::PrintErr("%s: unrecognized\n", name_);
       return;
     }
     switch (type_) {
       case kBoolean: {
-        OS::Print("%s: %s (%s)\n", name_, *this->bool_ptr_ ? "true" : "false",
-                  comment_);
+        OS::PrintErr("%s: %s (%s)\n", name_,
+                     *this->bool_ptr_ ? "true" : "false", comment_);
         break;
       }
       case kInteger: {
-        OS::Print("%s: %d (%s)\n", name_, *this->int_ptr_, comment_);
+        OS::PrintErr("%s: %d (%s)\n", name_, *this->int_ptr_, comment_);
         break;
       }
       case kUint64: {
-        OS::Print("%s: %" Pu64 " (%s)\n", name_, *this->uint64_ptr_, comment_);
+        OS::PrintErr("%s: %" Pu64 " (%s)\n", name_, *this->uint64_ptr_,
+                     comment_);
         break;
       }
       case kString: {
         if (*this->charp_ptr_ != NULL) {
-          OS::Print("%s: '%s' (%s)\n", name_, *this->charp_ptr_, comment_);
+          OS::PrintErr("%s: '%s' (%s)\n", name_, *this->charp_ptr_, comment_);
         } else {
-          OS::Print("%s: (null) (%s)\n", name_, comment_);
+          OS::PrintErr("%s: (null) (%s)\n", name_, comment_);
         }
         break;
       }
       case kOptionHandler:
       case kFlagHandler: {
-        OS::Print("%s: (%s)\n", name_, comment_);
+        OS::PrintErr("%s: (%s)\n", name_, comment_);
         break;
       }
       default:
@@ -391,8 +392,8 @@
     // unrecognized flags.
     if (!flag->IsUnrecognized()) {
       if (!SetFlagFromString(flag, argument)) {
-        OS::Print("Ignoring flag: %s is an invalid value for flag %s\n",
-                  argument, name);
+        OS::PrintErr("Ignoring flag: %s is an invalid value for flag %s\n",
+                     argument, name);
       }
     }
   }
@@ -473,7 +474,7 @@
 }
 
 void Flags::PrintFlags() {
-  OS::Print("Flag settings:\n");
+  OS::PrintErr("Flag settings:\n");
   for (intptr_t i = 0; i < num_flags_; ++i) {
     flags_[i]->Print();
   }
diff --git a/runtime/vm/freelist.cc b/runtime/vm/freelist.cc
index 6e5dded..c90fead 100644
--- a/runtime/vm/freelist.cc
+++ b/runtime/vm/freelist.cc
@@ -265,7 +265,7 @@
     small_objects += list_length;
     intptr_t list_bytes = list_length * i * kObjectAlignment;
     small_bytes += list_bytes;
-    OS::Print(
+    OS::PrintErr(
         "small %3d [%8d bytes] : "
         "%8" Pd " objs; %8.1f KB; %8.1f cum KB\n",
         i, i * kObjectAlignment, list_length,
@@ -322,12 +322,12 @@
     intptr_t list_length = pair->second();
     intptr_t list_bytes = list_length * size;
     large_bytes += list_bytes;
-    OS::Print("large %3" Pd " [%8" Pd
-              " bytes] : "
-              "%8" Pd " objs; %8.1f KB; %8.1f cum KB\n",
-              size / kObjectAlignment, size, list_length,
-              list_bytes / static_cast<double>(KB),
-              large_bytes / static_cast<double>(KB));
+    OS::PrintErr("large %3" Pd " [%8" Pd
+                 " bytes] : "
+                 "%8" Pd " objs; %8.1f KB; %8.1f cum KB\n",
+                 size / kObjectAlignment, size, list_length,
+                 list_bytes / static_cast<double>(KB),
+                 large_bytes / static_cast<double>(KB));
   }
 }
 
diff --git a/runtime/vm/hash_table.h b/runtime/vm/hash_table.h
index 24ae04c..2c408e7 100644
--- a/runtime/vm/hash_table.h
+++ b/runtime/vm/hash_table.h
@@ -323,7 +323,7 @@
     const intptr_t num25 = NumLT25Collisions();
     const intptr_t num_more = NumGT25Collisions();
     // clang-format off
-    OS::Print("Stats for %s table :\n"
+    OS::PrintErr("Stats for %s table :\n"
               " Size of table = %" Pd ",Number of Occupied entries = %" Pd "\n"
               " Number of Grows = %" Pd "\n"
               " Number of lookups with < 5 collisions = %" Pd "\n"
diff --git a/runtime/vm/heap_test.cc b/runtime/vm/heap_test.cc
index d073611..23def28f 100644
--- a/runtime/vm/heap_test.cc
+++ b/runtime/vm/heap_test.cc
@@ -82,10 +82,10 @@
   }
 
   static void DumpClassHeapStats(ClassHeapStats* stats) {
-    OS::Print("%" Pd " ", stats->recent.new_count);
-    OS::Print("%" Pd " ", stats->post_gc.new_count);
-    OS::Print("%" Pd " ", stats->pre_gc.new_count);
-    OS::Print("\n");
+    OS::PrintErr("%" Pd " ", stats->recent.new_count);
+    OS::PrintErr("%" Pd " ", stats->post_gc.new_count);
+    OS::PrintErr("%" Pd " ", stats->pre_gc.new_count);
+    OS::PrintErr("\n");
   }
 };
 
diff --git a/runtime/vm/interpreter.cc b/runtime/vm/interpreter.cc
index c61a2d5..4d58732 100644
--- a/runtime/vm/interpreter.cc
+++ b/runtime/vm/interpreter.cc
@@ -2135,25 +2135,169 @@
   }
 
   {
-    BYTECODE(NativeCall, A_B_C);
-    NativeFunctionWrapper trampoline =
-        reinterpret_cast<NativeFunctionWrapper>(LOAD_CONSTANT(rA));
-    Dart_NativeFunction function =
-        reinterpret_cast<Dart_NativeFunction>(LOAD_CONSTANT(rB));
-    intptr_t argc_tag = reinterpret_cast<intptr_t>(LOAD_CONSTANT(rC));
-    const intptr_t num_arguments = NativeArguments::ArgcBits::decode(argc_tag);
+    BYTECODE(NativeCall, __D);
+    RawTypedData* native_entry = static_cast<RawTypedData*>(LOAD_CONSTANT(rD));
+    // TODO(regis): Introduce a new VM class subclassing Object and containing
+    // the four untagged values currently stored as TypeData array elements.
+    MethodRecognizer::Kind kind =
+        static_cast<MethodRecognizer::Kind>(*(reinterpret_cast<uintptr_t*>(
+            native_entry->ptr()->data() + (0 << kWordSizeLog2))));
+    switch (kind) {
+      case MethodRecognizer::kObjectEquals: {
+        SP[-1] = SP[-1] == SP[0] ? Bool::True().raw() : Bool::False().raw();
+        SP--;
+      } break;
+      case MethodRecognizer::kStringBaseLength:
+      case MethodRecognizer::kStringBaseIsEmpty: {
+        RawInstance* instance = reinterpret_cast<RawInstance*>(SP[0]);
+        SP[0] = reinterpret_cast<RawObject**>(
+            instance->ptr())[String::length_offset() / kWordSize];
+        if (kind == MethodRecognizer::kStringBaseIsEmpty) {
+          SP[0] =
+              SP[0] == Smi::New(0) ? Bool::True().raw() : Bool::False().raw();
+        }
+      } break;
+      case MethodRecognizer::kGrowableArrayLength: {
+        RawInstance* instance = reinterpret_cast<RawInstance*>(SP[0]);
+        SP[0] = reinterpret_cast<RawObject**>(
+            instance->ptr())[GrowableObjectArray::length_offset() / kWordSize];
+      } break;
+      case MethodRecognizer::kObjectArrayLength:
+      case MethodRecognizer::kImmutableArrayLength: {
+        RawInstance* instance = reinterpret_cast<RawInstance*>(SP[0]);
+        SP[0] = reinterpret_cast<RawObject**>(
+            instance->ptr())[Array::length_offset() / kWordSize];
+      } break;
+      case MethodRecognizer::kTypedDataLength: {
+        RawInstance* instance = reinterpret_cast<RawInstance*>(SP[0]);
+        SP[0] = reinterpret_cast<RawObject**>(
+            instance->ptr())[TypedData::length_offset() / kWordSize];
+      } break;
+      case MethodRecognizer::kClassIDgetID: {
+        SP[0] = InterpreterHelpers::GetClassIdAsSmi(SP[0]);
+      } break;
+      case MethodRecognizer::kGrowableArrayCapacity: {
+        RawInstance* instance = reinterpret_cast<RawInstance*>(SP[0]);
+        instance = reinterpret_cast<RawInstance**>(
+            instance->ptr())[GrowableObjectArray::data_offset() / kWordSize];
+        SP[0] = reinterpret_cast<RawObject**>(
+            instance->ptr())[Array::length_offset() / kWordSize];
+      } break;
+      case MethodRecognizer::kListFactory: {
+        // factory List<E>([int length]) {
+        //   return (:arg_desc.positional_count == 2) ? new _List<E>(length)
+        //                                            : new _GrowableList<E>(0);
+        // }
+        if (InterpreterHelpers::ArgDescPosCount(argdesc_) == 2) {
+          SP[1] = SP[0];   // length
+          SP[2] = SP[-1];  // type
+          Exit(thread, FP, SP + 3, pc);
+          NativeArguments native_args(thread, 2, SP + 1, SP - 1);
+          INVOKE_RUNTIME(DRT_AllocateArray, native_args);
+          SP -= 1;  // Result is in SP - 1.
+        } else {
+          // SP[0] is type.
+          *++SP = Smi::New(0);  // len
+          *++SP = thread->isolate()->object_store()->growable_list_factory();
+          argdesc_ = ArgumentsDescriptor::New(0, 2);  // Returns a cached desc.
+          if (!Invoke(thread, SP - 2, SP, &pc, &FP, &SP)) {
+            HANDLE_EXCEPTION;
+          }
+        }
+      } break;
+      case MethodRecognizer::kObjectArrayAllocate: {
+        SP[1] = SP[0];   // length
+        SP[2] = SP[-1];  // type
+        Exit(thread, FP, SP + 3, pc);
+        NativeArguments native_args(thread, 2, SP + 1, SP - 1);
+        INVOKE_RUNTIME(DRT_AllocateArray, native_args);
+        SP -= 1;  // Result is in SP - 1.
+      } break;
+      case MethodRecognizer::kLinkedHashMap_getIndex: {
+        RawInstance* instance = reinterpret_cast<RawInstance*>(SP[0]);
+        SP[0] = reinterpret_cast<RawObject**>(
+            instance->ptr())[LinkedHashMap::index_offset() / kWordSize];
+      } break;
+      case MethodRecognizer::kLinkedHashMap_setIndex: {
+        RawInstance* instance = reinterpret_cast<RawInstance*>(SP[-1]);
+        reinterpret_cast<RawObject**>(
+            instance->ptr())[LinkedHashMap::index_offset() / kWordSize] = SP[0];
+        *--SP = null_value;
+      } break;
+      case MethodRecognizer::kLinkedHashMap_getData: {
+        RawInstance* instance = reinterpret_cast<RawInstance*>(SP[0]);
+        SP[0] = reinterpret_cast<RawObject**>(
+            instance->ptr())[LinkedHashMap::data_offset() / kWordSize];
+      } break;
+      case MethodRecognizer::kLinkedHashMap_setData: {
+        RawInstance* instance = reinterpret_cast<RawInstance*>(SP[-1]);
+        reinterpret_cast<RawObject**>(
+            instance->ptr())[LinkedHashMap::data_offset() / kWordSize] = SP[0];
+        *--SP = null_value;
+      } break;
+      case MethodRecognizer::kLinkedHashMap_getHashMask: {
+        RawInstance* instance = reinterpret_cast<RawInstance*>(SP[0]);
+        SP[0] = reinterpret_cast<RawObject**>(
+            instance->ptr())[LinkedHashMap::hash_mask_offset() / kWordSize];
+      } break;
+      case MethodRecognizer::kLinkedHashMap_setHashMask: {
+        RawInstance* instance = reinterpret_cast<RawInstance*>(SP[-1]);
+        reinterpret_cast<RawObject**>(
+            instance->ptr())[LinkedHashMap::hash_mask_offset() / kWordSize] =
+            SP[0];
+        *--SP = null_value;
+      } break;
+      case MethodRecognizer::kLinkedHashMap_getUsedData: {
+        RawInstance* instance = reinterpret_cast<RawInstance*>(SP[0]);
+        SP[0] = reinterpret_cast<RawObject**>(
+            instance->ptr())[LinkedHashMap::used_data_offset() / kWordSize];
+      } break;
+      case MethodRecognizer::kLinkedHashMap_setUsedData: {
+        RawInstance* instance = reinterpret_cast<RawInstance*>(SP[-1]);
+        reinterpret_cast<RawObject**>(
+            instance->ptr())[LinkedHashMap::used_data_offset() / kWordSize] =
+            SP[0];
+        *--SP = null_value;
+      } break;
+      case MethodRecognizer::kLinkedHashMap_getDeletedKeys: {
+        RawInstance* instance = reinterpret_cast<RawInstance*>(SP[0]);
+        SP[0] = reinterpret_cast<RawObject**>(
+            instance->ptr())[LinkedHashMap::deleted_keys_offset() / kWordSize];
+      } break;
+      case MethodRecognizer::kLinkedHashMap_setDeletedKeys: {
+        RawInstance* instance = reinterpret_cast<RawInstance*>(SP[-1]);
+        reinterpret_cast<RawObject**>(
+            instance->ptr())[LinkedHashMap::deleted_keys_offset() / kWordSize] =
+            SP[0];
+        *--SP = null_value;
+      } break;
+      default: {
+        NativeFunctionWrapper trampoline =
+            reinterpret_cast<NativeFunctionWrapper>(
+                *(reinterpret_cast<uintptr_t*>(native_entry->ptr()->data() +
+                                               (1 << kWordSizeLog2))));
+        Dart_NativeFunction function = reinterpret_cast<Dart_NativeFunction>(
+            *(reinterpret_cast<uintptr_t*>(native_entry->ptr()->data() +
+                                           (2 << kWordSizeLog2))));
+        intptr_t argc_tag =
+            static_cast<intptr_t>(*(reinterpret_cast<uintptr_t*>(
+                native_entry->ptr()->data() + (3 << kWordSizeLog2))));
+        const intptr_t num_arguments =
+            NativeArguments::ArgcBits::decode(argc_tag);
 
-    *++SP = null_value;  // Result slot.
+        *++SP = null_value;  // Result slot.
 
-    RawObject** incoming_args = SP - num_arguments;
-    RawObject** return_slot = SP;
-    Exit(thread, FP, SP, pc);
-    NativeArguments args(thread, argc_tag, incoming_args, return_slot);
-    INVOKE_NATIVE(trampoline, function,
-                  reinterpret_cast<Dart_NativeArguments>(&args));
+        RawObject** incoming_args = SP - num_arguments;
+        RawObject** return_slot = SP;
+        Exit(thread, FP, SP, pc);
+        NativeArguments args(thread, argc_tag, incoming_args, return_slot);
+        INVOKE_NATIVE(trampoline, function,
+                      reinterpret_cast<Dart_NativeArguments>(&args));
 
-    *(SP - num_arguments) = *return_slot;
-    SP -= num_arguments;
+        *(SP - num_arguments) = *return_slot;
+        SP -= num_arguments;
+      }
+    }
     DISPATCH();
   }
 
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 5337d5a..f0840c0 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -700,7 +700,7 @@
 MessageHandler::MessageStatus IsolateMessageHandler::ProcessUnhandledException(
     const Error& result) {
   if (FLAG_trace_isolates) {
-    OS::Print(
+    OS::PrintErr(
         "[!] Unhandled exception in %s:\n"
         "         exception: %s\n",
         T->isolate()->name(), result.ToErrorCString());
@@ -1104,7 +1104,7 @@
 #endif
   if (FLAG_trace_isolates) {
     if (name_prefix == NULL || strcmp(name_prefix, "vm-isolate") != 0) {
-      OS::Print(
+      OS::PrintErr(
           "[+] Starting isolate:\n"
           "\tisolate:    %s\n",
           result->name());
@@ -1765,7 +1765,7 @@
   }
   if (FLAG_trace_isolates) {
     heap()->PrintSizes();
-    OS::Print(
+    OS::PrintErr(
         "[-] Stopping isolate:\n"
         "\tisolate:    %s\n",
         name());
@@ -1826,7 +1826,7 @@
     if (FLAG_support_compiler_stats && FLAG_compiler_stats &&
         !ServiceIsolate::IsServiceIsolateDescendant(this) &&
         (this != Dart::vm_isolate())) {
-      OS::Print("%s", aggregate_compiler_stats()->PrintToZone());
+      OS::PrintErr("%s", aggregate_compiler_stats()->PrintToZone());
     }
   }
 
@@ -2506,7 +2506,7 @@
         const int64_t reload_time_micros =
             OS::GetCurrentMonotonicMicros() - start_time_micros;
         double reload_millis = MicrosecondsToMilliseconds(reload_time_micros);
-        OS::Print("Reloading has finished! (%.2f ms)\n", reload_millis);
+        OS::PrintErr("Reloading has finished! (%.2f ms)\n", reload_millis);
       }
       break;
     }
diff --git a/runtime/vm/json_writer.cc b/runtime/vm/json_writer.cc
index 4e7c98a..7c3aa7f 100644
--- a/runtime/vm/json_writer.cc
+++ b/runtime/vm/json_writer.cc
@@ -317,7 +317,7 @@
 void JSONWriter::EnsureIntegerIsRepresentableInJavaScript(int64_t i) {
 #ifdef DEBUG
   if (!Utils::IsJavascriptInt(i)) {
-    OS::Print(
+    OS::PrintErr(
         "JSONWriter::EnsureIntegerIsRepresentableInJavaScript failed on "
         "%" Pd64 "\n",
         i);
diff --git a/runtime/vm/kernel_isolate.cc b/runtime/vm/kernel_isolate.cc
index 64b6982..dd39430 100644
--- a/runtime/vm/kernel_isolate.cc
+++ b/runtime/vm/kernel_isolate.cc
@@ -134,7 +134,7 @@
  protected:
   static void ShutdownIsolate(uword parameter) {
     if (FLAG_trace_kernel) {
-      OS::Print(DART_KERNEL_ISOLATE_NAME ": ShutdownIsolate\n");
+      OS::PrintErr(DART_KERNEL_ISOLATE_NAME ": ShutdownIsolate\n");
     }
     Isolate* I = reinterpret_cast<Isolate*>(parameter);
     I->WaitForOutstandingSpawns();
@@ -168,7 +168,7 @@
     // Shut the isolate down.
     Dart::ShutdownIsolate(I);
     if (FLAG_trace_kernel) {
-      OS::Print(DART_KERNEL_ISOLATE_NAME ": Shutdown.\n");
+      OS::PrintErr(DART_KERNEL_ISOLATE_NAME ": Shutdown.\n");
     }
     // This should be the last line so the check
     // IsKernelIsolate works during the shutdown process.
@@ -184,8 +184,8 @@
     const Library& root_library =
         Library::Handle(Z, I->object_store()->root_library());
     if (root_library.IsNull()) {
-      OS::Print(DART_KERNEL_ISOLATE_NAME
-                ": Embedder did not install a script.");
+      OS::PrintErr(DART_KERNEL_ISOLATE_NAME
+                   ": Embedder did not install a script.");
       // Kernel isolate is not supported by embedder.
       return false;
     }
@@ -196,8 +196,8 @@
         Z, root_library.LookupFunctionAllowPrivate(entry_name));
     if (entry.IsNull()) {
       // Kernel isolate is not supported by embedder.
-      OS::Print(DART_KERNEL_ISOLATE_NAME
-                ": Embedder did not provide a main function.");
+      OS::PrintErr(DART_KERNEL_ISOLATE_NAME
+                   ": Embedder did not provide a main function.");
       return false;
     }
     ASSERT(!entry.IsNull());
@@ -207,9 +207,9 @@
     if (result.IsError()) {
       // Kernel isolate did not initialize properly.
       const Error& error = Error::Cast(result);
-      OS::Print(DART_KERNEL_ISOLATE_NAME
-                ": Calling main resulted in an error: %s",
-                error.ToErrorCString());
+      OS::PrintErr(DART_KERNEL_ISOLATE_NAME
+                   ": Calling main resulted in an error: %s",
+                   error.ToErrorCString());
       return false;
     }
     ASSERT(result.IsReceivePort());
@@ -236,7 +236,8 @@
   }
   ASSERT(!Exists());
   if (FLAG_trace_kernel) {
-    OS::Print(DART_KERNEL_ISOLATE_NAME ": InitCallback for %s.\n", I->name());
+    OS::PrintErr(DART_KERNEL_ISOLATE_NAME ": InitCallback for %s.\n",
+                 I->name());
   }
   SetKernelIsolate(I);
 }
diff --git a/runtime/vm/log.h b/runtime/vm/log.h
index e28c02d..8c851a4 100644
--- a/runtime/vm/log.h
+++ b/runtime/vm/log.h
@@ -26,7 +26,7 @@
 
 class Log {
  public:
-  explicit Log(LogPrinter printer = OS::Print);
+  explicit Log(LogPrinter printer = OS::PrintErr);
   ~Log();
 
   static Log* Current();
diff --git a/runtime/vm/log_test.cc b/runtime/vm/log_test.cc
index f17c4d9..49ce2ea 100644
--- a/runtime/vm/log_test.cc
+++ b/runtime/vm/log_test.cc
@@ -38,7 +38,7 @@
   test_output_ = buffer;
 
   // Also print to stdout to see the overall result.
-  OS::Print("%s", test_output_);
+  OS::PrintErr("%s", test_output_);
 }
 
 class LogTestHelper : public AllStatic {
diff --git a/runtime/vm/megamorphic_cache_table.cc b/runtime/vm/megamorphic_cache_table.cc
index a8811c1..7d0c165 100644
--- a/runtime/vm/megamorphic_cache_table.cc
+++ b/runtime/vm/megamorphic_cache_table.cc
@@ -99,8 +99,8 @@
       max_size = buckets.Length();
     }
   }
-  OS::Print("%" Pd " megamorphic caches using %" Pd "KB.\n", table.Length(),
-            size / 1024);
+  OS::PrintErr("%" Pd " megamorphic caches using %" Pd "KB.\n", table.Length(),
+               size / 1024);
 
   intptr_t* probe_counts = new intptr_t[max_size];
   intptr_t entry_count = 0;
@@ -141,9 +141,10 @@
   intptr_t cumulative_entries = 0;
   for (intptr_t i = 0; i <= max_probe_count; i++) {
     cumulative_entries += probe_counts[i];
-    OS::Print("Megamorphic probe %" Pd ": %" Pd " (%lf)\n", i, probe_counts[i],
-              static_cast<double>(cumulative_entries) /
-                  static_cast<double>(entry_count));
+    OS::PrintErr("Megamorphic probe %" Pd ": %" Pd " (%lf)\n", i,
+                 probe_counts[i],
+                 static_cast<double>(cumulative_entries) /
+                     static_cast<double>(entry_count));
   }
   delete[] probe_counts;
 }
diff --git a/runtime/vm/message_handler.cc b/runtime/vm/message_handler.cc
index 1a1ca67..2bc806d 100644
--- a/runtime/vm/message_handler.cc
+++ b/runtime/vm/message_handler.cc
@@ -106,7 +106,7 @@
   bool task_running;
   MonitorLocker ml(&monitor_);
   if (FLAG_trace_isolates) {
-    OS::Print(
+    OS::PrintErr(
         "[+] Starting message handler:\n"
         "\thandler:    %s\n",
         name());
@@ -130,7 +130,7 @@
     if (FLAG_trace_isolates) {
       Isolate* source_isolate = Isolate::Current();
       if (source_isolate) {
-        OS::Print(
+        OS::PrintErr(
             "[>] Posting message:\n"
             "\tlen:        %" Pd "\n\tsource:     (%" Pd64
             ") %s\n\tdest:       %s\n"
@@ -138,7 +138,7 @@
             message->Size(), static_cast<int64_t>(source_isolate->main_port()),
             source_isolate->name(), name(), message->dest_port());
       } else {
-        OS::Print(
+        OS::PrintErr(
             "[>] Posting message:\n"
             "\tlen:        %" Pd
             "\n\tsource:     <native code>\n"
@@ -214,7 +214,7 @@
   while (message != NULL) {
     intptr_t message_len = message->Size();
     if (FLAG_trace_isolates) {
-      OS::Print(
+      OS::PrintErr(
           "[<] Handling message:\n"
           "\tlen:        %" Pd
           "\n"
@@ -235,7 +235,7 @@
     message = NULL;  // May be deleted by now.
     ml->Enter();
     if (FLAG_trace_isolates) {
-      OS::Print(
+      OS::PrintErr(
           "[.] Message handled (%s):\n"
           "\tlen:        %" Pd
           "\n"
@@ -459,13 +459,13 @@
       if (FLAG_trace_isolates) {
         if (status != kOK && thread() != NULL) {
           const Error& error = Error::Handle(thread()->sticky_error());
-          OS::Print(
+          OS::PrintErr(
               "[-] Stopping message handler (%s):\n"
               "\thandler:    %s\n"
               "\terror:    %s\n",
               MessageStatusString(status), name(), error.ToCString());
         } else {
-          OS::Print(
+          OS::PrintErr(
               "[-] Stopping message handler (%s):\n"
               "\thandler:    %s\n",
               MessageStatusString(status), name());
@@ -534,7 +534,7 @@
 void MessageHandler::ClosePort(Dart_Port port) {
   MonitorLocker ml(&monitor_);
   if (FLAG_trace_isolates) {
-    OS::Print(
+    OS::PrintErr(
         "[-] Closing port:\n"
         "\thandler:    %s\n"
         "\tport:       %" Pd64
@@ -547,7 +547,7 @@
 void MessageHandler::CloseAllPorts() {
   MonitorLocker ml(&monitor_);
   if (FLAG_trace_isolates) {
-    OS::Print(
+    OS::PrintErr(
         "[-] Closing all ports:\n"
         "\thandler:    %s\n",
         name());
diff --git a/runtime/vm/native_entry.cc b/runtime/vm/native_entry.cc
index d993921..3aaf67e 100644
--- a/runtime/vm/native_entry.cc
+++ b/runtime/vm/native_entry.cc
@@ -102,7 +102,7 @@
   UNREACHABLE();
 }
 
-#if defined(TARGET_ARCH_DBC)
+#if defined(TARGET_ARCH_DBC) || defined(DART_USE_INTERPRETER)
 uword NativeEntry::BootstrapNativeCallWrapperEntry() {
   uword entry =
       reinterpret_cast<uword>(NativeEntry::BootstrapNativeCallWrapper);
@@ -223,7 +223,7 @@
   const Library& library = Library::Handle(zone, cls.library());
 
   *is_bootstrap_native =
-      Bootstrap::IsBootstapResolver(library.native_entry_resolver());
+      Bootstrap::IsBootstrapResolver(library.native_entry_resolver());
 
   const String& native_name = String::Handle(zone, func.native_name());
   ASSERT(!native_name.IsNull());
diff --git a/runtime/vm/native_entry.h b/runtime/vm/native_entry.h
index 048c12e..638d1c1 100644
--- a/runtime/vm/native_entry.h
+++ b/runtime/vm/native_entry.h
@@ -129,7 +129,7 @@
                                                uword pc);
   static const uint8_t* ResolveSymbol(uword pc);
 
-#if defined(TARGET_ARCH_DBC)
+#if defined(TARGET_ARCH_DBC) || defined(DART_USE_INTERPRETER)
   static uword BootstrapNativeCallWrapperEntry();
   static void BootstrapNativeCallWrapper(Dart_NativeArguments args,
                                          Dart_NativeFunction func);
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index beb89ec..2428bab 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -9143,8 +9143,8 @@
       token_objects_.Add(str_);
       if (kPrintTokenObjects) {
         int iid = Isolate::Current()->main_port() % 1024;
-        OS::Print("%03x ident <%s -> %s>\n", iid, ident.ToCString(),
-                  str_.ToCString());
+        OS::PrintErr("%03x ident <%s -> %s>\n", iid, ident.ToCString(),
+                     str_.ToCString());
       }
     }
     WriteIndex(index);
@@ -12622,7 +12622,7 @@
   func = GetFunction(all_libs, #class_name, #function_name);                   \
   if (func.IsNull()) {                                                         \
     has_errors = true;                                                         \
-    OS::Print("Function not found %s.%s\n", #class_name, #function_name);      \
+    OS::PrintErr("Function not found %s.%s\n", #class_name, #function_name);   \
   } else {                                                                     \
     CHECK_FINGERPRINT3(func, class_name, function_name, dest, fp);             \
   }
@@ -12662,7 +12662,7 @@
   func = GetFunction(all_libs, #class_name, #factory_name);                    \
   if (func.IsNull()) {                                                         \
     has_errors = true;                                                         \
-    OS::Print("Function not found %s.%s\n", #class_name, #factory_name);       \
+    OS::PrintErr("Function not found %s.%s\n", #class_name, #factory_name);    \
   } else {                                                                     \
     CHECK_FINGERPRINT2(func, symbol, cid, fp);                                 \
   }
diff --git a/runtime/vm/object_store.cc b/runtime/vm/object_store.cc
index b9eeeba..dd182ff 100644
--- a/runtime/vm/object_store.cc
+++ b/runtime/vm/object_store.cc
@@ -221,6 +221,12 @@
   ASSERT(!cls.IsNull());
   set_pragma_class(cls);
 
+  cls = core_lib.LookupClassAllowPrivate(Symbols::_GrowableList());
+  ASSERT(!cls.IsNull());
+  growable_list_factory_ =
+      cls.LookupFactoryAllowPrivate(Symbols::_GrowableListFactory());
+  ASSERT(growable_list_factory_ != Function::null());
+
   // Cache the core private functions used for fast instance of checks.
   simple_instance_of_function_ =
       PrivateObjectLookup(Symbols::_simpleInstanceOf());
diff --git a/runtime/vm/object_store.h b/runtime/vm/object_store.h
index 01b5a52..cf0f807 100644
--- a/runtime/vm/object_store.h
+++ b/runtime/vm/object_store.h
@@ -108,6 +108,7 @@
   RW(Function, lookup_port_handler)                                            \
   RW(TypedData, empty_uint32_array)                                            \
   RW(Function, handle_message_function)                                        \
+  RW(Function, growable_list_factory)                                          \
   RW(Function, simple_instance_of_function)                                    \
   RW(Function, simple_instance_of_true_function)                               \
   RW(Function, simple_instance_of_false_function)                              \
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index ed8d624..6686b52 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -150,8 +150,8 @@
   type_arguments2.SetTypeAt(0, type1);
   type_arguments2.SetTypeAt(1, type2);
   EXPECT_NE(type_arguments1.raw(), type_arguments2.raw());
-  OS::Print("1: %s\n", type_arguments1.ToCString());
-  OS::Print("2: %s\n", type_arguments2.ToCString());
+  OS::PrintErr("1: %s\n", type_arguments1.ToCString());
+  OS::PrintErr("2: %s\n", type_arguments2.ToCString());
   EXPECT(type_arguments1.Equals(type_arguments2));
   TypeArguments& type_arguments3 = TypeArguments::Handle();
   type_arguments1.Canonicalize();
@@ -3765,16 +3765,17 @@
 
 static void PrintMetadata(const char* name, const Object& data) {
   if (data.IsError()) {
-    OS::Print("Error in metadata evaluation for %s: '%s'\n", name,
-              Error::Cast(data).ToErrorCString());
+    OS::PrintErr("Error in metadata evaluation for %s: '%s'\n", name,
+                 Error::Cast(data).ToErrorCString());
   }
   EXPECT(data.IsArray());
   const Array& metadata = Array::Cast(data);
-  OS::Print("Metadata for %s has %" Pd " values:\n", name, metadata.Length());
+  OS::PrintErr("Metadata for %s has %" Pd " values:\n", name,
+               metadata.Length());
   Object& elem = Object::Handle();
   for (int i = 0; i < metadata.Length(); i++) {
     elem = metadata.At(i);
-    OS::Print("  %d: %s\n", i, elem.ToCString());
+    OS::PrintErr("  %d: %s\n", i, elem.ToCString());
   }
 }
 
diff --git a/runtime/vm/os.h b/runtime/vm/os.h
index 94bb98d..dcee83d 100644
--- a/runtime/vm/os.h
+++ b/runtime/vm/os.h
@@ -92,6 +92,9 @@
   static uintptr_t GetProgramCounter();
 
   // Print formatted output to stdout/stderr for debugging.
+  // Tracing and debugging prints from the VM should strongly prefer to use
+  // PrintErr to avoid interfering with the application's output, which may
+  // be parsed by another program.
   static void Print(const char* format, ...) PRINTF_ATTRIBUTE(1, 2);
   static void PrintErr(const char* format, ...) PRINTF_ATTRIBUTE(1, 2);
   static void VFPrint(FILE* stream, const char* format, va_list args);
diff --git a/runtime/vm/os_thread_android.cc b/runtime/vm/os_thread_android.cc
index 16eaa14..5eab0b8 100644
--- a/runtime/vm/os_thread_android.cc
+++ b/runtime/vm/os_thread_android.cc
@@ -17,15 +17,12 @@
 #include "platform/signal_blocker.h"
 #include "platform/utils.h"
 
-#include "vm/profiler.h"
-
 namespace dart {
 
 #define VALIDATE_PTHREAD_RESULT(result)                                        \
   if (result != 0) {                                                           \
     const int kBufferSize = 1024;                                              \
     char error_message[kBufferSize];                                           \
-    NOT_IN_PRODUCT(Profiler::DumpStackTrace());                                \
     Utils::StrError(result, error_message, kBufferSize);                       \
     FATAL2("pthread error: %d (%s)", result, error_message);                   \
   }
@@ -37,7 +34,6 @@
   if (result != 0) {                                                           \
     const int kBufferSize = 1024;                                              \
     char error_message[kBufferSize];                                           \
-    NOT_IN_PRODUCT(Profiler::DumpStackTrace());                                \
     Utils::StrError(result, error_message, kBufferSize);                       \
     FATAL3("[%s] pthread error: %d (%s)", name_, result, error_message);       \
   }
diff --git a/runtime/vm/os_thread_linux.cc b/runtime/vm/os_thread_linux.cc
index 03ccfd6..4b8da4d 100644
--- a/runtime/vm/os_thread_linux.cc
+++ b/runtime/vm/os_thread_linux.cc
@@ -19,15 +19,12 @@
 #include "platform/signal_blocker.h"
 #include "platform/utils.h"
 
-#include "vm/profiler.h"
-
 namespace dart {
 
 #define VALIDATE_PTHREAD_RESULT(result)                                        \
   if (result != 0) {                                                           \
     const int kBufferSize = 1024;                                              \
     char error_buf[kBufferSize];                                               \
-    NOT_IN_PRODUCT(Profiler::DumpStackTrace());                                \
     FATAL2("pthread error: %d (%s)", result,                                   \
            Utils::StrError(result, error_buf, kBufferSize));                   \
   }
@@ -40,7 +37,6 @@
   if (result != 0) {                                                           \
     const int kBufferSize = 1024;                                              \
     char error_buf[kBufferSize];                                               \
-    NOT_IN_PRODUCT(Profiler::DumpStackTrace());                                \
     FATAL3("[%s] pthread error: %d (%s)", name_, result,                       \
            Utils::StrError(result, error_buf, kBufferSize));                   \
   }
diff --git a/runtime/vm/os_thread_macos.cc b/runtime/vm/os_thread_macos.cc
index 8867693..39f0047 100644
--- a/runtime/vm/os_thread_macos.cc
+++ b/runtime/vm/os_thread_macos.cc
@@ -23,15 +23,12 @@
 #include "platform/safe_stack.h"
 #include "platform/utils.h"
 
-#include "vm/profiler.h"
-
 namespace dart {
 
 #define VALIDATE_PTHREAD_RESULT(result)                                        \
   if (result != 0) {                                                           \
     const int kBufferSize = 1024;                                              \
     char error_message[kBufferSize];                                           \
-    NOT_IN_PRODUCT(Profiler::DumpStackTrace());                                \
     Utils::StrError(result, error_message, kBufferSize);                       \
     FATAL2("pthread error: %d (%s)", result, error_message);                   \
   }
@@ -43,7 +40,6 @@
   if (result != 0) {                                                           \
     const int kBufferSize = 1024;                                              \
     char error_message[kBufferSize];                                           \
-    NOT_IN_PRODUCT(Profiler::DumpStackTrace());                                \
     Utils::StrError(result, error_message, kBufferSize);                       \
     FATAL3("[%s] pthread error: %d (%s)", name_, result, error_message);       \
   }
diff --git a/runtime/vm/pages.cc b/runtime/vm/pages.cc
index 2beff46..288f8ff 100644
--- a/runtime/vm/pages.cc
+++ b/runtime/vm/pages.cc
@@ -806,7 +806,7 @@
   if ((start - last_code_collection_in_us) >
       FLAG_code_collection_interval_in_us) {
     if (FLAG_log_code_drop) {
-      OS::Print("Trying to detach code.\n");
+      OS::PrintErr("Trying to detach code.\n");
     }
     page_space_controller_.set_last_code_collection_in_us(start);
     return true;
@@ -933,9 +933,9 @@
     NoSafepointScope no_safepoints;
 
     if (FLAG_print_free_list_before_gc) {
-      OS::Print("Data Freelist (before GC):\n");
+      OS::PrintErr("Data Freelist (before GC):\n");
       freelist_[HeapPage::kData].Print();
-      OS::Print("Executable Freelist (before GC):\n");
+      OS::PrintErr("Executable Freelist (before GC):\n");
       freelist_[HeapPage::kExecutable].Print();
     }
 
@@ -1054,9 +1054,9 @@
     heap_->RecordTime(kSweepLargePages, end - mid3);
 
     if (FLAG_print_free_list_after_gc) {
-      OS::Print("Data Freelist (after GC):\n");
+      OS::PrintErr("Data Freelist (after GC):\n");
       freelist_[HeapPage::kData].Print();
-      OS::Print("Executable Freelist (after GC):\n");
+      OS::PrintErr("Executable Freelist (after GC):\n");
       freelist_[HeapPage::kExecutable].Print();
     }
 
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 08388da..c2090ec 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -83,8 +83,8 @@
         intptr_t line, column;
         script.GetTokenLocation(token_pos, &line, &column);
         PrintIndent();
-        OS::Print("%s (line %" Pd ", col %" Pd ", token %" Pd ")\n", msg, line,
-                  column, token_pos.value());
+        OS::PrintErr("%s (line %" Pd ", col %" Pd ", token %" Pd ")\n", msg,
+                     line, column, token_pos.value());
       }
       (*indent_)++;
     }
@@ -99,7 +99,7 @@
  private:
   void PrintIndent() {
     for (intptr_t i = 0; i < *indent_; i++) {
-      OS::Print(". ");
+      OS::PrintErr(". ");
     }
   }
   intptr_t* indent_;
@@ -4766,7 +4766,7 @@
   String* enum_name =
       ExpectUserDefinedTypeIdentifier("enum type name expected");
   if (FLAG_trace_parser) {
-    OS::Print("TopLevel parsing enum '%s'\n", enum_name->ToCString());
+    OS::PrintErr("TopLevel parsing enum '%s'\n", enum_name->ToCString());
   }
   ExpectToken(Token::kLBRACE);
   if (!IsIdentifier()) {
@@ -4823,7 +4823,7 @@
   const TokenPosition classname_pos = TokenPos();
   String& class_name = *ExpectUserDefinedTypeIdentifier("class name expected");
   if (FLAG_trace_parser) {
-    OS::Print("TopLevel parsing class '%s'\n", class_name.ToCString());
+    OS::PrintErr("TopLevel parsing class '%s'\n", class_name.ToCString());
   }
   Class& cls = Class::Handle(Z);
   TypeArguments& orig_type_parameters = TypeArguments::Handle(Z);
@@ -5356,8 +5356,8 @@
   const TokenPosition classname_pos = TokenPos();
   String& class_name = *ExpectUserDefinedTypeIdentifier("class name expected");
   if (FLAG_trace_parser) {
-    OS::Print("toplevel parsing mixin application alias class '%s'\n",
-              class_name.ToCString());
+    OS::PrintErr("toplevel parsing mixin application alias class '%s'\n",
+                 class_name.ToCString());
   }
   const Object& obj = Object::Handle(Z, library_.LookupLocalObject(class_name));
   if (!obj.IsNull()) {
@@ -5542,8 +5542,8 @@
          Type::Cast(function_type).signature());
 
   if (FLAG_trace_parser) {
-    OS::Print("TopLevel parsing function type alias '%s'\n",
-              String::Handle(Z, signature_function.Signature()).ToCString());
+    OS::PrintErr("TopLevel parsing function type alias '%s'\n",
+                 String::Handle(Z, signature_function.Signature()).ToCString());
   }
   // The alias should not be marked as finalized yet, since it needs to be
   // checked in the class finalizer for illegal self references.
diff --git a/runtime/vm/parser_test.cc b/runtime/vm/parser_test.cc
index bd06546..a04d599 100644
--- a/runtime/vm/parser_test.cc
+++ b/runtime/vm/parser_test.cc
@@ -42,7 +42,7 @@
       AstPrinter ast_printer;
       ast_printer.PrintFunctionNodes(*parsed_function);
     } else {
-      OS::Print("AST printer not supported.");
+      OS::PrintErr("AST printer not supported.");
     }
     retval = true;
   } else {
diff --git a/runtime/vm/port.cc b/runtime/vm/port.cc
index 3bc0370..27ee26d 100644
--- a/runtime/vm/port.cc
+++ b/runtime/vm/port.cc
@@ -107,7 +107,7 @@
     map_[index].handler->increment_live_ports();
   }
   if (FLAG_trace_isolates) {
-    OS::Print(
+    OS::PrintErr(
         "[^] Port (%s) -> (%s): \n"
         "\thandler:    %s\n"
         "\tport:       %" Pd64 "\n",
@@ -168,7 +168,7 @@
   MaintainInvariants();
 
   if (FLAG_trace_isolates) {
-    OS::Print(
+    OS::PrintErr(
         "[+] Opening port: \n"
         "\thandler:    %s\n"
         "\tport:       %" Pd64 "\n",
@@ -323,9 +323,9 @@
   for (intptr_t i = 0; i < capacity_; i++) {
     if (map_[i].handler == handler) {
       if (map_[i].state == kLivePort) {
-        OS::Print("Live Port = %" Pd64 "\n", map_[i].port);
+        OS::PrintErr("Live Port = %" Pd64 "\n", map_[i].port);
         msg_handler = DartLibraryCalls::LookupHandler(map_[i].port);
-        OS::Print("Handler = %s\n", msg_handler.ToCString());
+        OS::PrintErr("Handler = %s\n", msg_handler.ToCString());
       }
     }
   }
diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
index 13ab5b0..7f424f3 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler.cc
@@ -154,9 +154,9 @@
   cursor_ = 0;
 
   if (FLAG_trace_profiler) {
-    OS::Print("Profiler holds %" Pd " samples\n", capacity);
-    OS::Print("Profiler sample is %" Pd " bytes\n", Sample::instance_size());
-    OS::Print("Profiler memory usage = %" Pd " bytes\n", size);
+    OS::PrintErr("Profiler holds %" Pd " samples\n", capacity);
+    OS::PrintErr("Profiler sample is %" Pd " bytes\n", Sample::instance_size());
+    OS::PrintErr("Profiler memory usage = %" Pd " bytes\n", size);
   }
 }
 
diff --git a/runtime/vm/profiler_service.cc b/runtime/vm/profiler_service.cc
index 9cdfa47..286f2dd 100644
--- a/runtime/vm/profiler_service.cc
+++ b/runtime/vm/profiler_service.cc
@@ -49,7 +49,7 @@
     if ((size_before > 0) && FLAG_trace_profiler) {
       intptr_t length_before = previous_.Length();
       intptr_t length_after = current_.Length();
-      OS::Print(
+      OS::PrintErr(
           "Updating isolate deoptimized code array: "
           "%" Pd " -> %" Pd " [%" Pd " -> %" Pd "]\n",
           size_before, size_after, length_before, length_after);
@@ -163,9 +163,9 @@
     ProfileFunctionSourcePosition& position = source_position_ticks_[i];
     if (position.token_pos().value() == token_position.value()) {
       if (FLAG_trace_profiler_verbose) {
-        OS::Print("Ticking source position %s %s\n",
-                  exclusive ? "exclusive" : "inclusive",
-                  token_position.ToCString());
+        OS::PrintErr("Ticking source position %s %s\n",
+                     exclusive ? "exclusive" : "inclusive",
+                     token_position.ToCString());
       }
       // Found existing position, tick it.
       position.Tick(exclusive);
@@ -179,9 +179,9 @@
   // Add new one, sorted by token position value.
   ProfileFunctionSourcePosition pfsp(token_position);
   if (FLAG_trace_profiler_verbose) {
-    OS::Print("Ticking source position %s %s\n",
-              exclusive ? "exclusive" : "inclusive",
-              token_position.ToCString());
+    OS::PrintErr("Ticking source position %s %s\n",
+                 exclusive ? "exclusive" : "inclusive",
+                 token_position.ToCString());
   }
   pfsp.Tick(exclusive);
 
@@ -1027,8 +1027,8 @@
   ~ProfileCodeInlinedFunctionsCache() {
     if (FLAG_trace_profiler) {
       intptr_t total = cache_hit_ + cache_miss_;
-      OS::Print("LOOKUPS: %" Pd " HITS: %" Pd " MISSES: %" Pd "\n", total,
-                cache_hit_, cache_miss_);
+      OS::PrintErr("LOOKUPS: %" Pd " HITS: %" Pd " MISSES: %" Pd "\n", total,
+                   cache_hit_, cache_miss_);
     }
   }
 
diff --git a/runtime/vm/raw_object.cc b/runtime/vm/raw_object.cc
index 31ae26e..cbe81d8 100644
--- a/runtime/vm/raw_object.cc
+++ b/runtime/vm/raw_object.cc
@@ -276,7 +276,7 @@
       size = Size();
       break;
     default:
-      OS::Print("Class Id: %" Pd "\n", class_id);
+      OS::PrintErr("Class Id: %" Pd "\n", class_id);
       UNREACHABLE();
       break;
   }
diff --git a/runtime/vm/regexp.cc b/runtime/vm/regexp.cc
index 4d99e0f..909f00a 100644
--- a/runtime/vm/regexp.cc
+++ b/runtime/vm/regexp.cc
@@ -3471,23 +3471,23 @@
 };
 
 void DotPrinter::PrintNode(const char* label, RegExpNode* node) {
-  OS::Print("digraph G {\n  graph [label=\"");
+  OS::PrintErr("digraph G {\n  graph [label=\"");
   for (intptr_t i = 0; label[i]; i++) {
     switch (label[i]) {
       case '\\':
-        OS::Print("\\\\");
+        OS::PrintErr("\\\\");
         break;
       case '"':
-        OS::Print("\"");
+        OS::PrintErr("\"");
         break;
       default:
-        OS::Print("%c", label[i]);
+        OS::PrintErr("%c", label[i]);
         break;
     }
   }
-  OS::Print("\"];\n");
+  OS::PrintErr("\"];\n");
   Visit(node);
-  OS::Print("}\n");
+  OS::PrintErr("}\n");
 }
 
 void DotPrinter::Visit(RegExpNode* node) {
@@ -3497,7 +3497,7 @@
 }
 
 void DotPrinter::PrintOnFailure(RegExpNode* from, RegExpNode* on_failure) {
-  OS::Print("  n%p -> n%p [style=dotted];\n", from, on_failure);
+  OS::PrintErr("  n%p -> n%p [style=dotted];\n", from, on_failure);
   Visit(on_failure);
 }
 
@@ -3508,18 +3508,18 @@
     if (first_) {
       first_ = false;
     } else {
-      OS::Print("|");
+      OS::PrintErr("|");
     }
   }
   void PrintBit(const char* name, bool value) {
     if (!value) return;
     PrintSeparator();
-    OS::Print("{%s}", name);
+    OS::PrintErr("{%s}", name);
   }
   void PrintPositive(const char* name, intptr_t value) {
     if (value < 0) return;
     PrintSeparator();
-    OS::Print("{%s|%" Pd "}", name, value);
+    OS::PrintErr("{%s|%" Pd "}", name, value);
   }
 
  private:
@@ -3527,7 +3527,7 @@
 };
 
 void DotPrinter::PrintAttributes(RegExpNode* that) {
-  OS::Print(
+  OS::PrintErr(
       "  a%p [shape=Mrecord, color=grey, fontcolor=grey, "
       "margin=0.1, fontsize=10, label=\"{",
       that);
@@ -3538,17 +3538,17 @@
   printer.PrintBit("SI", info->follows_start_interest);
   BlockLabel* label = that->label();
   if (label->IsBound()) printer.PrintPositive("@", label->Position());
-  OS::Print(
+  OS::PrintErr(
       "}\"];\n"
       "  a%p -> n%p [style=dashed, color=grey, arrowhead=none];\n",
       that, that);
 }
 
 void DotPrinter::VisitChoice(ChoiceNode* that) {
-  OS::Print("  n%p [shape=Mrecord, label=\"?\"];\n", that);
+  OS::PrintErr("  n%p [shape=Mrecord, label=\"?\"];\n", that);
   for (intptr_t i = 0; i < that->alternatives()->length(); i++) {
     GuardedAlternative alt = that->alternatives()->At(i);
-    OS::Print("  n%p -> n%p", that, alt.node());
+    OS::PrintErr("  n%p -> n%p", that, alt.node());
   }
   for (intptr_t i = 0; i < that->alternatives()->length(); i++) {
     GuardedAlternative alt = that->alternatives()->At(i);
@@ -3557,120 +3557,120 @@
 }
 
 void DotPrinter::VisitText(TextNode* that) {
-  OS::Print("  n%p [label=\"", that);
+  OS::PrintErr("  n%p [label=\"", that);
   for (intptr_t i = 0; i < that->elements()->length(); i++) {
-    if (i > 0) OS::Print(" ");
+    if (i > 0) OS::PrintErr(" ");
     TextElement elm = that->elements()->At(i);
     switch (elm.text_type()) {
       case TextElement::ATOM: {
         ZoneGrowableArray<uint16_t>* data = elm.atom()->data();
         for (intptr_t i = 0; i < data->length(); i++) {
-          OS::Print("%c", static_cast<char>(data->At(i)));
+          OS::PrintErr("%c", static_cast<char>(data->At(i)));
         }
         break;
       }
       case TextElement::CHAR_CLASS: {
         RegExpCharacterClass* node = elm.char_class();
-        OS::Print("[");
-        if (node->is_negated()) OS::Print("^");
+        OS::PrintErr("[");
+        if (node->is_negated()) OS::PrintErr("^");
         for (intptr_t j = 0; j < node->ranges()->length(); j++) {
           CharacterRange range = node->ranges()->At(j);
           PrintUtf16(range.from());
-          OS::Print("-");
+          OS::PrintErr("-");
           PrintUtf16(range.to());
         }
-        OS::Print("]");
+        OS::PrintErr("]");
         break;
       }
       default:
         UNREACHABLE();
     }
   }
-  OS::Print("\", shape=box, peripheries=2];\n");
+  OS::PrintErr("\", shape=box, peripheries=2];\n");
   PrintAttributes(that);
-  OS::Print("  n%p -> n%p;\n", that, that->on_success());
+  OS::PrintErr("  n%p -> n%p;\n", that, that->on_success());
   Visit(that->on_success());
 }
 
 void DotPrinter::VisitBackReference(BackReferenceNode* that) {
-  OS::Print("  n%p [label=\"$%" Pd "..$%" Pd "\", shape=doubleoctagon];\n",
-            that, that->start_register(), that->end_register());
+  OS::PrintErr("  n%p [label=\"$%" Pd "..$%" Pd "\", shape=doubleoctagon];\n",
+               that, that->start_register(), that->end_register());
   PrintAttributes(that);
-  OS::Print("  n%p -> n%p;\n", that, that->on_success());
+  OS::PrintErr("  n%p -> n%p;\n", that, that->on_success());
   Visit(that->on_success());
 }
 
 void DotPrinter::VisitEnd(EndNode* that) {
-  OS::Print("  n%p [style=bold, shape=point];\n", that);
+  OS::PrintErr("  n%p [style=bold, shape=point];\n", that);
   PrintAttributes(that);
 }
 
 void DotPrinter::VisitAssertion(AssertionNode* that) {
-  OS::Print("  n%p [", that);
+  OS::PrintErr("  n%p [", that);
   switch (that->assertion_type()) {
     case AssertionNode::AT_END:
-      OS::Print("label=\"$\", shape=septagon");
+      OS::PrintErr("label=\"$\", shape=septagon");
       break;
     case AssertionNode::AT_START:
-      OS::Print("label=\"^\", shape=septagon");
+      OS::PrintErr("label=\"^\", shape=septagon");
       break;
     case AssertionNode::AT_BOUNDARY:
-      OS::Print("label=\"\\b\", shape=septagon");
+      OS::PrintErr("label=\"\\b\", shape=septagon");
       break;
     case AssertionNode::AT_NON_BOUNDARY:
-      OS::Print("label=\"\\B\", shape=septagon");
+      OS::PrintErr("label=\"\\B\", shape=septagon");
       break;
     case AssertionNode::AFTER_NEWLINE:
-      OS::Print("label=\"(?<=\\n)\", shape=septagon");
+      OS::PrintErr("label=\"(?<=\\n)\", shape=septagon");
       break;
   }
-  OS::Print("];\n");
+  OS::PrintErr("];\n");
   PrintAttributes(that);
   RegExpNode* successor = that->on_success();
-  OS::Print("  n%p -> n%p;\n", that, successor);
+  OS::PrintErr("  n%p -> n%p;\n", that, successor);
   Visit(successor);
 }
 
 void DotPrinter::VisitAction(ActionNode* that) {
-  OS::Print("  n%p [", that);
+  OS::PrintErr("  n%p [", that);
   switch (that->action_type_) {
     case ActionNode::SET_REGISTER:
-      OS::Print("label=\"$%" Pd ":=%" Pd "\", shape=octagon",
-                that->data_.u_store_register.reg,
-                that->data_.u_store_register.value);
+      OS::PrintErr("label=\"$%" Pd ":=%" Pd "\", shape=octagon",
+                   that->data_.u_store_register.reg,
+                   that->data_.u_store_register.value);
       break;
     case ActionNode::INCREMENT_REGISTER:
-      OS::Print("label=\"$%" Pd "++\", shape=octagon",
-                that->data_.u_increment_register.reg);
+      OS::PrintErr("label=\"$%" Pd "++\", shape=octagon",
+                   that->data_.u_increment_register.reg);
       break;
     case ActionNode::STORE_POSITION:
-      OS::Print("label=\"$%" Pd ":=$pos\", shape=octagon",
-                that->data_.u_position_register.reg);
+      OS::PrintErr("label=\"$%" Pd ":=$pos\", shape=octagon",
+                   that->data_.u_position_register.reg);
       break;
     case ActionNode::BEGIN_SUBMATCH:
-      OS::Print("label=\"$%" Pd ":=$pos,begin\", shape=septagon",
-                that->data_.u_submatch.current_position_register);
+      OS::PrintErr("label=\"$%" Pd ":=$pos,begin\", shape=septagon",
+                   that->data_.u_submatch.current_position_register);
       break;
     case ActionNode::POSITIVE_SUBMATCH_SUCCESS:
-      OS::Print("label=\"escape\", shape=septagon");
+      OS::PrintErr("label=\"escape\", shape=septagon");
       break;
     case ActionNode::EMPTY_MATCH_CHECK:
-      OS::Print("label=\"$%" Pd "=$pos?,$%" Pd "<%" Pd "?\", shape=septagon",
-                that->data_.u_empty_match_check.start_register,
-                that->data_.u_empty_match_check.repetition_register,
-                that->data_.u_empty_match_check.repetition_limit);
+      OS::PrintErr("label=\"$%" Pd "=$pos?,$%" Pd "<%" Pd "?\", shape=septagon",
+                   that->data_.u_empty_match_check.start_register,
+                   that->data_.u_empty_match_check.repetition_register,
+                   that->data_.u_empty_match_check.repetition_limit);
       break;
     case ActionNode::CLEAR_CAPTURES: {
-      OS::Print("label=\"clear $%" Pd " to $%" Pd "\", shape=septagon",
-                that->data_.u_clear_captures.range_from,
-                that->data_.u_clear_captures.range_to);
+      OS::PrintErr("label=\"clear $%" Pd " to $%" Pd "\", shape=septagon",
+                   that->data_.u_clear_captures.range_from,
+                   that->data_.u_clear_captures.range_to);
       break;
     }
   }
-  OS::Print("];\n");
+  OS::PrintErr("];\n");
   PrintAttributes(that);
   RegExpNode* successor = that->on_success();
-  OS::Print("  n%p -> n%p;\n", that, successor);
+  OS::PrintErr("  n%p -> n%p;\n", that, successor);
   Visit(successor);
 }
 
diff --git a/runtime/vm/regexp_assembler.cc b/runtime/vm/regexp_assembler.cc
index f2570c5..ecd1914 100644
--- a/runtime/vm/regexp_assembler.cc
+++ b/runtime/vm/regexp_assembler.cc
@@ -13,7 +13,7 @@
 void PrintUtf16(uint16_t c) {
   const char* format =
       (0x20 <= c && c <= 0x7F) ? "%c" : (c <= 0xff) ? "\\x%02x" : "\\u%04x";
-  OS::Print(format, c);
+  OS::PrintErr(format, c);
 }
 
 
diff --git a/runtime/vm/regexp_assembler_ir.cc b/runtime/vm/regexp_assembler_ir.cc
index 64753cb..72b4e93 100644
--- a/runtime/vm/regexp_assembler_ir.cc
+++ b/runtime/vm/regexp_assembler_ir.cc
@@ -323,7 +323,7 @@
       Object::Handle(zone, DartEntry::InvokeFunction(fun, args));
   if (retval.IsError()) {
     const Error& error = Error::Cast(retval);
-    OS::Print("%s\n", error.ToErrorCString());
+    OS::PrintErr("%s\n", error.ToErrorCString());
     // Should never happen.
     UNREACHABLE();
   }
@@ -569,7 +569,7 @@
 #define HANDLE_DEAD_CODE_EMISSION()                                            \
   if (current_instruction_ == NULL) {                                          \
     if (FLAG_trace_irregexp) {                                                 \
-      OS::Print(                                                               \
+      OS::PrintErr(                                                            \
           "WARNING: Attempting to append to a closed assembler. "              \
           "This could be either a bug or generation of dead code "             \
           "inherited from V8.\n");                                             \
diff --git a/runtime/vm/regexp_ast.cc b/runtime/vm/regexp_ast.cc
index 2edfe08..5b51a6f 100644
--- a/runtime/vm/regexp_ast.cc
+++ b/runtime/vm/regexp_ast.cc
@@ -134,76 +134,76 @@
 };
 
 void* RegExpUnparser::VisitDisjunction(RegExpDisjunction* that, void* data) {
-  OS::Print("(|");
+  OS::PrintErr("(|");
   for (intptr_t i = 0; i < that->alternatives()->length(); i++) {
-    OS::Print(" ");
+    OS::PrintErr(" ");
     (*that->alternatives())[i]->Accept(this, data);
   }
-  OS::Print(")");
+  OS::PrintErr(")");
   return NULL;
 }
 
 void* RegExpUnparser::VisitAlternative(RegExpAlternative* that, void* data) {
-  OS::Print("(:");
+  OS::PrintErr("(:");
   for (intptr_t i = 0; i < that->nodes()->length(); i++) {
-    OS::Print(" ");
+    OS::PrintErr(" ");
     (*that->nodes())[i]->Accept(this, data);
   }
-  OS::Print(")");
+  OS::PrintErr(")");
   return NULL;
 }
 
 void RegExpUnparser::VisitCharacterRange(CharacterRange that) {
   PrintUtf16(that.from());
   if (!that.IsSingleton()) {
-    OS::Print("-");
+    OS::PrintErr("-");
     PrintUtf16(that.to());
   }
 }
 
 void* RegExpUnparser::VisitCharacterClass(RegExpCharacterClass* that,
                                           void* data) {
-  if (that->is_negated()) OS::Print("^");
-  OS::Print("[");
+  if (that->is_negated()) OS::PrintErr("^");
+  OS::PrintErr("[");
   for (intptr_t i = 0; i < that->ranges()->length(); i++) {
-    if (i > 0) OS::Print(" ");
+    if (i > 0) OS::PrintErr(" ");
     VisitCharacterRange((*that->ranges())[i]);
   }
-  OS::Print("]");
+  OS::PrintErr("]");
   return NULL;
 }
 
 void* RegExpUnparser::VisitAssertion(RegExpAssertion* that, void* data) {
   switch (that->assertion_type()) {
     case RegExpAssertion::START_OF_INPUT:
-      OS::Print("@^i");
+      OS::PrintErr("@^i");
       break;
     case RegExpAssertion::END_OF_INPUT:
-      OS::Print("@$i");
+      OS::PrintErr("@$i");
       break;
     case RegExpAssertion::START_OF_LINE:
-      OS::Print("@^l");
+      OS::PrintErr("@^l");
       break;
     case RegExpAssertion::END_OF_LINE:
-      OS::Print("@$l");
+      OS::PrintErr("@$l");
       break;
     case RegExpAssertion::BOUNDARY:
-      OS::Print("@b");
+      OS::PrintErr("@b");
       break;
     case RegExpAssertion::NON_BOUNDARY:
-      OS::Print("@B");
+      OS::PrintErr("@B");
       break;
   }
   return NULL;
 }
 
 void* RegExpUnparser::VisitAtom(RegExpAtom* that, void* data) {
-  OS::Print("'");
+  OS::PrintErr("'");
   ZoneGrowableArray<uint16_t>* chardata = that->data();
   for (intptr_t i = 0; i < chardata->length(); i++) {
     PrintUtf16(chardata->At(i));
   }
-  OS::Print("'");
+  OS::PrintErr("'");
   return NULL;
 }
 
@@ -211,50 +211,50 @@
   if (that->elements()->length() == 1) {
     (*that->elements())[0].tree()->Accept(this, data);
   } else {
-    OS::Print("(!");
+    OS::PrintErr("(!");
     for (intptr_t i = 0; i < that->elements()->length(); i++) {
-      OS::Print(" ");
+      OS::PrintErr(" ");
       (*that->elements())[i].tree()->Accept(this, data);
     }
-    OS::Print(")");
+    OS::PrintErr(")");
   }
   return NULL;
 }
 
 void* RegExpUnparser::VisitQuantifier(RegExpQuantifier* that, void* data) {
-  OS::Print("(# %" Pd " ", that->min());
+  OS::PrintErr("(# %" Pd " ", that->min());
   if (that->max() == RegExpTree::kInfinity) {
-    OS::Print("- ");
+    OS::PrintErr("- ");
   } else {
-    OS::Print("%" Pd " ", that->max());
+    OS::PrintErr("%" Pd " ", that->max());
   }
-  OS::Print(that->is_greedy() ? "g " : that->is_possessive() ? "p " : "n ");
+  OS::PrintErr(that->is_greedy() ? "g " : that->is_possessive() ? "p " : "n ");
   that->body()->Accept(this, data);
-  OS::Print(")");
+  OS::PrintErr(")");
   return NULL;
 }
 
 void* RegExpUnparser::VisitCapture(RegExpCapture* that, void* data) {
-  OS::Print("(^ ");
+  OS::PrintErr("(^ ");
   that->body()->Accept(this, data);
-  OS::Print(")");
+  OS::PrintErr(")");
   return NULL;
 }
 
 void* RegExpUnparser::VisitLookahead(RegExpLookahead* that, void* data) {
-  OS::Print("(-> %s", (that->is_positive() ? "+ " : "- "));
+  OS::PrintErr("(-> %s", (that->is_positive() ? "+ " : "- "));
   that->body()->Accept(this, data);
-  OS::Print(")");
+  OS::PrintErr(")");
   return NULL;
 }
 
 void* RegExpUnparser::VisitBackReference(RegExpBackReference* that, void*) {
-  OS::Print("(<- %" Pd ")", that->index());
+  OS::PrintErr("(<- %" Pd ")", that->index());
   return NULL;
 }
 
 void* RegExpUnparser::VisitEmpty(RegExpEmpty*, void*) {
-  OS::Print("%%");
+  OS::PrintErr("%%");
   return NULL;
 }
 
diff --git a/runtime/vm/regexp_interpreter.cc b/runtime/vm/regexp_interpreter.cc
index 27cc976..8b960b0 100644
--- a/runtime/vm/regexp_interpreter.cc
+++ b/runtime/vm/regexp_interpreter.cc
@@ -84,21 +84,21 @@
         printable
             ? "pc = %02x, sp = %d, curpos = %d, curchar = %08x (%c), bc = %s"
             : "pc = %02x, sp = %d, curpos = %d, curchar = %08x .%c., bc = %s";
-    OS::Print(format, pc - code_base, stack_depth, current_position,
-              current_char, printable ? current_char : '.', bytecode_name);
+    OS::PrintErr(format, pc - code_base, stack_depth, current_position,
+                 current_char, printable ? current_char : '.', bytecode_name);
     for (int i = 0; i < bytecode_length; i++) {
-      OS::Print(", %02x", pc[i]);
+      OS::PrintErr(", %02x", pc[i]);
     }
-    OS::Print(" ");
+    OS::PrintErr(" ");
     for (int i = 1; i < bytecode_length; i++) {
       unsigned char b = pc[i];
       if (b < 127 && b >= 32) {
-        OS::Print("%c", b);
+        OS::PrintErr("%c", b);
       } else {
-        OS::Print(".");
+        OS::PrintErr(".");
       }
     }
-    OS::Print("\n");
+    OS::PrintErr("\n");
   }
 }
 
@@ -167,7 +167,7 @@
 
 #ifdef DEBUG
   if (FLAG_trace_regexp_bytecodes) {
-    OS::Print("Start irregexp bytecode interpreter\n");
+    OS::PrintErr("Start irregexp bytecode interpreter\n");
   }
 #endif
   while (true) {
diff --git a/runtime/vm/report.cc b/runtime/vm/report.cc
index 4b45c37..ac3989d 100644
--- a/runtime/vm/report.cc
+++ b/runtime/vm/report.cc
@@ -154,7 +154,7 @@
       const String& msg = String::Handle(String::NewFormattedV(format, args));
       const String& snippet_msg = String::Handle(
           PrependSnippet(kind, script, token_pos, report_after_token, msg));
-      OS::Print("%s", snippet_msg.ToCString());
+      OS::PrintErr("%s", snippet_msg.ToCString());
       return;
     }
   }
diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc
index ede255c..a99794c 100644
--- a/runtime/vm/runtime_entry.cc
+++ b/runtime/vm/runtime_entry.cc
@@ -486,7 +486,7 @@
                  String::Handle(instantiated_type.Name()).ToCString(),
                  String::Handle(type.Name()).ToCString(), caller_frame->pc());
     if (!bound_error.IsNull()) {
-      OS::Print("  bound error: %s\n", bound_error.ToErrorCString());
+      OS::PrintErr("  bound error: %s\n", bound_error.ToErrorCString());
     }
   }
   const Function& function =
@@ -513,13 +513,13 @@
   // inlined assembly.
   if (new_cache.IsNull()) {
     if (FLAG_trace_type_checks) {
-      OS::Print("UpdateTypeTestCache: cache is null\n");
+      OS::PrintErr("UpdateTypeTestCache: cache is null\n");
     }
     return;
   }
   if (instance.IsSmi()) {
     if (FLAG_trace_type_checks) {
-      OS::Print("UpdateTypeTestCache: instance is Smi\n");
+      OS::PrintErr("UpdateTypeTestCache: instance is Smi\n");
     }
     return;
   }
@@ -540,7 +540,7 @@
     if (Closure::Cast(instance).function_type_arguments() !=
         TypeArguments::null()) {
       if (FLAG_trace_type_checks) {
-        OS::Print(
+        OS::PrintErr(
             "UpdateTypeTestCache: closure function_type_arguments is "
             "not null\n");
       }
@@ -1906,9 +1906,9 @@
       Code::Handle(function.unoptimized_code()).GetDeoptIdForOsr(frame->pc());
   ASSERT(osr_id != Compiler::kNoOSRDeoptId);
   if (FLAG_trace_osr) {
-    OS::Print("Attempting OSR for %s at id=%" Pd ", count=%" Pd "\n",
-              function.ToFullyQualifiedCString(), osr_id,
-              function.usage_counter());
+    OS::PrintErr("Attempting OSR for %s at id=%" Pd ", count=%" Pd "\n",
+                 function.ToFullyQualifiedCString(), osr_id,
+                 function.usage_counter());
   }
 
   // Since the code is referenced from the frame and the ZoneHandle,
@@ -2482,7 +2482,7 @@
 
 // Print the stop message.
 DEFINE_LEAF_RUNTIME_ENTRY(void, PrintStopMessage, 1, const char* message) {
-  OS::Print("Stop message: %s\n", message);
+  OS::PrintErr("Stop message: %s\n", message);
 }
 END_LEAF_RUNTIME_ENTRY
 
diff --git a/runtime/vm/safepoint.cc b/runtime/vm/safepoint.cc
index 09c5646..4fb88a4 100644
--- a/runtime/vm/safepoint.cc
+++ b/runtime/vm/safepoint.cc
@@ -110,8 +110,8 @@
         if (num_attempts > 10) {
           // We have been waiting too long, start logging this as we might
           // have an issue where a thread is not checking in for a safepoint.
-          OS::Print("Attempt:%" Pd " waiting for %d threads to check in\n",
-                    num_attempts, number_threads_not_at_safepoint_);
+          OS::PrintErr("Attempt:%" Pd " waiting for %d threads to check in\n",
+                       num_attempts, number_threads_not_at_safepoint_);
         }
       }
     }
diff --git a/runtime/vm/scanner_test.cc b/runtime/vm/scanner_test.cc
index 38ffc86..93fa232 100644
--- a/runtime/vm/scanner_test.cc
+++ b/runtime/vm/scanner_test.cc
@@ -13,13 +13,13 @@
 typedef ZoneGrowableArray<Scanner::TokenDescriptor> GrowableTokenStream;
 
 static void LogTokenDesc(Scanner::TokenDescriptor token) {
-  OS::Print("pos %2d:%d-%d token %s  ", token.position.line,
-            token.position.column, token.position.column,
-            Token::Name(token.kind));
+  OS::PrintErr("pos %2d:%d-%d token %s  ", token.position.line,
+               token.position.column, token.position.column,
+               Token::Name(token.kind));
   if (token.literal != NULL) {
-    OS::Print("%s", token.literal->ToCString());
+    OS::PrintErr("%s", token.literal->ToCString());
   }
-  OS::Print("\n");
+  OS::PrintErr("\n");
 }
 
 static void LogTokenStream(const GrowableTokenStream& token_stream) {
@@ -100,7 +100,7 @@
 };
 
 static const GrowableTokenStream& Scan(const char* source) {
-  OS::Print("\nScanning: <%s>\n", source);
+  OS::PrintErr("\nScanning: <%s>\n", source);
 
   Scanner scanner(String::Handle(String::New(source)),
                   String::Handle(String::New("")));
diff --git a/runtime/vm/scavenger.cc b/runtime/vm/scavenger.cc
index 9ca79a7..3121e86 100644
--- a/runtime/vm/scavenger.cc
+++ b/runtime/vm/scavenger.cc
@@ -6,6 +6,7 @@
 
 #include "vm/dart.h"
 #include "vm/dart_api_state.h"
+#include "vm/flag_list.h"
 #include "vm/isolate.h"
 #include "vm/lockers.h"
 #include "vm/object.h"
@@ -31,7 +32,7 @@
             new_gen_garbage_threshold,
             90,
             "Grow new gen when less than this percentage is garbage.");
-DEFINE_FLAG(int, new_gen_growth_factor, 4, "Grow new gen by this factor.");
+DEFINE_FLAG(int, new_gen_growth_factor, 2, "Grow new gen by this factor.");
 
 // Scavenger uses RawObject::kMarkBit to distinguish forwarded and non-forwarded
 // objects. The kMarkBit does not intersect with the target address because of
@@ -350,10 +351,9 @@
   // going to use for forwarding pointers.
   ASSERT(Object::tags_offset() == 0);
 
-  // Set initial size resulting in a total of three different levels.
-  const intptr_t initial_semi_capacity_in_words =
-      max_semi_capacity_in_words /
-      (FLAG_new_gen_growth_factor * FLAG_new_gen_growth_factor);
+  // Set initial semi space size in words.
+  const intptr_t initial_semi_capacity_in_words = Utils::Minimum(
+      max_semi_capacity_in_words, FLAG_new_gen_semi_initial_size * MBInWords);
 
   const intptr_t kVmNameSize = 128;
   char vm_name[kVmNameSize];
diff --git a/runtime/vm/scope_timer.h b/runtime/vm/scope_timer.h
index c895225..c910e34 100644
--- a/runtime/vm/scope_timer.h
+++ b/runtime/vm/scope_timer.h
@@ -32,7 +32,8 @@
     }
     int64_t elapsed = GetElapsed();
     double seconds = MicrosecondsToSeconds(elapsed);
-    OS::Print("%s: %f seconds (%" Pd64 " \u00B5s)\n", name_, seconds, elapsed);
+    OS::PrintErr("%s: %f seconds (%" Pd64 " \u00B5s)\n", name_, seconds,
+                 elapsed);
   }
 
  private:
diff --git a/runtime/vm/simulator_arm.cc b/runtime/vm/simulator_arm.cc
index 3415481..f61af66 100644
--- a/runtime/vm/simulator_arm.cc
+++ b/runtime/vm/simulator_arm.cc
@@ -122,7 +122,7 @@
 SimulatorDebugger::~SimulatorDebugger() {}
 
 void SimulatorDebugger::Stop(Instr* instr, const char* message) {
-  OS::Print("Simulator hit %s\n", message);
+  OS::PrintErr("Simulator hit %s\n", message);
   Debug();
 }
 
@@ -258,7 +258,7 @@
   if (token_pos.IsReal()) {
     script.GetTokenLocation(token_pos, &line, &column);
   }
-  OS::Print(
+  OS::PrintErr(
       "pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s%s (%s:%" Pd ":%" Pd ")\n", pc,
       fp, sp, is_optimized ? (is_inlined ? "inlined " : "optimized ") : "",
       func_name.ToCString(), url.ToCString(), line, column);
@@ -303,13 +303,13 @@
                      GetApproximateTokenIndex(code, frame->pc()),
                      code.is_optimized(), false);
     } else {
-      OS::Print("pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s frame\n",
-                frame->pc(), frame->fp(), frame->sp(),
-                frame->IsEntryFrame()
-                    ? "entry"
-                    : frame->IsExitFrame()
-                          ? "exit"
-                          : frame->IsStubFrame() ? "stub" : "invalid");
+      OS::PrintErr("pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s frame\n",
+                   frame->pc(), frame->fp(), frame->sp(),
+                   frame->IsEntryFrame()
+                       ? "entry"
+                       : frame->IsExitFrame()
+                             ? "exit"
+                             : frame->IsStubFrame() ? "stub" : "invalid");
     }
     frame = frames.NextFrame();
   }
@@ -378,12 +378,12 @@
     if (last_pc != sim_->get_pc()) {
       last_pc = sim_->get_pc();
       if (Simulator::IsIllegalAddress(last_pc)) {
-        OS::Print("pc is out of bounds: 0x%" Px "\n", last_pc);
+        OS::PrintErr("pc is out of bounds: 0x%" Px "\n", last_pc);
       } else {
         if (FLAG_support_disassembler) {
           Disassembler::Disassemble(last_pc, last_pc + Instr::kInstrSize);
         } else {
-          OS::Print("Disassembler not supported in this mode.\n");
+          OS::PrintErr("Disassembler not supported in this mode.\n");
         }
       }
     }
@@ -399,7 +399,7 @@
                         "%" XSTR(ARG_SIZE) "s",
                         cmd, arg1, arg2);
       if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) {
-        OS::Print(
+        OS::PrintErr(
             "c/cont -- continue execution\n"
             "disasm -- disassemble instrs at current pc location\n"
             "  other variants are:\n"
@@ -421,7 +421,7 @@
             "unstop -- if current pc is a stop instr make it a nop\n"
             "q/quit -- Quit the debugger and exit the program\n");
       } else if ((strcmp(cmd, "quit") == 0) || (strcmp(cmd, "q") == 0)) {
-        OS::Print("Quitting\n");
+        OS::PrintErr("Quitting\n");
         OS::Exit(0);
       } else if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
         sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc()));
@@ -435,14 +435,14 @@
           uint32_t value;
           if (strcmp(arg1, "icount") == 0) {
             const uint64_t icount = sim_->get_icount();
-            OS::Print("icount: %" Pu64 " 0x%" Px64 "\n", icount, icount);
+            OS::PrintErr("icount: %" Pu64 " 0x%" Px64 "\n", icount, icount);
           } else if (GetValue(arg1, &value)) {
-            OS::Print("%s: %u 0x%x\n", arg1, value, value);
+            OS::PrintErr("%s: %u 0x%x\n", arg1, value, value);
           } else {
-            OS::Print("%s unrecognized\n", arg1);
+            OS::PrintErr("%s unrecognized\n", arg1);
           }
         } else {
-          OS::Print("print <reg or icount or value or *addr>\n");
+          OS::PrintErr("print <reg or icount or value or *addr>\n");
         }
       } else if ((strcmp(cmd, "ps") == 0) ||
                  (strcmp(cmd, "printsingle") == 0)) {
@@ -450,12 +450,12 @@
           float fvalue;
           if (GetFValue(arg1, &fvalue)) {
             uint32_t value = bit_cast<uint32_t, float>(fvalue);
-            OS::Print("%s: 0%u 0x%x %.8g\n", arg1, value, value, fvalue);
+            OS::PrintErr("%s: 0%u 0x%x %.8g\n", arg1, value, value, fvalue);
           } else {
-            OS::Print("%s unrecognized\n", arg1);
+            OS::PrintErr("%s unrecognized\n", arg1);
           }
         } else {
-          OS::Print("printfloat <sreg or *addr>\n");
+          OS::PrintErr("printfloat <sreg or *addr>\n");
         }
       } else if ((strcmp(cmd, "pd") == 0) ||
                  (strcmp(cmd, "printdouble") == 0)) {
@@ -463,13 +463,13 @@
           double dvalue;
           if (GetDValue(arg1, &dvalue)) {
             uint64_t long_value = bit_cast<uint64_t, double>(dvalue);
-            OS::Print("%s: %llu 0x%llx %.8g\n", arg1, long_value, long_value,
-                      dvalue);
+            OS::PrintErr("%s: %llu 0x%llx %.8g\n", arg1, long_value, long_value,
+                         dvalue);
           } else {
-            OS::Print("%s unrecognized\n", arg1);
+            OS::PrintErr("%s unrecognized\n", arg1);
           }
         } else {
-          OS::Print("printdouble <dreg or *addr>\n");
+          OS::PrintErr("printdouble <dreg or *addr>\n");
         }
       } else if ((strcmp(cmd, "po") == 0) ||
                  (strcmp(cmd, "printobject") == 0)) {
@@ -479,20 +479,20 @@
           if (((arg1[0] == '*') && GetValue(arg1 + 1, &value)) ||
               GetValue(arg1, &value)) {
             if (Isolate::Current()->heap()->Contains(value)) {
-              OS::Print("%s: \n", arg1);
+              OS::PrintErr("%s: \n", arg1);
 #if defined(DEBUG)
               const Object& obj =
                   Object::Handle(reinterpret_cast<RawObject*>(value));
               obj.Print();
 #endif  // defined(DEBUG)
             } else {
-              OS::Print("0x%x is not an object reference\n", value);
+              OS::PrintErr("0x%x is not an object reference\n", value);
             }
           } else {
-            OS::Print("%s unrecognized\n", arg1);
+            OS::PrintErr("%s unrecognized\n", arg1);
           }
         } else {
-          OS::Print("printobject <*reg or *addr>\n");
+          OS::PrintErr("printobject <*reg or *addr>\n");
         }
       } else if (strcmp(cmd, "disasm") == 0) {
         uint32_t start = 0;
@@ -505,8 +505,9 @@
             // No length parameter passed, assume 10 instructions.
             if (Simulator::IsIllegalAddress(start)) {
               // If start isn't a valid address, warn and use PC instead.
-              OS::Print("First argument yields invalid address: 0x%x\n", start);
-              OS::Print("Using PC instead\n");
+              OS::PrintErr("First argument yields invalid address: 0x%x\n",
+                           start);
+              OS::PrintErr("Using PC instead\n");
               start = sim_->get_pc();
             }
             end = start + (10 * Instr::kInstrSize);
@@ -516,8 +517,9 @@
           if (GetValue(arg1, &start) && GetValue(arg2, &length)) {
             if (Simulator::IsIllegalAddress(start)) {
               // If start isn't a valid address, warn and use PC instead.
-              OS::Print("First argument yields invalid address: 0x%x\n", start);
-              OS::Print("Using PC instead\n");
+              OS::PrintErr("First argument yields invalid address: 0x%x\n",
+                           start);
+              OS::PrintErr("Using PC instead\n");
               start = sim_->get_pc();
             }
             end = start + (length * Instr::kInstrSize);
@@ -527,63 +529,63 @@
           if (FLAG_support_disassembler) {
             Disassembler::Disassemble(start, end);
           } else {
-            OS::Print("Disassembler not supported in this mode.\n");
+            OS::PrintErr("Disassembler not supported in this mode.\n");
           }
         } else {
-          OS::Print("disasm [<address> [<number_of_instructions>]]\n");
+          OS::PrintErr("disasm [<address> [<number_of_instructions>]]\n");
         }
       } else if (strcmp(cmd, "gdb") == 0) {
-        OS::Print("relinquishing control to gdb\n");
+        OS::PrintErr("relinquishing control to gdb\n");
         OS::DebugBreak();
-        OS::Print("regaining control from gdb\n");
+        OS::PrintErr("regaining control from gdb\n");
       } else if (strcmp(cmd, "break") == 0) {
         if (args == 2) {
           uint32_t addr;
           if (GetValue(arg1, &addr)) {
             if (!SetBreakpoint(reinterpret_cast<Instr*>(addr))) {
-              OS::Print("setting breakpoint failed\n");
+              OS::PrintErr("setting breakpoint failed\n");
             }
           } else {
-            OS::Print("%s unrecognized\n", arg1);
+            OS::PrintErr("%s unrecognized\n", arg1);
           }
         } else {
-          OS::Print("break <addr>\n");
+          OS::PrintErr("break <addr>\n");
         }
       } else if (strcmp(cmd, "del") == 0) {
         if (!DeleteBreakpoint(NULL)) {
-          OS::Print("deleting breakpoint failed\n");
+          OS::PrintErr("deleting breakpoint failed\n");
         }
       } else if (strcmp(cmd, "flags") == 0) {
-        OS::Print("APSR: ");
-        OS::Print("N flag: %d; ", sim_->n_flag_);
-        OS::Print("Z flag: %d; ", sim_->z_flag_);
-        OS::Print("C flag: %d; ", sim_->c_flag_);
-        OS::Print("V flag: %d\n", sim_->v_flag_);
-        OS::Print("FPSCR: ");
-        OS::Print("N flag: %d; ", sim_->fp_n_flag_);
-        OS::Print("Z flag: %d; ", sim_->fp_z_flag_);
-        OS::Print("C flag: %d; ", sim_->fp_c_flag_);
-        OS::Print("V flag: %d\n", sim_->fp_v_flag_);
+        OS::PrintErr("APSR: ");
+        OS::PrintErr("N flag: %d; ", sim_->n_flag_);
+        OS::PrintErr("Z flag: %d; ", sim_->z_flag_);
+        OS::PrintErr("C flag: %d; ", sim_->c_flag_);
+        OS::PrintErr("V flag: %d\n", sim_->v_flag_);
+        OS::PrintErr("FPSCR: ");
+        OS::PrintErr("N flag: %d; ", sim_->fp_n_flag_);
+        OS::PrintErr("Z flag: %d; ", sim_->fp_z_flag_);
+        OS::PrintErr("C flag: %d; ", sim_->fp_c_flag_);
+        OS::PrintErr("V flag: %d\n", sim_->fp_v_flag_);
       } else if (strcmp(cmd, "unstop") == 0) {
         intptr_t stop_pc = sim_->get_pc() - Instr::kInstrSize;
         Instr* stop_instr = reinterpret_cast<Instr*>(stop_pc);
         if (stop_instr->IsSvc() || stop_instr->IsBkpt()) {
           stop_instr->SetInstructionBits(Instr::kNopInstruction);
         } else {
-          OS::Print("Not at debugger stop.\n");
+          OS::PrintErr("Not at debugger stop.\n");
         }
       } else if (strcmp(cmd, "trace") == 0) {
         if (FLAG_trace_sim_after == ULLONG_MAX) {
           FLAG_trace_sim_after = sim_->get_icount();
-          OS::Print("execution tracing on\n");
+          OS::PrintErr("execution tracing on\n");
         } else {
           FLAG_trace_sim_after = ULLONG_MAX;
-          OS::Print("execution tracing off\n");
+          OS::PrintErr("execution tracing off\n");
         }
       } else if (strcmp(cmd, "bt") == 0) {
         PrintBacktrace();
       } else {
-        OS::Print("Unknown command: %s\n", cmd);
+        OS::PrintErr("Unknown command: %s\n", cmd);
       }
     }
     delete[] line;
@@ -605,7 +607,7 @@
   char line_buf[256];
   intptr_t offset = 0;
   bool keep_going = true;
-  OS::Print("%s", prompt);
+  OS::PrintErr("%s", prompt);
   while (keep_going) {
     if (fgets(line_buf, sizeof(line_buf), stdin) == NULL) {
       // fgets got an error. Just give up.
@@ -1059,8 +1061,8 @@
 
 // Unsupported instructions use Format to print an error and stop execution.
 void Simulator::Format(Instr* instr, const char* format) {
-  OS::Print("Simulator found unsupported instruction:\n 0x%p: %s\n", instr,
-            format);
+  OS::PrintErr("Simulator found unsupported instruction:\n 0x%p: %s\n", instr,
+               format);
   UNIMPLEMENTED();
 }
 
diff --git a/runtime/vm/simulator_arm64.cc b/runtime/vm/simulator_arm64.cc
index 020321c..51ac7bb 100644
--- a/runtime/vm/simulator_arm64.cc
+++ b/runtime/vm/simulator_arm64.cc
@@ -122,7 +122,7 @@
 SimulatorDebugger::~SimulatorDebugger() {}
 
 void SimulatorDebugger::Stop(Instr* instr, const char* message) {
-  OS::Print("Simulator hit %s\n", message);
+  OS::PrintErr("Simulator hit %s\n", message);
   Debug();
 }
 
@@ -280,7 +280,7 @@
   if (token_pos.IsReal()) {
     script.GetTokenLocation(token_pos, &line, &column);
   }
-  OS::Print(
+  OS::PrintErr(
       "pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s%s (%s:%" Pd ":%" Pd ")\n", pc,
       fp, sp, is_optimized ? (is_inlined ? "inlined " : "optimized ") : "",
       func_name.ToCString(), url.ToCString(), line, column);
@@ -325,13 +325,13 @@
                      GetApproximateTokenIndex(code, frame->pc()),
                      code.is_optimized(), false);
     } else {
-      OS::Print("pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s frame\n",
-                frame->pc(), frame->fp(), frame->sp(),
-                frame->IsEntryFrame()
-                    ? "entry"
-                    : frame->IsExitFrame()
-                          ? "exit"
-                          : frame->IsStubFrame() ? "stub" : "invalid");
+      OS::PrintErr("pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s frame\n",
+                   frame->pc(), frame->fp(), frame->sp(),
+                   frame->IsEntryFrame()
+                       ? "entry"
+                       : frame->IsExitFrame()
+                             ? "exit"
+                             : frame->IsStubFrame() ? "stub" : "invalid");
     }
     frame = frames.NextFrame();
   }
@@ -400,12 +400,12 @@
     if (last_pc != sim_->get_pc()) {
       last_pc = sim_->get_pc();
       if (Simulator::IsIllegalAddress(last_pc)) {
-        OS::Print("pc is out of bounds: 0x%" Px "\n", last_pc);
+        OS::PrintErr("pc is out of bounds: 0x%" Px "\n", last_pc);
       } else {
         if (FLAG_support_disassembler) {
           Disassembler::Disassemble(last_pc, last_pc + Instr::kInstrSize);
         } else {
-          OS::Print("Disassembler not supported in this mode.\n");
+          OS::PrintErr("Disassembler not supported in this mode.\n");
         }
       }
     }
@@ -421,7 +421,7 @@
                         "%" XSTR(ARG_SIZE) "s",
                         cmd, arg1, arg2);
       if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) {
-        OS::Print(
+        OS::PrintErr(
             "c/cont -- continue execution\n"
             "disasm -- disassemble instrs at current pc location\n"
             "  other variants are:\n"
@@ -444,7 +444,7 @@
             "unstop -- if current pc is a stop instr make it a nop\n"
             "q/quit -- Quit the debugger and exit the program\n");
       } else if ((strcmp(cmd, "quit") == 0) || (strcmp(cmd, "q") == 0)) {
-        OS::Print("Quitting\n");
+        OS::PrintErr("Quitting\n");
         OS::Exit(0);
       } else if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
         sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc()));
@@ -458,26 +458,26 @@
           uint64_t value;
           if (strcmp(arg1, "icount") == 0) {
             value = sim_->get_icount();
-            OS::Print("icount: %" Pu64 " 0x%" Px64 "\n", value, value);
+            OS::PrintErr("icount: %" Pu64 " 0x%" Px64 "\n", value, value);
           } else if (GetValue(arg1, &value)) {
-            OS::Print("%s: %" Pu64 " 0x%" Px64 "\n", arg1, value, value);
+            OS::PrintErr("%s: %" Pu64 " 0x%" Px64 "\n", arg1, value, value);
           } else {
-            OS::Print("%s unrecognized\n", arg1);
+            OS::PrintErr("%s unrecognized\n", arg1);
           }
         } else {
-          OS::Print("print <reg or icount or value or *addr>\n");
+          OS::PrintErr("print <reg or icount or value or *addr>\n");
         }
       } else if ((strcmp(cmd, "pf") == 0) || (strcmp(cmd, "printfloat") == 0)) {
         if (args == 2) {
           uint32_t value;
           if (GetSValue(arg1, &value)) {
             float svalue = bit_cast<float, uint32_t>(value);
-            OS::Print("%s: %d 0x%x %.8g\n", arg1, value, value, svalue);
+            OS::PrintErr("%s: %d 0x%x %.8g\n", arg1, value, value, svalue);
           } else {
-            OS::Print("%s unrecognized\n", arg1);
+            OS::PrintErr("%s unrecognized\n", arg1);
           }
         } else {
-          OS::Print("printfloat <vreg or *addr>\n");
+          OS::PrintErr("printfloat <vreg or *addr>\n");
         }
       } else if ((strcmp(cmd, "pd") == 0) ||
                  (strcmp(cmd, "printdouble") == 0)) {
@@ -485,13 +485,13 @@
           uint64_t long_value;
           if (GetDValue(arg1, &long_value)) {
             double dvalue = bit_cast<double, uint64_t>(long_value);
-            OS::Print("%s: %" Pu64 " 0x%" Px64 " %.8g\n", arg1, long_value,
-                      long_value, dvalue);
+            OS::PrintErr("%s: %" Pu64 " 0x%" Px64 " %.8g\n", arg1, long_value,
+                         long_value, dvalue);
           } else {
-            OS::Print("%s unrecognized\n", arg1);
+            OS::PrintErr("%s unrecognized\n", arg1);
           }
         } else {
-          OS::Print("printdouble <vreg or *addr>\n");
+          OS::PrintErr("printdouble <vreg or *addr>\n");
         }
       } else if ((strcmp(cmd, "pq") == 0) || (strcmp(cmd, "printquad") == 0)) {
         if (args == 2) {
@@ -509,17 +509,19 @@
             const float sval1 = bit_cast<float, int32_t>(s1);
             const float sval2 = bit_cast<float, int32_t>(s2);
             const float sval3 = bit_cast<float, int32_t>(s3);
-            OS::Print("%s: %" Pu64 " 0x%" Px64 " %.8g\n", arg1, d0, d0, dval0);
-            OS::Print("%s: %" Pu64 " 0x%" Px64 " %.8g\n", arg1, d1, d1, dval1);
-            OS::Print("%s: %d 0x%x %.8g\n", arg1, s0, s0, sval0);
-            OS::Print("%s: %d 0x%x %.8g\n", arg1, s1, s1, sval1);
-            OS::Print("%s: %d 0x%x %.8g\n", arg1, s2, s2, sval2);
-            OS::Print("%s: %d 0x%x %.8g\n", arg1, s3, s3, sval3);
+            OS::PrintErr("%s: %" Pu64 " 0x%" Px64 " %.8g\n", arg1, d0, d0,
+                         dval0);
+            OS::PrintErr("%s: %" Pu64 " 0x%" Px64 " %.8g\n", arg1, d1, d1,
+                         dval1);
+            OS::PrintErr("%s: %d 0x%x %.8g\n", arg1, s0, s0, sval0);
+            OS::PrintErr("%s: %d 0x%x %.8g\n", arg1, s1, s1, sval1);
+            OS::PrintErr("%s: %d 0x%x %.8g\n", arg1, s2, s2, sval2);
+            OS::PrintErr("%s: %d 0x%x %.8g\n", arg1, s3, s3, sval3);
           } else {
-            OS::Print("%s unrecognized\n", arg1);
+            OS::PrintErr("%s unrecognized\n", arg1);
           }
         } else {
-          OS::Print("printquad <vreg or *addr>\n");
+          OS::PrintErr("printquad <vreg or *addr>\n");
         }
       } else if ((strcmp(cmd, "po") == 0) ||
                  (strcmp(cmd, "printobject") == 0)) {
@@ -529,20 +531,20 @@
           if (((arg1[0] == '*') && GetValue(arg1 + 1, &value)) ||
               GetValue(arg1, &value)) {
             if (Isolate::Current()->heap()->Contains(value)) {
-              OS::Print("%s: \n", arg1);
+              OS::PrintErr("%s: \n", arg1);
 #if defined(DEBUG)
               const Object& obj =
                   Object::Handle(reinterpret_cast<RawObject*>(value));
               obj.Print();
 #endif  // defined(DEBUG)
             } else {
-              OS::Print("0x%" Px64 " is not an object reference\n", value);
+              OS::PrintErr("0x%" Px64 " is not an object reference\n", value);
             }
           } else {
-            OS::Print("%s unrecognized\n", arg1);
+            OS::PrintErr("%s unrecognized\n", arg1);
           }
         } else {
-          OS::Print("printobject <*reg or *addr>\n");
+          OS::PrintErr("printobject <*reg or *addr>\n");
         }
       } else if (strcmp(cmd, "disasm") == 0) {
         uint64_t start = 0;
@@ -555,9 +557,10 @@
             // No length parameter passed, assume 10 instructions.
             if (Simulator::IsIllegalAddress(start)) {
               // If start isn't a valid address, warn and use PC instead.
-              OS::Print("First argument yields invalid address: 0x%" Px64 "\n",
-                        start);
-              OS::Print("Using PC instead\n");
+              OS::PrintErr("First argument yields invalid address: 0x%" Px64
+                           "\n",
+                           start);
+              OS::PrintErr("Using PC instead\n");
               start = sim_->get_pc();
             }
             end = start + (10 * Instr::kInstrSize);
@@ -567,9 +570,10 @@
           if (GetValue(arg1, &start) && GetValue(arg2, &length)) {
             if (Simulator::IsIllegalAddress(start)) {
               // If start isn't a valid address, warn and use PC instead.
-              OS::Print("First argument yields invalid address: 0x%" Px64 "\n",
-                        start);
-              OS::Print("Using PC instead\n");
+              OS::PrintErr("First argument yields invalid address: 0x%" Px64
+                           "\n",
+                           start);
+              OS::PrintErr("Using PC instead\n");
               start = sim_->get_pc();
             }
             end = start + (length * Instr::kInstrSize);
@@ -579,58 +583,58 @@
           if (FLAG_support_disassembler) {
             Disassembler::Disassemble(start, end);
           } else {
-            OS::Print("Disassembler not supported in this mode.\n");
+            OS::PrintErr("Disassembler not supported in this mode.\n");
           }
         } else {
-          OS::Print("disasm [<address> [<number_of_instructions>]]\n");
+          OS::PrintErr("disasm [<address> [<number_of_instructions>]]\n");
         }
       } else if (strcmp(cmd, "gdb") == 0) {
-        OS::Print("relinquishing control to gdb\n");
+        OS::PrintErr("relinquishing control to gdb\n");
         OS::DebugBreak();
-        OS::Print("regaining control from gdb\n");
+        OS::PrintErr("regaining control from gdb\n");
       } else if (strcmp(cmd, "break") == 0) {
         if (args == 2) {
           uint64_t addr;
           if (GetValue(arg1, &addr)) {
             if (!SetBreakpoint(reinterpret_cast<Instr*>(addr))) {
-              OS::Print("setting breakpoint failed\n");
+              OS::PrintErr("setting breakpoint failed\n");
             }
           } else {
-            OS::Print("%s unrecognized\n", arg1);
+            OS::PrintErr("%s unrecognized\n", arg1);
           }
         } else {
-          OS::Print("break <addr>\n");
+          OS::PrintErr("break <addr>\n");
         }
       } else if (strcmp(cmd, "del") == 0) {
         if (!DeleteBreakpoint(NULL)) {
-          OS::Print("deleting breakpoint failed\n");
+          OS::PrintErr("deleting breakpoint failed\n");
         }
       } else if (strcmp(cmd, "flags") == 0) {
-        OS::Print("APSR: ");
-        OS::Print("N flag: %d; ", sim_->n_flag_);
-        OS::Print("Z flag: %d; ", sim_->z_flag_);
-        OS::Print("C flag: %d; ", sim_->c_flag_);
-        OS::Print("V flag: %d\n", sim_->v_flag_);
+        OS::PrintErr("APSR: ");
+        OS::PrintErr("N flag: %d; ", sim_->n_flag_);
+        OS::PrintErr("Z flag: %d; ", sim_->z_flag_);
+        OS::PrintErr("C flag: %d; ", sim_->c_flag_);
+        OS::PrintErr("V flag: %d\n", sim_->v_flag_);
       } else if (strcmp(cmd, "unstop") == 0) {
         intptr_t stop_pc = sim_->get_pc() - Instr::kInstrSize;
         Instr* stop_instr = reinterpret_cast<Instr*>(stop_pc);
         if (stop_instr->IsExceptionGenOp()) {
           stop_instr->SetInstructionBits(Instr::kNopInstruction);
         } else {
-          OS::Print("Not at debugger stop.\n");
+          OS::PrintErr("Not at debugger stop.\n");
         }
       } else if (strcmp(cmd, "trace") == 0) {
         if (FLAG_trace_sim_after == ULLONG_MAX) {
           FLAG_trace_sim_after = sim_->get_icount();
-          OS::Print("execution tracing on\n");
+          OS::PrintErr("execution tracing on\n");
         } else {
           FLAG_trace_sim_after = ULLONG_MAX;
-          OS::Print("execution tracing off\n");
+          OS::PrintErr("execution tracing off\n");
         }
       } else if (strcmp(cmd, "bt") == 0) {
         PrintBacktrace();
       } else {
-        OS::Print("Unknown command: %s\n", cmd);
+        OS::PrintErr("Unknown command: %s\n", cmd);
       }
     }
     delete[] line;
@@ -652,7 +656,7 @@
   char line_buf[256];
   intptr_t offset = 0;
   bool keep_going = true;
-  OS::Print("%s", prompt);
+  OS::PrintErr("%s", prompt);
   while (keep_going) {
     if (fgets(line_buf, sizeof(line_buf), stdin) == NULL) {
       // fgets got an error. Just give up.
@@ -1159,8 +1163,8 @@
 
 // Unsupported instructions use Format to print an error and stop execution.
 void Simulator::Format(Instr* instr, const char* format) {
-  OS::Print("Simulator found unsupported instruction:\n 0x%p: %s\n", instr,
-            format);
+  OS::PrintErr("Simulator found unsupported instruction:\n 0x%p: %s\n", instr,
+               format);
   UNIMPLEMENTED();
 }
 
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index 68ebca2..5f97708 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -391,7 +391,7 @@
     str_ = String::ScrubName(str_);
     cls_ = library_.LookupClassAllowPrivate(str_);
     if (cls_.IsNull()) {
-      OS::Print("Name of class not found %s\n", str_.ToCString());
+      OS::PrintErr("Name of class not found %s\n", str_.ToCString());
       SetReadException("Invalid Class object found in message.");
     }
     cls_.EnsureIsFinalized(thread());
@@ -1082,7 +1082,7 @@
         return true;
       }
       default:
-        OS::Print("class id = %" Pd "\n", id);
+        OS::PrintErr("class id = %" Pd "\n", id);
         break;
     }
   }
diff --git a/runtime/vm/snapshot_test.cc b/runtime/vm/snapshot_test.cc
index e3d9d82..cbe79e2 100644
--- a/runtime/vm/snapshot_test.cc
+++ b/runtime/vm/snapshot_test.cc
@@ -1121,7 +1121,7 @@
     script ^= lib_scripts.At(i);
     EXPECT(!script.IsNull());
     uri = script.url();
-    OS::Print("Generating source for part: %s\n", uri.ToCString());
+    OS::PrintErr("Generating source for part: %s\n", uri.ToCString());
     GenerateSourceAndCheck(script);
   }
 }
@@ -1142,7 +1142,7 @@
     lib ^= libs.At(i);
     EXPECT(!lib.IsNull());
     uri = lib.url();
-    OS::Print("Generating source for library: %s\n", uri.ToCString());
+    OS::PrintErr("Generating source for library: %s\n", uri.ToCString());
     IterateScripts(lib);
   }
 
diff --git a/runtime/vm/stack_frame_test.cc b/runtime/vm/stack_frame_test.cc
index f5c5684..6facc4f 100644
--- a/runtime/vm/stack_frame_test.cc
+++ b/runtime/vm/stack_frame_test.cc
@@ -42,8 +42,8 @@
   const Instance& expected = Instance::CheckedHandle(arguments->NativeArgAt(0));
   const Instance& actual = Instance::CheckedHandle(arguments->NativeArgAt(1));
   if (!expected.OperatorEquals(actual)) {
-    OS::Print("expected: '%s' actual: '%s'\n", expected.ToCString(),
-              actual.ToCString());
+    OS::PrintErr("expected: '%s' actual: '%s'\n", expected.ToCString(),
+                 actual.ToCString());
     FATAL("Expect_equals fails.\n");
   }
 }
diff --git a/runtime/vm/symbols.cc b/runtime/vm/symbols.cc
index 2e8c7db..78c655e 100644
--- a/runtime/vm/symbols.cc
+++ b/runtime/vm/symbols.cc
@@ -676,12 +676,12 @@
   intptr_t capacity = -1;
   // First dump VM symbol table stats.
   GetStats(Dart::vm_isolate(), &size, &capacity);
-  OS::Print("VM Isolate: Number of symbols : %" Pd "\n", size);
-  OS::Print("VM Isolate: Symbol table capacity : %" Pd "\n", capacity);
+  OS::PrintErr("VM Isolate: Number of symbols : %" Pd "\n", size);
+  OS::PrintErr("VM Isolate: Symbol table capacity : %" Pd "\n", capacity);
   // Now dump regular isolate symbol table stats.
   GetStats(isolate, &size, &capacity);
-  OS::Print("Isolate: Number of symbols : %" Pd "\n", size);
-  OS::Print("Isolate: Symbol table capacity : %" Pd "\n", capacity);
+  OS::PrintErr("Isolate: Number of symbols : %" Pd "\n", size);
+  OS::PrintErr("Isolate: Symbol table capacity : %" Pd "\n", capacity);
   // TODO(koda): Consider recording growth and collision stats in HashTable,
   // in DEBUG mode.
 }
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc
index 7f1c0d3..62d93a8 100644
--- a/runtime/vm/thread.cc
+++ b/runtime/vm/thread.cc
@@ -538,7 +538,7 @@
       // False result from HandleOOBMessages signals that the isolate should
       // be terminating.
       if (FLAG_trace_isolates) {
-        OS::Print(
+        OS::PrintErr(
             "[!] Terminating isolate due to OOB message:\n"
             "\tisolate:    %s\n",
             isolate()->name());
diff --git a/runtime/vm/thread_interrupter_fuchsia.cc b/runtime/vm/thread_interrupter_fuchsia.cc
index 375f98d..d2f19c6 100644
--- a/runtime/vm/thread_interrupter_fuchsia.cc
+++ b/runtime/vm/thread_interrupter_fuchsia.cc
@@ -37,8 +37,8 @@
 class ThreadSuspendScope {
  public:
   explicit ThreadSuspendScope(zx_handle_t thread_handle)
-      : thread_handle_(thread_handle), suspended_(true) {
-    zx_status_t status = zx_task_suspend(thread_handle);
+      : thread_handle_(thread_handle), suspend_token_(ZX_HANDLE_INVALID) {
+    zx_status_t status = zx_task_suspend_token(thread_handle, &suspend_token_);
     // If a thread is somewhere where suspend is impossible, zx_task_suspend()
     // can return ZX_ERR_NOT_SUPPORTED.
     if (status != ZX_OK) {
@@ -46,27 +46,21 @@
         OS::PrintErr("ThreadInterrupter: zx_task_suspend failed: %s\n",
                      zx_status_get_string(status));
       }
-      suspended_ = false;
     }
   }
 
   ~ThreadSuspendScope() {
-    if (suspended_) {
-      zx_status_t status = zx_task_resume(thread_handle_, 0);
-      if (status != ZX_OK) {
-        // If we fail to resume a thread, then it's likely the program will
-        // hang. Crash instead.
-        FATAL1("zx_task_resume failed: %s", zx_status_get_string(status));
-      }
+    if (suspend_token_ != ZX_HANDLE_INVALID) {
+      zx_handle_close(suspend_token_);
     }
     zx_handle_close(thread_handle_);
   }
 
-  bool suspended() const { return suspended_; }
+  bool suspended() const { return suspend_token_ != ZX_HANDLE_INVALID; }
 
  private:
   zx_handle_t thread_handle_;
-  bool suspended_;
+  zx_handle_t suspend_token_;  // ZX_HANDLE_INVALID when not suspended.
 
   DISALLOW_ALLOCATION();
   DISALLOW_COPY_AND_ASSIGN(ThreadSuspendScope);
diff --git a/runtime/vm/thread_test.cc b/runtime/vm/thread_test.cc
index e033319..e4155eb 100644
--- a/runtime/vm/thread_test.cc
+++ b/runtime/vm/thread_test.cc
@@ -58,7 +58,7 @@
 
     // Check whether this attempt falls within the expected time limits.
     int64_t wakeup_time = (stop - start) / kMicrosecondsPerMillisecond;
-    OS::Print("wakeup_time: %" Pd64 "\n", wakeup_time);
+    OS::PrintErr("wakeup_time: %" Pd64 "\n", wakeup_time);
     const int kAcceptableTimeJitter = 20;    // Measured in milliseconds.
     const int kAcceptableWakeupDelay = 150;  // Measured in milliseconds.
     if (((wait_time - kAcceptableTimeJitter) <= wakeup_time) &&
diff --git a/runtime/vm/timeline.cc b/runtime/vm/timeline.cc
index 56b11d6..bea9fb6 100644
--- a/runtime/vm/timeline.cc
+++ b/runtime/vm/timeline.cc
@@ -1123,7 +1123,7 @@
       OS::SCreate(NULL, "%s/dart-timeline-%" Pd ".json", directory, pid);
   void* file = (*file_open)(filename, true);
   if (file == NULL) {
-    OS::Print("Failed to write timeline file: %s\n", filename);
+    OS::PrintErr("Failed to write timeline file: %s\n", filename);
     free(filename);
     return;
   }
@@ -1450,7 +1450,7 @@
   block->Open();
   head_ = block;
   if (FLAG_trace_timeline) {
-    OS::Print("Created new block %p\n", block);
+    OS::PrintErr("Created new block %p\n", block);
   }
   return head_;
 }
@@ -1540,7 +1540,7 @@
     OSThread* os_thread = OSThread::Current();
     ASSERT(os_thread != NULL);
     intptr_t tid = OSThread::ThreadIdToIntPtr(os_thread->id());
-    OS::Print("StartEvent in block %p for thread %" Px "\n", this, tid);
+    OS::PrintErr("StartEvent in block %p for thread %" Px "\n", this, tid);
   }
   return &events_[length_++];
 }
@@ -1595,7 +1595,7 @@
 
 void TimelineEventBlock::Finish() {
   if (FLAG_trace_timeline) {
-    OS::Print("Finish block %p\n", this);
+    OS::PrintErr("Finish block %p\n", this);
   }
   in_use_ = false;
   if (Service::timeline_stream.enabled()) {
diff --git a/runtime/vm/timeline_analysis.cc b/runtime/vm/timeline_analysis.cc
index 4c08d6b..cb02834 100644
--- a/runtime/vm/timeline_analysis.cc
+++ b/runtime/vm/timeline_analysis.cc
@@ -181,7 +181,7 @@
   error_msg_ = zone_->VPrint(format, args);
   ASSERT(error_msg_ != NULL);
   if (FLAG_trace_timeline_analysis) {
-    OS::Print("TimelineAnalysis error = %s\n", error_msg_);
+    OS::PrintErr("TimelineAnalysis error = %s\n", error_msg_);
   }
 }
 
diff --git a/runtime/vm/unit_test.cc b/runtime/vm/unit_test.cc
index a88106a..7e3cd7a 100644
--- a/runtime/vm/unit_test.cc
+++ b/runtime/vm/unit_test.cc
@@ -719,10 +719,10 @@
   const Instructions& instructions = Instructions::Handle(code_.instructions());
   uword start = instructions.PayloadStart();
   if (FLAG_disassemble) {
-    OS::Print("Code for test '%s' {\n", name_);
+    OS::PrintErr("Code for test '%s' {\n", name_);
     uword start = instructions.PayloadStart();
     Disassembler::Disassemble(start, start + assembler_->CodeSize());
-    OS::Print("}\n");
+    OS::PrintErr("}\n");
   }
   Disassembler::Disassemble(start, start + assembler_->CodeSize(), disassembly_,
                             DISASSEMBLY_SIZE);
@@ -790,7 +790,7 @@
   ASSERT(isolate != NULL);
   const Error& error = Error::Handle(Compiler::Compile(library, script));
   if (!error.IsNull()) {
-    OS::Print("Error compiling test script:\n%s\n", error.ToErrorCString());
+    OS::PrintErr("Error compiling test script:\n%s\n", error.ToErrorCString());
   }
   return error.IsNull();
 }
diff --git a/runtime/vm/virtual_memory_android.cc b/runtime/vm/virtual_memory_android.cc
index 5f0b0de..ff39c23 100644
--- a/runtime/vm/virtual_memory_android.cc
+++ b/runtime/vm/virtual_memory_android.cc
@@ -15,7 +15,6 @@
 #include "platform/utils.h"
 
 #include "vm/isolate.h"
-#include "vm/profiler.h"
 
 namespace dart {
 
@@ -39,7 +38,6 @@
     int error = errno;
     const int kBufferSize = 1024;
     char error_buf[kBufferSize];
-    NOT_IN_PRODUCT(Profiler::DumpStackTrace());
     FATAL2("munmap error: %d (%s)", error,
            Utils::StrError(error, error_buf, kBufferSize));
   }
@@ -132,7 +130,6 @@
     int error = errno;
     const int kBufferSize = 1024;
     char error_buf[kBufferSize];
-    NOT_IN_PRODUCT(Profiler::DumpStackTrace());
     FATAL2("mprotect error: %d (%s)", error,
            Utils::StrError(error, error_buf, kBufferSize));
   }
diff --git a/runtime/vm/virtual_memory_fuchsia.cc b/runtime/vm/virtual_memory_fuchsia.cc
index fbcccb5..0b676c2 100644
--- a/runtime/vm/virtual_memory_fuchsia.cc
+++ b/runtime/vm/virtual_memory_fuchsia.cc
@@ -27,7 +27,7 @@
 #define LOG_ERR(msg, ...)                                                      \
   OS::PrintErr("VMVM: %s:%d: " msg, __FILE__, __LINE__, ##__VA_ARGS__)
 #define LOG_INFO(msg, ...)                                                     \
-  OS::Print("VMVM: %s:%d: " msg, __FILE__, __LINE__, ##__VA_ARGS__)
+  OS::PrintErr("VMVM: %s:%d: " msg, __FILE__, __LINE__, ##__VA_ARGS__)
 #else
 #define LOG_ERR(msg, ...)
 #define LOG_INFO(msg, ...)
diff --git a/runtime/vm/virtual_memory_linux.cc b/runtime/vm/virtual_memory_linux.cc
index f07eb8e..80fb7c7 100644
--- a/runtime/vm/virtual_memory_linux.cc
+++ b/runtime/vm/virtual_memory_linux.cc
@@ -15,7 +15,6 @@
 #include "platform/utils.h"
 
 #include "vm/isolate.h"
-#include "vm/profiler.h"
 
 namespace dart {
 
@@ -39,7 +38,6 @@
     int error = errno;
     const int kBufferSize = 1024;
     char error_buf[kBufferSize];
-    NOT_IN_PRODUCT(Profiler::DumpStackTrace());
     FATAL2("munmap error: %d (%s)", error,
            Utils::StrError(error, error_buf, kBufferSize));
   }
@@ -132,7 +130,6 @@
     int error = errno;
     const int kBufferSize = 1024;
     char error_buf[kBufferSize];
-    NOT_IN_PRODUCT(Profiler::DumpStackTrace());
     FATAL2("mprotect error: %d (%s)", error,
            Utils::StrError(error, error_buf, kBufferSize));
   }
diff --git a/runtime/vm/virtual_memory_macos.cc b/runtime/vm/virtual_memory_macos.cc
index dbb680e..e9dcc4b 100644
--- a/runtime/vm/virtual_memory_macos.cc
+++ b/runtime/vm/virtual_memory_macos.cc
@@ -15,7 +15,6 @@
 #include "platform/utils.h"
 
 #include "vm/isolate.h"
-#include "vm/profiler.h"
 
 namespace dart {
 
@@ -39,7 +38,6 @@
     int error = errno;
     const int kBufferSize = 1024;
     char error_buf[kBufferSize];
-    NOT_IN_PRODUCT(Profiler::DumpStackTrace());
     FATAL2("munmap error: %d (%s)", error,
            Utils::StrError(error, error_buf, kBufferSize));
   }
@@ -132,7 +130,6 @@
     int error = errno;
     const int kBufferSize = 1024;
     char error_buf[kBufferSize];
-    NOT_IN_PRODUCT(Profiler::DumpStackTrace());
     FATAL2("mprotect error: %d (%s)", error,
            Utils::StrError(error, error_buf, kBufferSize));
   }
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 843e633..ee8e653 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -870,7 +870,8 @@
   @DomName('Animation.finished')
   @DocsEditable()
   @Experimental() // untriaged
-  final Future finished;
+  Future<Animation> get finished =>
+      promiseToFuture<Animation>(JS("", "#.finished", this));
 
   @DomName('Animation.id')
   @DocsEditable()
@@ -890,7 +891,8 @@
   @DomName('Animation.ready')
   @DocsEditable()
   @Experimental() // untriaged
-  final Future ready;
+  Future<Animation> get ready =>
+      promiseToFuture<Animation>(JS("", "#.ready", this));
 
   @DomName('Animation.startTime')
   @DocsEditable()
@@ -2118,7 +2120,8 @@
   @DomName('BeforeInstallPromptEvent.userChoice')
   @DocsEditable()
   @Experimental() // untriaged
-  final Future userChoice;
+  Future<Map<String, dynamic>> get userChoice =>
+      promiseToFutureAsMap(JS("", "#.userChoice", this));
 
   @DomName('BeforeInstallPromptEvent.prompt')
   @DocsEditable()
@@ -19387,7 +19390,8 @@
   @DomName('FetchEvent.preloadResponse')
   @DocsEditable()
   @Experimental() // untriaged
-  final Future preloadResponse;
+  Future get preloadResponse =>
+      promiseToFuture(JS("", "#.preloadResponse", this));
 
   @DomName('FetchEvent.request')
   @DocsEditable()
@@ -20108,7 +20112,8 @@
   @DomName('FontFace.loaded')
   @DocsEditable()
   @Experimental() // untriaged
-  final Future loaded;
+  Future<FontFace> get loaded =>
+      promiseToFuture<FontFace>(JS("", "#.loaded", this));
 
   @DomName('FontFace.status')
   @DocsEditable()
@@ -25820,7 +25825,7 @@
   @DomName('MediaKeySession.closed')
   @DocsEditable()
   @Experimental() // untriaged
-  final Future closed;
+  Future<void> get closed => promiseToFuture<void>(JS("", "#.closed", this));
 
   @DomName('MediaKeySession.expiration')
   @DocsEditable()
@@ -33137,7 +33142,9 @@
   @DomName('PresentationReceiver.connectionList')
   @DocsEditable()
   @Experimental() // untriaged
-  final Future connectionList;
+  Future<PresentationConnectionList> get connectionList =>
+      promiseToFuture<PresentationConnectionList>(
+          JS("", "#.connectionList", this));
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -33330,7 +33337,7 @@
   @DomName('PromiseRejectionEvent.promise')
   @DocsEditable()
   @Experimental() // untriaged
-  final Future promise;
+  Future get promise => promiseToFuture(JS("", "#.promise", this));
 
   @DomName('PromiseRejectionEvent.reason')
   @DocsEditable()
@@ -36013,7 +36020,8 @@
   @DomName('ServiceWorkerContainer.ready')
   @DocsEditable()
   @Experimental() // untriaged
-  final Future ready;
+  Future<ServiceWorkerRegistration> get ready =>
+      promiseToFuture<ServiceWorkerRegistration>(JS("", "#.ready", this));
 
   @DomName('ServiceWorkerContainer.getRegistration')
   @DocsEditable()
diff --git a/tests/html/html.status b/tests/html/html.status
index 9fe79e4..647ae2e 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -401,7 +401,6 @@
 
 [ $compiler == dart2js && $browser ]
 custom/created_callback_test: Fail # Support for created constructor. Issue 14835
-fontface_loaded_test: Fail # Support for promises.
 
 [ $compiler == dart2js && $browser && $csp ]
 custom/element_upgrade_test: Fail # Issue 17298
@@ -522,6 +521,9 @@
 custom/entered_left_view_test/viewless_document: Fail # Polyfill does not handle this
 fontface_test: Fail # Fontface not supported on these.
 
+[ $compiler == dart2js && ($runtime == safari || $ie) ]
+fontface_loaded_test: Fail # Not supported on these.
+
 [ $runtime == chrome && $system == macos ]
 canvasrenderingcontext2d_test/drawImage_video_element: Skip # Times out. Please triage this failure.
 canvasrenderingcontext2d_test/drawImage_video_element_dataUrl: Skip # Times out. Please triage this failure.
diff --git a/tests/lib_2/html/fontface_loaded_test.dart b/tests/lib_2/html/fontface_loaded_test.dart
index a9334b6..7f2ebc5 100644
--- a/tests/lib_2/html/fontface_loaded_test.dart
+++ b/tests/lib_2/html/fontface_loaded_test.dart
@@ -32,22 +32,33 @@
       treeSanitizer: new NullTreeSanitizer());
   document.head.append(style);
 
-  test('document fonts - temporary', () {
+  test('document fonts - temporary', () async {
     var atLeastOneFont = false;
-    var loaded = <Future>[];
-    document.fonts.forEach((FontFace fontFace, _, __) {
+    var loaded = <Future<FontFace>>[];
+    document.fonts.forEach((FontFace fontFace, _, __) async {
       atLeastOneFont = true;
-      Future f1 = fontFace.loaded;
-      Future f2 = fontFace.loaded;
+      var f1 = fontFace.loaded;
+      var f2 = fontFace.loaded;
       loaded.add(fontFace.load());
       loaded.add(f1);
       loaded.add(f2);
     });
     expect(atLeastOneFont, isTrue);
-    return Future.wait(loaded).then(expectAsync((_) {
+    return Future.wait(loaded).then(expectAsync((_) async {
       document.fonts.forEach((fontFace, _, __) {
         expect(fontFace.status, 'loaded');
       });
+      expect(loaded.length, 3);
+      for (var loadedEntry in loaded) {
+        var fontFace = await loadedEntry;
+        expect(fontFace.status, 'loaded');
+        var fontFamily = fontFace.family;
+        if (fontFamily.startsWith('"')) {
+          // FF wraps family in quotes - remove the quotes.
+          fontFamily = fontFamily.substring(1, fontFamily.length - 1);
+        }
+        expect(fontFamily, 'Ahem');
+      }
     }));
   });
 }
diff --git a/tests/lib_2/lib_2_dart2js.status b/tests/lib_2/lib_2_dart2js.status
index e3b55be..ca9b2be 100644
--- a/tests/lib_2/lib_2_dart2js.status
+++ b/tests/lib_2/lib_2_dart2js.status
@@ -186,6 +186,7 @@
 html/fileapi_supported_throws_test: RuntimeError
 html/filereader_test: RuntimeError
 html/filteredelementlist_test: RuntimeError
+html/fontface_loaded_test: RuntimeError
 html/fontface_test: RuntimeError
 html/form_data_test: RuntimeError
 html/form_element_test: RuntimeError
@@ -339,7 +340,6 @@
 collection/list_test: RuntimeError
 
 [ $compiler == dart2js && $runtime != d8 && $runtime != jsshell ]
-html/fontface_loaded_test: RuntimeError
 html/html_mock_test: RuntimeError # Issue 31038
 html/input_element_attributes_test: RuntimeError
 html/js_dart_functions_test: RuntimeError # does not implement Dart 2 implicit `.call` tearoff
@@ -462,6 +462,7 @@
 html/element_types_shadow_test: RuntimeError # Issue 29922
 html/file_sample_test: Skip # FileSystem not supported on Safari.
 html/fileapi_supported_throws_test: Skip # FileSystem not supported on Safari
+html/fontface_loaded_test: RuntimeError # FontFace polyfill?
 html/js_mock_test: RuntimeError # Issue 32286
 html/storage_promise_test: RuntimeError # Not supported on Safari
 html/xhr_test: RuntimeError
@@ -474,7 +475,6 @@
 
 [ $compiler == dart2js && $browser ]
 html/custom/created_callback_test: RuntimeError
-html/fontface_loaded_test: Fail # Support for promises.
 html/js_typed_interop_lazy_test/01: RuntimeError
 html/notification_permission_test: Timeout, Pass # Issue 32002
 html/private_extension_member_test: RuntimeError
@@ -688,7 +688,6 @@
 [ $compiler == dart2js && $fasta && $host_checked ]
 html/custom/mirrors_2_test: Crash # 'file:*/pkg/compiler/lib/src/common_elements.dart': Failed assertion: line 405 pos 12: 'element.name == '=='': is not true.
 html/custom/mirrors_test: Crash # 'file:*/pkg/compiler/lib/src/common_elements.dart': Failed assertion: line 405 pos 12: 'element.name == '=='': is not true.
-html/fontface_loaded_test: RuntimeError # TypeError: Cannot read property 'createFragment$3$treeSanitizer$validator' of undefined
 html/indexeddb_3_test: Crash # 'file:*/pkg/compiler/lib/src/common_elements.dart': Failed assertion: line 405 pos 12: 'element.name == '=='': is not true.
 html/indexeddb_5_test: Crash # 'file:*/pkg/compiler/lib/src/common_elements.dart': Failed assertion: line 405 pos 12: 'element.name == '=='': is not true.
 html/js_array_test: CompileTimeError
@@ -725,7 +724,6 @@
 html/event_customevent_test: RuntimeError
 html/file_sample_test: RuntimeError
 html/fileapi_entry_test: RuntimeError
-html/fontface_loaded_test: RuntimeError
 html/indexeddb_1_test/functional: RuntimeError
 html/indexeddb_2_test: RuntimeError
 html/indexeddb_3_test: RuntimeError
@@ -791,3 +789,6 @@
 html/custom/attribute_changed_callback_test/unsupported_on_polyfill: Fail # Polyfill does not support
 html/custom/entered_left_view_test/viewless_document: Fail # Polyfill does not handle this
 html/fontface_test: Fail # Fontface not supported on these.
+
+[ $compiler == dart2js && ($runtime == safari || $ie) ]
+html/fontface_loaded_test: RuntimeError # FontFace polyfill?
diff --git a/tests/lib_2/lib_2_dartdevc.status b/tests/lib_2/lib_2_dartdevc.status
index bbfa3a4..db43afe 100644
--- a/tests/lib_2/lib_2_dartdevc.status
+++ b/tests/lib_2/lib_2_dartdevc.status
@@ -82,7 +82,6 @@
 html/custom_elements_test: Skip # Issue 29922
 html/deferred_multi_app_htmltest: Skip # Issue 29919
 html/element_classes_test: RuntimeError # Issue 29922
-html/fontface_loaded_test: RuntimeError
 html/isolates_test: RuntimeError # Issue 29922
 html/js_typed_interop_default_arg_test/default_value: MissingCompileTimeError # Issue 29922
 html/js_typed_interop_side_cast_exp_test/01: RuntimeError # Requires --experimental-trust-js-interop-type-annotations flag.
diff --git a/tests/standalone_2/io/code_collection_test.dart b/tests/standalone_2/io/code_collection_test.dart
index 1ee3b4f..99344df 100644
--- a/tests/standalone_2/io/code_collection_test.dart
+++ b/tests/standalone_2/io/code_collection_test.dart
@@ -12,7 +12,7 @@
   x = x + 1;
   // Print marker message while foo is on the stack so the code cannot be
   // collected.
-  print("foo=$x");
+  stderr.write("foo=$x\n");
   return x;
 }
 
@@ -56,7 +56,7 @@
   if (arguments.contains("--run")) {
     doTest();
   } else {
-    // Run the test and capture stdout.
+    // Run the test and capture stderr.
     var args = packageOptions();
     args.addAll([
       "--verbose-gc",
@@ -72,13 +72,13 @@
 
     Expect.equals(0, pr.exitCode);
 
-    // Code drops are logged with --log-code-drop. Look through stdout for the
+    // Code drops are logged with --log-code-drop. Look through stderr for the
     // message that foo's code was dropped.
-    print(pr.stdout);
+    print(pr.stderr);
     bool saw_foo2 = false;
     bool saw_detaching_foo = false;
     bool saw_foo3 = false;
-    pr.stdout.split("\n").forEach((line) {
+    pr.stderr.split("\n").forEach((line) {
       if (line.contains("foo=2")) {
         Expect.isFalse(saw_foo2, "foo=2 ran twice");
         saw_foo2 = true;
diff --git a/tests/standalone_2/io/issue_30687_test.dart b/tests/standalone_2/io/issue_30687_test.dart
new file mode 100644
index 0000000..96b514d
--- /dev/null
+++ b/tests/standalone_2/io/issue_30687_test.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2017, 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';
+
+import 'package:expect/expect.dart';
+
+main() async {
+  Link link1 = new Link(
+      Directory.systemTemp.path + Platform.pathSeparator + 'link1.lnk');
+  Link link2 = new Link(
+      Directory.systemTemp.path + Platform.pathSeparator + 'link2.lnk');
+
+  Directory target1 = new Directory(
+      Directory.systemTemp.path + Platform.pathSeparator + 'target1');
+  Directory target2 = new Directory(
+      Directory.systemTemp.path + Platform.pathSeparator + 'target2');
+
+  target1.createSync();
+  target2.createSync();
+
+  Expect.isTrue(target1.existsSync());
+  Expect.isTrue(target2.existsSync());
+
+  link1.createSync(target1.path);
+  link2.createSync(target2.path);
+  Expect.isTrue(link1.existsSync());
+  Expect.isTrue(link2.existsSync());
+
+  try {
+    Link renamed = await link1.rename(link2.path);
+    Expect.isFalse(link1.existsSync());
+    Expect.isTrue(renamed.existsSync());
+    Expect.equals(renamed.path, link2.path);
+  } finally {
+    target1.delete();
+    target2.delete();
+    link2.delete();
+    if (link1.existsSync()) {
+      link1.delete();
+    }
+  }
+}
diff --git a/tests/standalone_2/io/stdio_implicit_close_script.dart b/tests/standalone_2/io/stdio_implicit_close_script.dart
index 4be58a88..2b09e2f 100644
--- a/tests/standalone_2/io/stdio_implicit_close_script.dart
+++ b/tests/standalone_2/io/stdio_implicit_close_script.dart
@@ -7,9 +7,8 @@
 void main(List<String> arguments) {
   // Access stdout and stderr so that the system grabs a handle to it. This
   // initializes some internal structures.
-  if (stdout.hashCode == -1234 && stderr.hashCode == (stderr.hashCode + 1)) {
-    throw "we have other problems.";
-  }
+  stdout.write("APPLE");
+  stderr.write("BANANA");
 
   if (arguments.contains("stdout")) {
     stdout.close();
diff --git a/tests/standalone_2/io/stdio_implicit_close_test.dart b/tests/standalone_2/io/stdio_implicit_close_test.dart
index 4fcd719..0df0e04 100644
--- a/tests/standalone_2/io/stdio_implicit_close_test.dart
+++ b/tests/standalone_2/io/stdio_implicit_close_test.dart
@@ -13,11 +13,7 @@
   var scriptFile = "stdio_implicit_close_script.dart";
   var script = Platform.script.resolve(scriptFile).toFilePath();
 
-  // Relying on these flags to print something specific on stdout and stderr
-  // is brittle, but otherwise we would need to add our own flag.
   var arguments = [
-    "--print-metrics", // Prints on stderr.
-    "--timing", //         Prints on stdout.
     script,
   ];
   if (closeStdout) arguments.add("stdout");
@@ -32,17 +28,8 @@
     print(result.stderr);
     Expect.equals(0, result.exitCode);
 
-    if (closeStdout) {
-      Expect.equals("", result.stdout);
-    } else {
-      Expect.isTrue(result.stdout.contains("Timing for"));
-    }
-
-    if (closeStderr) {
-      Expect.equals("", result.stderr);
-    } else {
-      Expect.isTrue(result.stderr.contains("Printing metrics"));
-    }
+    Expect.isTrue(result.stdout.contains("APPLE"));
+    Expect.isTrue(result.stderr.contains("BANANA"));
 
     asyncEnd();
   });
diff --git a/tools/VERSION b/tools/VERSION
index ffb6364..ee58962 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 0
 PATCH 0
-PRERELEASE 62
+PRERELEASE 63
 PRERELEASE_PATCH 0
diff --git a/tools/bots/try_benchmarks.sh b/tools/bots/try_benchmarks.sh
index a2be3ca..919e1bb 100755
--- a/tools/bots/try_benchmarks.sh
+++ b/tools/bots/try_benchmarks.sh
@@ -72,6 +72,9 @@
     ./tools/build.py --mode=release --arch=ia32 create_sdk
     ./tools/build.py --mode=release --arch=ia32 runtime
     tar -czf linux-ia32_profile.tar.gz \
+      --exclude .git \
+      --exclude .gitignore \
+      -- \
       third_party/d8/linux/ia32/natives_blob.bin \
       third_party/d8/linux/ia32/snapshot_blob.bin \
       out/ReleaseIA32/vm_outline.dill \
@@ -92,8 +95,7 @@
       pkg \
       runtime/bin \
       runtime/lib \
-      --exclude .git \
-      --exclude .gitignore || (rm -f linux-ia32_profile.tar.gz; exit 1)
+      || (rm -f linux-ia32_profile.tar.gz; exit 1)
     strip -w \
       -K 'kDartVmSnapshotData' \
       -K 'kDartVmSnapshotInstructions' \
@@ -171,6 +173,9 @@
       -K '_ZN4dart7Version7commit_E' \
       -K '_ZN4dart9Bootstrap*_paths_E' third_party/d8/linux/ia32/d8
     tar -czf linux-ia32.tar.gz \
+      --exclude .git \
+      --exclude .gitignore \
+      -- \
       third_party/d8/linux/ia32/natives_blob.bin \
       third_party/d8/linux/ia32/snapshot_blob.bin \
       out/ReleaseIA32/vm_outline.dill \
@@ -192,8 +197,7 @@
       pkg \
       runtime/bin \
       runtime/lib \
-      --exclude .git \
-      --exclude .gitignore || (rm -f linux-ia32.tar.gz; exit 1)
+      || (rm -f linux-ia32.tar.gz; exit 1)
   elif [ "$command" = linux-ia32-benchmark ]; then
     rm -rf tmp
     mkdir tmp
@@ -237,6 +241,9 @@
     ./tools/build.py --mode=release --arch=simdbc64 runtime
     ./tools/build.py --mode=release --arch=x64 runtime_kernel
     tar -czf linux-x64_profile.tar.gz \
+      --exclude .git \
+      --exclude .gitignore \
+      -- \
       third_party/d8/linux/x64/natives_blob.bin \
       third_party/d8/linux/x64/snapshot_blob.bin \
       out/ReleaseX64/vm_outline.dill \
@@ -260,8 +267,7 @@
       pkg \
       runtime/bin \
       runtime/lib \
-      --exclude .git \
-      --exclude .gitignore || (rm -f linux-x64_profile.tar.gz; exit 1)
+      || (rm -f linux-x64_profile.tar.gz; exit 1)
     strip -w \
       -K 'kDartVmSnapshotData' \
       -K 'kDartVmSnapshotInstructions' \
@@ -358,6 +364,9 @@
       -K '_ZN4dart7Version7commit_E' \
       -K '_ZN4dart9Bootstrap*_paths_E' out/ReleaseX64/dart_precompiled_runtime
     tar -czf linux-x64.tar.gz \
+      --exclude .git \
+      --exclude .gitignore \
+      -- \
       third_party/d8/linux/x64/natives_blob.bin \
       third_party/d8/linux/x64/snapshot_blob.bin \
       out/ReleaseX64/vm_outline.dill \
@@ -381,8 +390,7 @@
       pkg \
       runtime/bin \
       runtime/lib \
-      --exclude .git \
-      --exclude .gitignore  || (rm -f linux-x64.tar.gz; exit 1)
+      || (rm -f linux-x64.tar.gz; exit 1)
   elif [ "$command" = linux-x64-benchmark ]; then
     rm -rf tmp
     mkdir tmp
diff --git a/tools/dom/scripts/systemhtml.py b/tools/dom/scripts/systemhtml.py
index 324900c..458d810 100644
--- a/tools/dom/scripts/systemhtml.py
+++ b/tools/dom/scripts/systemhtml.py
@@ -771,12 +771,14 @@
                  parameterized Promise type.
 '''
 promise_attributes = monitored.Dict('systemhtml.promise_attr_type', {
-    "Animation.finished": {"type": "Animation"},
-    "Animation.ready": {"type": "Animation"},
-    "FontFace.loaded": {"type": "FontFace"},
-    "FontFaceSet.ready": {"type": "FontFaceSet"},
-    "PresentationReceiver.connectionList": {"type": "PresentationConnectionList"},
-    "ServiceWorkerContainer.ready": {"type": "ServiceWorkerRegistration"},
+  "Animation.finished": {"type": "Animation"},
+  "Animation.ready": {"type": "Animation"},
+  "BeforeInstallPromptEvent.userChoice": {"type": "dictionary"},
+  "FontFace.loaded": {"type": "FontFace"},
+  "FontFaceSet.ready": {"type": "FontFaceSet"},
+  "MediaKeySession.closed": {"type": "void"},
+  "PresentationReceiver.connectionList": {"type": "PresentationConnectionList"},
+  "ServiceWorkerContainer.ready": {"type": "ServiceWorkerRegistration"},
 })
 
 promise_operations = monitored.Dict('systemhtml.promise_oper_type', {
@@ -1125,6 +1127,8 @@
     metadata = self._Metadata(attribute.type.id, attribute.id, output_type)
     rename = self._RenamingAnnotation(attribute.id, html_name)
     if not read_only:
+      if attribute.type.id == 'Promise':
+        _logger.warn('R/W member is a Promise: %s.%s' % (self._interface.id, html_name))
       self._members_emitter.Emit(
           '\n  $RENAME$METADATA$TYPE $NAME;'
           '\n',
@@ -1134,17 +1138,44 @@
           TYPE=output_type)
     else:
       template = '\n  $RENAME$(ANNOTATIONS)final $TYPE $NAME;\n'
-      # Need to use a getter for list.length properties so we can add a
-      # setter which throws an exception, satisfying List API.
-      if self._interface_type_info.list_item_type() and html_name == 'length':
-        template = ('\n  $RENAME$(ANNOTATIONS)$TYPE get $NAME => ' +
-            'JS("$TYPE", "#.$NAME", this);\n')
-      self._members_emitter.Emit(
-          template,
-          RENAME=rename,
-          ANNOTATIONS=metadata,
-          NAME=html_name,
-          TYPE=input_type if output_type == 'double' else output_type)
+      if attribute.type.id == 'Promise':
+          lookupOp = "%s.%s" % (self._interface.id, html_name)
+          promiseFound = _GetPromiseAttributeType(lookupOp)
+          promiseType = 'Future'
+          promiseCall = 'promiseToFuture'
+          if promiseFound is not (None):
+              if 'maplike' in promiseFound:
+                  promiseCall = 'promiseToFuture<dynamic>'
+                  promiseType = 'Future'
+              elif promiseFound['type'] == 'dictionary':
+                  # It's a dictionary so return as a Map.
+                  promiseCall = 'promiseToFutureAsMap'
+                  promiseType = 'Future<Map<String, dynamic>>'
+              else:
+                  paramType = promiseFound['type']
+                  promiseCall = 'promiseToFuture<%s>' % paramType
+                  promiseType = 'Future<%s>' % paramType
+
+          template = '\n  $RENAME$(ANNOTATIONS)$TYPE get $NAME => $PROMISE_CALL(JS("", "#.$NAME", this));\n'
+
+          self._members_emitter.Emit(template,
+                                     RENAME=rename,
+                                     ANNOTATIONS=metadata,
+                                     TYPE=promiseType,
+                                     PROMISE_CALL=promiseCall,
+                                     NAME=html_name)
+      else:
+        # Need to use a getter for list.length properties so we can add a
+        # setter which throws an exception, satisfying List API.
+        if self._interface_type_info.list_item_type() and html_name == 'length':
+          template = ('\n  $RENAME$(ANNOTATIONS)$TYPE get $NAME => ' +
+              'JS("$TYPE", "#.$NAME", this);\n')
+        self._members_emitter.Emit(
+            template,
+            RENAME=rename,
+            ANNOTATIONS=metadata,
+            NAME=html_name,
+            TYPE=input_type if output_type == 'double' else output_type)
 
   def _AddAttributeUsingProperties(self, attribute, html_name, read_only):
     self._AddRenamingGetter(attribute, html_name)
diff --git a/tools/infra/config/cq.cfg b/tools/infra/config/cq.cfg
index 9c3f0bf..54077f3 100644
--- a/tools/infra/config/cq.cfg
+++ b/tools/infra/config/cq.cfg
@@ -12,7 +12,6 @@
      dry_run_access_list: "project-dart-tryjob-access"
      allow_submit_with_open_deps: true
   }
-  sign_cla {}
   tree_status {
     tree_status_url: "https://dart-status.appspot.com"
   }
diff --git a/utils/compile_platform.gni b/utils/compile_platform.gni
index 5158a53..9c157b7 100644
--- a/utils/compile_platform.gni
+++ b/utils/compile_platform.gni
@@ -14,17 +14,36 @@
 _dart_root = get_path_info("..", "abspath")
 
 template("compile_platform") {
-  assert(defined(invoker.sources), "Need 'sources' in $target_name")
+  assert(defined(invoker.libraries_specification_uri),
+      "Need 'libraries_specification_uri' in $target_name")
   assert(defined(invoker.outputs), "Need 'outputs' in $target_name")
   assert(defined(invoker.args), "Need 'args' in $target_name")
+  if (defined(invoker.single_root_scheme)) {
+    assert(defined(invoker.single_root_base),
+        "Need 'single_root_base' in $target_name")
+  }
+  if (defined(invoker.single_root_base)) {
+    assert(defined(invoker.single_root_scheme),
+        "Need 'single_root_scheme' in $target_name")
+  }
   assert(!defined(invoker.script), "Remove 'script' from $target_name")
   assert(!defined(invoker.depfile), "Remove 'depfile' from $target_name")
 
+  # In order to automatically compute dependencies, we need to add a dependency
+  # on vm_outline.dill. This is used to include the source code of Fasta itself
+  # in the dependency file. Without this, a change to Fasta wouldn't cause the
+  # platform dill files to be rebuilt.  However, when building
+  # vm_outline_strong.dill, we shouldn't list it as a dependency as this would
+  # lead to cyclic dependencies.
+  add_implicit_vm_platform_dependency = true
+  if (defined(invoker.add_implicit_vm_platform_dependency)) {
+    add_implicit_vm_platform_dependency =
+        invoker.add_implicit_vm_platform_dependency
+  }
+
   action(target_name) {
     script = "$_dart_root/tools/compile_platform.py"
 
-    sources = invoker.sources
-
     outputs = invoker.outputs
 
     inputs = []
@@ -39,6 +58,10 @@
       inputs += invoker.inputs
     }
 
+    if (add_implicit_vm_platform_dependency) {
+      inputs += [ "$root_out_dir/vm_outline_strong.dill" ]
+      deps += [ "$_dart_root/runtime/vm:vm_platform" ]
+    }
     depfile = outputs[0] + ".d"
 
     if (_is_fuchsia) {
@@ -58,7 +81,17 @@
     }
 
     args += invoker.args
-    args += rebase_path(sources, root_build_dir)
+    if (defined(invoker.single_root_scheme)) {
+      args += ["--single-root-scheme=" + invoker.single_root_scheme]
+    }
+    if (defined(invoker.single_root_base)) {
+      args += ["--single-root-base=" + invoker.single_root_base]
+    }
+    if (defined(invoker.single_root_scheme)) {
+      args += [invoker.libraries_specification_uri]
+    } else {
+      args += [rebase_path(invoker.libraries_specification_uri, root_build_dir)]
+    }
     args += rebase_path(outputs, root_build_dir)
   }
 }
diff --git a/utils/compiler/BUILD.gn b/utils/compiler/BUILD.gn
index fbc9258..c94d732 100644
--- a/utils/compiler/BUILD.gn
+++ b/utils/compiler/BUILD.gn
@@ -76,9 +76,9 @@
 }
 
 compile_platform("compile_dart2js_platform") {
-  sources = [
-    "../../sdk/lib/libraries.json",
-  ]
+  single_root_scheme = "org-dartlang-sdk"
+  single_root_base = "../../"
+  libraries_specification_uri = "org-dartlang-sdk:///sdk/lib/libraries.json"
 
   outputs = [
     "$root_out_dir/dart2js_platform.dill",
@@ -92,9 +92,9 @@
 }
 
 compile_platform("compile_dart2js_platform_strong") {
-  sources = [
-    "../../sdk/lib/libraries.json",
-  ]
+  single_root_scheme = "org-dartlang-sdk"
+  single_root_base = "../../"
+  libraries_specification_uri = "org-dartlang-sdk:///sdk/lib/libraries.json"
 
   outputs = [
     "$root_out_dir/dart2js_platform_strong.dill",
@@ -109,9 +109,9 @@
 }
 
 compile_platform("compile_dart2js_server_platform") {
-  sources = [
-    "../../sdk/lib/libraries.json",
-  ]
+  single_root_scheme = "org-dartlang-sdk"
+  single_root_base = "../../"
+  libraries_specification_uri = "org-dartlang-sdk:///sdk/lib/libraries.json"
 
   outputs = [
     "$root_out_dir/dart2js_server_platform.dill",
@@ -125,9 +125,9 @@
 }
 
 compile_platform("compile_dart2js_server_platform_strong") {
-  sources = [
-    "../../sdk/lib/libraries.json",
-  ]
+  single_root_scheme = "org-dartlang-sdk"
+  single_root_base = "../../"
+  libraries_specification_uri = "org-dartlang-sdk:///sdk/lib/libraries.json"
 
   outputs = [
     "$root_out_dir/dart2js_server_platform_strong.dill",